如何从HttpActionContext获取Content-Type以兼容多格式请求体的端点授权
获取请求Content-Type的正确路径
你之前觉得“无法预先获取Content-Type”的核心误区,是把Content-Type和请求体内容绑定在了一起。实际上Content-Type是HTTP请求头附带的元数据,和请求体的解析完全独立,在HttpActionContext初始化完成、还未读取请求体时就已经可以直接访问,读取路径为:actionContext.Request.Content.Headers.ContentType?.MediaType
该属性会直接返回字符串形式的MIME标识,常见值对应:
application/json:JSON格式请求体application/x-www-form-urlencoded:URL编码表单请求体- 空值:请求未声明Content-Type(通常对应无请求体的GET请求)
双格式兼容的授权逻辑改造
原有代码的核心问题是硬将所有请求体按JSON格式反序列化,碰到URL编码表单的纯键值对文本时自然会触发解析异常。改造时可以基于拿到的Content-Type分支处理不同格式的参数提取逻辑,保留原有授权判断流程不变。
改造后的可运行代码如下:
public override void OnAuthorization(HttpActionContext actionContext) { var request = actionContext.Request; try { // 直接读取请求头中的Content-Type,无需提前解析请求体 var contentType = request.Content.Headers.ContentType?.MediaType; string siteId = null; if (contentType == "application/json") { // 保留原有JSON解析逻辑 var rawJson = request.Content.ReadAsStringAsync().Result; var jsonResult = Newtonsoft.Json.JsonConvert.DeserializeObject<dynamic>(rawJson); siteId = jsonResult["siteID"]?.ToString(); } else if (contentType == "application/x-www-form-urlencoded") { // 表单编码格式解析,使用内置方法避免手动拆分的兼容问题 var formData = request.Content.ReadAsFormDataAsync().Result; siteId = formData["siteID"]; } else { // 不支持的格式直接返回415错误 actionContext.Response = request.CreateResponse(HttpStatusCode.UnsupportedMediaType, "当前接口仅支持JSON或表单编码格式的请求"); return; } // 空参数校验 if (string.IsNullOrWhiteSpace(siteId)) { actionContext.Response = request.CreateResponse(HttpStatusCode.BadRequest, "请求缺少必填参数siteID"); return; } // 保留原有站点权限校验逻辑 actionContext.Response = UserWorker.UserValidation(siteId, request) as HttpResponseMessage; } catch (Exception e) { actionContext.Response = request.CreateResponse(HttpStatusCode.BadRequest, e.Message); } }
关键避坑点
- 避免流读取冲突:授权层读取请求体后,底层请求流默认会停在读取完成的位置,后续管道中的动作方法模型绑定将无法读取到请求内容。可以在应用启动时配置
request.Content.LoadIntoBufferAsync()提前将请求体缓存到内存,实现流的可重复读取。 - 不要手动解析表单字符串:手动拆分
&和=的方式无法正确处理URL转义的特殊字符(比如带空格、中文、特殊符号的siteID值),直接使用内置的ReadAsFormDataAsync方法可以完整兼容RFC规范的表单编码格式。 - 做好空引用防护:读取
ContentType属性时必须加?.空判断,否则碰到无请求体的请求时会直接触发空引用异常,导致管道中断。
内容的提问来源于stack exchange,提问作者Katie P
相关产品推荐
相关产品推荐

