How to read request body multiple times in asp net core 2.2 middleware?

Alireza Yavari picture Alireza Yavari · Jan 30, 2019 · Viewed 8.2k times · Source

I tried this: Read request body twice and this: https://github.com/aspnet/Mvc/issues/4962 but did not work. I read request body like this:

app.Use(async (context, next) =>
{
    var requestBody = await ReadStream(context.Request.Body);
    var requestPath = context.Request.Path.ToString();
    //Do some thing

    await next.Invoke();

    var responseStatusCode = context.Response.StatusCode;
    //Do some other thing
});

private async Task<string> ReadStream(Stream stream)
{
    using (var streamReader = new StreamReader(stream))
    {
        var result = await streamReader.ReadToEndAsync();

        return result;
    }
}

In controller I get 'disposed object' or 'empty stream'.

Answer

Prateek Kumar Dalbehera picture Prateek Kumar Dalbehera · Mar 30, 2020

.netcore 3.1 version of @HoussamNasser's answer above. I have created a reusable function to read Request Body. Please note the change: HttpRequestRewindExtensions.EnableBuffering(request). EnableBuffering is now a part of HttpRequestRewindExtensions class.

public async Task<JObject> GetRequestBodyAsync(HttpRequest request)
    {
        JObject objRequestBody = new JObject();

        // IMPORTANT: Ensure the requestBody can be read multiple times.
        HttpRequestRewindExtensions.EnableBuffering(request);

        // IMPORTANT: Leave the body open so the next middleware can read it.
        using (StreamReader reader = new StreamReader(
            request.Body,
            Encoding.UTF8,
            detectEncodingFromByteOrderMarks: false,
            leaveOpen: true))
        {
            string strRequestBody = await reader.ReadToEndAsync();
            objRequestBody = SerializerExtensions.Deserialize<JObject>(strRequestBody);

            // IMPORTANT: Reset the request body stream position so the next middleware can read it
            request.Body.Position = 0;
        }

        return objRequestBody;
    }

This function will return a JObject which can used to read the properties of the Request Body object. SerializerExtensions is my custom extension for serializing & deserializing.

In the middleware, you can inject IHttpContextAccessor httpContextAccessor in the constructor. And then access the Request object like HttpRequest request = _httpContextAccessor.HttpContext.Request;. Finally, can call the reusable function like GetRequestBodyAsync(request)