.NET 8 Web API读取请求体为空?求正确获取方法
ASP.NET Core 8.0 Web API读取请求体为空的解决方法
问题原因
当Action方法包含CreateResponseWADto类型的参数时,ASP.NET Core的模型绑定机制会优先读取请求体完成对象反序列化,此时请求体流的位置已经移到末尾。后续即使调用Request.EnableBuffering()和Request.Body.Position = 0,也无法读到内容——因为这两个操作是在模型绑定之后执行的,流已经被消费过。
解决方法
方法一:移除自动模型绑定,直接读取请求体
如果不需要自动将请求体映射到DTO,可以去掉Action参数,直接读取原始请求体:
[Authorize] [ApiController] [Route("api/[controller]/[action]")] public class StatusWAController : ControllerBase { private readonly ILogger<StatusWAController> _logger; private readonly IstatusMensajeWAService _statusMensajeWAService; public StatusWAController(ILogger<StatusWAController> logger, IstatusMensajeWAService statusMensajeWAService) { _logger = logger; _statusMensajeWAService = statusMensajeWAService; } [HttpPost(Name = "CreateResponseWA")] public async Task<IActionResult> CreateResponseWA() { _logger.LogWarning("Request started: "); Request.EnableBuffering(); Request.Body.Position = 0; using var reader = new StreamReader(Request.Body); var body = await reader.ReadToEndAsync(); _logger.LogWarning("Request finished: " + body); // 若需使用DTO,可手动反序列化 // var dto = JsonSerializer.Deserialize<CreateResponseWADto>(body); return Ok(body); } }
方法二:全局启用请求体缓冲,保留模型绑定
如果需要同时使用模型绑定和读取原始请求体,需在模型绑定前启用请求体缓冲。在Program.cs中添加中间件配置:
var builder = WebApplication.CreateBuilder(args); // 添加控制器服务 builder.Services.AddControllers(); var app = builder.Build(); // 启用请求体缓冲中间件(必须在MapControllers之前) app.Use(async (context, next) => { context.Request.EnableBuffering(); await next(); }); app.MapControllers(); app.Run();
修改后的Action代码:
[HttpPost(Name = "CreateResponseWA")] public async Task<IActionResult> CreateResponseWA(CreateResponseWADto createResponseWADto) { _logger.LogWarning("Request started: "); // 重置流位置到开头 Request.Body.Position = 0; using var reader = new StreamReader(Request.Body); var body = await reader.ReadToEndAsync(); _logger.LogWarning("Request finished: " + body); // 读完后重置流位置,避免影响后续中间件 Request.Body.Position = 0; return Ok(body); }
方法三:使用内置中间件简化操作
ASP.NET Core提供了HttpRequestRewindMiddleware,可以一键启用请求体缓冲并重置位置。在Program.cs中替换中间件:
// 替换之前的自定义缓冲中间件 app.UseRewind();
此时Action中无需额外调用EnableBuffering(),直接重置位置读取即可。
内容的提问来源于stack exchange,提问作者Andres Camacho
相关产品推荐
相关产品推荐

