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 param = new Dictionary();
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;
}