Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WebAPI DataMember Name not used when de/serializing via application/x-www-form-urlencoded

Already spent couple of hours trying to resolve issue with ignored Name property on DataMemberAttribute when handling HTTP POST form request (Content-Type: application/x-www-form-urlencoded).

I'm having Microsoft.AspNet.WebApi 5.2.3 application running on .NET 4.5, hosted by IIS.

I have this model (demo):

// library
public interface IPayload
{
    string DataId { get; set; }
    int RelationId { get; set; }
}

// web app project
[DataContract]
public class MyPayload : IPayload
{
    [Required]
    [DataMember(Name = "id")]
    public string DataId { get; set; }

    [Required]
    [DataMember(Name = "rel")]
    public int RelationId { get; set; }
}

Then I have controller:

[HttpPost]
[Route("~/api/stuff")]
public async Task<HttpResponseMessage> DoMagic(MyPayload payload)
{
    // ... breakpoint
}

(Note I'm really using model type and not just interface in my controller)


When I send data like this:

curl -X POST --data '{"id":"foo","rel":1}' -H "Content-Type: application/json" -H "Content-Length: 20" http://localhost/api/stuff

I get my model deserialized correctly.


However, when I do:

curl --data "id=foo" --data "rel=1" http://localhost/api/stuff

... I'm getting empty model - custom name is ignored, all properties have default value.

Finally, when I do request like this:

curl --data "DataId=foo" --data "RelationId=1" http://localhost/api/stuff

... model is serialized correctly.


So I'm wondering, what am I doing wrong. I spent quite a lot of reading, most of cases I found were about missing DataContractAttribute which is present in my case.

Attribute FromBody in front of controller parameter is not changing anything as well.

In my application, these formatters are registered:

  • System.Net.Http.Formatting.JsonMediaTypeFormatter
  • System.Net.Http.Formatting.XmlMediaTypeFormatter
  • System.Net.Http.Formatting.FormUrlEncodedMediaTypeFormatter
  • System.Web.Http.ModelBinding.JQueryMvcFormUrlEncodedFormatter

Only last two contain application/x-www-form-urlencoded in SupportedMediaTypes.

like image 631
Zdeněk Avatar asked Apr 28 '15 17:04

Zdeněk


1 Answers

After time spent on debugging, I have to answer myself.

System.Net.Http.Formatting.FormUrlEncodedMediaTypeFormatter is not used as my model is not derived from FormDataCollection nor is JS token type. So formatter System.Web.Http.ModelBinding.JQueryMvcFormUrlEncodedFormatter is in use.

Binders used within CompositeModelBinder are:

  • TypeMatchModelBinder (skipped)
  • MutableObjectModelBinder (used)

I haven't found any trace of code, which would take in consideration Name attribute of DataMemberAttribute - so I have to implement own IModelBinder for my type, which will take care of customization.

Just note: when serializing object, everything works as expected - issue described above is related only to deserializing from request body.

Sources

  • System.Net.Http.Formatting.Formatting
  • System.Web.Http.ModelBinding

I hope I haven't missed anything. If so, please correct me.

like image 101
Zdeněk Avatar answered Sep 16 '22 20:09

Zdeněk