请求头为accept:application/xml时OData API仍返回JSON的问题排查
问题原因
配置和代码存在3处核心错误,导致XML响应无法正常返回:
- 重复调用
AddControllers()与AddMvc(),后者会覆盖前者注册的OData配置,你手动添加的XmlSerializerOutputFormatter注册在独立的AddMvc()链路中,不会被OData的内容协商逻辑识别,且OData默认注册的JSON格式化器优先级更高,会被优先匹配。 - 原生
XmlSerializerOutputFormatter不兼容OData的返回包装结构,默认不会纳入OData请求的输出格式化器候选列表。 - 控制器引入OData相关特性却未继承
ODataController基类,同时重复添加[FormatFilter]特性,会干扰Accept请求头驱动的内容协商流程。
修复步骤
1. 修正Program.cs服务注册
删除独立的AddMvc()调用,将XML格式化器注册、OData配置统一放在AddControllers()的构建链路下,推荐直接使用官方提供的XML格式化器扩展方法注册,避免手动添加的兼容性问题:
using Microsoft.AspNetCore.OData; var builder = WebApplication.CreateBuilder(args); // 其他原有业务配置... builder.Services.AddControllers() // 注册XML序列化格式化器,替代手动new XmlSerializerOutputFormatter的写法 .AddXmlSerializerFormatters() .AddOData(options => { options.Select().Filter().OrderBy().Expand().Count().SetMaxTop(100); }); // 后续中间件配置保持不变...
2. 调整控制器代码
- 将控制器基类从
ControllerBase改为ODataController,适配OData的格式化器匹配逻辑; - 删除控制器和Action上多余的
[FormatFilter]特性,该特性用于从路由参数识别响应格式,会覆盖Accept请求头的协商结果; - 确认
WeatherForecast模型类包含无参构造函数,所有需要序列化的属性都有公共get/set访问器,符合XML序列化的要求。
修正后的控制器代码:
using Microsoft.AspNetCore.OData.Query; using Microsoft.AspNetCore.OData.Routing.Controllers; namespace OData.Controllers { [Produces("application/json", "application/xml")] [ApiController] [Route("[controller]")] public class WeatherForecastController : ODataController { private static readonly string[] Summaries = new[] { "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" }; private readonly ILogger<WeatherForecastController> _logger; public WeatherForecastController(ILogger<WeatherForecastController> logger) { _logger = logger; } [HttpGet(Name = "GetWeatherForecast")] [EnableQuery] public IActionResult Get() { return Ok(Enumerable.Range(1, 5).Select(index => new WeatherForecast { Date = DateTime.Now.AddDays(index), TemperatureC = Random.Shared.Next(-20, 55), Summary = Summaries[Random.Shared.Next(Summaries.Length)] }) .ToArray()); } } }
3. 验证
修改完成后重启应用,发送带Accept: application/xml请求头的GET请求到WeatherForecast接口,即可返回XML格式响应。如果仍返回JSON,优先检查请求头是否被网关、反向代理中间件篡改,再确认XML格式化器是否被其他输出过滤逻辑拦截。
内容的提问来源于stack exchange,提问作者Noobie
相关产品推荐
相关产品推荐

