2009-07-17 17 views
30

私はHTTPモジュールを作成していましたが、デバッグ中は最初は(少なくとも)奇妙な動作のように思えるものに気付きました。HttpModule Initメソッドが何度か呼び出されます - なぜですか?

httpmoduleのinitメソッドにブレークポイントを設定すると、デバッグのためにウェブサイトを起動しただけで、httpモジュールのinitメソッドが複数回呼び出されていることがわかります。 1回のみ、他の回数は10回)。

私は、HttpApplicationのいくつかのインスタンスが実行され、各HTTPモジュールが作成されることを期待する必要があることを知っていますが、単一のページを要求すると、単一のHTTPアプリケーションオブジェクトによって処理されるため、イベントは一度関連していますが、各リクエストに対して何回もイベントを発生させますが、それは意味がありません - それは、httpApplication内で何度も追加されている必要があります - つまり、毎回呼び出されるのと同じhttpmodule initメソッド新しいhttpアプリケーションがブレークポイントに当たるたびに作成されます(下のコード例を参照してください)。

ここで間違っていますか?私はデバッグしているし、httpモジュールでブレークポイントを設定しているのでですか?

私はデバッグのためにWebサイトを起動し、httpmoduleのブレークポイントをすばやくステップするとinitメソッドを1回だけ実行し、イベントハンドラも同じように見えることに気付きました。私が代わりにブレークポイントで数秒間ハングさせた場合、initメソッドは何度か呼び出されています(ブレークポイントを踏むまでにどれくらい時間がかかっているかによって異なります)。たぶんこれは、httpmoduleが初期化され、httpアプリケーションが要求を処理できることを確認する機能をいくつか組み込んでいるかもしれませんが、壊滅的な結果を招く可能性のあるもののようです。

これは論理的に思えるかもしれません。要求を完了しようとしている可能性があり、何か問題が起こったと思ってブレークポイントを設定したため、initメソッドを再度呼び出そうとしていますか?それは要求を処理することができますか?

これは何が起きているのか、それはすべてうまく(私はちょうど推測していますか)、それとも本当の問題ですか?

私が特に気にしているのは、何かが「プロダクション/ライブ」サーバーに数秒間ハングアップすると、initを介して多くのイベントハンドラが追加され、ページへの各リクエストが突然イベントハンドラを起動する数回。

この現象により、すぐにサイトがダウンする可能性があります。

私はformauthenticationとrolemanagermoduleなどのhttpmodulesに使用されている "元の" .netコードを見てきましたが、私のコードはこれらのモジュールが使用するものとはまったく異なります。

私のコードは次のようになっています。ここ

public void Init(HttpApplication app) 
    { 
     if (CommunityAuthenticationIntegration.IsEnabled) 
     { 
      FormsAuthenticationModule formsAuthModule = (FormsAuthenticationModule) app.Modules["FormsAuthentication"];   

      formsAuthModule.Authenticate += new FormsAuthenticationEventHandler(this.OnAuthenticate); 
     } 
    } 

は何が起こっているか、誰を知っていますそれは、.NETフレームワーク

public void Init(HttpApplication app) 
    { 
     if (Roles.Enabled) 
     { 
      app.PostAuthenticateRequest += new EventHandler(this.OnEnter); 
      app.EndRequest += new EventHandler(this.OnLeave); 
     } 
    } 

からRoleManagerModuleで行われている方法の例ですか?

(私はそこに誰かがすべてが完全に罰金であることを私になぜこれが起こっている私に言うと保証することができることを望む:))

UPDATEが01​​

私が試してみましたが、問題を絞り込みますこれまで私は、呼び出されているInitメソッドが常に私のHTTPモジュールの新しいオブジェクトにあることを発見しました。

最初のリクエスト(サイトの起動時)は、作成されているHttpApplicationオブジェクトとそのモジュールのすべてが最初のリクエストを処理しようとしているため、追加されているイベントハンドラがすべてヒットしているようです。 なぜこれが起こっているのかわかりません。

私は別のページを要求した場合、すべての作成のHttpApplicationの(およびそのmoduless)は、再び、それはイベントハンドラを複数回ヒットさせる要求にサービスを提供しようとします。

しかし、私は最初のページ(または別のもの)にジャンプすれば、1つのHttpApplicationだけが要求を処理し始め、すべてが期待どおりであると思われます。ブレークポイント。

私がHttpApplicationのオブジェクトを作成し、HttpApplicationのオブジェクトを作成し始め、要求を処理したり処理したりするためにHttpApplications(1以上)を追加し始めます(現在停止しているHttpApplicationによって処理中です)ブレークポイントで)。

私は推測するか、負荷および/またはエラーを配布し、処理するために助けることのいくつかのインテリジェントな「舞台裏」の方法であるかもしれないことを願っています。しかし、私は手がかりがありません。 私はそれが完全にうまく、どのようになっていると私に保証することができるいくつかの希望がありますか?

+2

私のHttpModuleでもこの動作が見られます –

+0

ジョン:これを閉じるのを忘れました。ブラウザーが任意のリソース(イメージ、javascript、スタイルシート)を要求するたびにモジュールがヒットするため、少なくとも私の場合はこれが起こります。ヒットする理由は、MVCなどで使われているルーティングモジュールです。すべての要求はルーティングモジュールによって処理される必要があり、そのためすべての要求がモジュールを不幸にしてしまいます。私はこれについて質問しましたが、誰もそれに答えませんでした。 – MartinF

答えて

7
  1. モジュールのinitが起動される要求何のために、見てHttpContext.Current.Requestを点検。ブラウザが複数のリクエストを送信している可能性があります。

  2. あなたがIISに接続している場合は、任意の要求はあなたがブレークポイントで滞在している時間のために受信されているかどうかを知るためにIISログをチェックします。

+0

正しい。これは、すべての要求(すべてのリソース)がモジュールにヒットするために発生します。 私の場合、ルーティングモジュールのために見えます。 – MartinF

2

ここでは、何をいつ、どのように使い、どのように動作させるべきかについて説明します。 When to use Application_Start vs Init in Global.asax?

編集:もっと読み

The ASP Column: HTTP Modules

INFO: Application Instances, Application Events, and Application State in ASP.NET

+0

ご返信ありがとうございます。 私はそれらのどれも使用しません。グローバルasaxのInitがHttpApplicationのinitをオーバーライドしています。私の問題は、私のhttpmoduleのInitメソッドが何回か呼び出されていることです。 私が理解する限り、httpアプリケーションごとにhttpモジュールを作成する必要があります。リクエストごとに、インスタンス化されたHttpApplicationのリクエストの1つがリクエストを処理し、追加されたイベントを起動しますが、何らかの理由でイベントハンドラが同じHTTPモジュールのinitメソッドとして複数回追加されることがあります他のhttpアプリケーションの)はサーバ時間と呼ばれます。 – MartinF

+0

続きを読むが追加されました。 –

40

Init()メソッドが複数回呼び出されるのは正常です。アプリケーションが起動すると、ASP.NET Workerプロセスは、必要と思う数のHttpApplicationオブジェクトをインスタンス化し、プールします(たとえば、データベース接続プーリングと同様に新しい要求に対してそれらを再利用します)。

は今、それぞれのHttpApplicationオブジェクトのために、それはまた、登録されている各のIHttpModuleの一つのコピーをインスタンス化し、その何倍Initメソッドを呼び出します。したがって、5つのHttpApplicationオブジェクトが作成された場合、IHttpModuleの5つのコピーが作成され、Initメソッドが5回呼び出されます。理にかなっている?

なぜ、5つのHttpApplicationsオブジェクトがインスタンス化されているのですか? ASPXページには、ブラウザがダウンロードしようとする他のリソース、CSS、JavaScript、WebResource.aspx、おそらくどこかのiframeへのリンクがあります。あるいは、ASP.NET Worker Processが1つ以上のHttpApplicationオブジェクトを開始するための気分になっているかもしれません。これはIIS(またはWebサーバーに組み込まれたVS)で実行されるASP.NETプロセスの内部詳細/最適化です。

あなたは一度だけ実行する(とGlobal.asaxの中Application_StartUpイベントを使用する必要はありません)保証のコードをしたい場合は、あなたがのIHttpModuleに次のように試みることができる:

private static bool HasAppStarted = false; 
private readonly static object _syncObject = new object(); 

public void Init(HttpApplication context) 
{ 
    if (!HasAppStarted) 
    { 
     lock (_syncObject) 
     { 
      if (!HasAppStarted) 
      { 
       // Run application StartUp code here 

       HasAppStarted = true; 
      } 
     } 
    } 
} 

私は」私は何かを逃した場合に備えて私の仕事の批判を歓迎するつもりですが、同様のことをして、それは動作するようです。

+10

これは、ロックの代わりに 'Interlocked.CompareExchange'を使う場所です: –

+1

リソースファイルへのリクエストさえ、アプリケーションクラスの作成を引き起こし、それ自身のモジュールなので、このイベントの発生はありますか? –

1

上記のExamleは、すべての要求に対してIHttpModuleをロックしてから、アプリケーション全体をフリーズします。 あなたのIHttpModuleの呼び出しが何回かはのHttpApplication方法CompleteRequestを呼び出し、このようなのHttpApplicationのインスタンスを除去するために、EndRequestのイベントでのIHttpModuleののHttpApplicationインスタンスを配置するために必要とされる要求した場合:

public class TestModule :IHttpModule 
    { 
     #region IHttpModule Members 

     public void Dispose() 
     { 

     } 

     public void Init(HttpApplication context) 
     { 
      context.BeginRequest += new EventHandler(context_BeginRequest); 
      context.EndRequest += new EventHandler(context_EndRequest); 
     } 

     void context_EndRequest(object sender, EventArgs e) 
     { 
      HttpApplication app = sender as HttpApplication; 
      app.CompleteRequest(); 
      app.Dispose(); 
     } 

     void context_BeginRequest(object sender, EventArgs e) 
     { 
      //your code here 
     } 

     #endregion 
    } 

を使用すると、そののIHttpModule要求を必要とする場合ポストバックの再要求なしで上記のコードを使用してください。

+0

これは良い点ですが、(鉱山のような)一部のアプリケーションでは、実行されるコードはたかだか数マイクロ秒であるため、ロックは確かに費用効果が高いです。しかし、アイデアのおかげで、私はこれが私のコーディングを向上させることを知っていると思う。 – Abacus

関連する問題