ASP.Net Web API custom model binding with x-www-form-urlencoded posted data - nothing seems to work

南笙酒味 提交于 2019-12-02 20:59:07

I would recommend you reading the following blog post in which Mike Stall explains in details how model binding works in the Web API:

There are 2 techniques for binding parameters: Model Binding and Formatters. In practice, WebAPI uses model binding to read from the query string and Formatters to read from the body.

Here are the basic rules to determine whether a parameter is read with model binding or a formatter:

  1. If the parameter has no attribute on it, then the decision is made purely on the parameter’s .NET type. "Simple types" uses model binding. Complex types uses the formatters. A "simple type" includes: primitives, TimeSpan, DateTime, Guid, Decimal, String, or something with a TypeConverter that converts from strings.
  2. You can use a [FromBody] attribute to specify that a parameter should be read from the body.
  3. You can use a [ModelBinder] attribute on the parameter or the parameter’s type to specify that a parameter should be model bound. This attribute also lets you configure the model binder. [FromUri] is a derived instance of [ModelBinder] that specifically configures a model binder to only look in the URI.
  4. The body can only be read once. So if you have 2 complex types in the signature, at least one of them must have a [ModelBinder] attribute on it.

So if the source of your data is the request body then you can create a custom MediaTypeFormatter rather than a model binder.

ModelBinder seem relatively better to use than MediaTypeFormatter. You do not need to register it globally.

I found another alternative to use model binder to bind complex object types in Web API. In model binder, I am reading request body as string and then using JSON.NET to deserialize it to required object type. It can be used to map array of complex object types as well.

I added a model binder as follows:

public class PollRequestModelBinder : IModelBinder
{
    public bool BindModel(HttpActionContext actionContext, ModelBindingContext bindingContext)
    {
        var body = actionContext.Request.Content.ReadAsStringAsync().Result;
        var pollRequest = JsonConvert.DeserializeObject<PollRequest>(body);
        bindingContext.Model = pollRequest;
        return true;
    }
}

And then I am using it in Web API controller as follows:

    public async Task<PollResponse> Post(Guid instanceId, [ModelBinder(typeof(PollRequestModelBinder))]PollRequest request)
    {
       // api implementation  
    }
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!