3

<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:In this context, the answer is not available が表示されます。

4

3 に答える 3

7

"Capturing and Transforming ASP.NET Output with Response.Filter"に関する Rick Strahl の投稿を参照してください。

Response.Filter コンテンツはチャンク化されています。したがって、Response.Filter を効果的に実装するために必要なのは、カスタム ストリームを実装し、Write() メソッドを処理して、書き込まれた Response 出力をキャプチャすることだけです。一見、これは非常に単純に思えます。Write で出力をキャプチャし、それを変換して、変換されたコンテンツを 1 つのパスで書き出すだけです。そして、それは確かに少量のコンテンツで機能します. しかし、問題は、出力が単一の Write() ステートメントではなく、小さなバッファー チャンク (16k 弱に見える) に書き込まれることです。これは、ASP.NET がデータをストリーミングして戻すのに最適です。 IIS を小さなチャンクに分割して、途中でメモリ使用量を最小限に抑えます。

残念なことに、これはまた、すべての応答コンテンツに直接アクセスできないため、フィルタリング ルーチンを実装することをより困難にします。これは、特にこれらのフィルタリング ルーチンが、変換またはキャプチャするために応答全体を確認する必要がある場合に問題となります。私のセッションで紳士が求めた解決策に必要な出力。

したがって、これに対処するには、キャッシュされたストリームに渡されたすべての Write() バッファーを基本的にキャプチャし、ストリームが完了してフラッシュする準備ができたときにのみストリームを使用できるようにする、少し異なるアプローチが必要です。

実装について考えていたときに、Response.Filter 実装を使用したいくつかのインスタンスについても考え始めました。毎回、新しい Stream サブクラスを作成してカスタム機能を作成する必要がありましたが、最終的には各実​​装で同じことを行い、出力をキャプチャして変換しました。Response.Filter 実装に共通するストリーム変換を処理できる再利用可能な Stream クラスを作成することで、これを行うためのより簡単な方法があるはずだと思いました。

Rick Strahl は、正しい方法でテキストを置換できる独自のストリーム フィルターの実装を作成しました。

于 2013-04-19T15:58:32.987 に答える
3

私は小さな例をしました。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のこの投稿で解決策を見つけました。私のために働いた。

于 2013-02-17T21:05:38.197 に答える