Как обновить модель при привязке к 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 (до того, как он был PostPost).

Теперь я использую 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 работает с моей моделью просмотра из-за строки "Посетитель", сообщающей ей, какие значения сравнивать.