You can do this fairly easily with a custom model binder. Here is what worked for me. (Using Web API 2 and JSON.Net 6)
public class JsonPolyModelBinder : IModelBinder
{
readonly JsonSerializerSettings settings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.Auto };
public bool BindModel(HttpActionContext actionContext, ModelBindingContext bindingContext)
{
var content = actionContext.Request.Content;
string json = content.ReadAsStringAsync().Result;
var obj = JsonConvert.DeserializeObject(json, bindingContext.ModelType, settings);
bindingContext.Model = obj;
return true;
}
}
The Web API controller looks like this. (Note: should also work for regular MVC actions -- I've done something like this for them before as well.)
public class TestController : ApiController
{
// POST api/test
public void Post([ModelBinder(typeof(JsonPolyModelBinder))]ICommand command)
{
...
}
}
I should also note that when you serialize the JSON, you should serialize it with the same setting, and serialize it as an interface to make the Auto kick in and include the type hint. Something like this.
JsonSerializerSettings settings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.Auto };
string json = JsonConvert.SerializeObject(command, typeof(ICommand), settings);