ASP.NET Core 各版本 中间件或过滤器中获取Post参数方法

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;
}

你可能感兴趣的:(.net,core,C#,WebApi,c#,.net,core,.net,5,Post,webapi)