.net core reads Response.Body
Demo of reading request body stream
public static async Task GetBodyForm(this HttpContext http)
{
var content = string.Empty;
var request = http.Request;
try
{
request.Body.Position = 0;
using var reader = new StreamReader(request.Body, Encoding.UTF8, leaveOpen: true);
var strRequestBody = await reader.ReadToEndAsync();
Console.WriteLine("ok");
Console.WriteLine(strRequestBody == null ? "null" : strRequestBody);
request.Body.Position = 0;
}
catch (Exception ex)
{
Console.WriteLine("err");
Console.WriteLine(ex);
}
return content;
}
Read Request.Body in ActionFilter
public class ActionFilterTestA : ActionFilterAttribute
{
public override async void OnActionExecuting(ActionExecutingContext context)
{
Console.WriteLine("From Request Body---->");
Console.WriteLine(await context.HttpContext.GetBodyForm());
Console.WriteLine("From Request Body---->");
}
}
An error is reported, usually NotSupportedException is reported at Request.Body
Solution
Call EnableBuffering()
in custom middleware
app.Use(async (context, next) =>
{
context.Request.EnableBuffering();
await next();
});
Question
(Remove the correct solution code above) Why does calling context.HttpContext.Request.EnableBuffering();
in ActionFilterTestA
have no effect? (No error is reported, but the content is an empty string)
Guess
The request body flow is consumed before the ActionFilter and after the custom middleware. Middleware execution sequence
Test
// Cancel model binding
builder.Services.Configure(options =>
{
options.SuppressInferBindingSourcesForParameters = true;
});
The content of Request.Body is printed successfully.
Inference
The request body stream will be consumed when binding the model.
Other information
https://markb.uk/asp-net-core-read-raw-request-body-as-string.html
Conclusion
It is recommended to call EnableBuffering
through middleware to solve the problem
Notes:
- To avoid closing the StreamReader causing the Stream to be closed, you can solve this problem by
leaveOpen: true
- Reset Position = 0