4

I've been trying to make up my mind on how to deal with ViewModels in my MVC solution. I think, after reading different posts and blogs, that the best approach is having builders that implement an interface and then inject those into the controller itself.

Using automapper I would do the mapping between the entities and the viewmodels in the implementation of each builder and the controllers will remain very thin.

So I create this interface

public interface IViewModelBuilder<TViewModel, TEntity>
{
    TViewModel Build(TEntity entity);
}

For the moment I ignore the warnings about making them covariant and contravariant (don't know if that's needed).

For a particular ViewModel though I need to fetch two entities from two different services so I don't know what type argument should I pass.

public class ConcreteVMBuilder: IViewModelBuilder<concreteVM, ????>

Maybe that interface is not correct?

I understand merging the two entities fetched in the controller is not a clean solution, right?

If someone could give me a hand I would be very much obliged

mitomed
  • 2,006
  • 2
  • 29
  • 58

1 Answers1

4

What about making the injectable type a nested class of the vm?

e.g. something like

public class SomeViewModelBuilder : IViewModelBuilder<SomeViewModelBuilderArgs>
{
    public class SomeViewModelBuilderArgs 
    {
        public SomeEntity Entity1 { get; private set; }
        public SomeOtherEntity Entity2 { get; private set; }

        public SomeViewModelBuilderArgs(Entity1 someEntity, Entity2 someOtherEntity) 
        {
            SomeEntity = someEntity;
            SomeOtherEntity = someOtherEntity;
        }
    }

    public SomeViewModel Build(SomeViewModelBuilderArgs)
    {
        // Do work
        return new SomeViewModel();
    }
}

Then call your standard interface to inject the entities:

builderInterface.Build(new SomeViewModelClass.SomeViewModelBuilderArgs(ent1, ent2));

Does that help at all?

Edit: Additionally - is there any need for the first generic param since the interface doesn't even use it?

Edit2: Oh my bad you are returning it - ignore that last comment!

Charleh
  • 13,749
  • 3
  • 37
  • 57
  • Hi Charleh, thanks for your comment. This one is more or less the option I was referring to, merging both in another model, now you've "coded" it doesn't look that bad to me. The other option I was thinking of was passing the userId (which is the one I use for fetching both entities, I missed that important part in my question) to the builder. In this case I would fetch the entities in it instead of doing so in the controller, and therefore I would need to inject the classes to make the calls to the services, does it make sense? – mitomed Apr 15 '13 at 18:30
  • Yes both approaches should work - to be honest your idea about injecting the parameters instead of the actual entities is more along the lines of what I would do. This way it's up to a "builder" to gather the required entity data to build a VM - it's pretty much exactly the approach I take in one of my projects, with the exception that a VM builds itself (instantiation is done via the container and then the params are injected and the VM sets itself up - the builder just wraps the build calls) – Charleh Apr 16 '13 at 01:44