在过滤器中读取Response.Body流 [英] Reading the Response.Body stream in Filter

查看:174
本文介绍了在过滤器中读取Response.Body流的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我编写了一个在服务器方法调用后运行的过滤器,并将其内容打印到控制台.该代码是用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:

  1. CanRead = false
  2. 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 :

  1. 我们可以在执行动作之前动态创建一个全新的内存流,并劫持默认的 Response.Body 流.
  2. 执行动作后,使用 StreamReader 读取流,进行一些工作,然后设置 Response.Body =您的新流.
  1. We can create a brand new memory stream dynamically before action is executing , and hijack the default Response.Body stream .
  2. When action executed , read the stream using a StreamReader, do some work, and set the Response.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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆