已经花了几个小时尝试解决在处理HTTP POST表单请求(Content-Type: application/x-www-form-urlencoded
)时被忽略的DataMemberAttribute
中的Name
属性的问题。
我正在使用运行在.NET 4.5上,由IIS托管的Microsoft.AspNet.WebApi 5.2.3
应用程序。
我有这个模型(演示):
// 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; }
}
那么我有一个控制器:
[HttpPost]
[Route("~/api/stuff")]
public async Task<HttpResponseMessage> DoMagic(MyPayload payload)
{
// ... breakpoint
}
(请注意,我在控制器中真正使用的是模型类型而不仅仅是接口)
当我像这样发送数据:
curl -X POST --data '{"id":"foo","rel":1}' -H "Content-Type: application/json" -H "Content-Length: 20" http://localhost/api/stuff
我的模型被成功反序列化了。
然而,当我执行以下操作时:
curl --data "id=foo" --data "rel=1" http://localhost/api/stuff
......我得到了一个空模型 - 自定义名称被忽略,所有属性都具有默认值。
最后,当我像这样发送请求时:
curl --data "DataId=foo" --data "RelationId=1" http://localhost/api/stuff
...模型已正确序列化。
所以我在想,我做错了什么。我花了很多时间阅读,大多数情况下我发现都是关于缺少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-urlencoded
在SupportedMediaTypes
中。
ModelBinder
(空的,因为我没有实现任何自定义绑定器),它也没有帮助我太多。此外,我不会这样做 - 对于JSON,它可以工作,那么为什么我要在这里实现绑定器呢? - ZdeněkContent-Type:application/x-www-form-urlencoded
)”? - boostsRequestContext.RouteData
和Request.Content
是什么样子的?我不熟悉 curl,但是我在这里看到的与你的帖子有些不同。 - boostsHttpRouteValueDictionary
中没有值(这是正确的,在我的情况下没有查询字符串参数);Request.Content
设置了正确的头部application/x-www-form-urlencoded
,但是当我通过Request.Content.ReadAsStringAsync()
读取它的内容时,得到的是空字符串。 - Zdeněk