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

ASP.NET Core 3.1如何自定义HTTP 415状态码响应

问题成因
  • 你的中间件逻辑执行时机太晚,且没有拦截响应写入。ASP.NET Core管道按中间件注册顺序执行,你调用await next.Invoke()之后,后续的MVC/API格式化器、模型绑定组件已经检测到不支持的媒体类型,直接把默认的ProblemDetails格式415响应写入了响应流,这时候再调用WriteAsync就是在已有内容后面追加,自然会出现默认JSON和自定义文本拼接的结果。
  • 调用context.Response.Clear()无效是因为执行到这行代码时,响应已经开始向客户端发送(context.Response.HasStarted为true),此时响应头、部分响应体已经发到客户端,Clear方法只能清空服务器端还未发送的缓冲,没法撤回已经发送的内容,也无法覆盖已经写入的完整默认响应。
可行实现方案

方案1:纯中间件管道实现(符合优先修改请求管道的需求)

核心思路是在所有业务中间件执行前,用临时内存流替换原始响应流,拦截后续所有响应写入,等后续逻辑执行完再判断状态码,替换415的响应内容后再写回原始流。
注意:这个中间件必须注册在Configure方法里所有其他中间件的最前面,否则拦截不到后续中间件的响应写入。

public void Configure(IApplicationBuilder app)
{
    // 自定义415响应中间件,放在管道最开头
    app.Use(async (context, next) =>
    {
        // 保存原始响应流引用
        var originalResponseStream = context.Response.Body;
        // 创建临时内存流替换原始响应流,拦截后续写入
        using var tempStream = new MemoryStream();
        context.Response.Body = tempStream;

        await next();

        // 检测到415状态码时替换响应内容
        if (context.Response.StatusCode == StatusCodes.Status415UnsupportedMediaType)
        {
            // 清空临时流中已写入的默认响应
            tempStream.SetLength(0);
            // 重置响应头,避免和默认的ProblemDetails头冲突
            context.Response.ContentType = "text/plain; charset=utf-8";
            context.Response.ContentLength = null;
            // 写入自定义内容
            await context.Response.WriteAsync("Unsupported media type handled");
        }

        // 将最终的响应内容拷贝回原始流,返回给客户端
        tempStream.Seek(0, SeekOrigin.Begin);
        await tempStream.CopyToAsync(originalResponseStream);
        context.Response.Body = originalResponseStream;
    });

    // 后续注册其他中间件,比如app.UseRouting()、app.UseEndpoints()等
    // app.UseRouting();
    // app.UseEndpoints(endpoints => endpoints.MapControllers());
}

方案2:配置API行为选项(更轻量的官方推荐方案)

如果不需要强制用纯中间件实现,可以直接在服务配置阶段替换API内置的415响应生成逻辑,不需要拦截所有请求的响应流,性能更好。
在Startup.cs的ConfigureServices方法中添加如下配置:

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllers()
        .ConfigureApiBehaviorOptions(options =>
        {
            // 自定义415响应生成规则
            options.UnsupportedMediaTypeTypeResolver = context =>
            {
                // 可按需替换为JSON格式等其他自定义响应
                return new ContentResult
                {
                    StatusCode = StatusCodes.Status415UnsupportedMediaType,
                    Content = "Unsupported media type handled",
                    ContentType = "text/plain; charset=utf-8"
                };
            };
        });
}
注意事项
  • 所有对响应状态码、响应头、响应体的修改,必须在context.Response.HasStarted为false时执行,一旦响应开始发送,任何修改都不会生效。
  • 中间件的注册顺序直接决定执行顺序,处理响应的逻辑如果要修改后续中间件生成的内容,必须提前注册并拦截响应流。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.02 00:03:49