【问题标题】:Why won't my ASP.Net Core Web API Controller return XML?为什么我的 ASP.Net Core Web API 控制器不返回 XML?
【发布时间】:2016-07-11 21:16:59
【问题描述】:

我有以下简单的 Web API 控制器:

    // GET: api/customers
    [HttpGet]
    public async Task<IActionResult> Get()
        {
        var customers = await uow.Users.GetAllAsync();
        var dto = customers.Select(p => new CustomerDto {Id = p.Id, Email = p.Email, UserName = p.UserName});
        return Ok(dto); // IEnumerable<CustomerDto>
        }

在 Postman 中,我将 Accept 标头设置为 application/xml,但无论我如何尝试,我都只能取回 JSON 数据。

我在某处读到,为了获取 XML,我必须将 [DataContract][DataMember] 属性添加到我的 DTO,现在看起来像这样:

[DataContract]
public class CustomerDto
    {
    [DataMember]
    public string Id { get; set; }

    [Required]
    [EmailAddress]
    [Display(Name = "Email")]
    [DataMember]
    public string Email { get; set; }

    [Required]
    [Display(Name = "Login Name")]
    [DataMember]
    public string UserName { get; set; }
    }

我已经使用了几个小时了,但我只是不明白为什么它不起作用。我试过了:

  • 使action方法同步和异步

  • 直接返回数据,并设置返回类型为IEnumerable&lt;CustomerDto&gt;

  • 将集合转换为数组而不是列表

  • 返回IActionResult

  • 返回单个项目,而不是集合

  • 我已通过在调试器中检查 Accept 标头来验证它是否显示在请求中。

  • 大量“使用 Bing 搜索”并阅读各种博客

  • 从模板创建一个新的 WebAPI 项目,看看那里是否有任何灵感(不是真的)。​​

    我希望它很简单,但我看不到它......

【问题讨论】:

  • 你能证明你在 Startup.cs 中注册了你的 Xml 格式化程序吗?
  • 你配置过格式化程序吗?
  • 这当然是问题所在。上次我使用了默认启用的 WebAPI。我忘记了 ASP.Net 5 中新的轻量级现收现付方法!不过,扩展方法也不是很容易被发现。我必须知道安装另一个 NuGet 包,然后点到 AddMvc() 调用中。

标签: xml asp.net-web-api asp.net-core asp.net-core-mvc


【解决方案1】:

Xml 格式化程序是单独包的一部分:Microsoft.AspNetCore.Mvc.Formatters.Xml

添加上面的包并更新你的startup.cs,如下所示:

services
    .AddMvc()
    .AddXmlDataContractSerializerFormatters();

services
    .AddMvc()
    .AddXmlSerializerFormatters();

【讨论】:

  • 啊...我想知道它是否可能是这样的。遗憾的是文档有点未完成。 MVC5 中不是默认启用了 XML 格式化程序吗?
  • 是的,它在 MVC5 中,但在 ASP.NET 5 中很早就改变了
  • @TimLong:您可能必须在 MSDN 中查找该信息。
  • 最新版的asp.net core好像没有这些方法!
  • 在 mvc 1.1 中我需要:services.AddMvc(options =&gt; {options.RespectBrowserAcceptHeader = true;}).AddXmlSerializerFormatters().AddXmlDataContractSerializerFormatters(); 否则它总是会给我 json
【解决方案2】:

对于 Asp.Net Core 2.x,您基本上需要这 3 个东西才能返回 XML 响应:

Startup.cs:

services
    .AddMvcCore(options => options.OutputFormatters.Add(new XmlSerializerOutputFormatter())

CustomerController.cs:

using Microsoft.AspNetCore.Mvc;

namespace WebApplication
{
    [Route("api/[controller]")]
    public class CustomerController : ControllerBase
    {
        [HttpGet]
        public IActionResult Get()
        {
            var customer = new CustomerDto {Id = 1, Name = "John", Age = 45};
            return Ok(customer);
        }
    }
}

CustomerDto.cs:

namespace WebApplication
{
    public class CustomerDto
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public int Age { get; set; }
    }
}

然后在向请求中添加 Accept "application/xml" 标头后,将返回 XML 格式的结果。

我必须自己弄清楚的一个非常重要提示是,如果您的模型没有隐式的显式无参数构造函数,那么响应将被写为 json。给定以下示例

namespace WebApplication
{
    public class CustomerDto
    {
        public CustomerDto(int id, string name, int age)
        {
            Id = id;
            Name = name;
            Age = age;
        }

         public int Id { get; }
         public string Name { get; }
         public int Age { get; }
    }
}

它将返回 json。你应该在这个模型中添加

public CustomerDto()
{
}

这将再次返回 XML

【讨论】:

  • +1 用于无参数构造函数点,否则有人会花几个小时挠头想知道发生了什么!
  • 这不是基于提供的Accept 标头吗.. 我很确定 API 就是这样工作的..
  • 关于无参数构造函数:返回匿名对象时也是如此。当你这样做时,它总是会返回 JSON!
【解决方案3】:

对于 MVC 1.1,您需要添加 Package Microsoft.AspNetCore.Mvc.Formatters.Xml 并编辑您的 Startup.cs

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc(options => { options.RespectBrowserAcceptHeader = true; })
        .AddXmlSerializerFormatters()
        .AddXmlDataContractSeria‌​lizerFormatters();
}

现在您可以设置 Accept Header:

XML:application/xml

JSON:application/json

【讨论】:

    【解决方案4】:

    对于asp.net core 2.x,可以配置OutputFormatter

    您可以在 startup.cs 类的 ConfigureServices 方法中尝试以下代码片段。

    public void ConfigureServices(IServiceCollection services)
    {
         services.AddMvc(action =>
         {
             action.ReturnHttpNotAcceptable = true;
             action.OutputFormatters.Add(new XmlDataContractSerializerOutputFormatter());
         });
    
         //...
    }
    

    用于使用来自 nuget 的 Microsoft.AspNetCore.Mvc.Formatters 包的 XmlDataContractSerializerOutputFormatter 引用。

    现在它应该适用于 xmljson

    【讨论】:

      【解决方案5】:

      以下解决方案对我很有效。

      Startup.cs

      services.AddMvc()
             .AddXmlSerializerFormatters()
             .AddXmlDataContractSerializerFormatters();
      

      YourController.cs

          [HttpGet]
          [Route("Get")]
          [Produces("application/xml")] // If you don't like to send Content-Type header
          public IActionResult Get()
          {
              try
              {                
                  var user = _userManager.FindByNameAsync('user').Result;
                  if (user != null)
                  {
                      if (!_userManager.CheckPasswordAsync(user, 'password').Result)
                      {
                          return Unauthorized();
                      }
                      else
                      {
                          var result = _services.GetDataFromService(Convert.ToInt64(2), start_date, end_date);
                          return Ok(result);
                      }
                  }
                  else
                  {
                      return Unauthorized();
                  }
              }
              catch (Exception ex)
              {
                  return Unauthorized();
              }
          }
      

      【讨论】:

        【解决方案6】:

        对于 .net core 3.x,你可以像下面这样使用

        services.AddControllers(options=> {
                    options.OutputFormatters.RemoveType(typeof(SystemTextJsonOutputFormatter));
                    options.InputFormatters.RemoveType(typeof(SystemTextJsonInputFormatter));
                    options.ReturnHttpNotAcceptable = true;
                }).AddXmlSerializerFormatters();
        

        【讨论】:

          【解决方案7】:

          对于 Core 2.x 版本,您唯一需要做的就是在 Startup.cs 文件的 ConfigureServie 方法 中包含以下代码。 p>

          public void ConfigureServices(IServiceCollection services)
          {
              services.AddMvc()
                      .AddMvcOptions(o => o.OutputFormatters.Add(
                        new XmlDataContractSerializerOutputFormatter()));
          }
          

          您需要参考 Microsoft.AspNetCore.Mvc.Formatters

          【讨论】:

            【解决方案8】:

            对于 Core 2.x 版本,您必须做两件事。首先,您需要在 Startup.cs 文件的 ConfigureServices 方法中添加以下代码。

            services.AddMvc()
            .AddMvcOptions(o => o.OutputFormatters.Add(
                new XmlDataContractSerializerOutputFormatter())
            );
            

            然后在 Postman 上将 Accept "application/xml" 标头添加到请求中,如下所示。然后会返回 XML 格式的结果。

            【讨论】:

              猜你喜欢
              • 2015-08-17
              • 2019-12-17
              • 1970-01-01
              • 2021-05-17
              • 1970-01-01
              • 1970-01-01
              • 2013-01-14
              • 2017-09-08
              • 1970-01-01
              相关资源
              最近更新 更多