简体   繁体   English

如何使用 .net 4 api 端点从 Request.Content 对象获取原始请求正文

[英]How do I get the raw request body from the Request.Content object using .net 4 api endpoint

I'm trying to capture the raw request data for accountability and want to pull the request body content out of the Request object.我正在尝试捕获原始请求数据以进行问责,并希望从 Request 对象中提取请求正文内容。

I've seen suggestions doing a Request.InputStream, but this method is not available on the Request object.我已经看到建议执行 Request.InputStream,但此方法在 Request 对象上不可用。

Any idea of how to get a string representation of the Request.Content body?知道如何获取 Request.Content 正文的字符串表示吗?

观察变量

In your comment on @Kenneth's answer you're saying that ReadAsStringAsync() is returning empty string.在您对ReadAsStringAsync()的回答的评论中,您是说ReadAsStringAsync()返回空字符串。

That's because you (or something - like model binder) already read the content, so position of internal stream in Request.Content is on the end.那是因为您(或诸如模型绑定器之类的东西)已经阅读了内容,因此 Request.Content 中内部流的位置在末尾。

What you can do is this:你可以做的是:

public static string GetRequestBody()
{
    var bodyStream = new StreamReader(HttpContext.Current.Request.InputStream);
    bodyStream.BaseStream.Seek(0, SeekOrigin.Begin);
    var bodyText = bodyStream.ReadToEnd();
    return bodyText;
}

You can get the raw data by calling ReadAsStringAsAsync on the Request.Content property.您可以通过对Request.Content属性调用ReadAsStringAsAsync来获取原始数据。

string result = await Request.Content.ReadAsStringAsync();

There are various overloads if you want it in a byte or in a stream.如果您希望在字节或流中使用它,则有各种重载。 Since these are async-methods you need to make sure your controller is async:由于这些是异步方法,您需要确保您的控制器是异步的:

public async Task<IHttpActionResult> GetSomething()
{
    var rawMessage = await Request.Content.ReadAsStringAsync();
    // ...
    return Ok();
}

EDIT: if you're receiving an empty string from this method, it means something else has already read it.编辑:如果你从这个方法接收到一个空字符串,这意味着其他东西已经读取了它。 When it does that, it leaves the pointer at the end.当它这样做时,它将指针留在最后。 An alternative method of doing this is as follows:执行此操作的另一种方法如下:

public IHttpActionResult GetSomething()
{
    var reader = new StreamReader(Request.Body);
    reader.BaseStream.Seek(0, SeekOrigin.Begin); 
    var rawMessage = reader.ReadToEnd();

    return Ok();
}

In this case, your endpoint doesn't need to be async (unless you have other async-methods)在这种情况下,您的端点不需要是异步的(除非您有其他异步方法)

For other future users who do not want to make their controllers asynchronous, or cannot access the HttpContext, or are using dotnet core (this answer is the first I found on Google trying to do this), the following worked for me:对于不想让他们的控制器异步、或无法访问 HttpContext 或正在使用 dotnet 核心的其他未来用户(这个答案是我在 Google 上找到的第一个尝试这样做的答案),以下对我有用:

[HttpPut("{pathId}/{subPathId}"),
public IActionResult Put(int pathId, int subPathId, [FromBody] myViewModel viewModel)
{

    var body = new StreamReader(Request.Body);
    //The modelbinder has already read the stream and need to reset the stream index
    body.BaseStream.Seek(0, SeekOrigin.Begin); 
    var requestBody = body.ReadToEnd();
    //etc, we use this for an audit trail
}

If you need to both get the raw content from the request, but also need to use a bound model version of it in the controller, you will likely get this exception.如果您既需要从请求中获取原始内容,又需要在控制器中使用它的绑定模型版本,则可能会遇到此异常。

NotSupportedException: Specified method is not supported. 

For example, your controller might look like this, leaving you wondering why the solution above doesn't work for you:例如,您的控制器可能看起来像这样,让您想知道为什么上述解决方案对您不起作用:

public async Task<IActionResult> Index(WebhookRequest request)
{
    using var reader = new StreamReader(HttpContext.Request.Body);

    // this won't fix your string empty problems
    // because exception will be thrown
    reader.BaseStream.Seek(0, SeekOrigin.Begin); 
    var body = await reader.ReadToEndAsync();

    // Do stuff
}

You'll need to take your model binding out of the method parameters, and manually bind yourself:您需要将模型绑定从方法参数中取出,并手动绑定自己:

public async Task<IActionResult> Index()
{
    using var reader = new StreamReader(HttpContext.Request.Body);

    // You shouldn't need this line anymore.
    // reader.BaseStream.Seek(0, SeekOrigin.Begin);

    // You now have the body string raw
    var body = await reader.ReadToEndAsync();

    // As well as a bound model
    var request = JsonConvert.DeserializeObject<WebhookRequest>(body);
}

It's easy to forget this, and I've solved this issue before in the past, but just now had to relearn the solution.这个很容易忘记,这个问题我以前也解决过,只是现在不得不重新学习解决方法。 Hopefully my answer here will be a good reminder for myself...希望我在这里的回答对我自己是一个很好的提醒......

Here's this answer as an extension method:这是作为扩展方法的答案

using System.IO;
using System.Text;

namespace System.Web.Http
{
    public static class ApiControllerExtensions
    {
        public static string GetRequestBody(this ApiController controller)
        {
            using (var stream = new MemoryStream())
            {
                var context = (HttpContextBase)controller.Request.Properties["MS_HttpContext"];
                context.Request.InputStream.Seek(0, SeekOrigin.Begin);
                context.Request.InputStream.CopyTo(stream);
                var requestBody = Encoding.UTF8.GetString(stream.ToArray());
                return requestBody;
            }
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何使 .NET 4.8 中的 Request.Content 在.Net Core 中工作? 或者 Request.Body 从.Net Core 到 .NET 4.8? - How to make Request.Content from .NET 4.8 to work in .Net Core? Or Request.Body from .Net Core to .NET 4.8? 如何重定向Request.Content流 - How to redirect Request.Content stream asp.net 核心 1.0 mvc。 从 Request.Body 获取原始内容 - asp.net core 1.0 mvc. Get raw content from Request.Body 无法读取 ASP.NET WebApi 控制器中的 Request.Content - Cannot read Request.Content in ASP.NET WebApi controller 如何从 ASP.NET Web API ValueProvider 中的 HTTP POST 请求检索正文值? - How do I retrieve body values from an HTTP POST request in an ASP.NET Web API ValueProvider? 将Request.Content转换为FileStream C# - Converting Request.Content to FileStream C# 如何从 Azure API 管理中的请求正文获取原始日期时间值? - How to get raw datetime value from request body in Azure API Management? 如何从原始HTTP请求中提取正文? - How to extract body from a raw HTTP request? 我如何在ASP.NET Web API中记录原始HTTP请求,而不管它是否路由到控制器? - How do I log the raw HTTP request in ASP.NET Web API whether or not it routes to a controller? 我尝试 API 身体类型为 raw 的请求帖子来获取令牌,但需要了解问题所在 - I try API request post with body type raw to get a token but need understand what is wrong
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM