0

I am trying to read request body in ActionFilter but having some strange errors.

What I tried so far:

  1. Copying request body to memory stream
context.HttpContext.Request.Body.CopyTo(memoryStream) 

Throws an error that only async operations are supported.

  1. Copying request body to memory stream async
context.HttpContext.Request.Body.CopyToAsync(memoryStream).Wait()

Copies 0 bytes

  1. Using BodyReader:
context.HttpContext.Request.BodyReader.AsStream(true).CopyToAsync(requestBody).Wait();

throws ArgumentOutOfRange exception 'Specified argument was out of the range of valid values. (Parameter 'start')'

I am using .net core 3.1

st78
  • 8,028
  • 11
  • 49
  • 68
  • 1
    does this answer your question https://stackoverflow.com/questions/54442553/how-to-read-request-body-multiple-times-in-asp-net-core-2-2-middleware – Nonik Dec 01 '20 at 21:30
  • @Nonik None of that worked, but when I converted by code to MiddleWare instead of ActionFilter it worked – st78 Dec 02 '20 at 02:46

1 Answers1

0

I had to convert my code to MiddleWare which is able to deal with Body stream:

  1. MIddleware ccaptures request and put it to service.
  2. Action filter access service and decides what to do with it.

Here is a code of middleware

public class RequestReaderMiddleWare
{
    private readonly RequestDelegate _next;


    public RequestReaderMiddleWare(RequestDelegate next)
    {
        _next = next;
    }


    public virtual async Task Invoke(HttpContext context)
    {
        //replace and revert original request stream
        var requestBodyStream = new MemoryStream();
        var originalRequestBody = context.Request.Body;

        await context.Request.Body.CopyToAsync(requestBodyStream);
        requestBodyStream.Seek(0, SeekOrigin.Begin);

        var bodyContentService = context.RequestServices.GetService(typeof(BodyContentService))
            as BodyContentService;
        bodyContentService.Body = requestBodyStream.ToArray();
        
        requestBodyStream.Seek(0, SeekOrigin.Begin);
        context.Request.Body = requestBodyStream;

        await _next(context);

        context.Request.Body = originalRequestBody; //restore request body
    }
}

PS: You need to register it in startup:

app.UseMiddleware<RequestReaderMiddleWare>();
st78
  • 8,028
  • 11
  • 49
  • 68