A “404 File not found” issue caused by ASP.NET v4.0 Extensionless URL feature on IIS 6.0

 

Symptom

=======

 

After IIS is restarted, my customer received “404 File not found” error when he tried to visit his web site, e.g https://servername/ .

If he visited https://servername/index.htm, he would get the page successfully.

The failed request in IIS log is:

2011-12-01 09:38:43 W3SVC1 127.0.0.1 GET / - 80 - 127.0.0.1 404 0

 

At the beginning, this problem seems to be related to the Default Document setting. But actually the server should return “Directory Listing Denied” error instead of “404 File not found” error if Default Document is disabled.

The problem may or may not disappear after IIS is restarted.

Cause

=====

After the debugging, we finally found the “404 File not found” error was returned because IIS could not find the file /eurl.axd/<GUID>. (e.g. /eurl.axd/0abce804a5785d42aaf2473554a47d90)

The original request https://servername/ was changed to https://servername/eurl.axd/GUID  by the installed ASP.NET v4.0 ISAPI Filter because it enabled extensionless URL feature. By default .axd request should be handled by aspnet_isapi.dll. But on that problematic site the script mappings for ASP.NET had been removed for some reasons. Therefore the static file handler was responsible for handling the request /eurl.axd/GUID and then returns “404 File not found” error.

The following article explains how the ASP.NET v4.0 Extensionless URL feature works on IIS 6.0

https://blogs.msdn.com/b/tmarq/archive/2010/06/18/how-to-disable-the-asp-net-v4-0-extensionless-url-feature-on-iis-6-0.aspx

The problem only occurred intermittently after IIS was restarted. Why?

The problem may still exist even if IIS was restarted again.  Why?

The problem would disappear after IIS was restarted several times. Why?

 

Here are the tricks:

The problematic server has ASP.NET v4.0 installed. There are 2 web sites: Site1 and Site2 which are sharing the same application pool.

There is an ASP.NET 4.0 application running on Site2. But on Site1 the scrip mappings for ASP.NET v4.0 were removed because the customer thought there was no ASP.NET application running on Site1.

After IIS is restarted, if the *first* request comes to Site2, because Site2 meets extensionless feature conditions, ASP.NET v4.0 ISAPI filter will enable this feature and set some internal flags. Then all subsequent requests to Site1 are changed to /eurl.axd/GUID. Because ASP.NET v4.0 script mappings were removed (there is no .axd handler mapping), the static file handler is responsible for handling the request /eurl.axd/GUID and then returns “404 File not found” error.

 

If the *first* request comes to Site1, because Site1 does not have .axd handler mapping, Site1 does not meet the extensionless feature conditions. Therefore ASP.NET v4.0 ISAPI filter will set some internal flags to disable this feature. All subsequent requests to both of Site1 and Site2 will not change to /eurl.axd/GUID. The static file handler works as usual.

 

Solutions

========

We can choose one of them:

1.       Disable ASP.NET 4.0 extensionless feature

Refer to this article https://blogs.msdn.com/b/tmarq/archive/2010/06/18/how-to-disable-the-asp-net-v4-0-extensionless-url-feature-on-iis-6-0.aspx

2.       Re-create the script mappings for ASP.NET v4.0 on Site1.

3.       Put Site1 and Site2 in different application pools.

 

 

 

How to identify this issue quickly

=======================

Although we identified the root cause by live debugging, it is not efficient.

Use ETW trace can help us quickly identified which request returned “404 File not found” error.

 

  IISGeneral: GENERAL_STATIC_FILE_HANDLER - IIS processes a static file request

    FileName: c:\inetpub\wwwroot\eurl.axd\0abce804a5785d42aaf2473554a47d90\

    ContextIDSeq: 1

    Timestamp: 10:05:42.388.109000

 

  IISCache: FILE_CACHE_ACCESS_START - IIS starts accessing file cache

    FileName: c:\inetpub\wwwroot\eurl.axd\0abce804a5785d42aaf2473554a47d90\

    UserName: IUSR_SERVERNAME

    DomainName: SERVERNAME

    ContextIDSeq: 1

    Timestamp: 10:05:42.403.695000

 

  IISCache: FILE_CACHE_ACCESS_END - IIS ends accessing file cache

    ErrorCode: 0x80070003

    Successful: 0

    FileFromCache: 0

    FileAddedToCache: 0

    FileDirmoned: 1

    LastModCheckErrorIgnored: 0

    ContextIDSeq: 1

    Timestamp: 10:05:42.403.695000

 

  IISGeneral: GENERAL_SEND_CUSTOM_ERROR - IIS sends back a custom error

    HttpSubStatus: 0

    FileNameOrURL: C:\WINDOWS\help\iisHelp\common\404b.htm

    ContextIDSeq: 1

Timestamp: 10:05:42.403.695000

 

Here are my steps:

Create a txt file named iisprov.txt. Put the following providers in this txt file.

{dd5ef90a-6398-47a4-ad34-4dcecdef795f} 255 5   #http.sys

{3a2a4e84-4c21-4981-ae10-3fda0d9b0f83} 65534 5   #w3core.dll

{a1c2040e-8840-4c31-ba11-9871031a19ea} 255 5   #w3isapi.dll

{1fbecc45-c060-4e7c-8a0e-0dbd6116181b} 255 5   #Strmfilter.dll

{06b94d9a-b15e-456e-a4ef-37c984a2cb4b} 255 5   #asp.dll

{AFF081FE-0247-4275-9C4E-021F3DC1DA35} 255 5   #aspnet

{DC1271C2-A0AF-400f-850C-4E42FE16BE1C} 255 5   #iisadmin

 

 

Run the command: logman start iistrace -pf iisprov.txt -ets  

Use your browser to access https://servername to get the error “404 File not found”.

Run the following command to stop ETW trace:

logman stop iistrace -ets 

We will get the trace file iistrace.etl.

Download and install Log Parser 2.2.

Run the following command to parse the trace:

cscript "C:\Program Files\Log Parser 2.2\Samples\Scripts\dumptracereqs.js" iistrace.etl

We will get the above results.

 

Regards,

Xinjin From APAC DSI Team