Issues with .NET 3.5 SP1 and EPiServer CMS 5.1 on IIS7 and how to get around them.

by: Fredrik Tjärnberg

The recent release of .NET 3.5 SP1 has caused some issues for the ones that are running EPiServer CMS on IIS7 (including me and my colleagues on the EPiServer CMS development team). If you run in integrated mode, any static file handled by the EPiServerStaticFile handler that is not served by a unified virtual path provider will result in a NotSupportedException. The end result will be a site without stylesheets and other static resources loaded.

The cause of this problem is a couple of lines added to BeginProcessRequest of System.Web.DefaultHttpHandler which throws unconditionally in this scenario. Reflector gives us:

public virtual IAsyncResult BeginProcessRequest(HttpContext context, AsyncCallback callback, object state) { if (HttpRuntime.UseIntegratedPipeline) { throw new PlatformNotSupportedException(SR.GetString("Method_Not_Supported_By_Iis_Integrated_Mode", new object[] { "DefaultHttpHandler.BeginProcessRequest" })); } ... }

We discovered the issue immediately after upgrading the first developer machine in our office. Being in the end of a long development project it is kind of scary to bump into things like this but because it is a service release that eventually everyone will have on their box and that there actually are other things that we depend on we had no choice but finding a solution. The focus was set on fixing this for the upcoming release (EPiServer CMS 5.2 which will have official support for IIS7). We ended up changing our StaticFileHandler code and modifying the configuration to have the "native" StaticFileHandler (the one that comes with IIS7) taking care of all static files not delivered by any of the configured virtual path providers.

The code changes in our own StaticFileHandler was needed for 5.2 specific features so it turns out that with just a little web.config mangling we can make it work in 5.1 as well so here are the necessary pieces pulled out of our tool for generating the web.config file for different scenarios:

Replace the wildcard handler that uses EPiServer.Web.StaticFileHandler with the built-in StaticFileHandler. Now your <system.webServer> section on the application level should look something like this:

<system.webServer> <modules runAllManagedModulesForAllRequests="true"> <add name="Initializer" type="EPiServer.Scheduler.Initializer, EPiServer.Scheduler" preCondition="managedHandler" /> <add name="WorkflowRuntime" type="EPiServer.WorkflowFoundation.WorkflowSystem, EPiServer.WorkflowFoundation" preCondition="managedHandler" /> <add name="UrlRewriteModule" type="EPiServer.Web.UrlRewriteModule, EPiServer" preCondition="managedHandler" /> </modules> <handlers> <clear /> <add name="TraceHandler-Integrated" path="trace.axd" verb="GET,HEAD,POST,DEBUG" type="System.Web.Handlers.TraceHandler" modules="ManagedPipelineHandler" scriptProcessor="" resourceType="Unspecified" requireAccess="Script" allowPathInfo="false" preCondition="integratedMode" responseBufferLimit="4194304" /> <add name="WebAdminHandler-Integrated" path="WebAdmin.axd" verb="GET,DEBUG" type="System.Web.Handlers.WebAdminHandler" modules="ManagedPipelineHandler" scriptProcessor="" resourceType="Unspecified" requireAccess="Script" allowPathInfo="false" preCondition="integratedMode" responseBufferLimit="4194304" /> <add name="AssemblyResourceLoader-Integrated" path="WebResource.axd" verb="GET,DEBUG" type="System.Web.Handlers.AssemblyResourceLoader" modules="ManagedPipelineHandler" scriptProcessor="" resourceType="Unspecified" requireAccess="Script" allowPathInfo="false" preCondition="integratedMode" responseBufferLimit="4194304" /> <add name="PageHandlerFactory-Integrated" path="*.aspx" verb="GET,HEAD,POST,DEBUG" type="System.Web.UI.PageHandlerFactory" modules="ManagedPipelineHandler" scriptProcessor="" resourceType="Unspecified" requireAccess="Script" allowPathInfo="false" preCondition="integratedMode" responseBufferLimit="4194304" /> <add name="SimpleHandlerFactory-Integrated" path="*.ashx" verb="GET,HEAD,POST,DEBUG" type="System.Web.UI.SimpleHandlerFactory" modules="ManagedPipelineHandler" scriptProcessor="" resourceType="Unspecified" requireAccess="Script" allowPathInfo="false" preCondition="integratedMode" responseBufferLimit="4194304" /> <add name="WebServiceHandlerFactory-Integrated" path="*.asmx" verb="GET,HEAD,POST,DEBUG" type="System.Web.Services.Protocols.WebServiceHandlerFactory, System.Web.Services, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" modules="ManagedPipelineHandler" scriptProcessor="" resourceType="Unspecified" requireAccess="Script" allowPathInfo="false" preCondition="integratedMode" responseBufferLimit="4194304" /> <add name="HttpRemotingHandlerFactory-rem-Integrated" path="*.rem" verb="GET,HEAD,POST,DEBUG" type="System.Runtime.Remoting.Channels.Http.HttpRemotingHandlerFactory, System.Runtime.Remoting, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" modules="ManagedPipelineHandler" scriptProcessor="" resourceType="Unspecified" requireAccess="Script" allowPathInfo="false" preCondition="integratedMode" responseBufferLimit="4194304" /> <add name="HttpRemotingHandlerFactory-soap-Integrated" path="*.soap" verb="GET,HEAD,POST,DEBUG" type="System.Runtime.Remoting.Channels.Http.HttpRemotingHandlerFactory, System.Runtime.Remoting, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" modules="ManagedPipelineHandler" scriptProcessor="" resourceType="Unspecified" requireAccess="Script" allowPathInfo="false" preCondition="integratedMode" responseBufferLimit="4194304" /> <add name="TRACEVerbHandler" path="*" verb="TRACE" type="" modules="ProtocolSupportModule" scriptProcessor="" resourceType="Unspecified" requireAccess="None" allowPathInfo="false" preCondition="" responseBufferLimit="4194304" /> <add name="OPTIONSVerbHandler" path="*" verb="OPTIONS" type="" modules="ProtocolSupportModule" scriptProcessor="" resourceType="Unspecified" requireAccess="None" allowPathInfo="false" preCondition="" responseBufferLimit="4194304" /> <add name="StaticFileHandler" path="*" verb="*" modules="StaticFileModule,DefaultDocumentModule,DirectoryListingModule" resourceType="Either" requireAccess="Read" /> </handlers> </system.webServer>

Note the StaticFileHandler registration at the bottom.

Now set the EPiServer.Web.StaticFileHandler to serve static files coming from virtual path providers. In a default installation of 5.1 you will have three configured virtual path providers that needs to be taken care of PageFiles, Documents and Global. You do this by adding location elements that modifies the handler mapping for the configured virtual paths. If not already done, add the WebResource.axd handler as well so that requests for resources in a VPP initiates the WebResource handler correctly.

<location path="PageFiles"> <system.webServer> <handlers> <add name="WebResources" path="WebResource.axd" verb="GET" type="System.Web.Handlers.AssemblyResourceLoader" /> <add name="wildcard" path="*" verb="*" type="EPiServer.Web.StaticFileHandler, EPiServer" /> </handlers> </system.webServer> </location> <location path="Documents"> <system.webServer> <handlers> <add name="WebResources" path="WebResource.axd" verb="GET" type="System.Web.Handlers.AssemblyResourceLoader" /> <add name="wildcard" path="*" verb="*" type="EPiServer.Web.StaticFileHandler, EPiServer" /> </handlers> </system.webServer> </location> <location path="Global"> <system.webServer> <handlers> <add name="WebResources" path="WebResource.axd" verb="GET" type="System.Web.Handlers.AssemblyResourceLoader" /> <add name="wildcard" path="*" verb="*" type="EPiServer.Web.StaticFileHandler, EPiServer" /> </handlers> </system.webServer> </location>

That's it! With a little luck your site is now functioning as expected.

15 August 2008

Tags:


    Comments

    1. If you get into trouble with this, check that du have installed ASP.Net 3.5 SP1 (release) and not 3.5 SP1 Beta. VS 2008 reports ASP.Net 3.5 SP1 even though it's ASP.Net 3.5 Beta that's installed.
    2. If you get into trouble with this, check that du have installed ASP.Net 3.5 SP1 (release) and not 3.5 SP1 Beta. VS 2008 reports ASP.Net 3.5 SP1 even though it's ASP.Net 3.5 Beta that's installed.
    Post a comment    
    User verification Image for user verification  
    Fredrik Tjärnberg

    About me

    Developer and Team Lead for the backend development team with an unnatural interest in developer tools such as Visual Studio and MSBuild and Team Foundation Server.


    Syndications


    Archive


    Tag cloud

    EPiTrace logger