1

IIS 7 HttpModule を開発しました。私の目標は、特定のタグの応答コンテンツを確認することです。タグが見つかった場合、何かがログに記録されます。

この目標を達成するために、カスタマイズした ASP NET 応答フィルターを開発しました。このフィルターは、.NET Stream クラスを拡張します。

フィルタは、OnPreRequestHandlerExecute(Object source, EventArgs e) イベントに登録されます。

HTTP モジュールが正しく登録されました。フィルターは機能しています。問題は、ページを更新すると、Write the Write(byte[] buffer, int offset, int count) メソッドが期待どおりに呼び出されることですが、バイトをデコードするときの内容はグチャグチャです。

最初に応答バイトが正しくデコードされたのに、2 回目の要求 (つまり、ページの更新) の後では正しくデコードされない理由がわかりません。以下は、フィルターが設定されているコードと、フィルターのライター メソッドのコードです。私はすでに3日間、デバッグ、Googleでの調査を行っていましたが、まだ喜びがありませんでした。

public void OnPreRequestHandlerExecute(Object source, EventArgs e)
{

    HttpResponse response = HttpContext.Current.Response;
    if (response.ContentType == "text/html")
    {
        response.ContentEncoding = Encoding.UTF8; //forcing encoding UTF8
        response.Charset = "charset=utf-8";
        Encoding encoding = response.ContentEncoding;
        string encodingName = encoding.EncodingName;
        response.Filter = new MyFilter(response.Filter, response.ContentEncoding);
    }
}

    public override void Write(byte[] buffer, int offset, int count)
    {
        string strBuffer = string.Empty;

        try
        {
            strBuffer = Encoding.UTF8.GetString(buffer);
        }
        catch (EncoderFallbackException ex)
        {
            log(ex.Message);
        }


        // buffer doesn't contain the HTML end tag so we keep storing the 
        //incoming chunck of data

        if (!strBuffer.Contains("</html>"))
        {
            log(strBuffer.ToString() );
            _responseHtml.Append(strBuffer);

        }
        //the strbuffer contains the HTLM end tag ; we wrap it up now
  else
        {
            _responseHtml.Append(strBuffer); //append last chunck of data
            string finalHtml = _responseHtml.ToString();


               byte[] bytesBuffer = Encoding.UTF8.GetBytes(finalHtml);
                outputStream.Write(bytesBuffer, 0, bytesBuffer.Length);
            }

        }

    }

これは、応答バイトをデコードした後、htmlページが2回目に呼び出されたとき(つまり、ブラウザで更新したとき)に得られるものです

?\b\0\0\0\0\0\0?yw??/????Og??V.\ak?t:JhY??xP,u?I?Y? \"?\0???w?|?W???\0R?M?Y??I7E{?]??_}???z??8K??!?5O?8???? ??k?^?~k\?u????f?lE?????s=i??gqY%??O????<9x???BKuZg?a???4? Fq???KJ?t??8??????????$e\?E?,?

更新します。

初めてのタイマーなので、これを更新する方法がわかりません。そのため、問題を絞り込む/修正するために行ったことを入れています。

まず第一に、やはりノー・ジョイ。:-(

これは私がしたことです:

  1. Write メソッドは ASP NET によって複数回呼び出される可能性があるため、ASP NET によって Write メソッドが呼び出されるたびに、バイトをコレクションに格納してコレクションに追加します。

p

ublic override void Write(byte[] buffer, int offset, int count)
                {

                        for (int i = 0; i < count; i++)
                        {
                            bytesList.Add(buffer[i]);
                        }
                        log("Write was called "+ "number of bytes: "+ bytesList.Count + " - " + count);
                }
  1. フラッシュ メソッドでは、収集されたすべてのバイトに対して何らかの処理を行うメソッドを呼び出します。

    public override void Flush() { byte[] bytesContent = ProcessResponseContent(bytesList); outputStream.Write(bytesContent, 0, bytesContent.Length); outputStream.Flush(); }

    public override void Write(byte[] buffer, int offset, int count) {

            for (int i = 0; i < count; i++)
            {
                bytesList.Add(buffer[i]);
            }
            log("Write was called " + "number of bytes: " + bytesList.Count + " -" + count);
        }
    

    プライベートバイト[] ProcessResponseContent(List bytesList) {

           byte[] bytesArray = bytesList.ToArray();
            string html = string.Empty;
            byte[] encodedBytes = null;
    
            try
            {
                FilterEncoder encoder = new FilterEncoder();
                html = encoder.DecodeBytes(bytesArray.Length, bytesArray);
                encodedBytes = encoder.EncodeString(html);
                log("after encoding - encodedBytes" + encodedBytes.Length);
                log("after encoding - bytesArray" + bytesArray.Length);
            }
            catch (Exception ex)
            {
                log("exception ocurred " + ex.Message);
    

    …………
    }

ProcessResponseContent はダム メソッドです。バイトのリストをバイト配列に変換するだけです。このバイト配列は文字列にデコードされます。応答で送信されたすべてのバイトを bytesList (List ) に取得したため、問題は発生しません。

コードの目的はデコードされた文字列をファイルに記録することであるため、バイト配列はそのまま返されます。

        log("after decoding  " + html);

UTF8Encoding を作成したので、例外をキャッチしています。例外はファイルに記録されます。

HTML ページが初めて取得されたときに、コンテンツがファイルに記録されます。

ページを更新すると (Ctrl + F5)、例外がログに記録されます。

「例外が発生しました インデックス 0 のバイト [8B] を指定されたコード ページから Unicode に変換できません」

私の html ページのコンテンツは非常に小さいことに注意してください。すべての応答コンテンツが 1 つのチャンクで処理されます。

ページに初めてアクセスしたときの受信バイト数は 2805 です。これらのバイトが文字列にデコードされる直前。

ページが 2 回目に呼び出されたとき (Ctrl + F5)、受信されたバイト数は、デコードされる前でも 1436 です。

応答のバイト数が少ない理由はわかりません。これはデコード操作に影響を与えているのでしょうか。

これがすべて意味をなすことを願っています。不明な点があればお知らせください。私は長い間このコードを見てきました。

ありがとう、

4

1 に答える 1

0

これがすべての問題であるかどうかを判断するのは困難ですが、バッファ全体が有効であると仮定して、offsetとのcountパラメータを無視しています。Write

strBuffer = Encoding.UTF8.GetString(buffer);

また、これは文字の完全なセットであると想定しています。つまり、3 バイト文字のうち 2 バイトしか含まれていない可能性があります。呼び出し間で部分的に書き込まれた文字の状態を維持するために、 Encodercreated fromを使用して、ストリームをステートフルにする必要があります。Encoding.UTF8

また、1 回の呼び出しで の全体を取得できると想定していることにも注意してください。一方、1 回の呼び出しで取得し、次の呼び出しで</html>取得することもできます。ASP.NETが実際に最後に 1 回しか呼び出しを行わない可能性もありますが、おそらくそのようなことは想定すべきではありません。</html>

于 2012-06-02T08:10:05.303 に答える