Question

I have an [HttpPost] action method signature like this:

[HttpPost]
public ActionResult Edit(ExistingPostViewModel model)
{
   // Save the edited Post.
}

Now, in the past (when i didn't use ViewModels, e.g R&D), i had an implementation of an Edit method like this:

[HttpPost]
public ActionResult Edit(Post model)
{
    var existingPost = repo.Find(model.Id);
    TryUpdateModel(existingPost);
    repo.Save(existingPost);  
    return RedirectToAction("Success", existingPost.Id);
}

Which worked great.

But i'm confused how to adapt the above to the ViewModel approach.

If i do this:

TryUpdateModel(existingPost)

With my ViewModel approach, not much happens. No errors, but nothing is being updated because MVC won't know how to update a Post from a ExistingPostViewModel (before it was Post -> Post).

Now, i'm using AutoMapper. So i thought i could map from the ViewModel to the Post, then save the post.

But then im basically overriding everything. Which i don't want to do and defeats the point of the cut down ViewModel.

Can anyone un-confuse me?

This seems like a really common scenario, and i am totally stumped as to how people solve this. I can only see 3 possible solutions:

  1. Don't use a ViewModel in the HTTP POST. As i said i did this in the past for R&D and it works, but now i see how my View's have evolved (validation, simplicity), and i can't compromise that just for the sake of this problem.

  2. Don't use TryUpdateModel. Possibly, but then how would i merge in the changes?

  3. Use left-to-right. Ugh. But at the moment this seems to be the way im leaning.

Someone please give me solution #4! :)

BTW, i'm using ASP.NET MVC 3, Razor and Entity Framework.

Was it helpful?

Solution

I actually ran into this exact same issue in a project I'm currently working on. As much as I wasn't a fan of it, I ended up doing the left to right approach and manually mapping my viewmodel data back to my entity.

The only nice thing about this approach is it does give you more control. Since I started using more compound viewmodels, where you actually have fields from more than one entity in your viewmodel, it started making more sense to do things this way.

I'm also using AutoMapper, and you're absolutely right, it does get awkward when you're trying to do a simple update operation. Wish I had some super clever workaround for you, but the "old fashioned way" seems to get the job done best for the work I've been doing.

OTHER TIPS

For simple things where you don't have to run any controls prior to implementing the update what you are doing is okay (db.get(), and then update).

When things get complicated, you have to load the entity, and then select and apply user's changes from the view model, property by property. In those cases, you end up writing Update methods, which gets the new data as input, and then you load the existing entity, then compare states, and take the required actions based on the view model data. Actually in this case, probably you wont have an Update method but will have behaviors, like CancelPost, AddComment, EditPost (which also logs the edit reason), AddTagsToPost etc.

Not sure if this will help, but it is working for me. I have my underlying domain table as a Visitor Object. My viewmodel contains the Visitor Object plus a couple of IEnumerables for dropdowns.

    [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");

    }

The UpdateModel works off my viewmodel because of the "Visitor" string telling it what values to compare.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top