WebAPI DataMember通过application/x-www-form-urlencoded进行de/serial化时未使用的名称

Zde*_*něk 9 .net c# asp.net asp.net-web-api

在处理HTTP POST表单请求时,已经花了几个小时尝试解决忽略Name属性的问题.DataMemberAttributeContent-Type: application/x-www-form-urlencoded

Microsoft.AspNet.WebApi 5.2.3在.NET 4.5上运行应用程序,由IIS托管.

我有这个模型(演示):

// 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; }
}
Run Code Online (Sandbox Code Playgroud)

然后我有控制器:

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

(注意我实际上使用的是模型类型,而不仅仅是我控制器中的接口)


当我发送这样的数据时:

curl -X POST --data '{"id":"foo","rel":1}' -H "Content-Type: application/json" -H "Content-Length: 20" http://localhost/api/stuff
Run Code Online (Sandbox Code Playgroud)

我正确地反序列化了我的模型.


但是,当我这样做时:

curl --data "id=foo" --data "rel=1" http://localhost/api/stuff
Run Code Online (Sandbox Code Playgroud)

...我得到空模型 - 忽略自定义名称,所有属性都有默认值.

最后,当我这样请求时:

curl --data "DataId=foo" --data "RelationId=1" http://localhost/api/stuff
Run Code Online (Sandbox Code Playgroud)

...模型正确序列化.


所以我想知道,我做错了什么.我花了很多时间阅读,我发现的大部分案例都是关于DataContractAttribute我的案件中存在的遗失.

FromBody控制器参数前面的属性也没有改变任何东西.

在我的应用程序中,这些格式化程序已注册:

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

只有最后两个包含application/x-www-form-urlencodedSupportedMediaTypes.

Zde*_*něk 10

花在调试上的时间之后,我必须自己回答.

System.Net.Http.Formatting.FormUrlEncodedMediaTypeFormatter不使用,因为我的模型不是源自FormDataCollectionJS令牌类型也不是.所以格式化程序System.Web.Http.ModelBinding.JQueryMvcFormUrlEncodedFormatter正在使用中.

内部使用的粘合剂CompositeModelBinder是:

  • TypeMatchModelBinder (跳过)
  • MutableObjectModelBinder (用过的)

我没有找到任何代码的痕迹,这将考虑Name属性DataMemberAttribute- 所以我必须IModelBinder为我的类型实现自己,这将负责自定义.

请注意:序列化对象时,一切都按预期工作 - 上述问题仅与请求体的反序列化有关.

来源

我希望我没有错过任何东西.如果是这样,请纠正我.