c# - 使用 Controller 操作过滤器捕获 HTML 输出

标签 c# asp.net-mvc-2 stream controller action-filter

我在捕获 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;
        }
    }

我已经确定 StreamReader(stream).ReadToEnd() 返回一个空字符串,但我不知道为什么。

有什么办法解决这个问题吗?

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

最佳答案

我通过劫持 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);
    }
}

以上代码使用 HttpContext 来避免线程错误 - 请参阅 jaminto 的评论

private class RenderFilter : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        StringBuilder sb = new StringBuilder();
        StringWriter sw = new StringWriter(sb);
        HtmlTextWriter tw = new HtmlTextWriter(sw);
        HttpWriter output = (HttpWriter)filterContext.RequestContext.HttpContext.Response.Output;
        filterContext.HttpContext.Items["sb"] = sb;
        filterContext.HttpContext.Items["output"] = output;
        filterContext.RequestContext.HttpContext.Response.Output = tw;
    }

    public override void OnResultExecuted(ResultExecutedContext filterContext)
    {
        string response = filterContext.HttpContext.Items["sb"].ToString();
        //response processing
        ((HttpWriter)filterContext.HttpContext.Items["output"]).Write(response);
    }
}

关于c# - 使用 Controller 操作过滤器捕获 HTML 输出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7094742/

相关文章:

c# - 在 WPF 应用程序中使用 Silverlight 控件

c# - 取消不接受 CancellationToken 的异步操作的正确方法是什么?

templates - MVC 模板化助手 - DropDown

r - 将新数据 append 到 R 中的现有数据框 (RDS)

c# - 如果删除 *.exe.config 会发生什么?

c# - 为 .net 核心控制台应用程序创建签名和通知的 MacOS 安装程序

visual-studio - 在 IIS 6 上部署 Asp.Net MVC 2/C# 4.0 应用程序

c# - 无法使用 Moq 在 ASP.NET MVC Controller 中模拟方法调用

c++ - 将外部进程的输出通过管道传输到正在运行的 C++ 脚本中

java - Hibernate 4.2.2 从未知长度的输入流创建 blob