如果内容是 XML 格式,我如何在 .NET Core 2.2 中执行 POST?
How can I do a POST in .NET Core 2.2 if the content is XML formatted?
我对这个问题感到非常惊讶,因为我记得在较早的 .NET Core 版本中成功解决了这个问题。我正在开发一个 .NET Core 2.2 应用程序,它现在需要被另一个应用程序(外部开发)调用,它只能 post xml...
这是我的 ConfigureServices 方法:
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2).AddXmlSerializerFormatters();
}
这是我的控制器:
[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase
{
// POST api/values
[HttpPost]
public ActionResult<object> Post([FromBody] object value)
{
return ("Hi", "Hi2");
}
}
以下请求会导致状态代码为 200 的响应:
POST http://localhost:58774/api/values
Content-Type: application/json
Accept: application/xml
User-Agent: vscode-restclient
Accept-Encoding: gzip
{"a":5}
这给了我 xml 作为回应并且
POST http://localhost:58774/api/values
Content-Type: application/json
Accept: application/json
User-Agent: vscode-restclient
Accept-Encoding: gzip
{"a":5}
给出 json 作为响应。
但是,此调用导致状态代码为 500 的响应(这正是我的问题):
POST http://localhost:58774/api/values
Content-Type: application/xml
Accept: application/xml
User-Agent: vscode-restclient
Accept-Encoding: gzip
<A a="5"/>
所以我现在有麻烦了。 Xml 格式化工作,如果我 接受 它作为输出类型就变得清楚了。但是,如果我 post 自己作为 Content-Type 并测试它,我得到 500。我也试过 但它似乎不起作用在 .NET 核心 2.2 中。我究竟做错了什么?我如何在 .net core 2.2 中 post 我的 xml?
有用的评论后的更新。
导致 500 的异常是这个:
System.InvalidOperationException: There is an error in XML document
(1, 11). ---> System.InvalidOperationException: was not
expected.
但是,如果我添加一个 xmlns(基于 this),我仍然有 500:
POST http://localhost:5000/api/values
Content-Type: application/xml
Accept: application/xml
User-Agent: vscode-restclient
Accept-Encoding: gzip
<f:table xmlns:f="https://www.w3schools.com/furniture">
<f:name>African Coffee Table</f:name>
<f:width>80</f:width>
<f:length>120</f:length>
</f:table>
则异常信息为:
System.InvalidOperationException: There is an error in XML document
(1, 56). ---> System.InvalidOperationException: https://www.w3schools.com/furniture'> was not expected.
可能,我需要改变我的 xml。如何?即使是 w3cschools 的例子也对我没有帮助。
对于 Content-Type: application/json
和 {"a":5}
,您将在服务器端收到 { "a": 5 }
。它收到纯文本。
对于 Content-Type: application/xml
和 <A a="5"/>
,如果您更喜欢接收 <A a="5" />
,您可以实现自定义 XDocumentInputFormatter
,例如
public class XDocumentInputFormatter : InputFormatter, IInputFormatter, IApiRequestFormatMetadataProvider
{
public XDocumentInputFormatter()
{
SupportedMediaTypes.Add("application/xml");
}
protected override bool CanReadType(Type type)
{
if (type.IsAssignableFrom(typeof(XDocument))) return true;
return base.CanReadType(type);
}
public override async Task<InputFormatterResult> ReadRequestBodyAsync(InputFormatterContext context)
{
var xmlDoc = await XDocument.LoadAsync(context.HttpContext.Request.Body, LoadOptions.None, CancellationToken.None);
return InputFormatterResult.Success(xmlDoc);
}
}
在Startup.cs
中注册
services.AddMvc(config =>
{
config.InputFormatters.Insert(0, new XDocumentInputFormatter());
})
.SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
.AddXmlSerializerFormatters();
默认情况下,对于XmlSerializer
,我们需要提供Type type
,对象类型将无法反序列化。
如果 object value
的类型定义为
public class A
{
public int a { get; set; }
}
你可以像
那样改变你的方法
public ActionResult<object> Post([FromBody] A value)
{
return new A { a = 1 };//("Hi", "Hi2");
}
并且请求像
<A>
<a>1</a>
</A>
它将用 class 一个对象填充值。
我对这个问题感到非常惊讶,因为我记得在较早的 .NET Core 版本中成功解决了这个问题。我正在开发一个 .NET Core 2.2 应用程序,它现在需要被另一个应用程序(外部开发)调用,它只能 post xml...
这是我的 ConfigureServices 方法:
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2).AddXmlSerializerFormatters();
}
这是我的控制器:
[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase
{
// POST api/values
[HttpPost]
public ActionResult<object> Post([FromBody] object value)
{
return ("Hi", "Hi2");
}
}
以下请求会导致状态代码为 200 的响应:
POST http://localhost:58774/api/values
Content-Type: application/json
Accept: application/xml
User-Agent: vscode-restclient
Accept-Encoding: gzip
{"a":5}
这给了我 xml 作为回应并且
POST http://localhost:58774/api/values
Content-Type: application/json
Accept: application/json
User-Agent: vscode-restclient
Accept-Encoding: gzip
{"a":5}
给出 json 作为响应。
但是,此调用导致状态代码为 500 的响应(这正是我的问题):
POST http://localhost:58774/api/values
Content-Type: application/xml
Accept: application/xml
User-Agent: vscode-restclient
Accept-Encoding: gzip
<A a="5"/>
所以我现在有麻烦了。 Xml 格式化工作,如果我 接受 它作为输出类型就变得清楚了。但是,如果我 post 自己作为 Content-Type 并测试它,我得到 500。我也试过
有用的评论后的更新。 导致 500 的异常是这个:
System.InvalidOperationException: There is an error in XML document (1, 11). ---> System.InvalidOperationException: was not expected.
但是,如果我添加一个 xmlns(基于 this),我仍然有 500:
POST http://localhost:5000/api/values
Content-Type: application/xml
Accept: application/xml
User-Agent: vscode-restclient
Accept-Encoding: gzip
<f:table xmlns:f="https://www.w3schools.com/furniture">
<f:name>African Coffee Table</f:name>
<f:width>80</f:width>
<f:length>120</f:length>
</f:table>
则异常信息为:
System.InvalidOperationException: There is an error in XML document (1, 56). ---> System.InvalidOperationException: https://www.w3schools.com/furniture'> was not expected.
可能,我需要改变我的 xml。如何?即使是 w3cschools 的例子也对我没有帮助。
对于 Content-Type: application/json
和 {"a":5}
,您将在服务器端收到 { "a": 5 }
。它收到纯文本。
对于 Content-Type: application/xml
和 <A a="5"/>
,如果您更喜欢接收 <A a="5" />
,您可以实现自定义 XDocumentInputFormatter
,例如
public class XDocumentInputFormatter : InputFormatter, IInputFormatter, IApiRequestFormatMetadataProvider
{
public XDocumentInputFormatter()
{
SupportedMediaTypes.Add("application/xml");
}
protected override bool CanReadType(Type type)
{
if (type.IsAssignableFrom(typeof(XDocument))) return true;
return base.CanReadType(type);
}
public override async Task<InputFormatterResult> ReadRequestBodyAsync(InputFormatterContext context)
{
var xmlDoc = await XDocument.LoadAsync(context.HttpContext.Request.Body, LoadOptions.None, CancellationToken.None);
return InputFormatterResult.Success(xmlDoc);
}
}
在Startup.cs
中注册
services.AddMvc(config =>
{
config.InputFormatters.Insert(0, new XDocumentInputFormatter());
})
.SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
.AddXmlSerializerFormatters();
默认情况下,对于XmlSerializer
,我们需要提供Type type
,对象类型将无法反序列化。
如果 object value
的类型定义为
public class A
{
public int a { get; set; }
}
你可以像
那样改变你的方法public ActionResult<object> Post([FromBody] A value)
{
return new A { a = 1 };//("Hi", "Hi2");
}
并且请求像
<A>
<a>1</a>
</A>
它将用 class 一个对象填充值。