如何在 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的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Azure 数据工厂的 Web 活动中为 POST 请求传递正文中的内容
Asp.Net Web API,AngularJS POST 请求
如何在 ASP.Net 中为一组 Web 请求发送身份验证标头
如何在 ASP.NET Web API 中为 Json.NET 设置自定义 JsonSerializerSettings?