пятница, 6 июня 2008 г.

Вышла третья версия ASP.NET MVC (Preview) - перелопачиваем проект (а лучше создаем новый)

Значит, вышла, родная. Изменений немерено!
Скачать новую версию можно здесь. Там на странице внизу список доступных файлов. Обязательно скачайте Readme - он содержит перечень всех изменений. А для тех, кто не очень дружит с английским (ну и вообще - для уяснения) перечислю эти изменения здесь.

Контроллеры
Методы действия теперь возвращают экземпляр типа ActionResult. Вернее, один из типов, наследующих ActionResult, потому что ActionResult - абстрактный класс. Вот какие это могут быть типы:

  • ViewResult - такой тип возвращает метод контроллера View (то, что раньше было RenderView), параметры остаются те же

  • EmptyResult - ничего не делает - аналогичен тому, что метод действия возвращает null

  • RedirectResult - перенаправляет на другой URL

  • RedirectToRouteResult - перенаправление по указанному маршруту

  • JsonResult - содержимое ViewData сериализуется в формат JSON

  • ContentResult - рендерит некий текст (обычно это HTML)


Объекты всех этих типов возвращают соответствующие методы контроллера:

  • View

  • Redirect - перенаправляет на новый URL

  • RedirectToAction - перенаправляет на другой метод действия

  • RedirectToRoute - перенаправляет по новому маршруту

  • Json - возвращает экземпляр типа JsonResult

  • Content - рендерит текст (обычно это HTML)


Интересный момент. Если мы пытаемся вернуть объект, не наследующий ActionResult (теоритечески это может быть что угодно), то метод неявно сериализует этот объект в строку (вызывая его ToString()), после чего оборачивает полученный текст в ContentResult и передает его клиенту.

Представления
Теперь ViewData в представлении не заменяется объектом, из которого мы подтягиваем данные. А мы получаем к ним доступ через свойство Model, т.е. вместо ViewData.CitiesForCountry пишем теперь ViewData.Model.CitiesForCountry.

Роутинг
Дефолтные значения теперь задаются проще. Вместо:
routes.Add("route-name", new Route("{locale}/{year}", new MvcRouteHandler()) {
 Defaults = new RouteValueDictionary(new {locale="en-US", year=DateTime.Now.Year.ToString()})
}

теперь чуть проще
routes.MapRoute("route-name", "{locale}/{year}", new {locale="en-US", year=DateTime.Now.Year.ToString()});


Это основные новшества. Некоторые моменты касаются констрейнтов, контролов и т.д.

Установка
Поверх не ставится. Сначала надо удалить вторую версию.

Изменения в проекте
Попробуем скомпилировать наш маленький (пока еще) проект. Ну что ж, для начала неплохо - всего 24 ошибки.
Первое, что делаем - удаляем из списка ссылок ссылки на System.Web.Abstractions, System.Web.MVC, System.Web.Routing и заново добавляем их из C:\Program Files\Microsoft ASP.NET\ASP.NET MVC Preview 3\Assemblies. Компилируем опять, уже лучше - всего 14 ошибок.
Далее по тексту файла Readme меняем код. Все компилируется отлично, но одна маленькая проблема - полностью перестает работать роутинг. Т.е. вообще полностью - хотя маршруты и сохраняются в коллекции, однако перехода к методам контролов не осуществляется. Поэтому мне не осталось ничего другого, как создать новый проект, в котором это работает. Мне, к сожалению, так и не удалось найти "5 отличий" между измененным проектом и новым. Если кто-нибудь знает, как это пофиксить, сообщите пожалуйста.
Update Обнаружилась еще одна неприятная фича (которая, конечно, скорее бага). Если у вас модельная часть с edmx находится в отдельном проекте, то из проекта MVC не удалется получить к ней доступ. Т.е. компилируется проект нормально, но при обращении к странице, которая дергает данные из модели, вываливаются непонятные ошибки вроде "включите ссылку на namespace System.Data.Entity". После того, как на страницу импортируешь это пространство имен, начинает кричать, что он не знает, что такое System.Data.Objects. Как только модель была перенесена в проект MVC, подобные ошибки сразу же исчезли. Кто знает, как лечить по-другому, сообщайте.

4 комментария:

Ivan Makarevich комментирует...

Переходил с preview 2 на 3 строго по Readme. Проект отлично перешел. Роутинг продолжает работать.

Electric Cat комментирует...

Спасибо за комментарий.
Мне интересно, включены ли в ваш проект модели из Entity Framework?
Почему спрашиваю - дело в том, что до выхода последнего сервис пака у них был такой баг, что если в проект включена модель EF, то там были какие-то серьезные траблы то ли с контроллерами, то ли с чем-то еще - поэтому приходилось модель выносить в отдельный проект. Оба крошечных проекта, которые требовалось перевести на 3 версию, содержали модели EF, и в обоих перестал работать роутинг.

Ivan Makarevich комментирует...

Валидацию так и не добавили. Обешают в слелующем выпуске (ScottGu). Пока для валидации предлагается Validator Toolkit for ASP.NET MVC. Располагается он тоже на Codeplex. Статья про использование на англ тут.

---
Да. Entity Framework используется. В том же самом проекте. Траблов не замечал. Подумав, вспомнил что редирект c Default.aspx делался точно не так как в readme. Сделал "обычный" aspx с редиректом.
SP beta 1 НЕ ставил, EF бета 3 пока пользуюсь. Может там что потеряло совместимость.

Electric Cat комментирует...

Хм, не исключено, что сервис пак влияет. Вопрос - почему тогда работает новый проект? Нет идей, как можно установить, чем отличаются два разных проекта (содержащие одни и те же файлы и референсы)?