Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

"Merge" Model and ViewModel with or without AutoMapper?

I am currently using ViewModels to separate my Views from the actual Model structure.

For example I have a User persistence entity and a MyProfile ViewModel containing all the information, that a user can change on his own. For the conversion from User to MyProfile I am using Automapper.

Now after a user posts back his (changed) information, I need to save these. But the information in the ViewModel is not complete, and when AutoMapper creates a User persistence entity from the ViewModel, important information gets lost.

I do not want to expose this information to the View Layer, especially not with hidden form elements.

So i need a way to merge a ViewModel into a persistence entity. Can I do that with AutoMapper, or do I have to do it manually?

Example:

My User class contains ID, Firstname, Lastname, Username and Password. The user should only edit his First and Lastname in his profile. Therefore my ProfileViewModel contains ID, Firstname and Lastname. After posting back the information from the form, Automapper creates a User object from the transferred ProfileViewModel, and in this object only ID, Firstname and Lastname are set. When feeding this Entity to my Repository, I have lost username and password information.

like image 806
ckonig Avatar asked Apr 20 '12 14:04

ckonig


1 Answers

So i need a way to merge a ViewModel into a persistence entity. Can I do that with AutoMapper, or do I have to do it manually?

Yes, you can do that with AutoMapper. For example:

public class Model
{
    public int Id { get; set; }
    public string Name { get; set; }
}

public class ViewModel
{
    public string Name { get; set; }
}

class Program
{
    static void Main()
    {
        // define a map (ideally once per appdomain => usually goes in Application_Start)
        Mapper.CreateMap<ViewModel, Model>();

        // fetch an entity from a db or something
        var model = new Model
        {
            Id = 5,
            Name = "foo"
        };

        // we get that from the view. It contains only a subset of the
        // entity properties
        var viewModel = new ViewModel
        {
            Name = "bar"
        };

        // Now we merge the view model properties into the model
        Mapper.Map(viewModel, model);

        // at this stage the model.Id stays unchanged because
        // there's no Id property in the view model
        Console.WriteLine(model.Id);

        // and the name has been overwritten
        Console.WriteLine(model.Name);
    }
}

prints:

5
bar

And to translate this into a typical ASP.NET MVC pattern:

[HttpPost]
public ActionResult Update(MyViewModel viewModel)
{
    if (!ModelState.IsValid)
    {
        // validation failed => redisplay view 
        return View(viewModel);
    }

    // fetch the domain entity that we want to udpate
    DomainModel model = _repository.Get(viewModel.Id);

    // now merge the properties
    Mapper.Map(viewModel, model);

    // update the domain model
    _repository.Update(mdoel);

    return RedirectToAction("Success");
}
like image 152
Darin Dimitrov Avatar answered Nov 24 '22 09:11

Darin Dimitrov