Использование моделей представления в ASP.NET MVC 3
Я сравнительно недавно рассматриваю модели, и у меня возникают проблемы с их использованием. Здесь одна ситуация, когда мне интересно, что такое лучшая практика...
Я помещаю всю информацию, необходимую для просмотра в модель представления. Вот пример - пожалуйста, простите любые ошибки, это закодировано с верхней части моей головы.
public ActionResult Edit(int id)
{
var project = ProjectService.GetProject(id);
if (project == null)
// Something about not found, possibly a redirect to 404.
var model = new ProjectEdit();
model.MapFrom(project); // Extension method using AutoMapper.
return View(model);
}
Если экран разрешает только редактирование одного или двух полей, когда модель представления возвращается, у нее отсутствует достаточно данных (как и должно быть).
[HttpPost]
public ActionResult Edit(int id, ProjectEdit model)
{
var project = ProjectService.GetProject(id);
if (project == null)
// Something about not found, possibly a redirect to 404.
try
{
if (!ModelState.IsValid)
return View(model) // Won't work, view model is incomplete.
model.MapTo(project); // Extension method using AutoMapper.
ProjectService.UpdateProject(project);
// Add a message for the user to temp data.
return RedirectToAction("details", new { project.Id });
}
catch (Exception exception)
{
// Add a message for the user to temp data.
return View(model) // Won't work, view model is incomplete.
}
}
Мое временное решение состоит в том, чтобы воссоздать модель представления с нуля, повторно заполнить ее из модели домена, повторно применить данные формы к ней, а затем продолжить как обычно. Но это делает параметр модели зрения несколько бессмысленным.
[HttpPost]
public ActionResult Edit(int id, ProjectEdit model)
{
var project = ProjectService.GetProject(id);
if (project == null)
// Something about not found, possibly a redirect to 404.
// Recreate the view model from scratch.
model = new ProjectEdit();
model.MapFrom(project); // Extension method using AutoMapper.
try
{
TryUpdateModel(model); // Reapply the form data.
if (!ModelState.IsValid)
return View(model) // View model is complete this time.
model.MapTo(project); // Extension method using AutoMapper.
ProjectService.UpdateProject(project);
// Add a message for the user to temp data.
return RedirectToAction("details", new { project.Id });
}
catch (Exception exception)
{
// Add a message for the user to temp data.
return View(model) // View model is complete this time.
}
}
Есть ли более элегантный способ?
ИЗМЕНИТЬ
Оба ответа верны, поэтому я бы наградил их обоих, если мог. Ног идет в MJ, так как после проб и ошибок я считаю, что его решение было самым скудным.
Я все еще могу использовать помощников, Джимми. Если я добавлю то, что мне нужно отобразить в сумке просмотра (или просмотреть данные), например...
ViewBag.Project= project;
Затем я могу сделать следующее...
@Html.LabelFor(model => ((Project)ViewData["Project"]).Name)
@Html.DisplayFor(model => ((Project)ViewData["Project"]).Name)
Немного взлома, и в некоторых случаях требуется, чтобы модель домена была украшена System.ComponentModel.DisplayNameAttribute
, но я уже это делаю.
Мне бы хотелось позвонить...
@Html.LabelFor(model => ViewBag.Project.Name)
Но динамика вызывает проблему в выражениях.
Ответы
Ответ 1
После некоторого обучения с ошибкой (ака, это, а затем ненавижу) мой предпочтительный мой подход:
Я использую модели view только для привязки полей ввода. Поэтому в вашем случае, если ваше представление только редактирует два поля, то ваша модель просмотра будет иметь только два свойства. Для данных, необходимых для заполнения представления (раскрывающихся списков, меток и т.д.), Я использую динамический ViewBag.
Я считаю, что отображение вида (то есть заполнение всего, что должно отображаться в представлении), и захват опубликованных значений формы (привязка, проверка и т.д.) - две отдельные проблемы. И я считаю, что смешивание данных, необходимых для заполнения представления, тем, что отправлено назад из представления, становится беспорядочным, и создает именно вашу ситуацию чаще, чем нет. Мне не нравятся частично населенные объекты.
Я не уверен, как это происходит с Automapper (для отображения объекта домена в динамический ViewBag), хотя я его не использовал. Я считаю, что у него есть метод DynamicMap, который может работать? У вас не должно быть проблем с автоматическим отображением опубликованного строго типизированного ViewModel на объект Domain.
Ответ 2
Если я правильно понял, ваша viewmodel, вероятно, очень похожа на вашу сущность домена. Вы упомянули, что viewmodel может вернуться в основном пустым, потому что доступны только определенные поля.
Предполагая, что у вас есть представление, в котором доступно только несколько полей для редактирования (или отображения), это единственные поля, которые вы должны сделать доступными в своей модели viewmodel. Обычно я создаю одну модель представления для каждого представления и позволяю либо контроллеру, либо службе обрабатывать вход пользователя и сопоставлять его с объектом домена после выполнения некоторой проверки.
Здесь поток, касающийся лучших практик для моделей просмотра, которые могут вам пригодиться.
Изменить: Вы также можете принять другую модель просмотра в действии Edit/POST, чем действие Edit/GET. Я считаю, что это должно работать до тех пор, пока модельное связующее может понять это.