Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Request body from is empty in .Net Core 3.0

Okay so I've been wracking my brain and cannot for the life of me understand why the exact same piece of code works perfectly in .Net Core 2.2 but returns an empty string in .Net Core 3.0.

The piece of code I am running is this:

public static async Task<string> GetRequestBodyAsync(this HttpRequest request,
                                                     Encoding encoding = null)
{
    if (encoding == null) encoding = Encoding.UTF8;
    var body = "";

    request.EnableBuffering();
    if (request.ContentLength == null || !(request.ContentLength > 0) || !request.Body.CanSeek) return body;

    request.Body.Seek(0, SeekOrigin.Begin);
    using (var reader = new StreamReader(request.Body, encoding, true, 1024, true))
        body = await reader.ReadToEndAsync();

    request.Body.Position = 0;
    return body;
}

And I call this extension as such:

var bodyContent = await Request.GetRequestBodyAsync();
var body = new MemoryStream(Encoding.UTF8.GetBytes(bodyContent));

In .Net Core 2.2 I get the body of the sent payload exactly as I want it, but in .Net Core 3.0 I get an empty string.

I am using the extension in my startup to add Newtonsoft to my project for .Net Core 3.0, but if I remove that it still doesn't work.

Any ideas what I might've done wrong?

like image 432
Lennart Hammarström Avatar asked Dec 04 '19 22:12

Lennart Hammarström


3 Answers

Add this middleware in the startup class:

app.Use((context, next) =>
{
    context.Request.EnableBuffering();
    return next();
});
like image 73
Gid Avatar answered Nov 10 '22 11:11

Gid


I actually figured it out, in the controller-method I read the body using [FromBody] so that the body was being read twice and not rewinded the first time.

public async Task<ActionResult<string>> PaymentRequestCallbackAsync(/*[FromBody] SecretModel model*/)
{
    var body = await Request.GetRequestBodyAsync();
    var stream = new MemoryStream(Encoding.UTF8.GetBytes(body));
    return body;
}

So remove the [FromBody] and it should work just fine.

like image 34
Lennart Hammarström Avatar answered Nov 10 '22 12:11

Lennart Hammarström


Here is another solution which will help

write a middleware

public class EnableRequestBodyBufferingMiddleware
        {
            private readonly RequestDelegate _next;

            public EnableRequestBodyBufferingMiddleware(RequestDelegate next) =>
                _next = next;

            public async Task InvokeAsync(HttpContext context)
            {
                context.Request.EnableBuffering();

                await _next(context);
            }
        }

Then configure this middleware

app.UseMiddleware<EnableRequestBodyBufferingMiddleware>();

Now you can easily ready the body without any problem

        Request.EnableBuffering();
        Request.Body.Seek(0, SeekOrigin.Begin);
        using (StreamReader stream = new StreamReader(Request.Body))
        {
            string body = await stream.ReadToEndAsync();
        }
like image 1
Muhammad Junaid Avatar answered Nov 10 '22 12:11

Muhammad Junaid