在过滤器中读取Response.Body流 [英] Reading the Response.Body stream in Filter
问题描述
我编写了一个在服务器方法调用后运行的过滤器,并将其内容打印到控制台.该代码是用ASP.NET core v2.1编写的:
I writing my filter that running after a sever method call and print its content to Console. The code is written in ASP.NET core v2.1:
public class MyCustomFilter : ActionFilterAttribute
{
public override void OnResultExecuted(ResultExecutedContext context)
{
// ERROR on the next line!
using (StreamReader sr = new StreamReader(context.HttpContext.Response.Body))
{
Console.WriteLine(sr.ReadToEnd());
}
base.OnResultExecuted(context);
}
}
结果-异常:
流不可读.
进一步的研究使我发现流( context.HttpContext.Response
)具有以下值:
Further investigation leads me to the point that the stream (context.HttpContext.Response
) has those values:
- CanRead = false
- CanSeek =假
这可以解释为什么它无法读取身体...
That can explain why it cant read the body...
如何解决?
推荐答案
不确定为什么需要这样做. context.Result
是 IActionResult
的一个实例,您可以根据需要对其进行操作.如果您确实想阅读 Response.Body
,则可以做一些骇人听闻的事情.
Not sure why you need to do this . context.Result
is an instance of IActionResult
, you can manipulate it as you like . If you do want to read the Response.Body
, there's something hacky can be done.
由于默认的 Response.Body
不是可读的 Stream
,为了使主体易于阅读,我们需要劫持响应,即替换 Body
和我们自己的 Stream
实例:
Since the default Response.Body
is not a readable Stream
, in order to make the body readable , we need to hijack the response , namely replace the Body
with our own instance of Stream
:
- 我们可以在执行动作之前动态创建一个全新的内存流,并劫持默认的
Response.Body
流. - 执行动作后,使用
StreamReader
读取流,进行一些工作,然后设置Response.Body =您的新流
.
- We can create a brand new memory stream dynamically before action is executing , and hijack the default
Response.Body
stream . - When action executed , read the stream using a
StreamReader
, do some work, and set theResponse.Body=your new stream
.
使用纯内存流劫持 Response.Body
是安全的,因为 Body
的类型是纯 Stream
.
It's safe to hijack the Response.Body
with a plain memory stream because the type of Body
is plain Stream
.
public class MyCustomFilter : ActionFilterAttribute
{
private MemoryStream responseBody ;
public override void OnActionExecuting(ActionExecutingContext context){
this.responseBody=new MemoryStream();
// hijack the real stream with our own memory stream
context.HttpContext.Response.Body = responseBody;
}
public override void OnResultExecuted(ResultExecutedContext context)
{
responseBody.Seek(0, SeekOrigin.Begin);
// read our own memory stream
using (StreamReader sr = new StreamReader(responseBody))
{
var actionResult= sr.ReadToEnd();
Console.WriteLine(actionResult);
// create new stream and assign it to body
// context.HttpContext.Response.Body = ;
}
// no ERROR on the next line!
base.OnResultExecuted(context);
}
}
出于测试目的,我创建了一个操作方法:
For a testing purpose , I create an action method :
[MyCustomFilter]
public IActionResult Index()
{
return Ok("it wooooooooorks");
}
这篇关于在过滤器中读取Response.Body流的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!