You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#如何从System.Mvc.Web.ActionExecutingContext获取全部请求体数据

问题描述
  • 现有POST接口仅定义long game单个入参,业务需求要求将用户提交的全部请求体内容存入日志,接口定义代码如下:
[HttpPost]
[LogAPIUser]
public async Task<JsonResult> GameDetail(long game)
  • 使用Postman发起请求调试时,在ActionExecutingContext中仅能获取到已定义的单个Action参数,无法拿到完整原始请求体
  • 相关截图:
    • Postman请求示例
    • ActionExecutingContext参数获取情况
问题原因

ASP.NET Core的模型绑定流程会在Action执行前读取请求体流完成参数映射,默认请求体流是不支持重复读取的,读取完成后流指针会停在末尾,因此后续在过滤器中直接读取会得到空内容,只能拿到已经绑定完成的Action参数对象。

实现步骤

1. 开启请求体缓冲支持

首先需要在请求管道中开启请求体缓冲,允许请求流被多次读取,配置位置要放在路由、授权等中间件之前:

// Program.cs 中配置
var builder = WebApplication.CreateBuilder(args);
// ... 其他服务配置
var app = builder.Build();

// 👇 加在这里,在所有用到请求体的中间件之前
app.Use(async (context, next) =>
{
    context.Request.EnableBuffering();
    await next();
});

// ... 后续中间件配置 app.UseRouting()、app.UseAuthorization() 等

2. 在日志过滤器中读取原始请求体

修改LogAPIUser过滤器的逻辑,读取请求体前先将流指针重置到起始位置,读取完成后再复位指针,避免影响后续模型绑定流程:

using System.Text;
using Microsoft.AspNetCore.Mvc.Filters;

public class LogAPIUserAttribute : Attribute, IAsyncActionFilter
{
    public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
    {
        var request = context.HttpContext.Request;
        // 仅处理带请求体的POST请求,可按需加PUT等其他方法
        if (request.Method == HttpMethods.Post)
        {
            // 重置流指针到起始位置
            request.Body.Position = 0;
            
            // 读取全部请求体内容,注意leaveOpen参数要设为true,不要释放请求流
            using var reader = new StreamReader(
                request.Body,
                Encoding.UTF8,
                detectEncodingFromByteOrderMarks: false,
                bufferSize: 1024,
                leaveOpen: true);
            string rawRequestBody = await reader.ReadToEndAsync();
            
            // 此处即可拿到完整原始请求体,执行日志存储逻辑
            // 例如:_logger.LogInformation("接口请求体:{Body}", rawRequestBody);
            
            // 读取完成后再次复位指针,保证后续模型绑定正常执行
            request.Body.Position = 0;
        }

        // 继续执行后续Action流程
        await next();
    }
}
注意事项
  • 如果接口涉及大文件上传场景,不建议直接读取全量请求体到内存,会额外占用服务器资源,普通JSON/表单类接口使用该方案无问题
  • 必须配置EnableBuffering(),否则直接设置request.Body.Position会抛出流不支持Seek的异常
  • 读取请求体时必须将StreamReader的leaveOpen参数设为true,否则请求流会被释放,导致后续模型绑定失败

内容的提问来源于stack exchange,提问作者Chmn

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 19:21:32