子要求では、IIS で重複する ASP.NET イベントが生成されます

この記事では、Microsoft インターネット インフォメーション サービス (IIS) の統合パイプライン モード ワーカー プロセス中に子要求によって、重複する ASP.NET イベントが作成される設計上の動作について説明します。

元の製品バージョン: インターネット インフォメーション サービス 7.0、8.0、8.5
元の KB 番号: 2901671

現象

統合パイプライン モードを使用するように IIS 7.0 以降のバージョンの IIS が構成されています。 ただし、一部の HyperText Transfer Protocol (HTTP) モジュールまたはインターネット サーバー アプリケーション プログラム インターフェイス (ISAPI) アプリケーションでは、 や などのBeginRequestEndRequest重複した ASP.NET イベントがトリガーされる場合があります。

この問題が発生する状況

クライアントが特定の URL (Web ページ) を要求すると、IIS がサーバー側で同じ URL または別の URL を再要求することがあります。 クライアントの元の要求は 親要求と呼ばれ、IIS が実行する要求は 子要求と呼ばれます。

たとえば、次の両方が子要求を実行する場合があります。

  • 関数を使用 HSE_REQ_EXEC_URL support し、ワイルドカード スクリプト マップとしてインストールされる ISAPI 拡張機能。
  • メソッドを呼び出 IHttpContext::ExecuteRequest すネイティブ HTTP モジュール。

HSE_REQ_EXEC_URL では、ISAPI 拡張機能が URL 要求を書き換えて別の拡張機能を呼び出したり、 構造体を使用 HSE_EXEC_URL_INFO して元の URL を呼び出したりできます。 子要求を呼び出す場合は、構造体メンバーの HSE_EXEC_URL_INFO pszUrl を子 URL の URI ステムに設定します。 元の URL を呼び出す場合は、NULL に設定pszUrlします。 ISAPI 拡張機能にHSE_REQ_EXEC_URL加えて、 メソッドはIHttpContext::ExecuteRequest、 パラメーターで インターフェイスを指定して子要求をIHttpContextpHttpContext実行します。

親要求と子要求の両方が ASP をターゲットとする場合。統合パイプライン モードのワーカー プロセスで実行される NET 接続アプリケーションでは、重複する ASP.NET イベントが生成される場合があります。 この動作は、失敗した要求イベント バッファリング (FREB) を使用して確認できます。 これは、失敗した要求トレースとも呼ばれます。

ログ

次のログ エントリは、/parent.aspx へのクライアント要求を示しています。

イベント 情報
GENERAL_REQUEST_START SiteId="1", AppPoolId="DefaultAppPool", ConnId="610612739", RawConnId="0", RequestURL=";http://localhost:80/parent.aspx", RequestVerb="GET"

次のログ エントリは、 BEGIN_REQUEST global.asax の通知が /parent.aspx への要求によってトリガーされることを示しています。 これは最初 BEGIN_REQUEST の通知です。

イベント 情報
NOTIFY_MODULE_START ModuleName="global.asax", Notification="BEGIN_REQUEST", fIsPostNotification="false"
AspNetStart Data1="GET", Data2="/parent.aspx", Data3=""

次のログ エントリは、ネイティブ HTTP モジュール (myhttpmodule.dll) が実行され、子要求が実行されることを示child.aspx。

イベント 情報
NOTIFY_MODULE_START ModuleName="myhttpmodule", Notification="MAP_PATH", fIsPostNotification="false"
GENERAL_CHILD_REQUEST_START SiteId="1", RequestURL=";http://localhost:80/child.aspx", RequestVerb="GET", RecursiveLevel="1"
GENERAL_REQUEST_START SiteId="1", AppPoolId="DefaultAppPool", ConnId="1610612739", RawConnId="0", RequestURL=";http://localhost:80/child.aspx", RequestVerb="GET"

次のログ エントリは、global.asax の通知が /child.aspx への要求によってトリガーされることを BEGIN_REQUEST 示しています。 これは 2 番目 BEGIN_REQUEST の通知です。

イベント 情報
NOTIFY_MODULE_START ModuleName="global.asax", Notification="BEGIN_REQUEST", fIsPostNotification="false"
AspNetStart Data1="GET", Data2="/child.aspx", Data3=""

次のログ エントリは、global.asax の通知が /child.aspx への要求によってトリガーされることを END_REQUEST 示しています。 これは、最初のEND_REQUEST通知です。

イベント 情報
NOTIFY_MODULE_START ModuleName="global.asax", Notification="END_REQUEST", fIsPostNotification="false"
AspNetPipelineEnter Data1="ASP.global_asax"
AspNetPipelineLeave Data1="ASP.global_asax"

次のログ エントリは、子要求が完了したことを示しています。

イベント 情報
GENERAL_REQUEST_END BytesSent="332", BytesReceived="266", HttpStatus="200", HttpSubStatus="0"
GENERAL_CHILD_REQUEST_END BytesSent="332", HttpStatus="200", HttpSubStatus="0"
NOTIFY_MODULE_COMPLETION ModuleName="myhttpmodule", Notification="MAP_PATH", fIsPostNotificationEvent="false", CompletionBytes="0", ErrorCode="操作が正常に完了しました。 (0x0)"
AspNetEnd

次のログ エントリは、global.asax の通知が /parent.aspx への要求によってトリガーされることを END_REQUEST 示しています。 これは 2 番目 END_REQUEST の通知です。

イベント 情報
NOTIFY_MODULE_START ModuleName="global.asax", Notification="END_REQUEST", fIsPostNotification="false"
AspNetPipelineEnter Data1="ASP.global_asax"
AspNetPipelineLeave Data1="ASP.global_asax"

次のログ エントリは、親要求が完了したことを示しています。

イベント 情報
GENERAL_REQUEST_END BytesSent="332", BytesReceived="266", HttpStatus="200", HttpSubStatus="0"

関連情報

メソッドを呼び出して子要求を ExecuteRequest 実行する方法の詳細については、「 IHttpContext::ExecuteRequest メソッド」を参照してください。

このサンプル コードでは、親要求は で /default.aspx、子要求は です /example/default.aspx