(495) 925-0049, ITShop интернет-магазин 229-0436, Учебный Центр 925-0049
  Главная страница Карта сайта Контакты
Поиск
Вход
Регистрация
Рассылки сайта
 
 
 
 
 

Создание форм для глубоко вложенных View Model в ASP.NET MVC

Jimmy Bogard

Ёще один интересный пост от Jimmy Bogard, посвященный cозданию форм для глубоко вложенных View Model в ASP.NET MVC. Несмотря на то, что в нём постоянно идёт отсылка к ASP.NET MVC 2, информация актуальна и для 3-ей версии.

 ASP.NET MVC 2 представил множество строго типизированных помощников (helpers) для создания элементов форм в строго типизированных представлениях (views). Эти строго типизированные помощники используют лямбда выражения (lambda expressions) для того, чтобы создать полностью готовый элемент ввода, включая корректное имя и значение для элемента.

 Лямбда выражения достаточно выразительны. Они позволяют создавать вам достаточно сложные модели для редактирования и иметь привязку модели (model binding) для того, чтобы сложить всё вместе. Пример сложного типа view model:

public class ProductEditModel

{

  public string Name { get; set; }

  public PriceEditModel Price { get; set; }

 

  public class PriceEditModel

  {

    public decimal Value { get; set; }

    public string Currency { get; set; }

  }

}

 

* This source code was highlighted with Source Code Highlighter.

 Достаточно легко создать для него представление:
@using (Html.BeginForm()) {

  <p>

    @Html.LabelFor(m => m.Name)

    @Html.TextBoxFor(m => m.Name)

  </p>

  <p>

    @Html.LabelFor(m => m.Price.Currency)

    @Html.TextBoxFor(m => m.Price.Currency)

  </p>

  <p>

    @Html.LabelFor(m => m.Price.Value)

    @Html.TextBoxFor(m => m.Price.Value)

  </p>

}

 

* This source code was highlighted with Source Code Highlighter.

 До тех пор, пока мы используем выражения, строящиеся с самого верхнего уровня модели, чтобы создать элементы ввода, корректный HMTL будет получен. Предположим, что вы хотите сейчас вытащить PriceEditModel в частичное представление и отделить его от родительского представления. Мы меняем в нашем представлении рендеринг свойства на рендеринг частичного представления:

@using (Html.BeginForm()) {

  <p>

    @Html.LabelFor(m => m.Name)

    @Html.TextBoxFor(m => m.Name)

  </p>

  @Html.Partial("_PriceEditModel", Model.Price);

}

* This source code was highlighted with Source Code Highlighter.

 Наше частичное представление представляет собой просто вырезанный код представления, за исключением того, что сейчас оно основано на типе PriceEditModel:
@model ProductEditModel.PriceEditModel

<p>

  @Html.LabelFor(m => m.Currency)

  @Html.TextBoxFor(m => m.Currency)

</p>

<p>

  @Html.LabelFor(m => m.Value)

  @Html.TextBoxFor(m => m.Value)

</p>

* This source code was highlighted with Source Code Highlighter.

 Однако, получающийся в результате HTML больше не сопоставляет члены модели корректно. Несмотря на то, что на экране всё в порядке:

 
Но стоит нам заглянуть в HTML, как мы увидим ошибку:
 
 
Вместо имени нашего члена, имеющего правильный родительский член в своём имени, вроде "Price.Currency", мы видим только "Currency". Действительно, когда мы попадаем в POST действие (action), член Price равен null, т.к. привязка модели не смогла найти соответствие:
 
 

Не совсем то, что нам хотелось бы получить!

 Итак, какие у нас варианты? Для уверенности в том, что привязка модели работает для моделей с частичным представлением, мы можем привести эти модели в наших частичных представлениях к родительскому типу. Т.е. заменить типы наших моделей для частичных представлений с "PriceEditModel" на "ProductEditModel".

 Не очень привлекательный вариант!

 У нас есть вариант получше - шаблонизированные помощники из MVC 2. Шаблонизированные помощники элегантно решают проблему глубоко вложенных View Model.

Работа с шаблонизированными помощниками

Шаблонизированные помощники отличаются от частичных представлений тем, что в них специальная контекстная информация передаётся вниз от родителя к потомку тогда, когда мы используем методы Html.EditorXyz() из HtmlHelper. Для того чтобы перестроить наши представления на использование шаблонизированных помощников, давайте просто создадим шаблон редактора для каждой view model, которая у нас есть:

Эти шаблоны обычные частичные представления из Razor, за исключением того, что они помещаются в специальную папку EditorTemplates. Для нашего частичного представления c ProductEditModel, мы просто перемещаем всё, что у нас было в нашем представлении:

@model ProductEditModel

 

<p>

  @Html.LabelFor(m => m.Name)

  @Html.TextBoxFor(m => m.Name)

</p>

@Html.EditorFor(m => m.Price)

 

* This source code was highlighted with Source Code Highlighter.

 Однако, здесь есть одна незначительная деталь. Вместо рендеринга частичного представления Price, мы выполняем рендеринг редактор для члена Price. Шаблон PriceEditModel - это то, что у нас было в нашем оригинальном частичном представлении без каких-либо изменений:

@model ProductEditModel.PriceEditModel

<p>

  @Html.LabelFor(m => m.Currency)

  @Html.TextBoxFor(m => m.Currency)

</p>

<p>

  @Html.LabelFor(m => m.Value)

  @Html.TextBoxFor(m => m.Value)

</p>

 

* This source code was highlighted with Source Code Highlighter.

 На данный момент отличие заключается в том, что наш шаблонизированный помощник знает, что родительская модель использовала член "Price" для создания частичного представления. В нашем родительском представлении Edit всё ещё проще:

@using (Html.BeginForm()) {

  @Html.EditorForModel()

  <input type="submit" />

}

 

* This source code was highlighted with Source Code Highlighter.

 ASP.NET MVC будет проверять тип модели для того, чтобы убедиться в том, что шаблон редактора существует для этого типа модели, когда мы вызываем метод EditorForModel. Т.к. мы создаём шаблоны редактора для каждого отдельного типа модели, не имеет значения, где в иерархии расположены эти вложенные типы. ASP.NET MVC будет передавать родительский контекст, так что глубоко вложенные View Model будут иметь корректную информацию о нём.

 Просмотрев получившийся в результате HTML, мы можем убедиться, что всё в порядке:

Имя элемента ввода сейчас имеет корректное имя родительского свойства в качестве значения. А отладка POST действия подтверждает, что привязка модели сейчас работает корректно:

С шаблонизированными помощниками из ASP.NET MVC 2, мы можем создавать вложенные модели в наших представлениях и, вместе с тем, получать все преимущества частичных представлений. Единственное предостережение - убедитесь, что вы создали представления, используя шаблонизированные помощники и Html.EditorXyz методы. В противном случае, воздействие на ваши представления будет минимальным.

 И просто чтобы пожаловаться - этот способ сильно раздражает в MVC 1.0. Я выкинул кучу кода после того, как перешёл на старшие версии MVC!

Ссылки по теме


 Распечатать »
 Правила публикации »
  Написать редактору 
 Рекомендовать » Дата публикации: 01.11.2011 
 

Магазин программного обеспечения   WWW.ITSHOP.RU
Microsoft Office 365 Профессиональный Плюс. Подписка на 1 рабочее место на 1 год
Microsoft 365 Business Standard (corporate)
Microsoft Office для дома и учебы 2019 (лицензия ESD)
Microsoft Windows Professional 10, Электронный ключ
Microsoft 365 Apps for business (corporate)
 
Другие предложения...
 
Курсы обучения   WWW.ITSHOP.RU
 
Другие предложения...
 
Магазин сертификационных экзаменов   WWW.ITSHOP.RU
 
Другие предложения...
 
3D Принтеры | 3D Печать   WWW.ITSHOP.RU
 
Другие предложения...
 
Новости по теме
 
Рассылки Subscribe.ru
Информационные технологии: CASE, RAD, ERP, OLAP
Безопасность компьютерных сетей и защита информации
Новости ITShop.ru - ПО, книги, документация, курсы обучения
CASE-технологии
Программирование на Microsoft Access
Утиль - лучший бесплатный софт для Windows
Corel DRAW - от идеи до реализации
 
Статьи по теме
 
Новинки каталога Download
 
Исходники
 
Документация
 
 



    
rambler's top100 Rambler's Top100