【问题标题】:How to get raw request body in ASP.NET?如何在 ASP.NET 中获取原始请求正文?
【发布时间】:2011-06-15 18:53:18
【问题描述】:

HttpApplication.BeginRequest 事件中,如何读取整个原始请求正文?当我尝试阅读它时,InputStream 的长度为 0,让我相信它可能已经被 ASP.NET 读取了。

我尝试像这样读取 InputStream:

using (StreamReader reader = new StreamReader(context.Request.InputStream))
{
    string text = reader.ReadToEnd();
}

但我得到的只是一个空字符串。我已将位置重置回 0,但是当然,一旦读取了流,它就永远消失了,所以这不起作用。最后,检查流的长度返回 0。

编辑:这是针对 POST 请求的。

【问题讨论】:

  • 你读的怎么样?
  • 如果我把它放在 Global.asax 的 Application_BeginRequest 方法中,你的代码就可以工作
  • 如果您将代码放入 Application_BeginRequest 并且您使用的是 .Net 4.5,请使用以下构造函数来保持流打开,以便 ASP.NET 可以在您之后读取它: StreamReader(request.InputStream, Encoding.UTF8 , 真, 1024, 真

标签: asp.net http


【解决方案1】:

请求对象未填充到 BeginRequest 事件中。您需要在事件生命周期的后期访问此对象,例如 Init、Load 或 PreRender。此外,您可能希望将输入流复制到内存流中,这样您就可以使用 seek:

protected void Page_Load(object sender, EventArgs e)
{
    MemoryStream memstream = new MemoryStream();
    Request.InputStream.CopyTo(memstream);
    memstream.Position = 0;
    using (StreamReader reader = new StreamReader(memstream))
    {
        string text = reader.ReadToEnd();
    }
}

【讨论】:

  • ASP.NET 的哪个版本?
【解决方案2】:

Pål's answer 是正确的,但也可以做得更短:

string req_txt;
using (StreamReader reader = new StreamReader(HttpContext.Current.Request.InputStream))
{
    req_txt = reader.ReadToEnd();
}

这是 .NET 4.6。

【讨论】:

  • 这将关闭当前编写的InputStream,这将在稍后在 ASP.NET 管道中引发异常。 Pal 的回答是通过复制来避免这个陷阱。如果您只是删除 using 语句,您的答案将有效。
【解决方案3】:

在 ASP.NET Core 2 中:

using (var reader = new StreamReader(HttpContext.Request.Body)) {
    var body = reader.ReadToEnd();
}

【讨论】:

    【解决方案4】:

    我有类似的要求来获取原始内容并遇到了同样的问题。我发现调用Seek(0, SeekOrigin.Begin) 解决了这个问题。

    这不是一个特别好的方法,因为它对底层基础架构的运行方式进行了假设,但它似乎有效。

    【讨论】:

    • ASP.NET 的哪个版本?
    【解决方案5】:

    InputStream的位置重置很重要。

    var memstream = new MemoryStream();
    Request.InputStream.CopyTo(memstream);
    Request.InputStream.Position = 0;
    using (StreamReader reader = new StreamReader(memstream)) {
        var text = reader.ReadToEnd();
        Debug.WriteLine(text);
    }
    

    【讨论】:

    • 如果我没记错的话,问题是您只能阅读InputStream ONCE。我想阅读它并允许正常处理继续进行。
    【解决方案6】:

    这是我最终做的:

    //Save the request content. (Unfortunately it can't be written to a stream directly.)
    context.Request.SaveAs(filePath, false);
    

    【讨论】:

    • 我在工作时没有在我的计算机上安装 VS,或者我会发布一个真正的答案,但是有一种方法可以将请求“正文”转换为字符串。您的 OP 中的代码不起作用,因为它使用的 InputStream 对于 HTTP GET 请求是空的(但对于 POSTS 不是空的)。一个 GET 请求实际上只有一个查询字符串和一些标头。
    • 感谢您的反对票(假设是您)。这是一个 POST 请求。我知道 GET 和 POST 之间的区别,谢谢。
    • 你不应该使用这种方法,随着请求数量的增加,过多的IO操作会给你带来麻烦。最后读取 Request.InputStream 并将 Position 设置为 0 即可。
    • @sahs - 你能推荐一个更好的选择吗?这种方法是最后的努力。
    • @JoshM。正如我所说的 Request.InputStream 就是答案。 StreamReader.ReadToEnd 应该给你字符串。如果是空字符串,则表示请求中没有“body”。
    猜你喜欢
    • 1970-01-01
    • 2016-01-27
    • 1970-01-01
    • 1970-01-01
    • 2017-08-14
    • 1970-01-01
    • 2017-07-25
    • 1970-01-01
    • 2016-04-24
    相关资源
    最近更新 更多