Как обновить модель при привязке к ViewModel?
У меня есть подпись метода действия [HttpPost]
, как это:
[HttpPost]
public ActionResult Edit(ExistingPostViewModel model)
{
// Save the edited Post.
}
В прошлом (когда я не использовал ViewModels, например R & D), у меня была реализация метода Изменить, как это:
[HttpPost]
public ActionResult Edit(Post model)
{
var existingPost = repo.Find(model.Id);
TryUpdateModel(existingPost);
repo.Save(existingPost);
return RedirectToAction("Success", existingPost.Id);
}
Что отлично работает.
Но я смущен, как приспособить вышеприведенный подход к ViewModel.
Если я это сделаю:
TryUpdateModel(existingPost)
В моем подходе ViewModel не так много происходит. Нет ошибок, но ничего не обновляется, потому что MVC не знает, как обновить Post
от ExistingPostViewModel
(до того, как он был Post
→ Post
).
Теперь я использую AutoMapper. Поэтому я думал, что смогу отобразить из ViewModel в Post
, а затем сохранить сообщение.
Но тогда im в основном все переопределяет. Который я не хочу делать и побеждает точку вырезания ViewModel.
Кто-нибудь может смутить меня?
Это похоже на действительно распространенный сценарий, и я полностью зациклен на том, как люди это решают. Я могу видеть только 3 возможных решения:
-
Не используйте ViewModel в HTTP POST. Как я уже сказал, я делал это в прошлом для R & D, и он работает, но теперь я вижу, как изменился мой взгляд (валидация, простота), и я не могу скомпрометировать это только ради этой проблемы.
-
Не используйте TryUpdateModel. Возможно, но тогда как бы я слился в изменениях?
-
Используйте слева направо. Тьфу. Но на данный момент это похоже на то, как он склоняется.
Кто-то, пожалуйста, дайте мне решение №4!:)
Кстати, я использую ASP.NET MVC 3, Razor и Entity Framework.
Ответы
Ответ 1
Я действительно столкнулся с этой же проблемой в проекте, над которым я сейчас работаю. Насколько я не был в восторге от этого, я в конечном итоге сделал подход слева направо и вручную сопоставил данные моей модели viewmodel с моей сущностью.
Единственная приятная вещь в этом подходе - это дает вам больше контроля. Поскольку я начал использовать более сложные модели просмотра, где у вас на самом деле есть поля из более чем одного объекта в вашей модели viewmodel, у него стало больше смысла делать что-то таким образом.
Я также использую AutoMapper, и вы абсолютно правы, это становится неудобно, когда вы пытаетесь выполнить простую операцию обновления. Хотелось бы, чтобы у меня было какое-то превосходное обходное решение для вас, но "старомодный способ", похоже, лучше всего подходит для работы, которую я делал.
Ответ 2
Для простых вещей, когда вам не нужно запускать какие-либо элементы управления до внедрения обновления, что вы делаете, это нормально (db.get(), а затем обновляется).
Когда все усложняется, вам нужно загрузить объект, а затем выбрать и применить изменения пользователя из модели представления, свойство по свойству. В этих случаях вы заканчиваете тем, что пишете методы обновления, которые вводят новые данные в качестве входных данных, а затем вы загружаете существующий объект, затем сравниваете состояния и выполняете требуемые действия на основе данных модели представления. Фактически в этом случае, вероятно, у вас не будет метода Update, но будет иметь поведения, такие как CancelPost, AddComment, EditPost (который также регистрирует причину изменения), AddTagsToPost и т.д.
Ответ 3
Не уверен, что это поможет, но он работает для меня. У меня есть моя базовая таблица домена как объект посетителя. Моя viewmodel содержит объект Visitor плюс пару IEnumerables для выпадающих меню.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(int id)
{
Visitor Visitor = new Visitor();
Visitor = db.Visitors.FirstOrDefault(v => v.VisitorID == id);
UpdateModel(Visitor, "Visitor");
db.SaveChanges();
return RedirectToAction("Index");
}
UpdateModel работает с моей моделью просмотра из-за строки "Посетитель", сообщающей ей, какие значения сравнивать.