使用控制器动作过滤器捕获HTML输出

yoo*_*er8 7 c# controller stream action-filter asp.net-mvc-2

我在捕获HTML输出的动作上有以下过滤器,将其转换为字符串,执行一些操作以修改字符串,并返回带有新字符串的ContentResult.不幸的是,我一直以一个空字符串结束.

private class UpdateFilter : ActionFilterAttribute
    {
        private Stream stream;

        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            stream = filterContext.HttpContext.Response.Filter;
            stream = new MemoryStream();
            filterContext.HttpContext.Response.Filter = stream;
        }

        public override void OnResultExecuted(ResultExecutedContext filterContext)
        {
            StreamReader responsereader = new StreamReader(filterContext.HttpContext.Response.Filter);  //empty stream? why?
            responsereader.BaseStream.Position = 0;
            string response = responsereader.ReadToEnd();
            ContentResult contres = new ContentResult();
            contres.Content = response;
            filterContext.Result = contres;
        }
    }
Run Code Online (Sandbox Code Playgroud)

我已经确定了StreamReader(stream).ReadToEnd()返回一个空字符串,但我无法弄清楚原因.

任何想法如何解决这一问题?

编辑:我已经将OnActionExecuted更改为OnResultExecuted,现在在生成View之后调用它,但是流仍然是空的!

yoo*_*er8 11

我通过劫持HttpWriter并将其写入一个StringBuilder而不是响应来解决这个问题,然后在将其写入输出之前对响应做任何需要做的事情.

 private class UpdateFilter : ActionFilterAttribute
    {
        private HtmlTextWriter tw;
        private StringWriter sw;
        private StringBuilder sb;
        private HttpWriter output;

        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            sb = new StringBuilder();
            sw = new StringWriter(sb);
            tw = new HtmlTextWriter(sw);
            output = (HttpWriter)filterContext.RequestContext.HttpContext.Response.Output;
            filterContext.RequestContext.HttpContext.Response.Output = tw;
        }

        public override void OnResultExecuted(ResultExecutedContext filterContext)
        {
            string response = sb.ToString();
            //response processing
            output.Write(response);
        }
    }
Run Code Online (Sandbox Code Playgroud)

  • 警告:不建议在操作过滤器中使用实例变量.您不能保证在每个请求上获得ActionFilterAttribute的新实例.我根据这个答案编写了我的代码,并且当它以每秒数千个请求进入生产时遇到了麻烦 - 电线(线程)越来越多了.将实例变量存储在filterContext.HttpContext.Items中,如本文所述:http://stackoverflow.com/a/8937793/140449 (13认同)