Створення веб-додатків без форм

Ця стаття заснована на попередній версії платформи ASP.NET MVC. Дані відомості можуть бути змінені.
У статті розглядається:



Код доступний для завантаження за адресою: MVCFramework2008_03.exe (189 KB)

Я професійно займаюся розробкою вже близько 15 років, а до цього ще років 10 писав програми заради задоволення. Як і більшість програмістів мого віку, я почав з 8-бітних машин, а потім перейшов на платформу ПК. Переходячи від системи до системи, по зростаючій, я писав все підряд, починаючи з іграшок і закінчуючи програмами для керування особистими даними та контролю зовнішнього обладнання.
Треба сказати, спочатку мої програми об'єднувало одне: вони всі працювали локально, на настільному комп'ютері. На початку 90-х я почув про таку штуку як Інтернет. Замаячила надія написати веб-додаток, яке зможе вносити записи до картки обліку робочого часу – тоді б мені не довелося кожен раз їхати в офіс.
Ця задача виявилася, на жаль, нерозв'язною. У моїй настільно-комп'ютерної голові просто не вкладалося, як виконати захоплення при відсутності станів. Додайте до цього далеко не досконалу налагодження, сервер під UNIX, на якому у мене не було доступу до кореня, чортові кутові дужки – загалом, я з ганьбою повернувся до розробки програм для настільних комп'ютерів і займався нею ще кілька років.
Від веб-програмування я тримався осторонь. Зрозуміло, це важлива сторона розробки, але я не розумів самої моделі програмування. Потім з'явилися платформи Microsoft ®. NET і ASP.NET. Нарешті-то мені в руки потрапило засіб, що дозволяє працювати з веб-додатками і при цьому використовувати практично ті ж прийоми розробки, що застосовувалися в локальних програмах. Тепер я зможу створювати вікна (сторінки), прив'язувати елементи управління до подій і не маятися з кутовими дужками (слава режиму конструктора!). Найкраще було те, що ASP.NET сама вирішила питання з відсутністю станів: з'явилися стану подання. Я знову став щасливим програмістом … на якийсь час.
З появою досвіду я став більш розбірливим у програмуванні. Я виробив для себе певні принципи, яким ішов при роботі над додатками. Два з них виглядають наступним чином.


Ці принципи існують незалежно від використовуваних технологій. Поділ завдань – основний спосіб знизити складність проблеми. Якщо ви на один об'єкт навісите відразу декілька обов'язків, скажімо, розрахунок залишковий час роботи, форматування даних, побудова графіка, то тим самим тільки утрудните обслуговування програми. А автоматичне тестування необхідно тому, що без нього неможливо створити якісний код, зберігши при цьому душевну рівновагу. Особливо якщо ви оновлюєте старий проект.
З веб-формами в ASP.NET спочатку дуже просто працювати, але от щоб дотримати згадані принципи, мені довелося помучитися. Веб-форми цілком і повністю сконцентровані на інтерфейсі. Основною складовою є сторінка. Робота починається з проектування інтерфейсу користувача. Ви перетягуєте на сторінку елементи управління. Можливість зліпити логіку програми з обробників подій, розміщених на сторінці (як у Visual Basic ® для додатків Windows ®), дуже приваблива.
При цьому модульне тестування сторінок виконати дуже складно. Не можна провести об'єкт-сторінку через весь його життєвий цикл, не задіявши всю платформу ASP.NET. Веб-програми можна тестувати при допомоги http-запитів на сервер або за допомогою автоматизації оглядача, однак таке тестування дуже ненадійно (варто змінити хоч один код елемента керування – і все зламається), його складно налаштовувати (серверні компоненти на всіх комп'ютерах доводиться настроювати абсолютно однаково), і, крім того, вона відбирає багато часу.
Коли я перейшов до відносно складним веб-додатків, всі ці абстракції, пов'язані з веб-формами (елементи управління, стану подання, життєвий цикл сторінки), стали більше заважати, ніж допомагати. У мене все більше часу йшло на налаштування прив'язки даних (і на створення того шаленого кількості обробників, що було потрібно для правильного налаштування). Довелося замислитися над тим, як би скоротити розмір статку подання та прискорити завантаження сторінок. Для роботи веб-форм необхідно, щоб за кожним URL-адресою існував фізичний файл, а при створенні динамічних веб-сайтів (вікі-вузлів, наприклад) це можливо не завжди. Створення власного елемента WebControl (та ще й працездатного) – процес багаторівневий, що вимагає відмінної розуміння та життєвого циклу сторінок, і принципів роботи конструктора Visual Studio ®.
З тих пір, як я прийшов у Майкрософт, у мене з'явилася можливість поділитися тим, що я дізнався про больові точки платформи. NET і про те, як з ними боротися. Зовсім недовно я став учасником проекту Patterns & Practices Web Client Software Factory (codeplex.com / websf). Однією з обов'язкових складових додатків, створюваних нашою групою, є автоматичне тестування модулів. Для створення тестованих веб-форм ми запропонували використовувати шаблон MVP (модель – візуалізація – презентатор).
Якщо коротко, то в схемі MVP логіка не розміщується на сторінці. Замість цього зі сторінки виконується звернення до окремого об'єкту, презентатора. Об'єкт-презентатор виконує всі необхідні операції в відповідь на дії, вироблені з поданням, – як правило, використовуючи при цьому інші об'єкти (модель) для доступу до даних, для запуску бізнес-логіки і т. д. Проробивши все необхідне, презентатор оновлює подання. Такий підхід розширює можливості тестування, оскільки презентатор ізольований від конвеєра ASP.NET. Він взаємодіє з поданням через інтерфейс, тому його можна тестувати окремо від сторінки.
Схема MVP працює непогано, однак реалізовувати її іноді доводиться обхідними шляхами. Потрібен окремий інтерфейс подання, потрібна велика кількість функцій передачі подій. Але для забезпечення тестованості інтерфейсу веб-форм це, мабуть, найкращий варіент. Удосконалити його можна, тільки змінивши робочу платформу.


Схема MVC (модель – візуалізація – контролер)


На щастя, група розробки ASP.NET завжди прислухалася до думки програмістів. Вони приступили до створення нової платформи веб-додатків, в якій залишаться всіма улюблені веб-форми, але завдання конструювання дещо зміняться:


Нова платформа будується на базі схеми MVC (модель – візуалізація – контролер), звідси й назва – ASP.NET MVC. Схема MVC була придумана ще в 70-х, при розробці Smalltalk. У статті я постараюся показати, наскільки добре вона відповідає самій природі Інтернету. MVC ділить користувальницький інтерфейс на три різних об'єкта: контролер отримує вхідні дані і обробляє їх, модель містить логіку домену, подання оформляє отриманий результат. У контексті веб-додатків вхідні дані – це HTTP-запит. Хід обробки запитів зображений на рис. 1.


Figure 1 Хід обробки запиту у схемі MVC


У веб-формах цей процес виглядає зовсім по-іншому. Там вхідні дані відправляються на сторінку (до подання). Представлення відповідає і за обробку вхідних даних, і за відображення результату. У MVC ці обов'язки розділяються.
Зараз ви, напевно, ставите одним з двох питань: або "Ну відмінно, а як це застосовувати?", Або "Навіщо мені три об'єкти, якщо раніше обходилися одним?". Обидва питання цілком осмислені, і обоє можна пояснити на прикладі. Ми створимо неболяче веб-додаток на базі платформи MVC, щоб продемонстріроватть її переваги.


Створення контролера


Для початку потрібно встановити Visual Studio 2008 і платформу MVC. На момент написання статті її можна знайти в складі CTP-версії розширень для ASP.NET, випущеної в грудні 2007 року (asp.net/downloads/3.5-extensions). Вам знадобиться і самі розширення, і набір інструментів MVC Toolkit – у ньому є кілька дуже корисних допоміжних об'єктів. Коли ви завантажте CTP, в діалоговому вікні "Новий проект" з'явиться ще один тип проекту – веб-додаток ASP.NET MVC.
Цей тип проекту дещо відрізняється від звичайного веб-сайту або програми. Шаблон рішення створює для веб-додатки інший набір каталогів (див. рис. 2). У каталозі Controllers, наприклад, містяться класи контролерів, в каталозі Views (і у всіх його вкладених каталогах) – уявлення.


Figure 7 Редагування домашньої сторінки


Логіку створеного сайту можна подивитися в коді, доданому до цієї статті. А я хотів би зупинитися на тому, яким чином платформа MVC спрощує розміщення вікі-сайту в Інтернеті. Я почав з проектування структури URL-адреси. Він повинен був виглядати так:


Для початку просто відобразимо вікі-сторінку. Для цього я створив клас WikiPageController. Потім я додав операцію ShowPage. перша версія контролера WikiPageController показана на рис. 8. Медот ShowPage абсолютно простий. Класи WikiSpace і WikiPage представляють, відповідно, набір вікі-сторінок і окрему вікі-сторінку (і її редакцію). Створена операція завантажує модель і викликає метод RenderView. Навіщо тоді потрібна рядок "new WikiPageViewData"?
Figure 8 WikiPageController Implementation of ShowPage

public class WikiPageController : Controller
{
ISpaceRepository repository;

public ISpaceRepository Repository
{
get {
if (repository == null)
{
repository = new FileBasedSpaceRepository(
Request.MapPath(“~/WikiPages”));
}
return repository;
}

set { repository = value; }
}

[ControllerAction]
public void ShowPage(string pageName, int? version)
{
WikiSpace space = new WikiSpace(Repository);
WikiPage page = space.GetPage(pageName);

RenderView(“showpage”,
new WikiPageViewData
{
Name = pageName,
Page = page,
Version = version ?? 0
});
}
}


Один із способів передачі даних з контролера в уявлення був продемонстрований у попередньому прикладі: це Слован ViewData. Словники – річ зручна, але підступна. У них може зберігатися все що завгодно, а технологія IntelliSense ® до вмісту не застосовується. Словник ViewData відноситься до типу Dictionary <рядок, об'єкт>, і тому доводиться весь його вміст перетворювати перед використанням.
Якщо заздалегідь відомо, які дані будуть потрібні в поданні, можна не використовувати словник, а передати суворо типізований об'єкт ViewData. Я створив найпростіший об'єкт WikiPageViewData (він показаний на рис. 9). Цей об'єкт передає до подання інформацію про вікі-сторінці та кілька методів, здатних, наприклад, знайти версію HTML в розмітці вікі-сторінки.
Figure 9 WikiPageViewData Object

public class WikiPageViewData {

public string Name { get; set; }
public WikiPage Page { get; set; }
public int Version { get; set; }

public WikiPageViewData() {
Version = 0;
}

public string NewVersionUrl {
get {
return string.Format ("/ CreateNewVersion / {0}", Name);
}
}

public string Body {
get { return Page.Versions[Version].Body; }
}

public string HtmlBody {
get { return Page.Versions[Version].BodyAsHtml(); }
}

public string Creator {
get { return Page.Versions[Version].Creator; }
}

public string Tags {
get {return string.Join (",", Page.Versions [Version]. Tags);}
}
}


Отже, дані для подання визначені. Як їх використовувати? На сторінці ShowPage.aspx.cs є ось такий фрагмент коду:

namespace MiniWiki.Views.WikiPage {
public partial class ShowPage: ViewPage <WikiPageViewData>
{
}
}

Зверніть увагу, що базовий клас у нашому прикладі відноситься до типу ViewPage <WikiPageViewData>. Це означає, що властивість ViewData, наявне у сторінки, відноситься до типу WikiPageViewData, а не до типу Dictionary, як у попередньому випадку.
Розмітка у файлі ASPX насправді зовсім зрозуміла:

 <% @ Page Language = "C #" MasterPageFile = "~ / Views / Shared / Site.Master"
AutoEventWireup=”true” CodeBehind=”ShowPage.aspx.cs”
Inherits=”MiniWiki.Views.WikiPage.ShowPage” %>
<asp:Content
ID=”Content1″
ContentPlaceHolderID=”MainContentPlaceHolder”
runat=”server”>
<h1><%= ViewData.Name %></h1>
<div id=”content” class=”wikiContent”>
<%= ViewData.HtmlBody %>
</div>
</asp:Content>

Зверніть увагу, що в посиланнях на ViewData оператор індексації [] не використовується. Об'єкт ViewData суворо типізовані, тому до властивості можна звертатися безпосередньо. Ніяких перетворень при цьому не відбувається, так що можна скористатися технологією IntelliSense.
Уважний читач, напевно, помітив тег <asp:Content> в коді. Так, головні сторінки дійсно можна використовувати разом з уявленнями MVC. Більше того, головна сторінка сама може бути поданням. Погляньте на фоновий код головної сторінки:

namespace MiniWiki.Views.Layouts
{
public partial class Site :
System.Web.Mvc.ViewMasterPage<WikiPageViewData>
{
}
}

Відповідна розмітка показана на рис. 10. У такому вигляді головна сторінка використовується ті ж самі об'єкти ViewData, що і подання. Базовий клас головної сторінки в нашому прикладі має тип ViewMasterPage <WikiPageViewData>, значить тип об'єкта ViewData обраний правильно. Тепер можна додати теги DIV, щоб налаштувати зовнішній вигляд сторінки, заповнити список версій і, нарешті, вставити заповнювач для вмісту.
Figure 10 Site.Master

<%@ Master Language=”C#”
AutoEventWireup=”true”
CodeBehind=”Site.master.cs”
Inherits=”MiniWiki.Views.Layouts.Site” %>
<%@ Import Namespace=”MiniWiki.Controllers” %>
<%@ Import Namespace=”MiniWiki.DomainModel” %>
<%@ Import Namespace=”System.Web.Mvc” %>
<html >
<head runat=”server”>
<title><%= ViewData.Name %></title>
<link href="http://../../Content/Site.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div id=”inner”>
<div id=”top”>
<div id=”header”>
<h1><%= ViewData.Name %></h1>
</div>
<div id=”menu”>
<ul>
<li> <a href="http://Home"> Home </ a> </ li>
<li>
<%= Html.ActionLink(“Edit this page”,
new { controller = “WikiPage”,
action = “EditPage”,
pageName = ViewData.Name })%>
</ul>
</div>
</div>
<div id=”main”>
<div id=”revisions”>
Revision history:
<ul>
<%
int i = 0;
foreach (WikiPageVersion version in ViewData.Page.Versions)
{ %>
<li>
<A href = "http:// <% = ViewData.Name%>? Version = <% = i%>">
<%= version.CreatedOn %>
by
<%= version.Creator %>
</a>
</li>
<% ++i;
} %>
</ul>
</div>
<div id=”maincontent”>
<asp:ContentPlaceHolder
ID=”MainContentPlaceHolder”
runat=”server”>
</asp:ContentPlaceHolder>
</div>
</div>
</div>
</body>
</html>

Ще слід торкнутися виклику Html.ActionLink. Це приклад допоміжного класу візуалізації. У класів уявлень є дві властивості, Html і Url. Кожен з них використовує різні методи для породження фрагментів HTML-коду. У даному случає Html.ActionLink бере об'єкт (тут – анонімного типу) і проводить його через систему маршрутизації. У результаті виходить URL-адреса, за якою визначається контролер і операція. При такому розвитку подій цим посиланням: "Редагувати цю сторінку" завжди вірна – незалежно від того, як змінити маршрути.
Ну і нарешті, ви, напевно, звернули увагу на те, що посилання на попередні версії сторінки довелося створювати вручну. Поточна версія системи маршрутизації, на жаль, не здатна породжувати URL-адреси, якщо використовуються рядки запитів. У наступних версіях платформи це має бути виправлено.

Створення форм і виконання зворотної передачі
Тепер розглянемо операцію EditPage:

[ControllerAction]
public void EditPage(string pageName)
{
WikiSpace space = new WikiSpace(Repository);
WikiPage page = space.GetPage(pageName);

RenderView(“editpage”,
new WikiPageViewData {
Name = pageName,
Page = page });
}


Знову ж таки, операція ця досить проста: вона просто відображає подання на вказаній сторінці. З поданням, показаному на рис. 11, ситуація трохи цікавіше. Це файл створює HTML-форму, але тегів з атрибутом Runat = "server" в ньому немає. Тут застосовується допоміжний клас Url.Action – він створює URL-адресу, за якою форма випоняется зворотну передачу. Крім того, кілька разів використовуються інші допоміжні класи: TextBox, TextArea, SubmitButton. Нічого несподіваного вони не роблять, створюють HTML-код для різних полів введення даних.
Figure 11 EditPage.aspx

<%@ Page Language=”C#”
MasterPageFile=”~/Views/Shared/Site.Master”
AutoEventWireup=”true”
CodeBehind=”EditPage.aspx.cs”
Inherits=”MiniWiki.Views.WikiPage.EditPage” %>
<%@ Import Namespace=”System.Web.Mvc” %>
<%@ Import Namespace=”MiniWiki.Controllers” %>
<asp:Content ID=”Content1″
ContentPlaceHolderID=”MainContentPlaceHolder”
runat=”server”>
<form action=”<%= Url.Action(
new { controller = “WikiPage”,
action = “NewVersion”,
pageName = ViewData.Name })%>” method=post>
<%
if (ViewContext.TempData.ContainsKey(“errors”))
{
%>
<div id=”errorlist”>
<ul>
<%
foreach (string error in
(string[])ViewContext.TempData[“errors”])
{
%>
<li><%= error%></li>
<% } %>
</ul>
</div>
<% } %>
Your name: <%= Html.TextBox(“Creator”,
ViewContext.TempData.ContainsKey ("creator")?
(string)ViewContext.TempData[“creator”] :
ViewData.Creator)%>
<br />
Please enter your updates here:<br />
<% = Html.TextArea ("Body", ViewContext.TempData.ContainsKey ("body")?
(string)ViewContext.TempData[“body”] :
ViewData.Body, 30, 65)%>
<br />
Tags: <%= Html.TextBox(
"Tags", ViewContext.TempData.ContainsKey ("tags")?
(string)ViewContext.TempData[“tags”] :
ViewData.Tags)%>
<br />
<%= Html.SubmitButton(“SubmitAction”, “OK”)%>
<%= Html.SubmitButton(“SubmitAction”, “Cancel”)%>
</form>
</asp:Content>

Одна з найнеприємніших проблем веб-програмування – помилки у формах. Точніше кажучи, відображення повідомлення про помилку з збереженням введених даних. Кожному, напевно, траплялося допустити помилку у формі з 35 полів. Після цього бачиш купу повідомлень про помилки – і все доводиться заповнювати наново. Платформа MVC дозволяє зберігати введені дані в елементі TempData. У випадку помилки вони вставляються в форму. Елемент ViewState насправді здорово спрощує процедуру повторного заповнення веб-форм, оскільки вміст елементів управління зберігається здебільшого автоматично.
Було б здорово зробити те ж саме і в MVC. І тут на сцені з'являється TempData – це словник, багато в чому нагадує нетипізований словник ViewData. Різниця полягає в тому, що TempData існує тільки під час виконання запиту – потім він віддаляється. Щоб зрозуміти, як він використовується, погляньте на рис. 12 (на операцію NewVersion).
Figure 12 NewVersion Action

[ControllerAction]
public void NewVersion(string pageName)
{
NewVersionPostData postData = new NewVersionPostData();
postData.UpdateFrom(Request.Form);

if (postData.SubmitAction == “OK”)
{
if (postData.Errors.Length == 0)
{
WikiSpace space = new WikiSpace(Repository);
WikiPage page = space.GetPage(pageName);
WikiPageVersion newVersion = new WikiPageVersion(
postData.Body, postData.Creator, postData.TagList);
page.Add(newVersion);
}
else
{
TempData[“creator”] = postData.Creator;
TempData[“body”] = postData.Body;
TempData[“tags”] = postData.Tags;
TempData[“errors”] = postData.Errors;

RedirectToAction(new {
controller = “WikiPage”,
action = “EditPage”,
pageName = pageName });

return;
}
}

RedirectToAction(new {
controller = “WikiPage”,
action = “ShowPage”,
pageName = pageName });
}


Спочатку створюється об'єкт NewVersionPostData. Це ще один допоміжний об'єкт, у властивостях і методах якого зберігається вміст передачі і частково виконується перевірка. Для завантаження об'єкта postData я використовую допоміжну функцію з набору MVC Toolkit. UpdateFrom – це метод розширення, який використовує для зіставлення імен полів форми та імен властивостей об'єкта метод відображення. У результаті всі значення полів завантажуються в об'єкт postData. Недолік методу UpdateFrom в тому, що дані з форми він отримує за допомогою запиту HttpRequest, а це ускладнює тестування модулів.
Перше, що перевіряє NewVersion – це операція SubmitAction. Перевірка вважається пройденою, якщо користувач, що натиснув кнопку OK, дійсно намагався опублікувати відредаговану сторінку. Якщо в операції присутні якісь інші значення, чи йде перенаправлення до операції ShowPage і просто відображається вихідна сторінка.
Якщо користувач все ж натиснув кнопку OK, перевіряється властивість postData.Errors. Виконується кілька тестів стосовно до вмісту передачі. Якщо помилок не виявлено, нова версія сторінки зберігається на вікі-сайті. Набагато цікавіше, якщо помилки виявлені.
У такому випадку вміст об'єкта PostData записується в словник TempData. Потім користувач повертається на сторінку редагування. Форма заповнюється значеннями, збереженими в словнику TempData.
Зараз вся ця процедура передачі, перевірки і запису в словник TempData досить неприємна і дуже багато всього доводиться робити вручну. У наступних версіях платформи повинні з'явитися допоміжні методи, які допоможуть автоматизувати роботу, – принаймні перевірку словника TempData. Останнє, що потрібно про нього вказать: вміст словника TempData зберігається в сеансі роботи користувача з сервером. Якщо сеанс завершити, TempData працювати не буде.


Створення контролера


Базова версія вікі-сайту працює, але є кілька місць, які хотілося б пригладити. Наприклад, властивість Repository використовується для відділення логіки вікі-вузла від фізичного сховища. Вміст може зберігатися у файловій системі (як у моєму прикладі), в базі даних або десь ще. Тут виникають дві проблеми.
По-перше, клас контролера тісно пов'язаний зі стійким класом FileBasedSpaceRepository. Доводиться ставити значення за замовчуванням, щоб у разі відсутності значення у властивості було що використовувати. Більше того, шлях до файлів на диску теж задається жорстко. Він повинен принаймні визначатися конфігурацією.
По-друге, властивість Repository за фактом є обов'язковим: без нього об'єкт не працює. Добре б, щоб репозиторій ставилося у параметрі конструктора, а не у властивості. Але в конструктор його додати не можна, тому що за вимогами платформи MVC на контролерах повинні використовуватися конструктори без параметрів.
На щастя, існує обробник розширень, здатний допомогти в такій ситуації: фабрика контролерів. Як випливає з її називання, фабрика контролерів створює екземпляри об'єктів Controller. Потрібно створити клас, який реалізує інтерфейс IControllerFactory, і зареєструвати його в системі MVC. Фабрики можна реєструвати для окремих типів контролерів або для всіх контролерів відразу. На рис. 13 показана фабрика, створена для контролера WikiPageController, – вона дозволяє вказати репозиторій в параметрі конструктора.
Figure 13 Controller Factory

 public class WikiPageControllerFactory: IControllerFactory {

public IController CreateController(RequestContext context,
Type controllerType)
{
return new WikiPageController(
GetConfiguredRepository(context.HttpContext.Request));
}

private ISpaceRepository GetConfiguredRepository (IHttpRequest request)
{
return new FileBasedSpaceRepository (request.MapPath ("~ / WikiPages"));
}
}


У цьому випадку вирішення проблеми тривіально, а отримані інтерфейс дозволяє створювати набагато більш функціональні контролери (наприклад, контейнери для введення залежностей). Так чи інакше, тепер у нас всі дані, пов'язані з отриманням залежності, існують в окремому об'єкті, яким без праці можна управляти.
Залишилося тільки зареєструвати фабрику в платформі. За допомогою класу ControllerBuilder додамо в файл Global.asax.cs, в метод Application_Start, Наступний рядок. Додати її можна як до, так і після маршрутів.

ControllerBuilder.Current.SetControllerFactory(
typeof (WikiPageController), typeof (WiliPageControllerFactory));

Тепер фабрика зареєстрована для контролера WikiPageController. Якщо б у проекті були інші контролери, вони б не змогли використати цю фабрику, оскільки харегістрірована вона тільки для WikiPageController. Якщо фабрику будуть використовувати всі контролери, можна викликати метод SetDefaultControllerFactory.


Інші точки розширення


Фабрика контролерів – лише одна з можливостей розширення платформи. Всі описати в статті не вийде, тому я торкнуся лише самих примітних. По-перше, якщо у вихідних даних повинен міститися не тільки HTML-код (або якщо ви не хочете використовувати інший механізм створення шаблонів замість веб-форм), можна замінити фабрику ViewFactory для контролера. Інтерфейс IViewFactory дає повний контроль над процесом породження вихідних даних. Його можна застосовувати для створення RSS, XML і навіть графіки.
Система маршрутизації, як вже зазначалося, відрізняється достатньою гнучкістю. У ній немає жодного компонента, властивого ісключтельно платформі MVC. Кожен маршрут має властивість RouteHandler. До цих пір воно завжди мало значення MvcRouteHandler. Проте можна використовувати також інтерфейс IRouteHandler і прив'язати систему маршрутизації до інших веб-технологіям. У наступній версії платформи з'явиться WebFormsRouteHandler, значить у можна буде користуватися додатковими технологіями.
Контролери не обов'язково виводити з класу System.Web.Mvc.Controller. Єдина вимога – кожен контролер повинен реалізовувати інтерфейс IController, в якій є тільки один метод (Execute). А далі ви можете робити все що завгодно. З іншого боку, у базового класу Controller є ряд віртуальних функцій, і якщо їх перевизначити, можна налаштувати його поведінка:


InvokeAction – це метод, здатний визначити потрібну операцію і викликати її. Він допускає настройку цієї процедури (наприклад, можна позбутися від атрибута [ControllerAction]).
У класі Controller є й інші віртуальні методи, але вони скоріше застосовуються для тестування, а не для розширення можливостей. Наприклад, метод RedirectToAction є віртуальним, що дозволяє вивести з нього клас, який насправді не буде виконувати перенаправлення. Це дозволяє протестувати операції перенаправлення без застосування веб-сервера.


Прощайте, веб-форми?


Напевно, ви зараз ставите питанням: "А що ж буде з веб-формами? Невже MVC їх повністю замінить?" Ні, звичайно. Веб-форми – це добре продумана технологія, і Майкрософт буде як і раніше підтримувати і вдосконалювати її. Якщо чимало додатків, в яких веб-форми чудово працюють. Наприклад, якщо при створенні програми, що видає звіти по базам даних, використовувати веб-форми, то на нього піде значно менше часу, ніж при роботі в платформі MVC. Крім того, веб-форми підтримують найширший набір елементів управління, більшість яких мають складну структуру і зажадали б чималих зусиль, візьмися хто створювати їх заново.
Коли краще віддати перевагу MVC веб-форм? Це багато в чому залежить від конкретних вимог і ваших особистих переваг. Вам набридло боротися з URL, домагаючись потрібної їх форми? Вам потрібно засіб модульного тестування інтерфейсу? І в тому, і в іншому випадку варто, напевно, звернутися до платформи MVC. Вам доводиться відображати велику кількість даних, ви використовуєте складні сітки і дерева? Тоді краще зупинити свій вибір на веб-формах.
З часом платформа MVC, ймовірно, наздожене веб-форми за рівнем складності елементів управління, але навряд чи коли-то з нею буде так само просто почати працювати, як з веб-формами, в яких більшість дій зводиться до перетягування елементів. Але між тим, платформа ASP.NET MVC пропонує веб-розробникам абсолютно новий спосіб створення програм в Microsoft. NET Framework. У ній є широкі можливості тестування, в ній робиться наголос на HTTP, вона відмінно масштабується. Вона стане відмінним доповненням до веб-форм в тому випадку, коли розробнику потрібен повний контроль над веб-додатком.

Кріс Таварес (Chris Tavares) працює в групі Microsoft patterns & practices, займається розробкою рекомендацій щодо створення систем на базі платформ Microsoft. Крім цього, Кріс є віртуальним членом робочої групи ASP.NET MVC, бере участь в роботі над новою платформою. Зв'язатися з Крісом можна за адресою cct@tavaresstudios.com.

Схожі статті:


Сподобалася стаття? Ви можете залишити відгук або підписатися на RSS , щоб автоматично отримувати інформацію про нові статтях.

Коментарів поки що немає.

Ваш отзыв

Поділ на параграфи відбувається автоматично, адреса електронної пошти ніколи не буде опублікований, допустимий HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

*