ASP.NET Response.Filter(ASP.NET Response.Filter)

2019-08-17 00:36发布

我需要创建过滤器,更换标记<h2>在HTML以<h3>

我的过滤器

public class TagsFilter:Stream
{
    HttpContext qwe;

    public TagsFilter(HttpContext myContext)
    {
        qwe = myContext;
    }

    public override void Write(byte[] buffer, int offset, int count)
    {
        string html = System.Text.Encoding.UTF8.GetString(buffer);
        html = html.Replace("<h2>", "<h3>");
        qwe.Response.Write(html.ToCharArray(), 0, html.ToCharArray().Length);
    }

我的模块

public class TagsChanger : IHttpModule
{
    public void Init(HttpApplication context)
    {
        context.Response.Filter = new TagsFilter(context.Context);
    }

我得到错误System.Web.HttpException:在这种情况下,答案是不可用的。

Answer 1:

看看里克施特拉尔的一篇关于“捕获和转化ASP.NET输出与Response.Filter” 。

Response.Filter内容分块 。 因此,要实现一个Response.Filter有效只是你实现自定义数据流和处理Write()方法来捕获响应输出,因为它的书面要求。 乍一看,这似乎很简单 - 你捕捉写输出,转换,并写出一通变换内容。 这确实适用于少量的内容。 但是你看,问题是输出是写在小缓冲区块(略小于16K出现的话),而不仅仅是一个单一的write()语句转换成流,这非常有意义的ASP.NET将数据传送回IIS较小的块以减少内存使用途中。

不幸的是,这也使得它更难以实现任何的过滤程序,因为你不能直接获得所有的响应内容的这是有问题的,特别是如果这些过滤程序要求你看看整个响应以改造或捕捉输出需要的解决方案在我的会议绅士问。

因此,为了解决这个问题稍微不同的方法,要求基本上捕获所有的写()传递到缓存流缓冲区,然后使可用的流很完整,并准备进行冲洗,只有当。

正如我在想实施我也开始思考少数情况下,我用Response.Filter实现。 每次我要创建一个新的流子类,并创建我的自定义功能,但最终每个实现做同样的事情 - 捕捉输出并将其转变。 我想应该是通过创建一个可重复使用的Stream类可以处理流的转换是常见的Response.Filter实现来做到这一点更简单的方法。

里克施特拉尔写自己的实现流过滤器的允许文本替换正确的方式。



Answer 2:

我做了一个小例子。 我认为你必须访问原始数据流 ,而不是访问的HttpContext。

public class ReplacementStream : Stream
{
    private Stream stream;
    private StreamWriter streamWriter;

    public ReplacementStream(Stream stm)
    {
        stream = stm;
        streamWriter = new StreamWriter(stream, System.Text.Encoding.UTF8);
    }
    public override void Write(byte[] buffer, int offset, int count)
    {
        string html = System.Text.Encoding.UTF8.GetString(buffer);
        html = html.Replace("<h2>", "<h3>");
        streamWriter.Write(html.ToCharArray(), 0, html.ToCharArray().Length);
        streamWriter.Flush();
    }

    // all other necessary overrides go here ...
}

public class FilterModule : IHttpModule
{
    public String ModuleName
    {
        // Verweis auf Name in Web.config bei Modul-Registrierung
        get { return "FilterModule"; }
    }
    void context_BeginRequest(object sender, EventArgs e)
    {
        HttpContext context = HttpContext.Current;
        context.Response.Filter = new ReplacementStream(context.Response.Filter);
    }
    public void Init(HttpApplication context)
    {
       context.BeginRequest += new EventHandler(context_BeginRequest);
    }
}

在找到解决这个职位上的SO。 为我工作。



Answer 3:

问题是,你是在Init事件,其中只有每个应用程序实例出现一次应用的过滤器(它基本上是接近App_Start)。

你需要做的是钩从Init事件BeginRequest事件,然后应用上的BeginRequest过滤器。

public void Init(HttpApplication application)
{
    application.BeginRequest += BeginRequest;
}

private void BeginRequest(object sender, EventArgs e)
{
    var app = (HttpApplication)sender;
    var context = app.Context;
    context.Response.Filter = new TagsFilter(context);
}


文章来源: ASP.NET Response.Filter