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

.NET API中配置Swagger按ContentType展示不同模型类的方法

问题描述

我有一个.NET API项目,其中AddPet接口配置了[Consumes("multipart/form-data", "application/json")],并分别使用[FromForm] PetRequestInfo和[FromBody] PetJsonRequestInfo作为参数。但当前Swagger UI及生成的swagger.json文件中,无论请求ContentType是什么,仅展示PetJsonRequestInfo模型类。需要配置Swagger,使其根据请求ContentType(multipart/form-data和application/json)正确展示对应的模型类。

相关接口代码

public class PetRequestInfo
{
    // File upload specific to multipart/form-data
    public IFormFile PetImage { get; set; }
    // Common properties
    public string PetName { get; set; }
    public int PetAge { get; set; }
}

public class PetJsonRequestInfo
{
    // No file upload, JSON only
    // Common properties
    public string PetName { get; set; }
    public int PetAge { get; set; }
}

// POST: api/pets/add
[HttpPost("add")]
[Consumes("multipart/form-data", "application/json")]
public async Task<ActionResult<PetAdded>> AddPet([FromForm] PetRequestInfo petRequestInfo, [FromBody] PetJsonRequestInfo petJsonRequestInfo)
{
    // Validate inputs
    if (petRequestInfo == null || petJsonRequestInfo == null)
    {
        return BadRequest("Invalid request data.");
    }
    // logic will be here...
}

当前swagger.json异常片段

"/v1/Pet/add": {
    "post": {
        "summary": "Add a new pet.",
        "requestBody": {
            "description": "The pet request body.",
            "content": {
                "application/json": {
                    "schema": {
                        "$ref": "#/components/schemas/PetJsonRequestInfo"
                    }
                },
                "multipart/form-data": {
                    "schema": {
                        "$ref": "#/components/schemas/PetJsonRequestInfo"
                    }
                },
                "application/x-www-form-urlencoded": {
                    "schema": {
                        "$ref": "#/components/schemas/PetJsonRequestInfo"
                    }
                }
            }
        },
        "responses": {
            "201": {
                "description": "Created",
                "content": {
                    "application/json": {
                        "schema": {
                            "$ref": "#/components/schemas/PetAdded"
                        }
                    }
                }
            },
            "401": {
                "description": "Unauthorized",
                "content": {
                    "application/json": {
                        "schema": {
                            "$ref": "#/components/schemas/ErrorResult"
                        }
                    }
                }
            },
            "403": {
                "description": "Forbidden",
                "content": {
                    "application/json": {
                        "schema": {
                            "$ref": "#/components/schemas/ErrorResult"
                        }
                    }
                }
            }
        }
    }
}

期望的swagger.json片段

"requestBody": {
    "description": "The pet request body.",
    "content": {
        "application/json": {
            "schema": {
                "$ref": "#/components/schemas/PetJsonRequestInfo"
            }
        },
        "multipart/form-data": {
            "schema": {
                "$ref": "#/components/schemas/PetRequestInfo"
            }
        },
        "application/x-www-form-urlencoded": {
            "schema": {
                "$ref": "#/components/schemas/PetRequestInfo"
            }
        }
    }
}
解决方案

问题根源是Swagger默认会合并多个请求参数的模型,无法自动区分不同ContentType对应的参数。可以通过以下两种方式解决:

方式一:拆分接口(推荐)

将两种ContentType的请求拆分为独立接口,各自对应参数模型,Swagger会自动生成正确的文档:

// 处理application/json请求
[HttpPost("add/json")]
[Consumes("application/json")]
public async Task<ActionResult<PetAdded>> AddPetJson([FromBody] PetJsonRequestInfo petJsonRequestInfo)
{
    if (petJsonRequestInfo == null)
    {
        return BadRequest("Invalid request data.");
    }
    return await AddPetInternal(petJsonRequestInfo.PetName, petJsonRequestInfo.PetAge, null);
}

// 处理multipart/form-data请求
[HttpPost("add/form")]
[Consumes("multipart/form-data")]
public async Task<ActionResult<PetAdded>> AddPetForm([FromForm] PetRequestInfo petRequestInfo)
{
    if (petRequestInfo == null)
    {
        return BadRequest("Invalid request data.");
    }
    return await AddPetInternal(petRequestInfo.PetName, petRequestInfo.PetAge, petRequestInfo.PetImage);
}

// 内部共享业务逻辑
private async Task<ActionResult<PetAdded>> AddPetInternal(string petName, int petAge, IFormFile petImage)
{
    // 核心业务逻辑实现
    return CreatedAtAction(nameof(GetPet), new { id = 1 }, new PetAdded { Id = 1, Name = petName, Age = petAge });
}

方式二:自定义Swagger操作过滤器

如果不想拆分接口,可通过实现IOperationFilter手动修改Swagger文档的requestBody内容:

  1. 创建自定义过滤器类:
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.SwaggerGen;
using System.Linq;

public class RequestContentTypeFilter : IOperationFilter
{
    public void Apply(OpenApiOperation operation, OperationFilterContext context)
    {
        // 定位目标接口
        if (context.ApiDescription.ActionDescriptor.DisplayName.Contains("AddPet"))
        {
            // 生成两个模型的Schema引用
            var formSchema = context.SchemaGenerator.GenerateSchema(typeof(PetRequestInfo), context.SchemaRepository);
            var jsonSchema = context.SchemaGenerator.GenerateSchema(typeof(PetJsonRequestInfo), context.SchemaRepository);

            // 更新不同ContentType对应的Schema
            operation.RequestBody.Content["multipart/form-data"].Schema = formSchema;
            operation.RequestBody.Content["application/x-www-form-urlencoded"].Schema = formSchema;
            operation.RequestBody.Content["application/json"].Schema = jsonSchema;
        }
    }
}
  1. 在Program.cs中注册过滤器:
builder.Services.AddSwaggerGen(c =>
{
    c.OperationFilter<RequestContentTypeFilter>();
    // 其他Swagger配置项
});

注意:使用该方式时,需要调整原接口的参数校验逻辑(比如当请求为application/json时,petRequestInfo会为null,不能直接判断两个参数都不为null)。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 10:35:09