Child requests generate duplicate ASP.NET events in IIS
This article discusses a by design behavior that duplicate ASP.NET events are created by child requests during the Integrated pipeline mode worker process in Microsoft Internet Information Services (IIS).
Original product version: Internet Information Services 7.0, 8.0, 8.5
Original KB number: 2901671
Symptoms
You have IIS 7.0 or a later version of IIS configured to use integrated pipeline mode. However, some HyperText Transfer Protocol (HTTP) modules or Internet Server Application Program Interface (ISAPI) applications may trigger duplicate ASP.NET events such as BeginRequest
and EndRequest
.
Situations where this issue occurs
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. - The 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.
Logs
The following log entry shows client requests to /parent.aspx:
Event | Information |
---|---|
GENERAL_REQUEST_START | SiteId="1", AppPoolId="DefaultAppPool", ConnId="610612739", 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:
Event | Information |
---|---|
NOTIFY_MODULE_START | ModuleName="global.asax", Notification="BEGIN_REQUEST", fIsPostNotification="false" |
AspNetStart | Data1="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:
Event | Information |
---|---|
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" |
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:
Event | Information |
---|---|
NOTIFY_MODULE_START | ModuleName="global.asax", Notification="BEGIN_REQUEST", fIsPostNotification="false" |
AspNetStart | Data1="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:
Event | Information |
---|---|
NOTIFY_MODULE_START | ModuleName="global.asax", Notification="END_REQUEST", fIsPostNotification="false" |
AspNetPipelineEnter | Data1="ASP.global_asax" |
AspNetPipelineLeave | Data1="ASP.global_asax" |
The following log entry shows that the child request finishes:
Event | Information |
---|---|
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="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:
Event | Information |
---|---|
NOTIFY_MODULE_START | ModuleName="global.asax", Notification="END_REQUEST", fIsPostNotification="false" |
AspNetPipelineEnter | Data1="ASP.global_asax" |
AspNetPipelineLeave | Data1="ASP.global_asax" |
The following log entry shows that the parent request finishes:
Event | Information |
---|---|
GENERAL_REQUEST_END | BytesSent="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
.
Feedback
Submit and view feedback for