views:

68

answers:

3

For anything but trival view models, I use a view model builder that handles the responsibility of generating the view model object. Right now, I use constructor injection of the builders into my controllers but this smells a little since the builder is really dependent upon which action method is being executed. I have two ideas in mind. The first one would involve a custom ActioFilter allowing me to decorate each action method with the appropriate builder to use. The second would be to add an override of the View method that is open to accepting a generic.

This is what my code currently looks like. Note, the builder get injected via the ctor.

    [HttpGet, ImportModelStateFromTempData, Compress]
    public ActionResult MyAccount()
    {
        return View(accountBuilder.Build());
    }

Here is what option one would look like:

    [HttpGet, ImportModelStateFromTempData, Compress, ViewModelBuilder(typeof(IMyAccountViewModelBuilder)]
    public ActionResult MyAccount()
    {
        return View();
    }

Or option two:

    [HttpGet, ImportModelStateFromTempData, Compress]
    public ActionResult MyAccount()
    {
        return View<IMyAccountViewModelBuilder>();
    }

Any thoughts or suggestions would be great!

A: 

TheBuilder

I think you could move the responsibility of construct the correct view model to the builder. and you could pass the ViewModel type you want to build as a parameter, something like:

[HttpGet, ImportModelStateFromTempData, Compress]
public ActionResult MyAccount()
{
   return View( AccountBuilder.Build<MyAccountViewModel>( ) );
}

About candidates

FirstOptionThis

the above approach allows you to have more flexibility in the view you will render inside the action (what happens if your controller should choose between 3 views to show, and each one has a different view model? Filter solutions start to get complex.)

SecondOption

The View method responsibility is to take the model and render the view using it. it's the controller responsibility to build the model. so being a little orthodox, I would recommend to avoid putting model building logic in the View method : ).

SDReyes
Your first option is essentially what I am currently doing I believe. Does the AccountBuilder know how to build all ViewModel objects for the controller?Now the second option, what I envisioned would be the View method override use a service locator to grab the builder and set the model property with the result.
Marco
@Marco: Hi Marco!, the difference with your current approach is that the type is specified to the Builder object (in the example code it is not) : ). Yes, the AccountBuilder will know how to build all the viewModel objects for the controller (they are very related each other). about the second candidate, I think it is very original : ). but I would suggest to not delegate that responsibility to the View method, perhaps you would get a nice result using the Service locator idea inside the builder object : ). regards, SD
SDReyes
A: 

If you are asking for an opinion, now seeing your code, I would give my vote to your first option. I have used action filters that way extensively and it's nice - everything is in one place, enables easy decoratable actions, etc.

mare
how does this way affect your unit tests?
Marco
A: 

Your view model action filter could look at the expected model type on the ViewContext instead of requiring it in the attribute.

Ryan