Как стать автором
Обновить

Об опыте перевода проекта asp.net mvc на .net 4 (mvc 2)

Время на прочтение4 мин
Количество просмотров585
Здравствуйте! В этой статье я расскажу о своем опыте перевода проекта asp.net mvc на .net 4. В сети есть пост под названием ASP.NET MVC 2 Brings Breaking Changes. Здесь вы можете ознакомиться с основными нововведениями в asp.net mvc 2. Мой опыт миграции проекта касается как этого поста, так и того, что в нем не упомянуто. Скажу сразу что после конвертации проект компилировался, но был неработоспособен. Не отвечал на действия, либо генерировал исключения. Разберем каждую найденную мной особенность по порядку.

Изменилось поведение JsonResult


Начнем с такого класса как JsonResult. У меня с ним работает JQuery Grid. В MVC 2 JsonResult по умолчанию стал вовращать JSON не валидный для GET запросов, т.е. мой грид получал не валидный JSON и не мог его отоброзить. Лечится это изменением вызова.

//convert to JSON and return to client
//Работало для GET запросов в MVC1
return Json(result);

//convert to JSON and return to client
//Для получения того же поведения в MVC2, нужно изменить вызов
return Json(result,JsonRequestBehavior.AllowGet);


HTML хелперы теперь генерируют только валидные ID элементов формы


В моем проекте используется библиотека для валидации на стороне клиента и сервера, основанная на валидаторах и атрибутах из MS EnterpriseLibrary. Код для валидации на клиенте генерируется специальным классом. Выбор элементов формы для валидации на клиенте (скриптом) осуществляется на основе их ID. MVC1 генерировал ID на основе имени визуализируемого свойства объекта, то есть:
<%= Html.TextArea("Имя_Настоящее", Model.Имя_Настоящее, 2, 30)%>
Генерировал:
textarea cols="30" id="Имя_Настоящее" name="Имя_Настоящее" rows="2"
В MVC2 это поведение изменилось: хелпер генерирует только валидные ID, то есть в нашем случае не содержащие символов кириллицы. И… клиентская валидация не работала, т.к. ID у элемента «Имя_Настоящее» не генерировался, а скрипт пытался его найти.
Решение проблемы для MVC2:
<%= Html.TextArea("Имя_Настоящее", Model.Имя_Настоящее, 2, 30, new { id = "Имя_Настоящее" })%>

Это не очень хорошее решение, т.к. я используя хард кодинг. Но благодаря паттерну MVC, почти всегда знаешь где нужно и что поменять в случае изменений в названиях. В МVC2 появились типизированные хелперы, которые помогают избавиться от этой нехорошей работы со строками во views.

Binder незаполненным полям html формы вместо String.Empty присваивает null


Суть отражена в заголовке. Пусть у меня есть nullable свойство в классе, но на нем стоит валидатор:
[StringLengthValidator(250, MessageTemplate = "Не более 250 символов")]
public string Описание{get; set;}


В MVC1 binder на незаполненном поле устанавливает String.Empty и валидатор отрабатывает без ошибок. String.Empty — строка в ноль символов и он ее пропускает.

В MVC2 binder устанавливает null, и валидатор возбуждает исключение. Валидация не проходит.

Чтобы решить проблему, я не стал писать свой binder, т.к. это вносит дополнительную сложность в проект. Я думаю что в проекте должно быть как можно меньше самописных элементов, и ради такого мелкого исправления свой binder писать нецелесообразно.
Я изменил свойства у объекта таким образом:
(Этот кусок функциональности хорошо локализован, можно сказать что не вносит дополнительных зависимостей)

[StringLengthValidator(250, MessageTemplate = "Не более 250 символов")]
public string Описание
{
get
{
return this._Заказ.Описание;
}
set
{
if (value == null) this._Заказ.Описание = string.Empty;
else
this._Заказ.Описание = value;
}
}


Binder считывает поля, помеченые с bind=exclude


Имеем следующий класс:
[System.Web.Mvc.Bind(Exclude = "ИД_Заказа,ИД_Компании")]
public class ViewЗаказ : IViewЗаказ
{
public ViewЗаказ()
{
this._Заказ = new Заказ();
this._Заказ.КлиентReference.EntityKey =
new System.Data.EntityKey("ModelWebUchetCon.Клиенты", "ИД_Клиент", 0);
this._Заказ.ВалютаReference.EntityKey =
new System.Data.EntityKey("ModelWebUchetCon.Валюты", "ИД_Валюты", 0);
this._Заказ.ИсполнительReference.EntityKey =
new System.Data.EntityKey("ModelWebUchetCon.Пользователи", "ИД_Пользователя", 0);
this._Заказ.МенеджерReference.EntityKey =
new System.Data.EntityKey("ModelWebUchetCon.Пользователи", "ИД_Пользователя", 0);
this._Заказ.КомпанияReference.EntityKey =
new System.Data.EntityKey("ModelWebUchetCon.Компании", "ИД_Компании", 0);
this._Заказ.Описание = string.Empty;

}
public ViewЗаказ(Заказ Base)
{
this._Заказ = Base;
}

}

У нас есть два конструктора — первый для создания полностью нового объекта, а второй для создания объекта на основе имеющегося. Первый конструктор инициализирует свои поля значениями, которые затем будут переписаны. В MVC1 binder работает (с целью валидации, считывания, записи) только с теми полями, которые не отфильтрованы атрибутом Bind, поэтому в первом конструкторе я их не инициализирую. В MVC2 используется валидация всей модели, то есть на валидность проверяются все свойства объекта, а следовательно считываются все, в том числе не инициализированные первым конструктором свойства и возбуждается исключение NullReference. Для преодоления такого поведения пришлось включить логику инициализации этих свойств. Возможно кто-то напишет атрибут для класса, отключающий полную валидацию модели. Есть пример такого атрибута для всего контроллера.

Изменения в файле web.config


В .NET 4.0 web.config заметно почистился. Раньше все надстройки, появлявшиеся после .NET 2.0, регистрировались в этом файле. Сейчас когда вышла новая CLR, такая необходимость исчезла и вы можете заметно почистить свои конфиги. Для того чтобы все прошло ровно рекомендую сделать так:
  • Сделать бэкап старого конфига.
  • Создать новый проект MVC2.
  • Подключить к новому проекту все сборки, нужные вам в проекте где “подчищаем конфиги”.
  • Добавить в новый конфиг из старого: строки подключения, app settings, data providers, все что касается безопасности и, если имеются, ваши самописные moduls, handlers.
  • Добавить в целевой проект новый конфиг.

Заключение

Как мы знаем переход на новую версию .net не всегда бывает безболезненным. Microsoft каждые два года радует и разочаровывает нас. В этой статье я описал в основном то, что заставило меня несколько разочароваться и попотеть Нужно было заново тестировать проект, искать и исправлять неочевидные ошибки времени выполнения (раньше все работало). Правда я сумел найти ошибки, связанные с тем, что IE кэширует ajax запросы. То есть я нашел реальную ошибку, имевшую место в проекте. Есть плюс.
Теги:
Хабы:
Всего голосов 37: ↑23 и ↓14+9
Комментарии15

Публикации

Истории

Ближайшие события

One day offer от ВСК
Дата16 – 17 мая
Время09:00 – 18:00
Место
Онлайн
Конференция «Я.Железо»
Дата18 мая
Время14:00 – 23:59
Место
МоскваОнлайн
Антиконференция X5 Future Night
Дата30 мая
Время11:00 – 23:00
Место
Онлайн
Конференция «IT IS CONF 2024»
Дата20 июня
Время09:00 – 19:00
Место
Екатеринбург