使用ConsumesAttribute时Request.ContentType为null的问题排查
问题与解决方案:ConsumesAttribute未拦截Content-Type为null的POST请求
问题背景
使用[Consumes]属性限制接口仅处理特定内容类型时,发现该属性不会将Content-Type为null的请求判定为非法。查看ASP.NET Core源码注释可知,无Content-Type的请求不会返回415状态码,这是为了兼容控制器标记[Consumes]同时包含GET动作的场景(GET请求通常无Content-Type)。但标记了[HttpPost]的接口仍收到了Content-Type为null的请求,比如通过以下代码发送的请求:
new HttpClient().PostAsync(url, new ByteArrayContent(new byte[] { 50, 51 }))
修正方案
1. 自定义过滤器实现严格校验
由于默认ConsumesAttribute的设计偏向兼容GET场景,可自定义ActionFilterAttribute,对POST/PUT/PATCH等带请求体的方法强制校验Content-Type:
public class StrictConsumesAttribute : ActionFilterAttribute { private readonly string[] _allowedContentTypes; public StrictConsumesAttribute(params string[] allowedContentTypes) { _allowedContentTypes = allowedContentTypes.Select(ct => ct.ToLowerInvariant()).ToArray(); } public override void OnActionExecuting(ActionExecutingContext context) { var request = context.HttpContext.Request; // 仅针对带请求体的HTTP方法执行校验 if (new[] { "POST", "PUT", "PATCH" }.Contains(request.Method)) { var contentType = request.ContentType?.ToLowerInvariant(); // 无Content-Type或不在允许列表中,返回415 if (string.IsNullOrEmpty(contentType) || !_allowedContentTypes.Contains(contentType)) { context.Result = new StatusCodeResult(StatusCodes.Status415UnsupportedMediaType); return; } } base.OnActionExecuting(context); } }
使用示例:
[HttpPost] [StrictConsumes("application/json", "application/xml")] public IActionResult SubmitData([FromBody] RequestModel model) { // 业务逻辑 return Ok(); }
2. 客户端显式设置Content-Type
如果请求由己方客户端发起,可直接为请求内容指定Content-Type:
var content = new ByteArrayContent(new byte[] { 50, 51 }); content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream"); // 替换为你需要的合法类型 await new HttpClient().PostAsync(url, content);
是否属于ASP.NET Core Bug?
这不属于Bug,而是设计权衡的结果:源码注释明确说明该行为是为了支持控制器级[Consumes]搭配GET动作的常见场景。但这种设计确实会导致带请求体的接口无法拦截无Content-Type的请求,你提交的Issue会让官方团队评估是否需要优化逻辑,比如区分GET和带请求体的方法进行差异化校验。
内容的提问来源于stack exchange,提问作者Yola
相关产品推荐
相关产品推荐

