C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

ログ内検索
  • キーワードを複数指定する場合は 半角スペース で区切ってください。
  • 検索条件は、(AND)=[A かつ B] (OR)=[A または B] となっています。
  • [返信]をクリックすると返信ページへ移動します。
キーワード/ 検索条件 /
検索範囲/ 強調表示/ ON (自動リンクOFF)
結果表示件数/ 記事No検索/ ON
大文字と小文字を区別する

No.87867 の関連記事表示

<< 0 >>
■87867  ASPもしくはIISでhttpレスポンスボディを確認する方法
□投稿者/ abc -(2018/07/09(Mon) 08:54:45)

    分類:[ASP.NET (C#)] 

    環境
    IIS 8
    ASP.NET 3.5 C#

    自サイトがユーザに対して返すhttpレスポンスボディをログとして保存したく、ASP側で取得したいのですが方法が分かりません。
    今試しているのは、IHttpModuleを実装したwebmoduleを作り、Application_EndRequest()辺りで取得できないかやっていますが、なかなか上手くいきません。

    掲示板の主旨とは違いますが、もしIIS側でログ化できるならそれが一番いいのですが……
    ご存知の方いらっしゃいましたらご教授頂きたくお願い致します。
親記事 /過去ログ151より / 関連記事表示
削除チェック/

■87868  Re[1]: ASPもしくはIISでhttpレスポンスボディを確認する方法
□投稿者/ WebSurfer -(2018/07/09(Mon) 10:21:29)
記事No.87867 のレス /過去ログ151より / 関連記事表示
削除チェック/

■87869  Re[1]: ASPもしくはIISでhttpレスポンスボディを確認する方法
□投稿者/ WebSurfer -(2018/07/09(Mon) 12:35:26)
    No87867 (abc さん) に返信

    上のレスで「未検証・未確認ですが」と書きましたが、紹介した記事にあるように HttpResponse.Filter
    プロパティを利用して応答のコンテンツを取得できることは確認できました。お試しください。
記事No.87867 のレス /過去ログ151より / 関連記事表示
削除チェック/

■87870  Re[2]: ASPもしくはIISでhttpレスポンスボディを確認する方法
□投稿者/ abc -(2018/07/09(Mon) 13:45:53)
    No87869 (WebSurfer さん) に返信
    ご確認までして頂きありがとうございます。
    現状報告としまして、レスポンスボデイが取得できることは確認できましたが実装で引っ掛かっている状態です。
    
    ・ウェブページは正常に表示されるが、ログ上ではobject movedとなってしまい、以降記録されない
    ・今の方法だとアプリケーションプールが統合モードでしか動かないが、クラシックモードで実現したい(できれば)
    
    ■ログ
    [Request]2018/07/09 13:26:10:
    http://localhost:8888/hoge.aspx
    [Response]2018/07/09 13:26:13:
    (意図する正常なhtml)
    [Request]2018/07/09 13:26:17:
    http://localhost:8888/hoge.aspx
    [Response]2018/07/09 13:26:17:
    <h tml><h ead><t itle>Object moved</t itle></h ead><b ody>
    <h 2>Object moved to <a h ref="hoge.aspx">here</ a>.</h 2>
    </b ody></html>
    [Request]2018/07/09 13:26:17:
    http://localhost:8888/hoge.aspx
    [Response]2018/07/09 13:26:17:
    (以降記録されず……)
    
    ■ソース
    ※OutputFilterStreamはご紹介頂いた下記URLのものをコピペしています。
    https://stackoverflow.com/questions/1038466/logging-raw-http-request-response-in-asp-net-mvc-iis7#
    
    public class Logger : IHttpModule
        {
         static readonly string responseLogPath = @"D:\test.txt";
         OutputFilterStream filter;
    
         public void Init(HttpApplication application)
         {
             application.BeginRequest += (new EventHandler(this.Application_BeginRequest));
             application.EndRequest += (new EventHandler(this.Application_EndRequest));
         }
    
         public void Dispose()
         {
         }
    
         private void Application_BeginRequest(Object sender, EventArgs e)
         {
             HttpResponse response = HttpContext.Current.Response;
             WriteLog("[Request]" + DateTime.Now + ":" + Environment.NewLine + HttpContext.Current.Request.Url.ToString());
    
             filter = new OutputFilterStream(response.Filter);
             response.Filter = filter;
         }
    
         private void Application_EndRequest(object sender, EventArgs e)
         {
             WriteLog("[Response]" + DateTime.Now + ":" + Environment.NewLine + filter.ReadStream());
         }
    
         private void WriteLog(string log)
         {
             using (var sw = new StreamWriter(responseLogPath, true))
             {
                 sw.WriteLine(log);
             }
         }
    }
    
    
記事No.87867 のレス /過去ログ151より / 関連記事表示
削除チェック/

■87871  Re[3]: ASPもしくはIISでhttpレスポンスボディを確認する方法
□投稿者/ WebSurfer -(2018/07/09(Mon) 14:41:12)
    No87870 (abc さん) に返信

    > ・ウェブページは正常に表示されるが、ログ上ではobject movedとなってしまい、以降記録されない

    紹介した記事には、

    "Store filter where you can get to it in the EndRequest handler. I suggest in
    HttpContext.Items. There can then get the full response data in
    filter.ReadStream()."

    と HttpContext.Items を使うように書いてありましたが、質問者さんのコードではそう
    なっていないようです。

    質問者さんのケースでそこが原因かどうかは分かりませんが、少なくとも自分の環境では
    紹介した記事の通りにしてログは取れます。


    > ・今の方法だとアプリケーションプールが統合モードでしか動かないが、クラシックモードで実現したい(できれば)

    自分的には IIS のクラシックモードはすでに忘却の彼方にあって、クラシックモードの話に
    立ち入る元気はないです。

    お役に立てずすみませんが、他の方の回答をお待ちください。
記事No.87867 のレス /過去ログ151より / 関連記事表示
削除チェック/

■87872  Re[4]: ASPもしくはIISでhttpレスポンスボディを確認する方法
□投稿者/ abc -(2018/07/09(Mon) 17:55:44)
    No87871 (WebSurfer さん) に返信
    ご返信ありがとうございます。
    引き続き挑戦してみます。
記事No.87867 のレス /過去ログ151より / 関連記事表示
削除チェック/

■87874  Re[5]: ASPもしくはIISでhttpレスポンスボディを確認する方法
□投稿者/ abc -(2018/07/09(Mon) 18:16:24)
    取り敢えず、クラシックモードで一部のページのみ、ログ出力を実現できました。

    現状問題点としては下記の通りで、無知を晒すようで恥ずかしいですが、ひとまず整理してみます。
    環境的にデバッグが出来ないため、手探りでやっています……。

    1.マネージメントパイプラインモードがクラシックモードだと下記の例外が起きる
    [PlatformNotSupportedException: この操作を実行するには、IIS 統合パイプライン モードが必要です。]
    どの処理でこけるのか分かりませんが、動くページ、動かないページがあります。

    2.統合モードだとwebmoduleが動かない
    まだ調査出来ていません。クラシックモードと構成設定が違う?
    1の事情から、統合モードでの運用は必須かと思います。

    3.ページの一部が表示されない
    ログファイルでresponseBodyを確認すると、一部が文字化けしているので、文字コードの問題かと推測します。
    ただこの問題に限らず、今回のログ出力処理が実際のレスポンス内容に影響を与えることは避けなければいけません。

    もし何かヒントがありましたらコメント頂ければ幸いです。
    よろしくお願い致します。
記事No.87867 のレス /過去ログ151より / 関連記事表示
削除チェック/

■87875  Re[6]: ASPもしくはIISでhttpレスポンスボディを確認する方法
□投稿者/ WebSurfer -(2018/07/09(Mon) 18:46:06)
    No87874 (abc さん) に返信
    
    > もし何かヒントがありましたらコメント頂ければ幸いです。
    
    紹介した記事のように HttpContext.Items を使うという話はどうなったのですか?
    
    IIS のクラシックモードを使うのは諦めて統合パイプラインモードでやることにしたのですか?
    
    そのあたりをクリアにしてもらえないと、この先私がお役に立てるかどうか分からないのですが・・・
    
    とりあえず、検証に使った HTTP モジュールのコードをアップしておきます。環境は Windows 10
    Pro 64-bit, ローカル IIS10, Visual Studio 2015 Cimmunity, .NET 4.6.1 です。
    
    HTTP モジュールが動かないとか文字化けするという問題はありません。
    
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.IO;
    
    public class ResponseContentLogHttpModule : IHttpModule
    {
        public ResponseContentLogHttpModule()
        {
        }
    
        public String ModuleName
        {
            get { return "ResponseContentLogHttpModule"; }
        }
    
        // In the Init function, register for HttpApplication 
        // events by adding your handlers.
        public void Init(HttpApplication application)
        {
            application.BeginRequest += new EventHandler(this.Application_BeginRequest);
            application.EndRequest += new EventHandler(this.Application_EndRequest);
        }
    
        private void Application_BeginRequest(Object source, EventArgs e)
        {
            // Create HttpApplication and HttpContext objects to access
            // request and response properties.
            HttpApplication application = (HttpApplication)source;
            HttpContext context = application.Context;
            string filePath = context.Request.FilePath;
            string fileExtension = VirtualPathUtility.GetExtension(filePath);
            if (fileExtension.Equals(".aspx"))
            {
                HttpResponse response = context.Response;
                var filter = new OutputFilterStream(response.Filter);
                response.Filter = filter;
                context.Items["OutputFilterStream"] = filter;
            }
        }
    
        private void Application_EndRequest(Object source, EventArgs e)
        {
            HttpApplication application = (HttpApplication)source;
            HttpContext context = application.Context;
            string filePath = context.Request.FilePath;
            string fileExtension = VirtualPathUtility.GetExtension(filePath);
            if (fileExtension.Equals(".aspx"))
            {
                var filter = (OutputFilterStream)context.Items["OutputFilterStream"];
                string responseContent = filter.ReadStream();
                WriteLog(responseContent);
            }
        }
    
        private void WriteLog(string log)
        {
            string responseLogPath = HttpContext.Current.Server.MapPath("~/App_Data/log.txt");
            using (var sw = new StreamWriter(responseLogPath, true))
            {
                sw.WriteLine(log);
            }
        }
    
        public void Dispose() { }
    }
    
    public class OutputFilterStream : Stream
    {
        private readonly Stream InnerStream;
        private readonly MemoryStream CopyStream;
    
        public OutputFilterStream(Stream inner)
        {
            this.InnerStream = inner;
            this.CopyStream = new MemoryStream();
        }
    
        public string ReadStream()
        {
            lock (this.InnerStream)
            {
                if (this.CopyStream.Length <= 0L ||
                    !this.CopyStream.CanRead ||
                    !this.CopyStream.CanSeek)
                {
                    return String.Empty;
                }
    
                long pos = this.CopyStream.Position;
                this.CopyStream.Position = 0L;
                try
                {
                    return new StreamReader(this.CopyStream).ReadToEnd();
                }
                finally
                {
                    try
                    {
                        this.CopyStream.Position = pos;
                    }
                    catch { }
                }
            }
        }
    
    
        public override bool CanRead
        {
            get { return this.InnerStream.CanRead; }
        }
    
        public override bool CanSeek
        {
            get { return this.InnerStream.CanSeek; }
        }
    
        public override bool CanWrite
        {
            get { return this.InnerStream.CanWrite; }
        }
    
        public override void Flush()
        {
            this.InnerStream.Flush();
        }
    
        public override long Length
        {
            get { return this.InnerStream.Length; }
        }
    
        public override long Position
        {
            get { return this.InnerStream.Position; }
            set { this.CopyStream.Position = this.InnerStream.Position = value; }
        }
    
        public override int Read(byte[] buffer, int offset, int count)
        {
            return this.InnerStream.Read(buffer, offset, count);
        }
    
        public override long Seek(long offset, SeekOrigin origin)
        {
            this.CopyStream.Seek(offset, origin);
            return this.InnerStream.Seek(offset, origin);
        }
    
        public override void SetLength(long value)
        {
            this.CopyStream.SetLength(value);
            this.InnerStream.SetLength(value);
        }
    
        public override void Write(byte[] buffer, int offset, int count)
        {
            this.CopyStream.Write(buffer, offset, count);
            this.InnerStream.Write(buffer, offset, count);
        }
    }
記事No.87867 のレス /過去ログ151より / 関連記事表示
削除チェック/

■87877  Re[7]: ASPもしくはIISでhttpレスポンスボディを確認する方法
□投稿者/ PANG2 -(2018/07/10(Tue) 11:00:08)
記事No.87867 のレス /過去ログ151より / 関連記事表示
削除チェック/

■87878  Re[8]: ASPもしくはIISでhttpレスポンスボディを確認する方法
□投稿者/ abc -(2018/07/10(Tue) 17:49:07)
    No87875 (WebSurfer さん) に返信
    コードの提示ありがとうございます。勉強になります。
    HttpContext.Itemsを使うという意味がよく分からず、使わないやり方でも一応は動作していたためそのまま使っていましたが、ご提示頂いたコードでクラシックモードでも動作しました。ですので現状No87875のコードでクラシックモードです。
    HttpContext.Itemsで保持するのと、フィールド変数で保持するのとで動作が変わるのは何故なのでしょうか?

    文字化けは現在も発生していますが、文字化けが起こっていたのはAjaxToolKitに関する下記リクエストに対するレスポンスボディ部のみでした。OutputStreamを読むStreamReader部とログファイル出力のStreamWriter部で文字コードを指定してみましたがダメでした。対応方法はありますでしょうか。
    GET http://localhost:8080/hoge.aspx?_TSM_HiddenField_=ToolkitScriptManager1_HiddenField&_hogehoge
    Connection: Keep-Alive
    Accept: application/javascript, */*;q=0.8
    Accept-Encoding: gzip, deflate
    Accept-Language: ja-JP

    No87877 (PANG2 さん) に返信
    ご紹介頂きありがとうございます。
    現行の方法でほぼ期待する動作ができたため今はこのまま進めますが、Page派生クラスのPage.Renderを使う方法は分かりやすく次回検討させて頂きます。


記事No.87867 のレス /過去ログ151より / 関連記事表示
削除チェック/

■87880  Re[9]: ASPもしくはIISでhttpレスポンスボディを確認する方法
□投稿者/ WebSurfer -(2018/07/10(Tue) 19:46:51)
    No87878 (abc さん) に返信

    > HttpContext.Itemsを使うという意味がよく分からず、使わないやり方でも一応は動作していたためそのまま使っていましたが、

    分からなかったからと言って無視する・スルーするのは止めましょうよ。
    少なくとも分からないと言ってください。
    そうでないと話が噛み合わなくなりますし、せっかく答えたのにその甲斐がないです。

    > HttpContext.Itemsで保持するのと、フィールド変数で保持するのとで動作が変わるのは何故なのでしょうか?

    HttpContext.Itemsで保持すると、少なくとも HttpContext が存在する限り filter が指すオブジェクトは保持される
    (GC の対象にはならない)が、クラスのフィールド変数はその限りではないということだと思います。

    ただ、その具体的なメカニズムは自分は分かりませんが。

    >
    > 文字化けは現在も発生していますが、文字化けが起こっていたのはAjaxToolKitに関する下記リクエストに対するレスポンスボディ部のみでした。
    > 対応方法はありますでしょうか。

    そんなこと言われても、具体的な話が何もないので分かりません。コピペすれば問題を再現できるごくごく簡単な
    サンプルを書いてアップしてください。
記事No.87867 のレス /過去ログ151より / 関連記事表示
削除チェック/



<< 0 >>

パスワード/

- Child Tree -