Swashbuckle.AspNetCore使用[FromForm]时未生成nullable:true问题
问题描述
使用Swashbuckle.AspNetCore 6.4.0时,通过[FromForm]指定multipart/form-data请求类型后,DTO中标记为可选的属性(如string?、可选IFormFile)在生成的Swagger规范里不会带上"nullable": true标记,导致客户端代码生成器传入null时抛出异常。而改用[FromBody](application/json)时,可选属性会正确生成该标记。选择multipart/form-data是因为需要在DTO中上传文件,相比base64编码字节数组更合适。
示例代码
DTO定义
public class TestDTO { public string? SomeProp { get; set; } }
控制器代码
[ApiController] [Route("api/[controller]/[action]")] public class TestController : Controller { [HttpPost] public IActionResult Test([FromForm] TestDTO dto) { return this.Ok(dto); } }
生成的Swagger差异
使用[FromForm]时的Swagger片段
"/api/Test/Test": { "post": { "tags": [ "Test" ], "requestBody": { "content": { "multipart/form-data": { "schema": { "type": "object", "properties": { "SomeProp": { "type": "string" } } }, "encoding": { "SomeProp": { "style": "form" } } } } }, "responses": { "200": { "description": "Success" } } } }
SomeProp未包含"nullable": true标记。
使用[FromBody]时的Swagger片段
接口定义:
"/api/Test/Test": { "post": { "tags": [ "Test" ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TourificService.Endpoints.Admin.Controllers.TestDTO" } } } }, "responses": { "200": { "description": "Success" } } } }
对应的组件定义:
"TourificService.Endpoints.Admin.Controllers.TestDTO": { "type": "object", "properties": { "someProp": { "type": "string", "nullable": true } }, "additionalProperties": false }
someProp正确带有"nullable": true标记。
临时解决方案(不推荐)
手动在Swagger JSON中为可选属性添加"nullable": true后再传给客户端代码生成器,但该方式需要手动干预,违背自动代码生成的初衷。
可行解决方案
方案1:自定义Schema过滤器
创建一个Schema过滤器,识别[FromForm]绑定的DTO属性,为可空类型自动添加nullable: true标记:
public class FormDataNullableSchemaFilter : ISchemaFilter { public void Apply(OpenApiSchema schema, SchemaFilterContext context) { // 判断当前类型是否为FromForm绑定的DTO var isFromFormDto = context.ApiModel.ParameterDescriptions.Any(p => p.BindingInfo?.BinderType == typeof(FormFileModelBinder) || p.BindingInfo?.BindingSource == BindingSource.Form); if (!isFromFormDto) return; foreach (var property in schema.Properties) { var propertyInfo = context.Type.GetProperty(property.Key, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance); if (propertyInfo == null) continue; // 检查属性是否为可空值类型或可空引用类型 var isNullable = Nullable.GetUnderlyingType(propertyInfo.PropertyType) != null || (propertyInfo.PropertyType.IsReferenceType && Attribute.IsDefined(propertyInfo, typeof(NullableAttribute))); if (isNullable) { property.Value.Nullable = true; } } } }
在Swagger配置中注册该过滤器:
services.AddSwaggerGen(c => { c.SchemaFilter<FormDataNullableSchemaFilter>(); // 其他Swagger配置 });
方案2:升级Swashbuckle.AspNetCore版本
该问题在Swashbuckle.AspNetCore 6.5.0及以上版本中已被修复,升级到最新稳定版本后,[FromForm]绑定的DTO可空属性会自动生成"nullable": true标记。
内容的提问来源于stack exchange,提问作者spectacularbob
相关产品推荐
相关产品推荐

