kind_robot
kind_robot

Reputation: 2523

Inheritance based custom model binding

I need to create a post action to listen to bunch of event messages in ASP.NET MVC 4. There are lots of events so I cannot create an action per event. So it would be best to create an action with their base class as posted model use a custom model binder to hydrate the event.

Some of the events look like this:

public class QueryID : Identity<Guid>
{
    public QueryID(Guid id)
    {
        Identifier = id;
    }
}

public class QueryEvent : IEvent<QueryID>
{
    public QueryEvent(QueryID id)
    {
        Identity = id;
    }

    #region Implementation of IEvent<out QueryID>

    public QueryID Identity { get; private set; }

    #endregion
}

public class QueryCreated : QueryEvent
{
    public string ConnectionID { get; private set; }

    public QueryCreated(QueryID id, string connectionID)
        : base(id)
    {
        ConnectionID = connectionID;
    }
}

public class ColumnAdded : QueryEvent
{
    public string Column { get; private set; }

    public ColumnAdded(QueryID id, string column)
        : base(id)
    {
        Column = column;
    }
}

The action method to receive these messages would look something like this:

[HttpPost]
    public ActionResult Index(IEvent<IIdentity> e)
    {
        // whatever

        return new EmptyResult();
    }

The base Identity class implements the IEvent<IIdentity> interface.

What would the model binder look like to accomplish this?

Thanks

Upvotes: 0

Views: 1215

Answers (2)

Pricey
Pricey

Reputation: 5929

A custom model binder provider can be written to support interfaces in MVC3+, see this post.

http://www.matthidinger.com/archive/2011/08/16/An-inheritance-aware-ModelBinderProvider-in-MVC-3.aspx

Any types that inherit the particular interface are then passed to the relevant model binder which can then likely try a as ConcreteClass and a null check to find out what the actual type is.. I haven't tried this because I have a similar issue and have been unable to do a solution, but the relevant post looks like it points in the right direction.

Upvotes: 0

Suhas
Suhas

Reputation: 8458

Mere model binding would not help you here. The way model binding works is, framework looks at the type of the parameter that actions expects, creates a default instance of that type using reflection and hydrates every public property on it using the data sent in the form.

The parameter in your action is an interface and hence framework would fail to create an instance. It would just not know which implementation of the interface to create.

In one instance, I have used a hidden field in the form being posted to indicate which implementation of the interface is to be bound to the action parameter. But I had a simple scenario. One interface with two implementation. Each one corresponding to a form. So I could have a hidden filed tell me the name of the class that I wanted my model binder to create.

In you case, if the originator of the event (some client application I reckon) knows which model should be invoked, then you can have that information sent to your action along with other information.

Unfortunately I do not have the code at the moment. If you think this solution may help, I can dig out the code.

Upvotes: 1

Related Questions