ContentType:application/json
一、net core2.1 、3.1
1、权限(AuthorizationFilters)验证器中读取并只读取有一次请求串的方法
- HttpRequest request = context.HttpContext.Request;
- // post请求方式获取请求参数,.net core 2.0 不支持.Form 直接获取
- Stream stream = request.Body;
- byte[] buffer = new byte[request.ContentLength.Value];
- stream.Read(buffer, 0, buffer.Length);
- string querystring = Encoding.UTF8.GetString(buffer);
2、当在动作过滤器(ActionFilter)或者需要多次读取 request.body 的时候,.net core 可以通过调用request.EnableRewind()实现,可以重置读取位置 ,但是要在权限验证器中添加
- ///
- /// 请求验证,当前验证部分不要抛出异常,ExceptionFilter不会处理
- ///
- /// 请求内容信息
- public void OnAuthorization(AuthorizationFilterContext context)
- {
- HttpRequest request = context.HttpContext.Request;
- request.EnableRewind();
- request.Body.Position = 0;
- }
3、在任意想要读取的位置重复读取
- if (context.HttpContext.Request.ContentType == "application/json")
- {
- Stream straem = context.HttpContext.Request.Body;
- Encoding encoding = Encoding.UTF8;
- string data = string.Empty;
- using (StreamReader reader = new StreamReader(straem, encoding))
- {
- //data就是post传过来的值json格式
- data = reader.ReadToEndAsync().Result;
- }
- }
- ///
- /// 根据请求信息返回请求串
- ///
- /// 请求信息
- ///
请求串 - public static string QueryString(HttpRequest request)
- {
- // post 请求方式获取请求参数方式
- if (request.Method.ToLower().Equals("post"))
- {
- try
- {
- // post请求方式获取请求参数,.net core 2.0 不支持.Form 直接获取
- Stream stream = request.Body;
- byte[] buffer = new byte[request.ContentLength.Value];
- stream.Read(buffer, 0, buffer.Length);
- string querystring = Encoding.UTF8.GetString(buffer);
- return querystring;
- }
- catch
- {
- return string.Empty;
- }
- }
- else
- {
- return request.QueryString.Value;
- }
- }
- public class OperateLogFilter : ActionFilterAttribute
- {
- private Stopwatch Stopwatch { get; set; }
-
- public override void OnActionExecuting(ActionExecutingContext context)
- {
- base.OnActionExecuting(context);
-
- Stopwatch = new Stopwatch();
- Stopwatch.Start();
- }
-
- public override void OnActionExecuted(ActionExecutedContext context)
- {
- base.OnActionExecuted(context);
- Stopwatch.Stop();
-
- string apiName = context.ActionDescriptor.DisplayName;
- double elapsed = Stopwatch.Elapsed.TotalMilliseconds;
-
- // 获取请求参数
- HttpRequest request = context.HttpContext.Request;
- //-- 由于mvc里已经读过request.Body,现在它的position在末尾
- // 允许重新读body
- request.EnableRewind();
- // 将position置到开始位置
- request.Body.Position = 0;
- // 读取body的数据流,并转为string
- var reader = new StreamReader(request.Body);
- var contentFromBody = reader.ReadToEnd();
- }
-
- }
二、net 5.0
由于.net 5.0 倒带方式发生了改变,在asp.net core web api 项目中,框架为.NET5,启动倒带方式,为 request.EnableBuffering()
但是在过滤器中使用此方法时出现异常,request.body的长度总是为0,说明在请求到达过滤器时Steam已经被读取了。
错误代码:
- public class TestFilter : ActionFilterAttribute
- {
- public override void OnActionExecuting(ActionExecutingContext context)
- {
- base.OnActionExecuting(context);
- var request = context.HttpContext.Request;
- //启动倒带方式
- request.EnableBuffering();
- if (request.Method.ToLower().Equals("post"))
- {
- request.Body.Position = 0;
- using var requestReader = new StreamReader(request.Body);
- var requestContent = requestReader.ReadToEnd();
- request.Body.Position = 0;
- }
-
- }
- public override void OnActionExecuted(ActionExecutedContext context)
- {
- base.OnActionExecuted(context);
- }
-
- }
解决方法:
1、在项目的Startup
类中的Configure
方法中添加如下配置:
- public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
- {
- //其他代码
-
- //启动倒带方式
- app.Use(next => context =>
- {
- context.Request.EnableBuffering();
- return next(context);
- });
-
- app.UseEndpoints(endpoints =>
- {
- endpoints.MapControllers();
- });
-
- }
-
注意:
EnableBuffering
的配置一定要在UseEndpoints
的前面;
2、修改过后滤器中的代码:
- public override void OnActionExecuting(ActionExecutingContext context)
- {
- base.OnActionExecuting(context);
- var request = context.HttpContext.Request;
-
- if (request.Method.ToLower().Equals("post"))
- {
- request.Body.Position = 0;
- using var requestReader = new StreamReader(request.Body);
- var requestContent = requestReader.ReadToEnd();
- request.Body.Position = 0;
- }
- }
三、Post Form和Get方法获取参数
- switch (context.HttpContext.Request.Method.ToUpper())
- {
- case "GET":
- operateEntity.ExecuteParam = context.HttpContext.Request.QueryString.Value.ParseToString();
- break;
-
- case "POST":
- Dictionary<string, string> param = new Dictionary<string, string>();
- foreach (var item in context.ActionDescriptor.Parameters)
- {
- var itemType = item.ParameterType;
- if (itemType.IsClass && itemType.Name != "String")
- {
- PropertyInfo[] infos = itemType.GetProperties();
- foreach (PropertyInfo info in infos)
- {
- if (info.CanRead)
- {
- var propertyValue = context.HttpContext.Request.Form[info.Name];
- if (!param.ContainsKey(info.Name))
- {
- if (!string.IsNullOrEmpty(propertyValue))
- {
- param.Add(info.Name, propertyValue);
- }
- }
- }
- }
- }
- }
- break;
- }