Search code examples
c#interfaceasp.net-mvc-viewmodel

Interface for ViewModel Builders in MVC


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


Solution

  • 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!