ASPNetCore API 内容协商未生效

12

我正在尝试设置我的 API,使其根据 Accept 标头以 XML 或 JSON 形式响应。

我正在按照 Shawn W 的教程操作:https://wildermuth.com/2016/03/16/Content_Negotiation_in_ASP_NET_Core

他说要添加一个软件包到:"Microsoft.AspNet.Mvc.Formatters.Xml": "6.0.0-rc1-final"

但我找不到它,于是安装了:Microsoft.AspNetCore.Mvc.Formatters.Xml

他说要在 Startup 的 config services 部分中添加这个:

        // Add framework services.
        services
            .AddMvc(options => {
                options.RespectBrowserAcceptHeader = true;
                options.InputFormatters.Add(new XmlSerializerInputFormatter());
                options.OutputFormatters.Add(new XmlSerializerOutputFormatter());
            }).AddJsonOptions(options => {
                // Force Camel Case to JSON
                options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
            });

浏览器默认使用 Accept: text/xml 头部信息,因此应自动接收 XML。但我无论在浏览器中还是在 Postman 中都无法获得 XML,而是始终获取 Json,无论我将 Accept 头部设置为何值。

我尝试在我的控制器上添加 [Produces("application/xml")],但它只返回一个空的 200 OK 页面。

如何使我的 API 默认返回 Json,如果请求头中包含 Accept,则返回 XML?

编辑 1:

这是我的 HTTP GET 代码:

    [HttpGet]
    public IActionResult Get() {
        var invoices = context.Invoices.ToList();
        var mappedInvoices = mapper.Map<List<DomainModels.Invoice>, List<Invoice>>(invoices);
        return Ok(mappedInvoices);
    }

我正在尝试返回这个数据传输对象(DTO):

public class Invoice : TrackedObject {

    public DateTime Date { get; set; }

    public decimal Total { get; set; }

    public string OrderNumber { get; set; }


    public PaymentType? PaymentType { get; set; }

    public ICollection<InvoiceItem> Items { get; set; }
}
public enum PaymentType {
    Cheque,
    Cash,
    Card,
    Account
}

编辑2:

如果我更换这个:

 // Add framework services.
        services
            .AddMvc(options => {
                options.RespectBrowserAcceptHeader = true;
                options.InputFormatters.Add(new XmlSerializerInputFormatter());
                options.OutputFormatters.Add(new XmlSerializerOutputFormatter());
            }).AddJsonOptions(options => {
                // Force Camel Case to JSON
                options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
            });

并用以下内容替换:

        services.AddMvc().AddXmlSerializerFormatters();

如果我在我的GET方法上方加上[Produces("application/xml")], 我会收到一个406 Not Acceptable响应。


1
你应该使用 services.AddMvc().AddXmlSerializerFormatters(); 添加 XML 序列化器,这样会更容易一些。我之前也遇到过类似的问题,当时的原因是我返回的对象。你能否展示一下你返回的数据结构是什么样子的? - juunas
@juunas 我完全替换掉了我的 services.AddMvc,换成了你的,但它仍然返回 JSON! - Smithy
1个回答

15

我终于找到了正确的设置方式,通过accept头返回JSON和XML。

要使您的Web API控制器返回JSON或XML(默认为JSON),您需要将服务配置设置如下:

// Add framework services.
services
    .AddMvc(options => {
        options.RespectBrowserAcceptHeader = true;
    })
    //support application/xml
    .AddXmlDataContractSerializerFormatters()
    //support application/json
    .AddJsonOptions(options => {
        // Force Camel Case to JSON
        options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
    });

当你知道如何操作时,它就非常简单!现在有很多不正确的文档存在!


仍然不太清楚为什么 AddXmlSerializerFormatters() 不起作用。我在 .NET 5.0 上也遇到了同样的问题。 - Vladimir Panchenko

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