• Sign in
 
  •  
  • MSDN Blogs
  • Microsoft Blog Images
  • More ...
Common Tasks
  • Blog Home
  • Email Blog Author
  • RSS for comments
  • RSS for posts
Search
Tags
  • .NET Framework
  • Ajax/Javascript
  • ARR
  • ASP.NET
  • CLR
  • Cool stuff
  • DataAccess
  • Debugging/Windbg
  • Hotfix/Service Pack
  • IDEVDataCollector
  • IIS
  • Internet Explorer
  • Italian techs
  • LogParser
  • OT
  • Personal
  • Productivity
  • Random
  • Scripting/ASP
  • Security
  • Technology
  • Tools
  • Troubleshooting
  • Vista/Longhorn
  • Visual Studio
Archives
Archives
  • January 2013 (2)
  • November 2010 (1)
  • October 2010 (1)
  • July 2010 (2)
  • April 2010 (1)
  • March 2010 (2)
  • February 2010 (2)
  • January 2010 (1)
  • October 2009 (2)
  • September 2009 (2)
  • August 2009 (1)
  • July 2009 (5)
  • June 2009 (1)
  • May 2009 (1)
  • April 2009 (3)
  • March 2009 (3)
  • February 2009 (5)
  • January 2009 (3)
  • December 2008 (5)
  • November 2008 (3)
  • October 2008 (2)
  • September 2008 (3)
  • August 2008 (3)
  • July 2008 (3)
  • June 2008 (5)
  • May 2008 (4)
  • April 2008 (8)
  • March 2008 (4)
  • February 2008 (5)
  • January 2008 (2)
  • December 2007 (4)
  • November 2007 (6)
  • October 2007 (6)
  • September 2007 (8)
  • August 2007 (6)
  • July 2007 (7)
  • June 2007 (10)
  • May 2007 (9)
  • April 2007 (12)
  • March 2007 (8)
  • February 2007 (5)
  • January 2007 (3)
  • December 2006 (1)
  • November 2006 (4)
  • October 2006 (2)
  • September 2006 (9)
  • August 2006 (2)
  • July 2006 (1)

The importance of breaking changes

MSDN Blogs > Never doubt thy debugger > The importance of breaking changes

The importance of breaking changes

Carlo Cardella
17 May 2007 11:48 PM
  • Comments 3

Yesterday I closed a case about a migration issue from ASP.NET 1.1 to 2.0. The customer built this application based on ASP.NET 1.1 to generate some PDF documents on the fly on the web server, and stream the content to the client for reading; the application also served as a sort of archive browser, where online users are able to browse a list of archived PDF files. The customer thought carefully to his error handling (I think he did a very good job), and also decided to customize the standard 404 error page to something more friendly and informative for application's users, so he configured the <customErrors> section in his web.config to point to a specific page to handle the 404 return codes. But he wanted this custom page to be displayed also if the user requested a non existing PDF file, so he had to add a new mapping in IIS console, to have requests for .pdf files go through the ASP.NET execution channel (aspnet_isapi.dll etc...) and benefit of the advanced features (including security and error handling) granted by the .NET Framework.

pdf mapping

This worked pretty well fos some time, until the customer decided to migrate his web applications to ASP.NET 2.0. He recompiled the application with Visual Studio 2005, updated the IIS mapping to reference the aspnet_isapi.dll which comes with Framework 2.0 and then at the first run of the upgraded site got this weird behavior: if he tried to browse a non existing .aspx page he got his custom 404 page, but if he tried to browse a non existing .pdf file IIS prompted him to enter authentication credentials; but no matter which ones he inserted, after three attempts (all failing) he was redirected to the 401 error page.

They sent me a sample application, and reproducing the problem on my machine was quite straightforward. To be honest in my experience this is not a common scenario (maybe you can correct me?) so I didn't remeber exactly all the details about how to configure it, but I had some echoes of an ASP.NET training I attended a few years ago (which was part of my MCSD certification, before joining Microsoft) and I thought we had to tell somehow the runtime how to manage this new extension we wanted to add... My mind went to HttpHandlers, but I didn't find any new HttpHander in customer's web.config. So I added it to my sample:

<httpHandlers>
    <add path="*.pdf" verb="*" type="System.Web.StaticFileHandler" validate="true"/>
</httpHandlers>

I tested again, and I magically gor the custom 404 page also requesting a non existing .pdf file.

Next question is: if the application worked fine for some time with ASP.NET 1.1 without adding that HttpHandler, where is the difference? Well... thinking about how the configuration file mechanism works in ASP.NET, I opened "C:\WINDOWS\Microsoft.NET\Framework\v1.1.4322\CONFIG\machine.config" for 1.1 and "C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\CONFIG\web.config" for 2.0, and started looking at the differences in the <httpHandlers> section. ASP.NET 2.0 has a longer list of extensions and HttpHandlers perconfigured, but I found what I was looking for at the end of the section:

machine.config for ASP.NET 1.1

[…] <add verb="*" path="*.asp" type="System.Web.HttpForbiddenHandler" /> <add verb="*" path="*.licx" type="System.Web.HttpForbiddenHandler" /> <add verb="*" path="*.resx" type="System.Web.HttpForbiddenHandler" /> <add verb="*" path="*.resources" type="System.Web.HttpForbiddenHandler" /> <add verb="GET,HEAD" path="*" type="System.Web.StaticFileHandler" /> <add verb="*" path="*" type="System.Web.HttpMethodNotAllowedHandler" /> </httpHandlers> […]

root web.config for ASP.NET 2.0

[…] <add path="*.refresh" verb="*" type="System.Web.HttpForbiddenHandler" validate="true" /> <add path="*.svc" verb="*" type="System.ServiceModel.Activation.HttpHandler, System.ServiceModel,
Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
validate="false" /> <add path="*" verb="GET,HEAD,POST" type="System.Web.DefaultHttpHandler"
validate="true" />
<add path="*" verb="*" type="System.Web.HttpMethodNotAllowedHandler" validate="true" /> </httpHandlers> […]

That’s the difference: in ASP.NET 1.1, if a request has an extension which does not match one of the predefined extensions (and has a GET or HEAD verb) will match the “*” path and will go through the StaticFileHandler module, while in ASP.NET 2.0 if the same happens the request will go through the DefaultHttpHandler module, which has a different behavior. So to be 100% sure I removed the custom HttpHander from application web.config for the repro, and added it in the root web.config, and of course the problem was again resolved.

Another step forward: is it conceivable that we make such a change without documenting it? Well... I learnt to not be surpresed of anything in life, but before becoming too  philosophic I started searching our docs and I found a clear reference to this behavior in the ASP.NET Run-Time Breaking Changes page:

Short Description
When mapping custom extensions to an existing ASP.NET builtin handler, it is now necessary to configure a build provider for that extension.

Affected APIs
Configuration
Severity
Low
Compat Switch Available
No


Description
When mapping custom extensions to an existing ASP.NET builtin handler, it is now necessary to configure a build provider for that extension. In version 2.0, the ASP.NET build system requires a build provider to handle compilation. The builtin build providers can be reused but they need to be specified.


User Scenario
If an application maps a private file extensions (say .misc or .foo or whatever) to an existing ASP.NET handler type (say, the page handler), then it is now necessary to provide configuration that tells ASP.NET how to compile that file type. e.g.

<system.web>
    <httpHandlers>
        <add verb="*" path="*.misc" type="System.Web.UI.PageHandlerFactory" />
    </httpHandlers>
</system.web>

In v1, this would work as is. In version 2.0, they also need to register a BuildProvider. e.g.

<compilation>
    <buildProviders>
        <add extension=".misc" appliesTo="Web" type="System.Web.Compilation.PageBuildProvider" />
    </buildProviders>
</compilation>
Types mapped to the static file handler or star mapped types are not impacted by this, only compiled types.

Work Around
Add a configuration directive to tell ASP.NET how to compile that file type.

I sent everything to the customer and he's now happiling displying his custom 404 page also for non existing PDF files smile_regular.

Lesson learnt with this one: if I had the breaking change page at hand, I very likely saved the time spent in troubleshooting... but hey, at least we solved the problem!

 

Carlo

  • 3 Comments
ASP.NET, IIS
Leave a Comment
  • Please add 8 and 5 and type the answer here:
  • Post
Comments
  • Thamizh
    18 Jun 2007 3:12 PM

    I have .NET 2.0 and VS 2005. I am trying to access a custom web service but I could not, so when I googled I found it had to do with <httphandlers> in machine.config. The problem I am facing is I have <httphandlers> in machine.config under .NET 1.x and <httphandlers> in web.config under .NET 2.0.Shouldn't I have <httphandlers> in machine.config in 2.0?

  • Carlo Cardella
    18 Jun 2007 3:45 PM

    Thamizh, in ASP.NET 2.0 there has been a redesign in the default configuration file hierarchy; now we have the machine.config as in ASP.NET 1.x, but we also have a root web.config (in the same folder as the machine.config), so if you found your <HttpHandlers> section in the root web.config that fine.

    By the way, you'll see that you also have machine.default and machine.comments files (and web.comments and web.default): this is because to increase performances, the default config values have been hard coded in aspnet_isapi.dll, so you can use the *.comments as documentation and reference for those default values, while the *.comments is a doc file to explain you the meaning of each setting and how to change them.

    See http://msdn2.microsoft.com/en-us/library/ms178685.aspx and other articles in the same section.

    HTH

  • Thamizh
    19 Jun 2007 3:49 PM

    That was helpful, Carlo. Thank you

    Thamizh

Page 1 of 1 (3 items)
  • © 2013 Microsoft Corporation.
  • Terms of Use
  • Trademarks
  • Privacy & Cookies
  • Report Abuse
  • 5.6.426.415