2

I am using ASP.NET MVC 4 with SimpleInjector and came across an issue when the MVC framework is trying to resolve the concrete type it should create when passing the object back to the controller action from the view. This is the only place it does not work, I get an error [MissingMethodException: Cannot create an instance of an interface.]

I know there have been similar questions asked, but none that really deal with this exactly. Is the best practice to write a custom ModelBinder? or am I missing something with SimpleInjector? It seems curious to me that this does not work when everything else (like constructor injection) works pretty well.

View:

@model IEntityType
... Rest of View

Controller:

public ActionResult Update(IEntityType entityType)
    {
        ... controller code

        return RedirectToAction("Index");
    }

Global.asax

Container container = new SimpleInjector.Container();
container.Register<IEntityType, EntityTypeModel>();

IEntityType Definition:

public interface IEntityType
{
    Int32 EntityTypeId { get; set; }
    Guid EntityTypeGUID { get; set; }
    String EntityTypeName { get; set; }
    String EntityTypeDescription { get; set; }
}

EntityTypeModel Definition:

public class EntityTypeModel : IEntityType
{
    public Int32 EntityTypeId { get; set; }
    public Guid EntityTypeGUID { get; set; }
    public String EntityTypeName { get; set; }
    public String EntityTypeDescription { get; set; }
}
3
  • what do your interface and class look like Commented Mar 15, 2014 at 1:49
  • Why do you have an interface for that DTO anyway? What behavior are you abstracting away here? Commented Mar 15, 2014 at 8:19
  • @Steven For this object, probably nothing since it's pretty straightforward. Sure, I could just change the model to be the EntityTypeModel and things would work fine. However (I am by no means an expert), something just doesn't sit right with me that the model needs to be a concrete object. I cannot anticipate how my implementation will change in the future, hence why the interface gives me the flexibility to change it without having to update the views that depend on the model. It just seems wrong to abstract away everywhere else and then bind a concrete model in the view. IMO anyway. Commented Mar 16, 2014 at 1:12

1 Answer 1

2

By default, MVC can't model bind interfaces for you and you should typically not try to model bind interfaces. The idea is that you model bind simple data containers or DTOs, such as View Models. So your problem is not specific to Simple Injector; none of the common DI frameworks for .NET allow integration into the MVC model binding process by default, since this is not an advised approach.

So typically, you should send view model objects between the view and the controller, or in very simple scenarios you could even just send entities, but this only works when your entities are simple data containers as well. In case your entities are simple data containers, defining an interface for each entity is useless, since interfaces are meant to abstract behavior, not data. It would be rather useless to mock or fake a class that only contains data.

In case you're practicing Domain Driven Design, your entities will have behavior, but even in that case it's very unusual to define interfaces for your entities, since the entities are the core of your domain, they don't need mocking, faking, intercepting or decorating. Instead you pass in abstractions into the entity's methods. And when practicing DDD, it will be very unlikely to use the entities directly as view model in MVC, since in DDD you tend to hide the entity's invariants, while a view model is just a simple data container with get/set properties (or public fields).

Also note that entities are short lived objects, while the services you register in your DI container tend to be long lived. In other words, entities are newables, while services are injectables. You should not register newables in your container. In the case of entities, its usually your repository layer or ORM that creates entities; not the container.

So instead of trying to add custom model binders that hook into the container framework, my advice is to do the following:

  1. Ditch the IEntityType abstraction; its a useless abstraction.
  2. Remove the Register<IEntityType, EntityTypeModel>() registration, since it registers a newable, which is not the container's job.
  3. Model bind your EntityTypeModel directly by chaning your action method to accept an EntityTypeModel instead of accepting an interface, or wrap it in a custom view model that contains a public EntityTypeModel Model { get; set; } property.

Another -more sophisticated- approach is to define message objects in the core layer of your application that each describe a single Use Case. You can use these DTOs to map directly on the MVC view. This approach gets really useful when your your application is doing more than simply CRUD operations. Take a look here.

Sign up to request clarification or add additional context in comments.

1 Comment

So how to resolve my problem? I have 3 projects in my solution Web Business(BLL) and Data. In Data i have EF entities, repositories, DTOS ( same as entities) and mappers which return DTOs. In BLL i have service and interfaces for dtos and mappers. My Web project cannot use DTOs because it cannot see them. References in my project: Web -> BLL <- Data. Shold i moved dtos to bll?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.