Monday, 10 December 2012

My Journey with Sitecore and MVC - View model builders


Here is a small post on my experience with MVC controllers and view models. This post is not about Sitecore.

At times you will find that, due to the complexity of a View Model, your controller become a bit long winded. Controllers are called controllers for a reason, they control stuff. In my mind I see them as small traffic controller. Controllers get some data (parameters or view models) decide what to do with it and then direct the some data (view model) to a view or redirect.

Some view models may be simple. For example, you might have a view model with:

public class LogOnViewModel
    [Display(Name = "CustomerId")]
    public string CustomerId { get; set; }

    [Display(Name = "Password")]
    public string Password { get; set; }

    [Display(Name = "Remember me when I log in again?")]
    public bool RememberMe { get; set; }

This is not a very complete view model so in theory your could just get your controller to build it up. I still recommend using a view model builder as you never know when you will need more complexity. Later, if you don't use a view model builder, you might get lazy and just dirty up your controller and wish you had a builder. I say, use one from the beginning.

If you have a more complex view model (the following is not that complex but you can see what i'm getting at) then you will start to find the need to put more code in your controller to build up collections for drop down lists (there may be a few of these in the form you are trying to render in your view), custom string formats or collections for other rendering needs.

public class DashboardViewModel
    public LogOnViewModel LogOnModel { get; set; }
    public IEnumerable < VehicleViewModel > VehicleModels { get; set; }

Here is an Index action on my DashboardController:

public ActionResult Index()
    var dashboardViewModelBuilder = new DashboardViewModelBuilder(VehicleManager);
    var dashboardViewmodel = dashboardViewModelBuilder.Build();

    return View(dashboardViewmodel);

As you can see I am using my own custom DashboardViewmodelBuilder which abstracts all the work that is required to build up my DashboardViewModel.

This means that my ViewModelBuilder can get as complex as I like whilst my controller stays nice and clean.

Here is my DashboardViewModelBuilder.

public DashboardViewModel Build()
    List < VehicleViewModel > vehicleModels = new List < VehicleViewModel > ();

    DashboardViewModel dashboardViewModel = new DashboardViewModel { LogOnModel = new LogOnViewModel() };
    var vehicles = VehicleManager.GetVehiclesByCustomerId(1);  //Yes I know, hard coding, ignore this

    foreach (var vehicle in vehicles)
        var vehicleViewModel = Mapper.Map < Vehicle, VehicleViewModel > (vehicle);

    dashboardViewModel.VehicleModels = vehicleModels;

    return dashboardViewModel;

As you can see, it gets a IVehicleManager injected into it. I need this VehicleManager to get data from a database for my view.
I also use Automapper to map the Domain model Vehicle to my VehicleViewModel.
you don't really need to follow all this, i'm just trying to make a point that having all your logic to build up your view model inside a builder is much better than cluttering up your controller.

What you reckon?