最佳答案
我一直在努力从 ASP.NET Core 操作中获得 Response.Body
属性,我能够确定的唯一解决方案似乎是次优的。解决方案要求在将流读入字符串变量时用 MemoryStream
交换 Response.Body
,然后在发送到客户端之前将其交换回来。在下面的示例中,我试图在一个自定义中间件类中获取 Response.Body
值。出于某种原因,Response.Body
是 ASP.NET Core 中仅有的 准备好了属性?是我遗漏了什么,还是这是疏忽/错误/设计的问题?有没有更好的阅读 Response.Body
的方法?
当前(次优)解决方案:
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;
}
}
}
使用 EnableRewind ()尝试解决方案:
这只适用于 Request.Body
,不适用于 Response.Body
。这会导致从 Response.Body
读取空字符串,而不是实际的响应体内容。
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;
}
}