I've been struggling to get the Response.Body
property from an ASP.NET Core action and the only solution I've been able to identify seems sub-optimal. The solution requires swapping out Response.Body
with a MemoryStream
while reading the stream into a string variable, then swapping it back before sending to the client. In the examples below, I'm trying to get the Response.Body
value in a custom middleware class. Response.Body
is a set only property in ASP.NET Core for some reason? Am I just missing something here, or is this an oversight/bug/design issue? Is there a better way to read Response.Body
?
Current (sub-optimal) solution:
public class MyMiddleWare
{
private readonly RequestDelegate _next;
public MyMiddleWare(RequestDelegate next)
{
_next = next;
}
public async Task Invoke(HttpContext context)
{
using (var swapStream = new MemoryStream())
{
var originalResponseBody = context.Response.Body;
context.Response.Body = swapStream;
await _next(context);
swapStream.Seek(0, SeekOrigin.Begin);
string responseBody = new StreamReader(swapStream).ReadToEnd();
swapStream.Seek(0, SeekOrigin.Begin);
await swapStream.CopyToAsync(originalResponseBody);
context.Response.Body = originalResponseBody;
}
}
}
Attempted solution using EnableRewind():
This only works for Request.Body
, not Response.Body
. This results in reading an empty string from Response.Body
rather than the actual response body contents.
Startup.cs
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, IApplicationLifetime appLifeTime)
{
loggerFactory.AddConsole(Configuration.GetSection("Logging"));
loggerFactory.AddDebug();
app.Use(async (context, next) => {
context.Request.EnableRewind();
await next();
});
app.UseMyMiddleWare();
app.UseMvc();
// Dispose of Autofac container on application stop
appLifeTime.ApplicationStopped.Register(() => this.ApplicationContainer.Dispose());
}
MyMiddleWare.cs
public class MyMiddleWare
{
private readonly RequestDelegate _next;
public MyMiddleWare(RequestDelegate next)
{
_next = next;
}
public async Task Invoke(HttpContext context)
{
await _next(context);
string responseBody = new StreamReader(context.Request.Body).ReadToEnd(); //responseBody is ""
context.Request.Body.Position = 0;
}
}