如何在asp.net核心webapi控制器中读取请求正文? [英] How to read request body in an asp.net core webapi controller?

查看:57
本文介绍了如何在asp.net核心webapi控制器中读取请求正文?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试通过 OnActionExecuting 方法读取请求正文,但对于该操作,我总是会得到 null

I'm trying to read the request body in the OnActionExecuting method, but I always get null for the body.

var request = context.HttpContext.Request;
var stream = new StreamReader(request.Body);
var body = stream.ReadToEnd();

我试图将流位置显式设置为0,但这也没有用。由于这是ASP.NET Core,因此我认为情况有所不同。我可以在这里看到所有有关旧版Web API版本的示例。

I have tried to explicitly set the stream position to 0, but that also didn't work. Since this is ASP.NET Core, things are a little different I think. I can see all the samples here referring to old web API versions.

还有其他方法吗?

推荐答案

在ASP.Net Core中,多次阅读正文请求似乎很复杂,但是,如果您的第一次尝试以正确的方式进行,那么接下来的尝试应该没问题。

In ASP.Net Core it seems complicated to read several times the body request, however if your first attempt does it the right way, you should be fine for the next attempts.

例如,我通过替换体流阅读了几种周转方法,但是我认为以下是最干净的方法:

I read several turnaround for example by substituting the body stream, but I think the following is the cleanest:

最重要的一点是


  1. ,让请求知道您将阅读其正文两次或多次,

  2. 不关闭主体流,并且

  3. 将其倒回其初始位置,这样内部过程就不会丢失。

正如Murad指出的那样,您还可以利用.Net Core 2.1扩展: EnableBuffering 它将大请求存储到磁盘上,而不是将其保留在内存中,从而避免了存储在内存中的大数据流问题(文件,图像等)。
您可以通过设置 ASPNETCORE_TEMP 环境变量来更改临时文件夹,并在请求结束后删除文件。

As pointed out by Murad, you may also take advantage of the .Net Core 2.1 extension: EnableBuffering It stores large requests onto the disk instead of keeping it in memory, avoiding large-streams issues stored in memory (files, images, ...). You can change the temporary folder by setting ASPNETCORE_TEMP environment variable, and files are deleted once the request is over.

在AuthorizationFilter 中,您可以执行以下操作:

In an AuthorizationFilter, you can do the following:

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

然后您就可以使用主体了再次在请求处理程序中。

Then you can use the body again in the request handler.

在您的情况下,如果得到的结果为空,则可能意味着该正文已在较早的阶段被读取。在这种情况下,您可能需要使用中间件(见下文)。

In your case if you get a null result, it probably means that the body has already been read at an earlier stage. In that case you may need to use a middleware (see below).

但是,如果要处理大数据流,则该行为意味着所有内容均已加载到内存中,

However be careful if you handle large streams, that behavior implies that everything is loaded into memory, this should not be triggered in case of a file upload.

我的看起来像这样(同样,如果您下载/上传大文件,应该禁用它以避免内存问题):

Mine looks like this (again, if you download/upload large files, this should be disabled to avoid memory issues):

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

}

这篇关于如何在asp.net核心webapi控制器中读取请求正文?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆