ASP.NET Core 6.0如何为空请求体禁用Content-Type验证
问题根因
该问题本质是ASP.NET Core框架两个逻辑的执行顺序差异导致的:
[FromBody(EmptyBodyBehavior = EmptyBodyBehavior.Allow)]的生效阶段是模型绑定执行期:只有当框架已经根据Content-Type选好了对应的输入格式化器、准备读取请求体做反序列化时,才会判断请求体是否为空,如果为空就直接绑定null,不抛错。- 缺失
Content-Type返回415的逻辑发生在更早的输入格式化器选择阶段:框架处理带[FromBody]的参数时,第一步就是根据请求头里的Content-Type匹配支持的格式化器(比如System.Text.Json格式化器匹配application/json),如果请求根本没带这个头,框架会直接判定没有可用的格式化器,立刻返回415响应,根本走不到后续判断请求体是否为空的步骤,配置的EmptyBodyBehavior自然不会生效。
从逻辑合理性来说:当请求体本身为空时,完全不需要执行反序列化逻辑,这个阶段强制校验Content-Type没有实际意义,属于框架默认逻辑没有覆盖到的边界场景。
可用解决方案
可根据业务场景选择对应的实现方案:
方案1:全局配置开关(最简单,适合全接口统一规则的场景)
.NET 6 已经内置了对应的全局配置开关,直接在Program.cs的MVC配置中开启即可:
var builder = WebApplication.CreateBuilder(args); builder.Services.AddControllers() .AddMvcOptions(options => { // 允许空请求体场景下缺失Content-Type头时不触发415响应 options.AllowEmptyInputInBodyModelBinding = true; }); // 后续中间件配置保持原有逻辑不变
这个配置开启后,框架在选择输入格式化器之前,会先判断请求体是否为空,如果为空就直接跳过格式化器选择和Content-Type校验,直接走空请求体绑定逻辑。
方案2:自定义高优先级空请求体格式化器(最精准,不影响非空请求体验证逻辑)
如果不想修改全局默认行为,只希望对真的为空的请求体跳过Content-Type校验,可以自定义一个优先级最高的输入格式化器,专门处理空请求体场景:
- 首先实现自定义格式化器:
using Microsoft.AspNetCore.Mvc.Formatters; public class NullEmptyBodyInputFormatter : IInputFormatter { public bool CanRead(InputFormatterContext context) { // 仅对内容长度为0的请求生效 var request = context.HttpContext.Request; return request.ContentLength == 0; } public async Task<InputFormatterResult> ReadAsync(InputFormatterContext context) { // 空请求体直接返回对应类型的默认值(引用类型返回null,值类型返回默认实例) var defaultValue = context.ModelType.IsValueType ? Activator.CreateInstance(context.ModelType) : null; return await InputFormatterResult.SuccessAsync(defaultValue); } }
- 把这个格式化器注册到输入格式化器集合的第一个位置(保证最高优先级):
builder.Services.AddControllers(options => { // 插入到集合首位,优先于所有内置格式化器执行 options.InputFormatters.Insert(0, new NullEmptyBodyInputFormatter()); });
这个方案的优势是完全不会改变非空请求的原有校验逻辑:只要请求体有内容,还是会严格校验Content-Type是否匹配,只有真的是空请求体的时候才会跳过校验,和预期逻辑完全一致。
不推荐的临时方案
也可以在单个接口上通过[Consumes]特性把空字符串加入允许的媒体类型列表,比如[Consumes("application/json", "")],但这种方式需要给每个允许空请求体的接口都加特性,维护成本高,而且会放开非空请求体不带Content-Type的校验,不建议使用。
内容的提问来源于stack exchange,提问作者Konstantin Smolyakov
相关产品推荐
相关产品推荐

