You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET6 Core Web API错误返回XML而非JSON的解决求助

解决.NET6 Core Web API 严格分离JSON/XML返回格式(含异常场景)

一、基础配置(保留双格式化器)

先确保Program.cs中已正确启用Newtonsoft JSON和XML序列化支持:

builder.Services.AddControllers()
    .AddNewtonsoftJson() // 启用Newtonsoft JSON处理
    .AddXmlSerializerFormatters(); // 启用XML序列化

二、给接口强制绑定输出格式

通过[Produces]特性为每个接口固定返回格式,同时用[Consumes]限制输入类型,确保接口职责严格分离:

JSON专用接口

[ApiController]
[Route("api")]
public class FormatController : ControllerBase
{
    // 仅接受JSON输入,强制返回JSON
    [HttpPost("json")]
    [Produces("application/json")]
    [Consumes("application/json")]
    public IActionResult JsonPost([FromBody] JsonRequestModel model)
    {
        // 业务逻辑示例
        return Ok(new { Result = "JSON请求处理完成" });
    }
}

XML专用接口

// 仅接受XML输入,强制返回XML
[HttpPost("xml")]
[Produces("application/xml")]
[Consumes("application/xml")]
public IActionResult XmlPost([FromBody] XmlRequestModel model)
{
    // 业务逻辑示例
    return Ok(new XmlResponseModel { Result = "XML请求处理完成" });
}

注意:XML序列化要求模型类必须有无参构造函数,属性需为公共可读写(可配合[XmlElement]等特性自定义序列化规则)。

三、处理异常/验证错误场景

默认情况下,输入格式错误(如提交无效JSON到api/json)会触发模型验证失败,此时.NET会遍历格式化器列表选择第一个匹配项,导致错误返回XML。需通过自定义过滤器强制按接口指定格式返回错误:

1. 自定义异常过滤器(处理未捕获异常)

public class FormatLockedExceptionFilter : IExceptionFilter
{
    private readonly ILogger<FormatLockedExceptionFilter> _logger;

    public FormatLockedExceptionFilter(ILogger<FormatLockedExceptionFilter> logger)
    {
        _logger = logger;
    }

    public void OnException(ExceptionContext context)
    {
        // 获取当前接口指定的输出格式
        var producesAttr = context.ActionDescriptor.EndpointMetadata
            .OfType<ProducesAttribute>()
            .FirstOrDefault();

        if (producesAttr?.ContentTypes.Any() == true)
        {
            var targetType = producesAttr.ContentTypes.First();
            // 构造统一错误响应
            context.Result = new ObjectResult(new 
            {
                ErrorMsg = context.Exception.Message,
                StatusCode = StatusCodes.Status500InternalServerError
            })
            {
                ContentTypes = new MediaTypeCollection { targetType },
                StatusCode = StatusCodes.Status500InternalServerError
            };
            context.ExceptionHandled = true;
        }
        _logger.LogError(context.Exception, "接口执行异常");
    }
}

2. 自定义模型验证过滤器(处理输入格式错误)

public class FormatLockedValidationFilter : IActionFilter
{
    public void OnActionExecuting(ActionExecutingContext context)
    {
        if (!context.ModelState.IsValid)
        {
            var producesAttr = context.ActionDescriptor.EndpointMetadata
                .OfType<ProducesAttribute>()
                .FirstOrDefault();

            if (producesAttr?.ContentTypes.Any() == true)
            {
                var targetType = producesAttr.ContentTypes.First();
                // 构造验证错误响应
                var errors = context.ModelState.Values
                    .SelectMany(v => v.Errors)
                    .Select(e => e.ErrorMessage);

                context.Result = new BadRequestObjectResult(new 
                {
                    ValidationErrors = errors,
                    StatusCode = StatusCodes.Status400BadRequest
                })
                {
                    ContentTypes = new MediaTypeCollection { targetType }
                };
            }
        }
    }

    public void OnActionExecuted(ActionExecutedContext context) { }
}

3. 注册过滤器到全局

在Program.cs的控制器配置中添加两个过滤器:

builder.Services.AddControllers(options =>
{
    options.Filters.Add<FormatLockedExceptionFilter>();
    options.Filters.Add<FormatLockedValidationFilter>();
})
.AddNewtonsoftJson()
.AddXmlSerializerFormatters();

四、验证效果

  • 向api/json提交无效JSON,返回的错误响应为application/json格式
  • 向api/xml提交无效XML,返回的错误响应为application/xml格式
  • 正常请求时,两个接口分别返回对应格式的响应

内容的提问来源于stack exchange,提问作者Paja

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 00:05:21