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

能否在ASP.NET Core(Swashbuckle)中按HTTP状态码设置响应Content-Type?含OpenAPI3.0场景

ASP.NET Core 3.0 + Swashbuckle: Implementing application/json for Success, application/problem+json for 400 Errors

Great question—let’s break this down clearly, since this is a common scenario that doesn’t work out of the box as you’ve noticed.

First: Confirmation on "Out of the Box" Support

You’re absolutely right: ASP.NET Core 3.0 and Swashbuckle.AspNetCore (versions compatible with 3.0, typically 5.x) do NOT support this scenario natively.

By default:

  • Swashbuckle generates uniform response content types for most status codes (often including both application/json and plain text variants)
  • While ASP.NET Core’s ProblemDetails returns application/problem+json by default for validation errors, Swagger docs won’t automatically distinguish this from success responses or restrict the 400 response to only that media type.

Systemized Implementation Solution

Here’s a complete, maintainable way to set this up:

1. Configure ASP.NET Core to Return application/problem+json for 400 Errors

First, ensure your API properly sets the correct Content-Type when returning validation errors. Use ApiBehaviorOptions to override the default invalid model state response:

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.ModelBinding;

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllers()
        .ConfigureApiBehaviorOptions(options =>
        {
            options.InvalidModelStateResponseFactory = context =>
            {
                var validationProblem = new ValidationProblemDetails(context.ModelState)
                {
                    Type = "https://tools.ietf.org/html/rfc7231#section-6.5.1",
                    Title = "Validation Failed",
                    Status = StatusCodes.Status400BadRequest,
                    Detail = "Check the errors field for specific issues.",
                    Instance = context.HttpContext.Request.Path
                };
                // Add a trace ID for debugging (optional but useful)
                validationProblem.Extensions.Add("traceId", context.HttpContext.TraceIdentifier);

                // Explicitly set the Content-Type to application/problem+json
                return new BadRequestObjectResult(validationProblem)
                {
                    ContentTypes = { "application/problem+json" }
                };
            };
        });
}

This ensures any 400 from model validation returns the correct media type.

2. Customize Swashbuckle to Update OpenAPI Docs

Next, create a custom IOperationFilter to modify the Swagger document:

  • Remove default 400 response definitions
  • Add a 400 response that only includes application/problem+json
  • Ensure success responses only show application/json
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.SwaggerGen;
using System.Linq;

public class ProblemDetailsOperationFilter : IOperationFilter
{
    public void Apply(OpenApiOperation operation, OperationFilterContext context)
    {
        // Clean up existing 400 response if present
        if (operation.Responses.ContainsKey("400"))
        {
            operation.Responses.Remove("400");
        }

        // Generate schema for ProblemDetails
        var problemSchema = context.SchemaGenerator.GenerateSchema(typeof(ProblemDetails), context.SchemaRepository);

        // Add custom 400 response with application/problem+json only
        operation.Responses.Add("400", new OpenApiResponse
        {
            Description = "Validation Error",
            Content = new Dictionary<string, OpenApiMediaType>
            {
                ["application/problem+json"] = new OpenApiMediaType
                {
                    Schema = problemSchema
                }
            }
        });

        // Ensure success responses only use application/json
        foreach (var (statusCode, response) in operation.Responses.Where(r => r.Key != "400"))
        {
            // Remove unwanted media types (like text/plain)
            var unwantedContentTypes = response.Content.Keys.Where(ct => ct != "application/json").ToList();
            foreach (var ct in unwantedContentTypes)
            {
                response.Content.Remove(ct);
            }

            // If no application/json exists, add it with the existing schema
            if (!response.Content.ContainsKey("application/json") && response.Content.Any())
            {
                response.Content.Add("application/json", response.Content.Values.First());
            }
        }
    }
}

Register this filter in your Swagger setup:

public void ConfigureServices(IServiceCollection services)
{
    // ... other services ...

    services.AddSwaggerGen(c =>
    {
        c.SwaggerDoc("v1", new OpenApiInfo { Title = "Your API", Version = "v1" });
        // Register the custom filter
        c.OperationFilter<ProblemDetailsOperationFilter>();

        // Optional: Explicitly define the ProblemDetails schema for consistency
        c.MapType<ProblemDetails>(() => new OpenApiSchema
        {
            Type = "object",
            Properties = new Dictionary<string, OpenApiSchema>
            {
                ["type"] = new OpenApiSchema { Type = "string" },
                ["title"] = new OpenApiSchema { Type = "string" },
                ["status"] = new OpenApiSchema { Type = "integer", Format = "int32" },
                ["detail"] = new OpenApiSchema { Type = "string" },
                ["instance"] = new OpenApiSchema { Type = "string" },
                ["traceId"] = new OpenApiSchema { Type = "string" }
            }
        });
    });
}

3. Test and Validate

  • Run your API and trigger a 400 error (e.g., submit invalid model data) — check the response headers to confirm Content-Type: application/problem+json
  • Open the Swagger UI: Verify that 400 responses only show application/problem+json, while success responses (200, 201, etc.) only list application/json

OpenAPI 3.0 Specification Support

Your hunch is correct: this is fully supported in OpenAPI 3.0. The spec explicitly allows defining different media types per response status code.

In the generated OpenAPI document, the structure will look like this:

responses:
  '200':
    description: Success
    content:
      application/json:
        schema:
          $ref: '#/components/schemas/YourSuccessModel'
  '400':
    description: Validation Error
    content:
      application/problem+json:
        schema:
          $ref: '#/components/schemas/ProblemDetails'

This aligns perfectly with your requirement, and our implementation ensures Swashbuckle generates exactly this structure.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 08:28:19