Шаблон ASP.NET MVC ViewModel
EDIT: Я сделал что-то намного лучше заполнить и прочитать данные из представления с помощью ViewModels, назвав его ValueInjecter. http://valueinjecter.codeplex.com/
используется http://prodinner.codeplex.com - пример приложения ASP.net MVC
вы можете увидеть лучший способ использования ViewModels в prodinner
использование ViewModel для хранения логики отображения не было такой хорошей идеей, потому что было повторение и нарушение SRP, но теперь с ValueInjecter у меня есть чистые ViewModels и сухой код отображения
Что старый материал, не используйте его:
Я создал шаблон ViewModel для редактирования материалов в asp.net mvc
этот шаблон полезен, когда вам нужно создать форму для редактирования объекта, и вам нужно наложить на форму раскрывающееся меню, чтобы пользователь мог выбрать некоторые значения
public class OrganisationBadViewModel
{
//paramterless constructor required, cuz we are gonna get an OrganisationViewModel object from the form in the post save method
public OrganisationViewModel() : this(new Organisation()) {}
public OrganisationViewModel(Organisation o)
{
Organisation = o;
Country = new SelectList(LookupFacade.Country.GetAll(), "ID", "Description", CountryKey);
}
//that the Type for whom i create the viewmodel
public Organisation Organisation { get; set; }
...
}
Ответы
Ответ 1
Есть несколько вещей, которые меня беспокоят.
-
Терминология. ViewModel - это простой вид данных, который заполняется и затем потребляется контроллером. Просмотр ничего не знает о контроллере, поскольку инфраструктура ASP.NET MVC отвечает за выбор контроллеров и соответствующих действий. Контроллер обрабатывает взаимодействие пользователя. Я думаю, что это больше похоже на пассивный вид, чем на ViewModel (я полагаю, что ViewModel подразумевает модель Model-View-ViewModel).
-
Подробности. Контроллер, который заполняет данные просмотра, не должен знать подробные сведения о том, как выглядит представление. Однако OrganisationViewModel.Country раскрывает ненужные данные (SelectListItem - это подробное описание реализации). Таким образом, управление контроллером зависит от деталей реализации представления. Я думаю, это нужно изменить, чтобы избежать этого. Подумайте об использовании какого-либо объекта, который будет хранить данные для страны.
Надеюсь, что это поможет.
Ответ 2
Это очень похоже на рекомендованную практику в Wrox Professional ASP.NET MVC, первая глава которой доступна бесплатно указанный выше URL.
Начиная со страницы 100, они имеют раздел в ViewData и ViewModels.
Когда класс Controller решает вернуть HTML-ответ клиенту, он отвечает за явно передачу шаблону представления всех данных, необходимых для отображения ответа. Просмотр шаблонов никогда не должен выполнять какой-либо поиск данных или логику приложения - и вместо этого должен ограничивать себя только кодом рендеринга, который отключен от модели/данных, переданных ему контроллером.
[...]
При использовании шаблона "ViewModel" мы создаем строго типизированные классы, которые оптимизированы для наших конкретных сценариев просмотра, и которые предоставляют свойства для динамических значений/содержимого, необходимых для наших шаблонов представлений. Затем наши классы контроллеров могут заполнить и передать эти оптимизированные по просмотру классы в наш шаблон просмотра. Это позволяет проводить проверку типов, проверку времени компиляции и редактор intellisense в шаблонах просмотра.
Взято из "Главы 1" Nerd Dinner "из Профессионального ASP.NET MVC 1.0, написанного Робом Коннери и др., опубликованным Wrox". Оригинал доступен по адресу http://tinyurl.com/aspnetmvc
Ответ 3
В общем, я думаю, что он выглядит хорошо, и обычно это хорошая идея для создания viewmodels для ваших объектов домена.
Я не рассматривал каждую строку кода, но одна вещь, которая привлекла мое внимание, была конструкторами OrganisationViewModel. Я бы переписал его, используя:
public OrganisationViewModel() : this(new Organisation()) { }
public OrganisationViewModel(Organisation o)
{
Organisation = o;
InitCollections();
}
Это удаляет дубликат кода, так как вам не нужно вызывать InitCollections()
в обоих конструкторах. Конечно, это лишь незначительная деталь и не имеет ничего общего с общей идеей.
Ответ 4
Мы начали это делать, но наши контроллеры начали становиться чудовищными (поскольку наши ViewModels не обязательно отображались в нашей базе данных 1:1). Чтобы облегчить это, мы создали классы Mapper, которые создают ViewModel, а затем вернутся к привязке данных к базе данных. Затем контроллер просто вызывает методы класса Mapper. Кажется, хорошо работает.