ASP.NET Response.Filter

寫 ASP.NET 有時候會想要在畫面輸出前一刻進行攔截,並換掉 html 中的特定字元。例如網站中有許多頁面都有 www.google.com.tw 的超連結,我希望在測試機上可以把連結換成 www.microsoft.com.tw ,但又不希望去動到 aspx。這個時候就可以利用 Response.Filter 來做這個事情。

Response.Filter 本身就是一個 Stream 物件,所以要做的事情很簡單,就是再用一個 Stream 把它包起來,然後在 Write 方法加工就行了。為求使用方便,可以再加上 HttpModule 來處理所有 text/html 的回應。

 

public class CatchText : IHttpModule {
    void IHttpModule.Dispose() { }

    void IHttpModule.Init(HttpApplication context) {
        //註冊事件,在 BeginRequest 的時候把 Response.Filter 換掉
        context.BeginRequest += (sender, e) => {
            context.Response.Filter =
                new CatchTextStream(context.Response.Filter);
        };
    }
}

public class CatchTextStream : Stream {
    private Stream output;
    public CatchTextStream(Stream s) {
        output = s;
    }
    public override bool CanRead { 
        get { return output.CanRead; } 
    }
    
    public override bool CanSeek { 
        get { return output.CanSeek; }
    }

    public override bool CanWrite { 
        get { return output.CanWrite; }
    }

    public override void Flush() {
        output.Flush();
    }

    public override long Length { 
        get { return output.Length; } 
    }

    public override long Position {
        get { return output.Position; }
        set { output.Position = value; }
    }

    public override int Read(byte[] buffer, int offset, int count) {
        return output.Read(buffer, offset, count);
    }

    public override long Seek(long offset, SeekOrigin origin) {
        return output.Seek(offset, origin);
    }

    public override void SetLength(long value) {
        output.SetLength(value);
    }

    public override void Write(byte[] buffer, int offset, int count) {
        StringComparison ignore = StringComparison.CurrentCultureIgnoreCase;
        if (HttpContext.Current != null){
            HttpContext context = HttpContext.Current;
            if (context.Response.ContentType.Equals("text/html", ignore)) {
                Encoding encoding = context.Response.ContentEncoding;

                //在這邊把 google 換成 microsoft
                string html = encoding.GetString(buffer, offset, count)
                    .Replace("google", "microsoft");
                byte[] bytes = encoding.GetBytes(html);
                output.Write(bytes, 0, bytes.Length);
            } else 
                output.Write(buffer, offset, count);
        }
    }
}

  整個程式就只有這樣,主要就是在 Write 方法裡面動點手腳而已,剩下的就是設定 web.config,把這個 HttpModule 掛上去。

<httpModules>
    <add name="CatchText1" type="CatchText"/>
</httpModules>

  接著就可以看到效果了

posted @ 2016-02-24 00:14  star丶清影  阅读(315)  评论(0编辑  收藏  举报