I am having a simple middleware which fetches the body of the request and store it in a string. It is reading fine the stream, but the issue is it wont call my controller which
Few things are crucial here:
public void UseMyMiddleware(IApplicationBuilder app)
{
app.Use(async (context, next) =>
{
context.Request.EnableBuffering();
using (var reader = new StreamReader(context.Request.Body, Encoding.UTF8, false, 1024, true))
{
var body = await reader.ReadToEndAsync();
context.Request.Body.Seek(0, SeekOrigin.Begin);
}
await next.Invoke();
});
}
using (var mem = new MemoryStream())
using (var reader = new StreamReader(mem))
{
Request.Body.CopyTo(mem);
var body = reader.ReadToEnd();
//and this you can reset the position of the stream.
mem.Seek(0, SeekOrigin.Begin);
body = reader.ReadToEnd();
}
Here you are can read how it works. https://gunnarpeipman.com/aspnet-core-request-body/
You need to convert HttpContext.Request.Body from a forward only memory stream to a seekable stream, shown below.
// Enable seeking
context.Request.EnableBuffering();
// Read the stream as text
var bodyAsText = await new System.IO.StreamReader(context.Request.Body).ReadToEndAsync();
// Set the position of the stream to 0 to enable rereading
context.Request.Body.Position = 0;
when it comes to capturing the body of an HTTP request and/or response, this is no trivial effort. In ASP .NET Core, the body is a stream – once you consume it (for logging, in this case), it’s gone, rendering the rest of the pipeline useless.
public async Task Invoke(HttpContext httpContext)
{
var timer = Stopwatch.StartNew();
string bodyAsText = await new StreamReader(httpContext.Request.Body).ReadToEndAsync();
var injectedRequestStream = new MemoryStream();
var bytesToWrite = Encoding.UTF8.GetBytes(bodyAsText);
injectedRequestStream.Write(bytesToWrite, 0, bytesToWrite.Length);
injectedRequestStream.Seek(0, SeekOrigin.Begin);
httpContext.Request.Body = injectedRequestStream;
await _next(httpContext);
timer.Stop();
}