如果内容是XML格式,我该如何在.NET Core 2.2中执行POST操作?

4
我很惊讶这个问题,因为我记得在早期的.NET Core版本中成功了。我正在开发一个.NET Core 2.2应用程序,现在需要被另一个应用程序(外部开发)调用,该应用程序只能发布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格式作为输出类型 Accept,它可以正常工作。但是,如果我自己发布为Content-Type并测试,就会出现500错误。我也尝试了this (旧)方法,但在.NET Core 2.2中似乎不起作用。我做错了什么?如何在.NET Core 2.2中发布我的xml? 在有用的备注后更新。 导致500的异常如下:

System.InvalidOperationException: XML文档中存在错误(1,11)。---> System.InvalidOperationException:未预期到。

但是,如果我添加一个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: XML文档中存在一个错误(1, 56)。 ---> System.InvalidOperationException: https://www.w3schools.com/furniture'> 是未预期的。

可能需要更改我的xml。如何更改?即使来自w3cschools的示例也对我没有帮助。


3
500 错误背后应该有一个具体的例外情况。是什么? - Dan Wilson
有错误:System.InvalidOperationException: XML 文档中有一个错误 (1, 11)。---> System.InvalidOperationException: 未预期 <A xmlns=''>。 - Daan
有点冒险,但你尝试在xml的第一行添加一个xml声明了吗?例如:<?xml version="1.0" encoding="UTF-8" ? - Erresen
忘了那个 - 我创建了一个新的 WebAPI 项目,它报告 XML 声明错误。我认为这可能是 XML 序列化器的一个 bug,因为我直接从同一个端点复制了 XML 输出,并将其用作输入.... - Erresen
您对 object value 的期望值是多少? - Edward
1个回答

4
对于带有 {"a":5}Content-Type: application/json,您将在服务器端收到 { "a": 5 }。它接收了纯文本。
对于带有 <A a="5"/>Content-Type: application/xml,如果您想要接收 <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 A对象填充值。


好的答案 - 在我的测试中这个可行,但它似乎很奇怪,实际上需要这样做...默认的xmlserializer应该可以正常工作。 - Erresen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接