.net core 验证器(filter)读取post请求参数

本文介绍如何在.NET Core中解决权限验证器与动作过滤器中读取HTTP请求体的问题,包括一次性读取及多次读取的方法。针对.post请求方式获取参数时,由于.NET Core 2.0不支持直接通过.Form获取,文中提供了通过读取流的方式获取请求参数的解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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()实现,可以重置读取位置 ,但是要在权限验证器中添加,

  /// <summary>
        ///  请求验证,当前验证部分不要抛出异常,ExceptionFilter不会处理
        /// </summary>
        /// <param name="context">请求内容信息</param>
        public void OnAuthorization(AuthorizationFilterContext context)
        {
            HttpRequest request = context.HttpContext.Request;
            request.EnableRewind();
            request.Body.Position = 0;
        }

然后可以在任意想要读取的位置重复读取

     /// <summary>
        ///  根据请求信息返回请求串
        /// </summary>
        /// <param name="request">请求信息</param>
        /// <returns>请求串</returns>
        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;
            }
        }

<think>我们正在讨论如何在ASP.NETCore中从HttpContext读取POST请求body数据。根据引用中的信息,我们知道在ASP.NETCore中,请求体(Request.Body)是一个流(Stream),默认情况下只能被读取一次。如果不进行缓存(使用EnableBuffering),那么在读取后流的位置会指向末尾,无法再次读取,这可能导致在后续的模型绑定(ModelBinding)中出现问题。根据引用[1]、[2]和[3],我们可以采用以下步骤来读取POST请求body数据:1.首先,调用`HttpContext.Request.EnableBuffering()`方法。这个方法将允许请求体被多次读取,因为它将请求体缓冲到一个可以重新读取的流中。2.然后,我们可以通过`HttpContext.Request.Body`属性获取流,并使用`StreamReader`来读取流中的内容。3.读取完成后,需要将流的位置重置为0,即`HttpContext.Request.Body.Position=0`或者使用`Seek(0,SeekOrigin.Begin)`,这样后续的中间件或模型绑定就可以重新读取流。特别需要注意的是,引用[1]和[3]中展示了读取请求体的代码示例,并且都使用了`EnableBuffering`来启用缓冲。引用[3]还展示了读取两次请求体的方法,验证了启用缓冲后可以多次读取。另外,引用[4]展示的是在过滤器中读取POST请求体的代码,其中也使用了重置流位置的方法。下面,我将给出一个标准的读取POST请求体数据的代码示例(基于ASP.NETCore):```csharppublicasyncTask<string>GetRequestBodyAsync(HttpContexthttpContext){//启用缓冲以便多次读取httpContext.Request.EnableBuffering();//获取请求体流varrequestBodyStream=httpContext.Request.Body;//设置流位置为开始以便读取requestBodyStream.Seek(0,SeekOrigin.Begin);//使用StreamReader读取流using(varstreamReader=newStreamReader(requestBodyStream,Encoding.UTF8,leaveOpen:true)){varrequestBody=awaitstreamReader.ReadToEndAsync();//将流位置重置为开始,以便后续中间件或模型绑定读取requestBodyStream.Seek(0,SeekOrigin.Begin);returnrequestBody;}}```注意:上面的方法可以在中间件、过滤器中调用。在读取请求体之后,一定要重置流的位置,否则后续读取将无法获取到数据。另外,如果只是读取一次并希望不影响后续操作,也可以使用`EnableBuffering`然后读取,然后重置位置。最后,需要注意的是,在ASP.NETCore中,如果请求体较大,启用缓冲可能会带来一些性能开销,因此请确保只在需要的时候使用。相关引用:[^1][^2][^3][^4]§§相关问题§§1.在ASP.NETCore中,为什么需要启用缓冲(EnableBuffering)来读取请求体?2.除了启用缓冲,还有其他方法可以多次读取请求体吗?3.读取请求体时,如何避免内存泄漏?4.在ASP.NETCore中,读取请求体时有哪些注意事项?</think> 在 ASP.NET Core读取 POST 请求body 数据时,由于请求流默认只能读取一次,需要特殊处理来正确获取数据。以下是完整解决方案: ### 标准读取方法 (中间件/控制器) ```csharp public async Task<string> ReadRequestBody(HttpRequest request) { // 启用缓冲允许多次读取[^1][^2] request.EnableBuffering(); // 读取流内容[^3] request.Body.Seek(0, SeekOrigin.Begin); using (var reader = new StreamReader( request.Body, Encoding.UTF8, leaveOpen: true)) // 保持流开放[^4] { string body = await reader.ReadToEndAsync(); request.Body.Seek(0, SeekOrigin.Begin); // 重置流位置 return body; } } ``` ### 关键要点 1. **必须启用缓冲** `EnableBuffering()` 允许重复读取请求体[^2],否则: - 流只能读取一次 - 后续模型绑定会失败[^2] 2. **流位置重置** 读取后必须调用 `Seek(0, SeekOrigin.Begin)` 将流指针重置到起始位置[^3][^4],否则: - 后续中间件获取到请求体 - 模型绑定异常 3. **异步操作建议** - 使用 `ReadToEndAsync()` 而非同步方法[^1] - 避免阻塞线程(特别在高并发场景) ### 不同场景实现 #### 在控制器中: ```csharp [HttpPost] public IActionResult PostData() { Request.EnableBuffering(); using (var reader = new StreamReader(Request.Body)) { var body = reader.ReadToEnd(); Request.Body.Seek(0, SeekOrigin.Begin); // 处理body数据 } } ``` #### 在过滤器中 (Action Filter): ```csharp public override async Task OnActionExecutionAsync( ActionExecutingContext context, ActionExecutionDelegate next) { context.HttpContext.Request.EnableBuffering(); using (var reader = new StreamReader( context.HttpContext.Request.Body, Encoding.UTF8)) { var body = await reader.ReadToEndAsync(); context.HttpContext.Request.Body.Seek(0, SeekOrigin.Begin); // 记录/验证body数据 } await next(); } ``` ### 最佳实践 1. **最大尺寸限制** ```csharp services.Configure<KestrelServerOptions>(options => { options.Limits.MaxRequestBodySize = 100_000_000; // 100MB }); ``` 2. **内存优化** 大文件建议使用 `IFormFile` 或流式处理,避免全量加载到内存 3. **异常处理** ```csharp if (!Request.Body.CanRead) throw new InvalidOperationException("不可读的请求流"); ``` > **重要提示**:当请求包含 `Content-Type: multipart/form-data` 时,需使用 `Request.Form.Files` 处理文件上传,直接读取Body会损坏文件数据[^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值