为啥我的 ASP.Net Core Web API 控制器不返回 XML?

Posted

技术标签:

【中文标题】为啥我的 ASP.Net Core Web API 控制器不返回 XML?【英文标题】: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() 调用中。 【参考方案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 格式的结果。

【讨论】:

以上是关于为啥我的 ASP.Net Core Web API 控制器不返回 XML?的主要内容,如果未能解决你的问题,请参考以下文章

我正在将我的 asp.net web api 迁移到 asp.net core。 Cors 迁移

ASP.NET Core Web API DELETE 调用返回 405

ASP.NET Core Web API 身份验证

为啥我的 Asp.Net Core 日志中出现“不支持 POST 请求”?

带有 EF Core 更新实体的 ASP.Net 核心 Web Api 如何

如何在我的 ASP.NET Core Web API 中启用 BSON 序列化?