如何在 POST 正文中为 asp.net WebAPI POST 路由格式化 XML
Posted
技术标签:
【中文标题】如何在 POST 正文中为 asp.net WebAPI POST 路由格式化 XML【英文标题】:How to format XML in POST body for an asp.net WebAPI POST route 【发布时间】:2019-09-15 11:54:25 【问题描述】:我有一个 asp.net WebAPI RESTful 服务,其中有一个用于 GPS 位置的 POST 端点。
服务器控制器有以下路由:
public HttpResponseMessage PostGpsPositions(GpsPositionsModel positions)
body类如下:
public class GpsPositionsModel
[Required]
public int SenderId get; set;
[Required]
public List<GPSData> Positions get; set;
public class GPSData
[Required]
public double X get; set;
[Required]
public double Y get; set;
[Required]
public double Z get; set;
我一直只使用json
,但有人问我是否可以将正文提交到XML
。
通过包含Content-Type:"application/xml"
标头,这似乎应该是可能的。
我原以为格式如下所示:
<?xml version="1.0"?>
<GpsPositionsModel>
<SenderId>1</SenderId>
<Positions>
<GPSData>
<x>1.1</x>
<y>1.1</y>
<z>1.1</z>
</GPSData>
</Positions>
</GpsPositionsModel>
但这只是不起作用,我回复400 Bad Request
。
我在服务器上有一个验证过滤器:
ValidationFilterAttribute : ActionFilterAttribute
在OnActionExecuting
中我可以看到它确实有 XML 内容标头,但模型状态为 false:
那么,我的问题是这里的 XML 应该如何格式化?我是否需要在结构中的某处使用ArrayOf
,如果需要,如何将其应用于我发送的列表?
更新
添加了 cmets 中建议的属性。
所以我有服务器端:
namespace Models.Common
[DataContract(Namespace = "http://mynamespace.com")]
public class GpsPositionsModel
[DataMember]
[Required]
public int SenderId get; set;
[DataMember]
[Required]
public List<GPSData> Positions get; set;
[DataContract(Namespace = "http://mynamespace.com")]
public class GPSData
[DataMember]
[Required]
public double X get; set;
[DataMember]
[Required]
public double Y get; set;
[DataMember]
[Required]
public double Z get; set;
控制器:
[HttpPost]
[Route("gps")]
public HttpResponseMessage SubmitGpsData([FromBody]GpsPositionsModel gpsData)
return new HttpResponseMessage();
使用 Postman,我调用 using:
<?xml version="1.0"?>
<GpsPositionsModel xmlns="http://schemas.datacontract.org/2004/07/http://mynamespace.com">
<SenderId>1</SenderId>
<Positions>
<GPSData xmlns="http://schemas.datacontract.org/2004/07/http://mynamespace.com">
<x>1.1</x>
<y>1.1</y>
<z>1.1</z>
</GPSData>
<GPSData xmlns="http://schemas.datacontract.org/2004/07/http://mynamespace.com">
<x>1.1</x>
<y>1.1</y>
<z>1.1</z>
</GPSData>
</Positions>
</GpsPositionsModel>
在 Postman 控制台中我得到:
我用的是WebAPI2,asp.net全框架
<package id="Microsoft.AspNet.Cors" version="5.2.4" targetFramework="net47" />
<package id="Microsoft.AspNet.WebApi" version="5.2.4" targetFramework="net47" />
<package id="Microsoft.AspNet.WebApi.Client" version="5.2.4" targetFramework="net47" />
<package id="Microsoft.AspNet.WebApi.Core" version="5.2.4" targetFramework="net47" />
<package id="Microsoft.AspNet.WebApi.Cors" version="5.2.4" targetFramework="net47" />
<package id="Microsoft.AspNet.WebApi.Owin" version="5.2.4" targetFramework="net47" />
<package id="Microsoft.AspNet.WebApi.Tracing" version="5.2.4" targetFramework="net47" />
<package id="Microsoft.AspNet.WebApi.WebHost" version="5.2.4" targetFramework="net47" />
【问题讨论】:
【参考方案1】:尝试在action方法的参数中添加[FromBody]
属性
public HttpResponseMessage PostGpsPositions([FromBody]GpsPositionsModel positions)
还有,对于模型
在类名上添加[DataContract]
,在模型中的每个属性上添加[DataMember]
【讨论】:
谢谢@akg179,但不幸的是这并没有什么不同,上面看起来更像你为WCF所做的,但我还是尝试了。【参考方案2】:对于发布 xml,您需要以以下格式指定 xmlns:
http://schemas.datacontract.org/2004/07/Clr.Namespace
因此,在您的情况下,您需要像这样发布 xml:
<GpsPositionsModel xmlns="http://schemas.datacontract.org/2004/07/namespance containing GpsPositionsModel class">
<Positions>
<GPSData>
<X>1</X>
<Y>1</Y>
<Z>2</Z>
</GPSData>
</Positions>
<SenderId>1</SenderId>
</GpsPositionsModel>
如果 GpsPositionsModel 类不在任何命名空间内,您可以将其留空,例如:
xmlns="http://schemas.datacontract.org/2004/07/
参考:https://docs.microsoft.com/en-us/dotnet/framework/wcf/feature-details/data-contract-names
【讨论】:
感谢@Mohsin,但不幸的是这并没有什么区别,上面看起来更像你为 WCF 所做的,但我还是尝试了(包括命名空间) 您可以与命名空间共享更新的 xml 架构吗?我最终测试了它,它有效。我假设您使用的是 Asp.WebApi 2。另外,您使用的是哪个 .Net 框架?以上是关于如何在 POST 正文中为 asp.net WebAPI POST 路由格式化 XML的主要内容,如果未能解决你的问题,请参考以下文章