C# .Net4.8下ActionFilterAttribute读取POST JSON数据异常如何解决
结论
你只需要修改API端代码即可,客户端提交JSON的代码本身没有语法错误。
问题原因
HttpContext.Current.Request.Params 集合只会自动解析 application/x-www-form-urlencoded 类型的表单提交参数,JSON格式的请求体存储在请求输入流中,不会被自动加载到Params集合,因此读取结果为空。
解决方案
方案一(优先推荐):直接读取Action参数
如果你的接口方法已经定义了对应接收JSON的参数,比如:
public IHttpActionResult Post([FromBody] string dataFromClient) { // 接口业务逻辑 }
可以直接在Filter中读取已经被框架解析好的Action参数,不需要自己处理请求流:
public class myFilter : ActionFilterAttribute { public string Feature { get; set; } public myFilter(string feature) { this.Feature = feature; } public override void OnActionExecuting(ActionExecutingContext filterContext) { string dataFromClient = string.Empty; if (filterContext.ActionParameters.ContainsKey("dataFromClient")) { dataFromClient = filterContext.ActionParameters["dataFromClient"]?.ToString() ?? string.Empty; } // 兼容原有表单提交场景 else if (HttpContext.Current.Request.Params["dataFromClient"] != null) { dataFromClient = HttpContext.Current.Request.Params["dataFromClient"]; } // 原有后续逻辑不变 } }
方案二:手动读取请求流
如果你的接口没有定义明确的接收参数,可以手动读取请求输入流获取JSON内容,注意要保留流的开启状态并重置流位置,避免后续接口逻辑无法读取请求内容:
using System.IO; using System.Text; using Newtonsoft.Json.Linq; // 需先通过Nuget安装Newtonsoft.Json public class myFilter : ActionFilterAttribute { public string Feature { get; set; } public myFilter(string feature) { this.Feature = feature; } public override void OnActionExecuting(ActionExecutingContext filterContext) { string dataFromClient = string.Empty; var request = HttpContext.Current.Request; // 兼容原有表单提交场景 if (request.Params["dataFromClient"] != null) { dataFromClient = request.Params["dataFromClient"]; } // 处理JSON格式请求 else if (request.ContentType.Contains("application/json")) { // 重置流位置 request.InputStream.Position = 0; // leaveOpen设为true避免读取完直接关闭流 using (var reader = new StreamReader(request.InputStream, Encoding.UTF8, true, 1024, leaveOpen: true)) { string jsonBody = reader.ReadToEnd(); // 根据实际JSON结构调整取值逻辑 // 情况1:提交的JSON本身就是纯字符串 dataFromClient = jsonBody; // 情况2:提交的JSON是{"dataFromClient":"xxx"}结构 // JObject jObj = JObject.Parse(jsonBody); // dataFromClient = jObj.Value<string>("dataFromClient") ?? string.Empty; // 再次重置流位置,供后续接口逻辑使用 request.InputStream.Position = 0; } } // 原有后续逻辑不变 } }
注意事项
两种方案都可以同时兼容原有的表单提交场景,不需要修改客户端已有的表单提交代码。
内容的提问来源于stack exchange,提问作者mulllhausen
相关产品推荐
相关产品推荐

