Child requests generate duplicate ASP.NET events in IIS

Applies to: Internet Information Services 8.0Internet Information Services 8.5

Symptoms


You have Internet Information Services (IIS) 7.0 or a later version of IIS configured to use integrated pipeline mode. However, some HTTP modules or ISAPI applications may trigger duplicate ASP.NET events such as BeginRequest and EndRequest.

More Information


When a client requests a specific URL (webpage), IIS may sometimes re-request the same URL or another URL on the server side. The client’s original request is called the parent request, and the request that IIS executes is called the child request.

For example, both of the following may execute a child request:
  • An ISAPI extension that uses the HSE_REQ_EXEC_URL support function and that is installed as a wildcard script map
  • native HTTP module that calls the IHttpContext::ExecuteRequest method
HSE_REQ_EXEC_URL enables an ISAPI extension to rewrite a URL request in order to call another extension or to call the original URL by using the HSE_EXEC_URL_INFO structure. If you invoke the child request, you set pszUrl of the HSE_EXEC_URL_INFO structure member to the child URL’s URI stem. If you call the original URL, you set pszUrl to NULL. In addition to the HSE_REQ_EXEC_URL ISAPI extension, the IHttpContext::ExecuteRequest method executes the child request by specifying the IHttpContext interface in the pHttpContext parameter.

When both the parent request and the child request target an ASP.NET-connected application that runs in the Integrated pipeline mode worker process, duplicate ASP.NET events may be generated. You can confirm this behavior by using Failed Request Event Buffering (FREB). This is also known as Failed Request Tracing.

The following log entry shows client requests to /parent.aspx:
EventInformation
GENERAL_REQUEST_STARTSiteId="1", AppPoolId="DefaultAppPool", ConnId="1610612739", RawConnId="0", RequestURL="http://localhost:80/parent.aspx", RequestVerb="GET"

The following log entry shows that a BEGIN_REQUEST notification in global.asax is triggered by a request to /parent.aspx. This is the first BEGIN_REQUEST notification:
EventInformation
NOTIFY_MODULE_STARTModuleName="global.asax", Notification="BEGIN_REQUEST", fIsPostNotification="false"
AspNetStartData1="GET", Data2="/parent.aspx", Data3=""

The following log entry shows that the native HTTP module (myhttpmodule.dll) runs and that it executes the child request, child.aspx:
EventInformation
NOTIFY_MODULE_STARTModuleName="myhttpmodule", Notification="MAP_PATH", fIsPostNotification="false"
GENERAL_CHILD_REQUEST_STARTSiteId="1", RequestURL="http://localhost:80/child.aspx", RequestVerb="GET", RecursiveLevel="1"
GENERAL_REQUEST_STARTSiteId="1", AppPoolId="DefaultAppPool", ConnId="1610612739", RawConnId="0", RequestURL="http://localhost:80/child.aspx", RequestVerb="GET"

The following log entry shows that BEGIN_REQUEST notification in global.asax is triggered by a request to /child.aspx. This is the second BEGIN_REQUEST notification:
EventInformation
NOTIFY_MODULE_STARTModuleName="global.asax", Notification="BEGIN_REQUEST", fIsPostNotification="false"
AspNetStartData1="GET", Data2="/child.aspx", Data3=""

The following log entry shows that the END_REQUEST notification in global.asax is triggered by a request to /child.aspx. This is the first END_REQUEST notification:
EventInformation
NOTIFY_MODULE_STARTModuleName="global.asax", Notification="END_REQUEST", fIsPostNotification="false"
AspNetPipelineEnterData1="ASP.global_asax"
AspNetPipelineLeaveData1="ASP.global_asax"

The following log entry shows that the child request finishes:
EventInformation
GENERAL_REQUEST_ENDBytesSent="332", BytesReceived="266", HttpStatus="200", HttpSubStatus="0"
GENERAL_CHILD_REQUEST_ENDBytesSent="332", HttpStatus="200", HttpSubStatus="0"
NOTIFY_MODULE_COMPLETIONModuleName="myhttpmodule", Notification="MAP_PATH", fIsPostNotificationEvent="false", CompletionBytes="0", ErrorCode="The operation completed successfully. (0x0)"
AspNetEnd

The following log entry shows that END_REQUEST notification in global.asax is triggered by a request to /parent.aspx. This is the second END_REQUEST notification:
EventInformation
NOTIFY_MODULE_STARTModuleName="global.asax", Notification="END_REQUEST", fIsPostNotification="false"
AspNetPipelineEnterData1="ASP.global_asax"
AspNetPipelineLeaveData1="ASP.global_asax"

The following log entry shows that the parent request finishes:
EventInformation
GENERAL_REQUEST_ENDBytesSent="332", BytesReceived="266", HttpStatus="200", HttpSubStatus="0"

References


For more information about how to call the ExecuteRequest method to execute the child request, see IHttpContext::ExecuteRequest Method.
In this sample code, the parent request is /default.aspx, and the child request is /example/default.aspx.

Status


Microsoft has confirmed that this is "by design" in the Microsoft products that are listed in the "Applies to" section.