.NET

индекс
121,06

MVC Framework: большое введение для начинающих

Необходимое отступление: не так давно я разместил статью предназначавшуюся для печатного издания. Приведенная ниже статья имеет ту же самую судьбу: она не попала в печать в связи с тяжелым положением журнала. Как и в прошлый раз, я решил опубликовать статью на Хабре, благо тематика попадает под формат. Необходимо заметить, что статья оформлена и содержит текст для журнала, если бы она готовилась для Хабра, то некоторые часть могли бы быть изменены. Надеюсь, статья вам понравится.

В последнее время заметно, что компания Microsoft уделяет повышенное внимание развитию своих средств разработки, новым инструментам и механизмам разработки программ на своей платформе .net. Быстро развивается язык C#, четвертая версия которого не за горами. Представлен и активно продвигается новый язык F#. Для разработчиков баз данных разработан Entity Framework, который уже доступен в виде финальной версии в первом сервиспаке к .Net Framework 3.5 и Visual Studio 2008. Microsoft активно занялась и клиентской частью разработки web-проектов. Для нашего внимания предложен путь развития Ajax.Net 4.0. Internet Explorer 8 все больше соответствует стандартам и становится привлекательным инструментом для web-программистов, так например, его вкладка Developer Tools включает в себя профайлер Javascript. Очень хорошей новостью стало недавно объявление о полной поддержке и включении Javascript-библиотеки jQuery в следующее обновление Visual Studio. В этом свете возникает вопрос, что же предложено разработчикам ASP.NET? Ответ — MVC Framework. Целью данной статьи рассмотреть некоторые общие проблемы, с которыми могут столкнуться программисты, решившие использовать MVC Framework для своих web-проектов, и их решения.

O MVC


Паттерн Модель-представление-контроллер или по-английски Model-view-controller используется очень давно. Еще в 1979 году его описал Тригве Реенскауг в своей работе «Разработка приложений на Smalltalk-80: как использовать Модель-представление-контроллер». С тех пор паттерн зарекомендовал себя как очень удачная архитектура программного обеспечения.



Пользователь, работая с интерфейсом, управляет контроллером, который перехватывает действия пользователя. Далее контроллер уведомляет модель о действиях пользователя, тем самым изменяя состояние модели. Контроллер также уведомляет представление. Представление, используя текущее состояние модели, строит пользовательский интерфейс.
Основой паттерна является отделение модели данных приложения, его логики и представления данных друг от друга. Таким образом, следуя правилу «разделяй и властвуй», удается строить стройное программное обеспечение, в котором, во-первых, модель не зависит от представления и логики, а во-вторых, пользовательский интерфейс надежно отделен от управляющей логики.

На данный момент паттерн MVC реализован в том или ином виде для большинства языков программирования используемых для разработки web-приложений. Самое большое количество реализаций имеет PHP, но и для Java, Perl, Python, Ruby есть свои варианты. До появления версии MVC от Microsoft, для платформы .NET так же существовали свои варианты: Maverick.NET и MonoRail.

ASP.NET MVC Framework


10 декабря 2007 года Microsoft представила свой вариант реализации MVC для ASP.NET. Он по-прежнему базируется на .aspx, .ascx и .master файлах, полностью поддерживает аутентификацию на базе форм, роли, кэширование данных, управление состоянием сессий, health monitoring, конфигурирование, архитектуру провайдеров и другое.

С другой стороны, MVC Framework не предполагает использование классических web-форм и web-элементов управления, в нем отсутствуют такие механизмы как обратные вызовы (postbacks) и состояние представления (viewstate). MVC Framework так же предлагает использование URL-mapping и архитектуру REST в качестве модели запросов, что положительно повлияет на поисковую оптимизацию web-проектов.
--- Классический ASP.NET MVC
Модель запросов postback REST
Модель данных через код cs-файла страницы (code-behind) определяется паттерном MVC
Разработка интерфейса web-controls чистый html, MVC UI Helpers
Авто-генерация id да нет
ViewState есть нет
URL mapping нет есть

В целом, высказывая свое мнение, я могу сказать, что MVC Framework предложил для разработчиков ASP.NET новый стиль, ориентированный на качество клиентского кода. Генерируемый MVC код страниц не содержит ничего автоматически создаваемого, здесь нет раздутых идентификаторов, нет огромных viewstate, написание клиентских скриптов упрощено в связи с тем, что код страницы представляет собой чистый, созданный самим программистом HTML. В эпоху, когда понятие web 2.0 прочно вошло в нашу жизнь полный контроль над страницей на клиентской стороне – это залог успеха любого web-проекта.

Версии MVC Framework


MVC Framework от версии к версии все улучшается, и за период с сентября по октябрь вышли две версии, которые принесли много нового, так в Preview 5 произошли следующие изменения:
  • Добавлена поддержка рендеринга частичных представлений, по сути можно вставлять в представление свои пользовательские элементы;
  • Добавлен атрибут AcceptVerbs, который позволяет задавать action для конкретного типа запроса (POST или GET);
  • Добавлен атрибут ActionName, который позволяет задавать методу имя action. По умолчанию, имена action и имени метода совпадают, но теперь появляется возможность делать их разными;
  • Изменена работа атрибута HandleError. Теперь для разработчиков могут быть выведены стандартные «желтые страницы смерти» с информацией об ошибках;
  • Появилась поддержка комплексных типов через ModelBinder.

Вышедшая в середине октября MVC Framework Beta так же содержит массу дополнений:
  • Новое меню «Add View» в Visual Studio
  • Папка \scripts и поддержка jQuery
  • Встроенная поддержка Model Binder для комплексных типов
  • Перестроена инфраструктура Model Binder
  • Улучшены методы UpdateModel и TryUpdateModel
  • Улучшено тестирование сценариев UpdateModel и TryUpdateModel
  • Типизирован атрибут AcceptVerbs. Добавлено перечисление HttpVerbs.
  • Улучшены сообщения об ошибках по умолчанию при валидации
  • Модифицированы некоторые хелпер методы. Изменено создание формы. Методы стали extension-методами класса HtmlHelper.
  • Поддержка проектов с Silverlight 2
  • Сборка ASP.NET MVC Futures для этой беты вынесена отдельно и не входит в поставку
  • Поддержка размещения сборок в GAC

Советы


Как задать на странице html-элемент select


Для создания элемента используется метод DropDownList хелпер класса Html:
<%=Html.DropDownList("", «sampleSelect») %>

Первый параметр задает строку, которая добавится в список элемента, как строка по умолчанию, второй параметр – это имя нашего select.
Самое интересно заключается в том, как добавить для select данные. Допустим, мы имеем следующую модель данных:
public class Product
{
        public string Name
        {
            get;
            set;
        }
        public int Id
        {
            get;
            set;
        }
}


* This source code was highlighted with Source Code Highlighter.

Чтобы поместить в select набор данных типа Product необходимо проделать следующие действия:
var products = GetProducts();
ViewData[«sampleSelect»] = new SelectList(products, «Id», «Name»);

Где
GetProducts – это некий метод, источник данных в виде IEnumerable, такие источники данных следует располагать в модели данных, здесь приведено упрощенно для примера;
SelectList – это вспомогательный класс определенный в System.Web.MVC.

Здесь, через ViewData передается набор данных созданных с помощью класса SelectList, конструктор которого через первый параметр принимает данные в виде products. Имена свойств, определенных в классе Product, для значений и выводимого текста в select передается вторым и третьим параметрами.

Как отобразить пользовательский элемент управления


Для того чтобы отобразить свой элемент управления используется представленный в preview 5 метод Html.RenderPartial(...). Для того чтобы использовать пользовательский элемент управления в своих проектах он должен быть создан как MVC View User Control, а не как обычный Web User Control. Разница заключается в том, от какого класса наследуется созданный элемент. В случае MVC, элемент будет наследоваться от System.Web.Mvc.ViewUserControl.

Вывод пользовательского элемента не составляет труда:
<% Html.RenderPartial(«SampleUserCtrl»); %>

Где SampleUserCtrl – это имя класса, который представляет пользовательский элемент управления.

Как присвоить элементу, созданному через класс Html, атрибут class


Хэлпер класс HTML – это очень полезный инструмент MVC Framework, который позволяет единообразно создавать элементы управления на странице. И, конечно, методы этого класса позволяет задавать атрибуты html-элементов. На примере, мы зададим гиперссылке с текстом SampleLink, действием ActionName с параметром product.Id тэг rel = «nofollow».
Html.ActionLink(«SampleLink», ActionName, new {product.Id}, new {rel = «nofollow» })

Проблема начинается тогда, когда название атрибута совпадает с зарезервированным словом в C#, которым, конечно, является «class». Решение простое:
Html.ActionLink(«SampleLink», ActionName, new {product.Id}, new {@class = «sample-css-class» })

Когда мало ViewData


Иногда, требуется передать данные от одного action к другому. Скажем, на странице с полем ввода во время обработки введенных данных у нас произошла исключительная ситуация, о которой необходимо сообщить, вернувшись обратно на страницу. Так как обработкой введенных данных занимался один action, а обработкой страницы заведует другой, то, используемая в иных случаях ViewData, нам не поможет.
Для таких случаев в MVC существует TempData, структура данных, которая существует только во время запроса и потом удаляется.
<% if (TempData[«Message»] != null) {%>
<%=HttpUtility.HtmlEncode(TempData[«Message»].ToString()) %>
<%} %>

Данный код отобразит сообщение, в случае, когда оно существует. Само сообщение задается элементарно:
if (String.IsNullOrEmpty(UserText))
{
    TempData["Message"] = "Введите текст сообщения";
    return RedirectToAction("Index");
}


* This source code was highlighted with Source Code Highlighter.

Разделяем логику GET и POST запросов


MVC Framework preview 5 принес, кроме всего прочего, один замечательный механизм, который позволяет разделить логику для POST и GET запросов. Производится такое разделение через атрибут AcceptVerbs. Для примера допустим у нас на главной странице есть форма для ввода логина и пароля. Так же есть action Login, который отвечает за проверку введенного логина и пароля, аутентификацию и авторизацию пользователя. Для безопасности можно ограничить действие этого action заставив обрабатывать его только POST запросы от формы на странице. А все остальные запросы отправить в другой action, который бы просто возвращал ту же самую страницу.
[AcceptVerbs("GET")]
public ActionResult Login()
{
    return View("Index");
}

[AcceptVerbs("POST")]
public ActionResult Login(string userLogin, string userPass)
{
    [… реализуем логику …]
    return RedirectToAction("Index", "Home");
}


* This source code was highlighted with Source Code Highlighter.

Помимо этого, в MVC Framework Beta появилось перечисление HttpVerbs, с помощью которого, можно задать параметр атрибута AcceptVerbs строго типизированным значением.
[AcceptVerbs(HttpVerbs.Post)]

Управление кэшированием


MVC Framework позволяет управлять кэшированием результата каждого action. То есть, вы можете задать каким образом и сколько будет кэшироваться тот или иной запрос на сервере или на клиенте. Для этого существует аналог директивы классического asp.net <%@ OutputCache %> атрибут [OutputCache]. Ниже перечислены его параметры:
Параметр Описание
VaryByHeader строка с разделенными через точку с запятой значениями http-заголовков по которым будет производиться условное кэширование
VaryByParam задает условное кэширование основанное на значениях строки запроса при GET или параметров при POST
VaryByContentEncoding указывает условие кэширование в зависимости от содержимого директивы http-заголовка Accept-Encoding
Duration Duration задает значение времени в секундах, в течение которого страница или пользовательский элемент кэшируются
NoStore принимает булево значение. Если значение равно true, то добавляет в директиву http-заголовка Cache-Control параметр no-store
CacheProfile используется для указания профиля кэширования заданного через web.config и секцию caching
OutputCacheLocation этот параметр описывает правило для места хранения кэша и принимает одно из значений перечисления OutputCacheLocation
VaryByCustom любой текст для управление кэшированием. Если этот текст равен «browser», то кэширование будет производиться условно по имени браузера и его версии (major version). Если у VaryByCustom будет указана строка, то вы обязаны переопределить метод GetVaryByCustomString в файле Global.asax для осуществления условного кэширования.

Использование OutputCache очень элементарное. Следующий пример показывает, как кэшировать результат action Index на 10 секунд.
[OutputCache(Duration = 10)]
public ActionResult Index()
{

}


* This source code was highlighted with Source Code Highlighter.

Сложные страницы и пользовательские модели


Зачастую в создании страниц участвует множество самых разнородных данных. Скажем, на персональной странице пользователя какого-либо портала могут быть данные с его избранными новостями, данные его профиля, данные о сообщениях посланных ему другими участниками, данные о погоде или дата и точное время, и еще масса разных данных.

Такие данные при хранении в базах данных хранятся не в одной таблице, а в нескольких, может даже в нескольких десятках. В таком случае, если вы используете ОRM – объектную модель базы данных, то для создания одной страницы MVC Framework вам придется инициализировать множество списочных или других переменных и заполнить их данными.

Я рекомендую в таком случае сделать свою комплексную модель данных, реализовав букву M из слова MVC. Ниже я приведу пример одного из вариантов реализации такой модели:
    public class BankInfoModel
    {
        public Bank Bank;
        public IEnumerable<BankBranch> BankBranches;
    }


* This source code was highlighted with Source Code Highlighter.

Создается модель, которая содержит значение Bank и перечисление всех отделений этого банка (допустим, по ряду причин, мы не можем получить список отделений просто через Bank).

Для прозрачного использования нашей модели мы должны сделать следующее: переделать базовый класс нашего представления с
public partial class Index: ViewPage

на
public partial class Index : ViewPage<BankInfoModel>

* This source code was highlighted with Source Code Highlighter.

Теперь, в коде представления, нам доступен инстанцированный экземпляр модели типа BankInfoModel через ViewData.Model. Конечно, контроллер должен его инициализировать для нас, но это элементарно:

public ActionResult Info(int? id)
{
    var info = new BankInfoModel {Bank = db.Banks.Single(x => x.id == id)};
    info.BankBranches = info.Bank.LocationBranches
.Where(x => x.Address.Street.cityId == 1).SelectMany(x => x.BankBranches);

    return View(info);
}


* This source code was highlighted with Source Code Highlighter.

Где int? id – это параметр, который указывает на идентификатор банка

Использование экземпляра нашей модели в представлении также просто:
<div class="vcard">
<h1><span class="fn org"><%=ViewData.Model.Bank.shortName %></span></h1>
<p>Телефон: <span class="fn phone"><%=ViewData.Model.Bank.phone %></span></p>
</div>


* This source code was highlighted with Source Code Highlighter.

Сложные типы, ModelBinder


MVC Framework так устроен, что передача значений формы производится через параметры action. Например, ниже представлена форма с двумя полями для ввода данных логина и пароля.
<form method="post" action="<%= Html.AttributeEncode(Url.Action("Login", "Home")) %>">
<ul><li>
<label for="txtLogin">Введите логин</label><%= Html.TextBox("userLogin", “”, new {id = "txtLogin"})     %></li><li>
<label for="txtPass">Введите пароль</label><%= Html.Password("userPass", “”, new {id = "txtPass"}) %></li><li>
<input type="submit" value="Войти" />
</li></ul>
</form>


* This source code was highlighted with Source Code Highlighter.

Данные, которые пользователь ввел в этой форме, передадутся в action через соответствующие параметры, так как показано ниже:
[AcceptVerbs(«POST»)]
public ActionResult Login(string userLogin, string userPass)

Но что делать, когда форма содержит десятки вводимых полей? Неужели создавать десятки параметров у action? Нет, MVC Framework содержит механизм, который позволяет избежать такого некрасивого шага, как многочисленные параметры метода. Такой механизм называется ModelBinder. Для начала объявим класс, описывающий нашу форму:
public class LoginModel
{
     public string userLogin { get; set; }
     public string userPass { get; set; }

     public LoginModel()
     {
     }
}


* This source code was highlighted with Source Code Highlighter.

Затем, нам необходимо определить класс реализующий интерфейс IModelBinder:
public class LoginModelBinder : IModelBinder
{
public object GetValue(ControllerContext controllerContext, string modelName,
                                    Type modelType, ModelStateDictionary modelState)

{
                            LoginModel modelData = new LoginModel ();
                            modelData.userLogin = controllerContext.HttpContext.Request["userLogin"];
                            modelData.userPass = controllerContext.HttpContext.Request["userPass"];

                            return modelData;
}
}


* This source code was highlighted with Source Code Highlighter.

Обратите внимание, мы определяем метод GetValue и заполняем в нем данные модели через контекст запроса.

Перед заключительным шагом нам необходимо указать для нашего класса модели LoginModel атрибут ModelBinder:
[ModelBinder(typeof(LoginModelBinder))]
public class LoginModel
{
     public string userLogin { get; set; }
     public string userPass { get; set; }

     public LoginModel()
     {
     }
}


* This source code was highlighted with Source Code Highlighter.

В заключение, используем наши конструкции для автоматической инициализации параметров переданных с формы:
[AcceptVerbs(«POST»)]
public ActionResult Login([ModelBinder(typeof(LoginModelBinder))] LoginModel loginModelData)

Данный вариант появился в MVC Framework preview 5.
MVC Framework Beta принесла значительные улучшения в это плане. Теперь существует встроенный binder, который автоматически обслуживает передачу стандартных .NET типов. То есть, вместо того, чтобы создавать свой ModelBinder в предыдущем примере мы можем создать упрощенный код:
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Login(LoginModel loginModelData)

Кроме того, для разработчиков доступен атрибут Bind, который позволяет управлять префиксом имен параметров формы, так что возможно изменить его значение или указать, что префикса не будет вовсе. Этот же атрибут позволяет задавать «белые» или «черные» списки свойств формы, которые будут связываться со значениями параметра комплексного типа.
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Login([Bind(Prefix=””, Include=”userLogin, userPass”)] LoginModel loginModelData)

И хотя мы не обязаны создавать свои варианты ModelBinder этот инструмент все же может пригодиться и будет полезным для тонкой настройки обработки значений комплексных типов переданных с формы.

Перехват необработанных ошибок, неверных URL


Известно, что ничего так не сбивает с толку пользователя как непонятная ошибка, возникшая на ровном месте. Даже, если в вашем проекте такие ошибки время от времени происходят, необходимо позаботится о том, чтобы пользователь получал уведомление как можно более дружелюбно. Для таких целее используются страницы ошибок, перехват необработанных исключений, а так же обработка 404 ошибки http «Страница не найдена».

Для перехвата необработанных исключений необходимо создать в папке Views/Shared страницу Error.aspx с информацией об ошибке, которая содержит, например, такой код:
<span>
        Ой! Извините, но на нашей странице произошла ошибка.<br />
        Текст ошибки: <%= ViewData.Model.Exception.Message %>
</span>


* This source code was highlighted with Source Code Highlighter.

Для того, чтобы все необработанные исключения перенаправлялись на нашу страницу необходимо каждому контроллеру указать атрибут HandleError:
[HandleError]
public class HomeController: Controller

Далее, чтобы обрабатывать все неверные URL, которые не подпадают под наш маршрут заданный в global.asax, необходимо создать еще один маршрут, который бы направлял все неверные запросы на специальную страницу:
routes.MapRoute(«Error», "{*url}", new
{
controller = «Error»,
action = «Http404»
});

Как можно заметить все неверные URL, будут приводить к action Http404 контроллера Error. Необходимо создать такой контроллер и добавить action:
    public class ErrorController : Controller
    {
        public ActionResult Index()
        {
            return RedirectToAction("Http404");
        }        
        public ActionResult Http404()
        {
            Response.StatusCode = 404;
            return View();
        }
    }


* This source code was highlighted with Source Code Highlighter.

Содержимое представления Http404.aspx элементарно:
<h1>404</h1>
<p>Запрошенной страницы не существует</p>


* This source code was highlighted with Source Code Highlighter.

Таким образом, мы отловим попытки переходов по неверному маршруту, но что делать, если маршрут попадает под шаблон, но все равно неверен? Выходом может стать проверка на местах с генерацией исключения:
public ActionResult Info(int? id)
{
if (!id.HasValue)
        throw new HttpException("404");

[ …работаем дальше… ]
}


* This source code was highlighted with Source Code Highlighter.

Для перехвата такого пользовательского исключения необходимо создать или изменить в web.config раздел customErrors:
<customErrors mode="RemoteOnly">
    <error statusCode="404" redirect="~/Error/Http404"/>
</customErrors>


* This source code was highlighted with Source Code Highlighter.

Таким образом, все наши пользовательские исключения типа 404 будут также перенаправляться на нашу страницу Http404.aspx, что позволит сохранить общий подход и объединить под понятие «ненайденной страницы» как неверные URL, так и URL-введенные с ошибкой или в силу каких-то других причин неприемлемые для обработки, например из-за нарушения прав доступа.

Следует учесть, что для правильно работы перехвата ошибок в IIS7 требуется выставить следующие параметры в разделе «Страницы ошибок» настроек вашего сайта.

Заключение


В статье я попытался описать некоторые аспекты работы с MVC Framework. Многие моменты – элементарны, некоторые не так просты, как кажутся, часть – хорошо описана в интернете, часть – не описана вовсе. Во всех случаях приведенный материал может сослужить хорошую службу как начинающим знакомство с MVC Framework, так и тем, кто уже имеет опыт создания web-приложений с его помощью.

MVC Framework сегодня – это, всего лишь, бета-версия того продукта, который будет в итоге. Но уже сейчас этот инструмент позволяет создавать web-приложения, используя все мощь паттерна MVC. Возможно, когда вы будете читать эту статью, выйдет финальный релиз MVC Framework, который ожидается к концу 2008 года, но можно предположить, что большинство функций уже не будет изменено.

Progg it
_________
Текст подготовлен в ХабраРедакторе
+53
21 января 2009, 11:48
122

комментарии (71)

+1
devprom #
За статью спасибо, но писать надо не Микрософт, а Майкрософт, тем более, если Вы собирались публиковать это в печатном издании.
+3
XaocCPS #
поправил
спасибо за ценный комментарий
НЛО прилетело и опубликовало эту надпись здесь
+1
XaocCPS #
я не люблю писать «Майкрософт», поэтому поправил на Microsoft, дабы угодить всем
всегда и везде говорю и пишу «Микрософт», тоже не вижу в этом ничего плохого
+1
mamba #
Осилил, интересно.
С точки зрения логичности изложения, переход от раздела Версии MVC Framework сразу к практическим советам выглядит слишком резким. В этом месте скорее ожидаешь прочитать про то, как строится URL, про Action, про Route — иными словами, про то, из чего все-таки состоит MVC в исполнении Майкрософт и как с ним оперировать. А вы сразу — Как задать на странице html-элемент select. :)
0
metaball #
Новичку наоборот важно как можно скорее начать практиковаться.
0
XaocCPS #
может быть, вы правы
статья — это больше сборник советов, чем описание работы MVC

*может быть неудачно назвал
+1
scorzh #
Да, статья хороша как сборник советов и ответов на первые возникающие вопросы по ASP.NET MVC Framework у новичков. Описаний работы MVC в инете куча, а доступных новичку квикстартов маловато.
0
Mephistophele #
А если не секрет, то в какой журнал ваша статья попадёт?
0
XaocCPS #
она должна была выйти в декабрьском выпуске журнала c`t.
0
mxc #
Отлично. Благодарен!
–3
VolCh #
Спасибо, узнал много нового о MS :) Ничего особо оригинального, чего нет в тех же PHP фреймворках, не увидел, но судя по всему любители «моногенных» решений должны быть в восторге.
0
XaocCPS #
конечно, ничего особо нового не может быть, все же фреймворк свежий и еще даже не вышел в финальной версии
0
VolCh #
Нет, серьезно радует, что если вдруг понадобится портировать или писать с нуля для .net, то не нужно будет изменять образ мышления. Грубо говоря надо просто преодолеть различия синтаксиса языков (а может уже и язык привычный портирован) и тонкостей реализации, но нежно менять архитектуры приложения
+1
gaidar #
Новые идеи сложно придумать сейчас на этапе становления MVC Framewrok. К тому же, существующие MVC Framework для Java, PHP, Perl и т.д. содержат много того, что уже просто обязан содержать MVC Framework, поэтому их нужно догнать по функционалу. А вот уже с версии 2.0 и далее можно будет заниматься активными инновациями.
+1
XaocCPS #
у вас есть что-то инсайдерское о второй версии? поделитесь :)

* или хотя бы есть информация о дате выхода новой версии «первого» MVC?
+1
gaidar #
К сожалению, инсайдерское только под NDA для MVP :)

Но про MVC могу чуть-чуть сказать, что есть большое желание выпустить релиз к MIX (март этого года), и очень быстро после релиза выпустить CTP версии 2.0. Но официально такого плана нет.
0
XaocCPS #
и то хлеб :)
0
VolCh #
Я наоборот рад, что нет ничего оригинального, что структура приложения практически не изменяется, при необходимости несложно будет портировать с .net скажем на symfony или наоборот
0
gaidar #
Рано или поздно какие-то новые идеи будут реализованы. Сейчас пока есть только подход к скэффолдингу — Dynamic Data, но я уверен, что будет больше декларативности добавлено.
+1
ness #
XaocCPS, спасибо за статью :)

Еще подскажите, пожалуйста, как можно реализовать следующие вещи:
1) общие объекты для всех страниц, которые в классическом ASP.NET вставлялись в Мастерпейдж и инициализировались(заполнялись данными т.п.) в MasterPage.Page_Load? Не будешь же вставлять код инициализации во все контроллеры…

2) Как можно передать юзерконтролу типизированные параметры? Опять-таки, из классики: есть юзер-контрол, который в зависимости от параметров решает, как и что ему выводить (событие Page_Load юзер-контрола), юзер-контрол вставляется в asp:Repeater, и выглядит типа

Заранее спасибо за ответ.

Собственно, это две вещи, которые пока не позволяют делать новые проекты на MVC, а хотелось бы, при его прочих достоинствах.
0
XaocCPS #
1. в mvc тоже есть мастерпейдж
2. public partial class IntroBox: ViewUserControl — определяет контрол с типом модели MyModel
<%= Html.RenderPartial(«IntroBox», ViewData.Model.DataForControl); %> — рисуем контрол передвая ему данные, которые содержаться в модели страницы
0
XaocCPS #
* хабр побил теги
public partial class IntroBox: ViewUserControl<MyModel>
0
ness #
А в Мастерпейдже в MVC есть событие Page_Load?

Т.е. фактически стоит задача выполнять некое действие, когда человек попадает на все страницы, связанные с этим мастерпейджем (но контроллеры разные).
0
XaocCPS #
вы можете определить базовый контроллер, а все остальные контроллеры определять от него и обрабатывать вообще все действия
0
ness #
Спасибо, как-то не подумал :)
0
gaidar #
или на уровне фабрики контроллеров написать код для инъекции глобальных задач для набора страниц.
0
second_pilot #
я на нем курсовую писал. Мне бы эту статью пару месяцев назад, не пришлось бы столько вникать в блоги Гюттри и иже с ним.
ASP.NET VMC — отличная вещь если вы — программист C# или фанат майкрософта. Во всем остальном пока выигрывают аналогичные фреймворки на руби и пхп. Надеюсь майкрософт сделает из него конфетку.
0
second_pilot #
*MVC
0
iZENfire #
А какое мнение у вас от: JSF, web-потока Shale, Facelets, Tiles? Каркас интеграции JSF и EJB3 (Hibernate) не заинтересовал?
0
second_pilot #
ой, я как-то с явой дружу только на уровне helloworld. Я сранивал asp.net mvc только с рельсами и знакомыми мне php фреймворками. ни в коем случае не холиварю, ибо люблю C# и asp.net, но работа есть по php)
0
adm0r #
простите за вопрос не по теме.
А что случилось с c't? Я его уже 6й месяц у себя в городе не могу найти, а ведь журнал очень хороший.
П.С. А статья понравилась, спасибо
0
XaocCPS #
по источникам из журнала, c`t накрыл кризис
большего мне не известно
0
adm0r #
жаль :( очень жаль
0
XaocCPS #
мне тоже
у журнала была лучшая типография и бумага
0
EXSlim #
Недавно пробовал запустить все это на линуксе под mono 2.2. Полдня портаченого времени и я таки запустил его на xsp2. Правда не работал роутинг… хотя можно было подсунуть свой метод — я спасовал =) В roadmap на mono сказано, что поддержка asp.net mvc будет в 2.6(july 2009). Ну да ладно, пока оно еще бета — можно подождать
0
XaocCPS #
на моно что-то пишите?
0
EXSlim #
Начал где-то год назад, и так несколько мелких проектов.
0
XaocCPS #
с удовольствием бы почитал что-нибудь про моно на Хабре
опыт, трудности, отличия, сильные и слабые стороны… все интересно
0
EXSlim #
К сожалению, катастрофически нехватает времени. Да и не такой уж большой опыт у меня с mono. Но скажу, прогресс разработки mono — огромный. ...MonoDevelop, GTK, ASP.NET, Gendarme, Monoxide и все это опенсоурс

Слабые стороны — пока небольшое комюнити
Сильные стороны — opensource; 3rdparty; когда сидиш, смотриш на работающий проект linux + csharp и думаеш — причем здесь майкрософт?
0
XaocCPS #
считаю, Мироксофту надо поддерживтаь Mono-комьюнити тем или иным способом
нанять чтоли человека, который бы освещал все что связано с mono
лично я просто не натыкаюсь на информацию, а специально искать нет времени, да и особого желания, поскольку применять пока негде

почитать бы чужой опыт было бы очень интересно
0
EXSlim #
Сейчас mono — узкий профиль. Но я буду чрезмерно рад, когда со временем Novell будет иметь в своем арсенале чистый, отлаженый и вылизаный mono. И считаю, что это неизбежно. Спасибо тебе, Мигель
0
EXSlim #
>лично я просто не натыкаюсь на информацию, а специально искать нет времени
есть форумы nabble, есть lor, кстати сегодня там и про moonlight
0
XaocCPS #
туда надо идти специально
я имел в виду, что на тех ресурсах которые посещаю я, многопрофильных, про моно пишуту крайне редко (а на хабре вовсе не пишут)
0
shai_xylyd #
Это точно — до сих пор новости о том, что версия mono 2.2 вышла нет. А там появилась такая вкусность как REPL для C#.
0
gaidar #
А может быть опишите как заставили работать под Linux? Какие подводные камни встретились? Я бы поделился с разработчиками информации и они порадовались бы :)
0
EXSlim #
Конечно. Итак нужно mono, xsp2 и сам asp.net mvc. Желательно самых новых версий.

Я перенес шаблонный mvc проект, который сгенерировал visualstudio. далее скопировал mvc библиотеки System.Web.Abstractions.dll, System.Web.Mvc.dll и System.Web.Routing.dll(они где-то в program files) в директорию Lib в корне проекта.

Web.config и csproj негодные, их придется править вручную. Из csproj я вырезал ненужные референсы(оставил необходимые, дамп — dumpz.org/4930/), visual studio targets и все project settings. Обязательно вырезать версию и токен из референса System.Web.Mvc.dll. В Web.config оставил только customErrors для отладки и pages для корректной работы хелперов.

Из-за того что библиотеки mvc не добавляются в GAC пришлось скопировать их в директорию bin в корне проекта. И заключающий этап это xbuild (входит в моно). Он сделает длл нашего проекта в bin. Запускаем xsp2…
0
gaidar #
Спасибо! Очень интересно.
0
EXSlim #
Всегда пожалуйста.
0
gaidar #
Ловите +1 в карму. Может быть будете что-нибудь интересное писать?
0
gaidar #
Опыт с Mono — очень интересно, было бы здорово побольше об этом знать.
0
EXSlim #
По моим наблюдениям в комментариях, mono интересен многим. Конечно, очень жаль, что на хабре так мало информации. Но, думаю, со временем, смогу писать на эту тему.
0
EXSlim #
Подводные камни? Да там каменная дорога под водой =)
0
gaidar #
Зато, наверное, очень увлекательная дорога :)
0
web4_0 #
Кстати, кто знает, кроме шаблонизации, существуют ли способы безболезненной замены представления? Например, был вывод в виде HTML, а стал в виде JSON, и основные алгоритмы вывода дублировать чтобы не пришлось.
0
ennui #
было

public JsonResult Test()
{
string[] test = {«Первый»,«Второй»,«Третий»};
return Json(test);
}
0
ennui #
извините

было
public ActionResult Test()
{
string[] test = {«Первый»,«Второй»,«Третий»};
ViewData = test;
return View();
}
стало то что выше
0
web4_0 #
Это только для простейших случаев, а если представление оперирует большим количеством данных с помощью разных итераторов, нужно постоянно копировать обход этих данных, но уже для другого представления, а этого хочется избежать.
0
ennui #
ActionResult может возвращать как html представление(View), так и Json. Задача сводится к тому, что бы сериализовать данные к нужному формату(xml или json), а return отдать то что нужно в итоге.
public ActionResult Test(string flag)
{
//формирование данных
string[] test = {«Первый»,«Второй»,«Третий»};
if(flag == «html)
{
ViewData[»data"] = test;
return View();
}
else
{
//если много сложных данных, сериализуем.
return Json(test);
}
}
0
dmitry39 #
Спасибо, отличная статья, уже создал solution :)
0
Dimchansky #
А по MVC фреймворку еще никаких книг нет?
0
XaocCPS #
русскоязычных нет
готовится к выпуску ряд книг на английском
0
gaidar #
Я вот собрался тут написать книгу, но дело идет сильно медленнее, чем я ожидал. Нет желания присоединиться и стать соавтором? :)
0
XaocCPS #
ответил в личку
0
spycode #
Может кто сталкивался с реализацией деревьев (типа TreeView) в ASP.NET MVC?

Заранее спасибо!
0
XaocCPS #
элементы dl вложенные друг в друга + js не подойдут?
или вам универсальное решение нужно?
0
shel #
Спасибо за статью.
posback

postback
0
XaocCPS #
спасибо, поправил
0
morph #
а в 6 IIS работает описанный вами в последней части метод редиректа на страницу с ошибками?
url mapping настроен, clean urls тоже настроены (aspnet_isapi.dll).
Продолжает выбрасывать Эксепшены, и обычная страница с ошибкой на 404.
0
XaocCPS #
вы проверяете локально? по идее все должно работать, но честно говоря на iis 6 не тестировал
0
morph #
да, все работает, видимо гдето ступил вчера.

кстати, для того чтобы с неверных УРЛ переправлял на /error/http404
не нужно добавлять дополнительный маршрут.

routes.MapRoute(«Error», "{*url}", new
{
controller = «Error»,
action = «Http404»
});

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.