当前位置: 首页 > 知识库问答 >
问题:

如何在ASP.NET核心webapi控制器中读取请求正文?

唐俊英
2023-03-14
var request = context.HttpContext.Request;
var stream = new StreamReader(request.Body);
var body = stream.ReadToEnd();

共有1个答案

阎冠玉
2023-03-14

在ASP.NET核心中,多次读取正文请求似乎很复杂,但是,如果您的第一次尝试以正确的方式进行,那么下次尝试就可以了。

我读了几个翻转,例如通过替换正文流,但我认为以下是最干净的:

最重要的一点是

    null
// Helper to enable request stream rewinds
using Microsoft.AspNetCore.Http.Internal;
[...]
public class EnableBodyRewind : Attribute, IAuthorizationFilter
{
    public void OnAuthorization(AuthorizationFilterContext context)
    {
        var bodyStr = "";
        var req = context.HttpContext.Request;

        // Allows using several time the stream in ASP.Net Core
        req.EnableRewind(); 

        // Arguments: Stream, Encoding, detect encoding, buffer size 
        // AND, the most important: keep stream opened
        using (StreamReader reader 
                  = new StreamReader(req.Body, Encoding.UTF8, true, 1024, true))
        {
            bodyStr = reader.ReadToEnd();
        }

        // Rewind, so the core is not lost when it looks the body for the request
        req.Body.Position = 0;

        // Do whatever work with bodyStr here

    }
}



public class SomeController : Controller
{
    [HttpPost("MyRoute")]
    [EnableBodyRewind]
    public IActionResult SomeAction([FromBody]MyPostModel model )
    {
        // play the body string again
    }
}

然后可以在请求处理程序中再次使用正文。

在您的例子中,如果您得到一个空结果,这可能意味着主体已经在较早的阶段被读取。在这种情况下,您可能需要使用中间件(见下文)。

但是,如果处理大流,请小心,这种行为意味着所有内容都被加载到内存中,这在文件上传的情况下不应该触发。

public sealed class BodyRewindMiddleware
{
    private readonly RequestDelegate _next;

    public BodyRewindMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    public async Task Invoke(HttpContext context)
    {
        try { context.Request.EnableRewind(); } catch { }
        await _next(context);
        // context.Request.Body.Dipose() might be added to release memory, not tested
    }
}
public static class BodyRewindExtensions
{
    public static IApplicationBuilder EnableRequestBodyRewind(this IApplicationBuilder app)
    {
        if (app == null)
        {
            throw new ArgumentNullException(nameof(app));
        }

        return app.UseMiddleware<BodyRewindMiddleware>();
    }

}
 类似资料: