Ajax - Don't You Love Me?

As the .Net 3.5 Framework becomes more prevalent in the wild (and now .Net 4.0) we're starting to see some versioning issues with the ASP.NET AJAX modules. These issues can raise their heads in numerous ways, but the basic issue is the same, version conflicts. Umbraco also sees some of these issue occasionally, resulting in some head-scratchers in the forum.

Background

Prior to .Net 3.5, AJAX was a separate install which had to be downloaded and integrated separately. Many tools and sites built prior to .Net 3.5 or targeting .Net 2.0 or .Net 3.0 which wanted AJAX functionality often used this previous version, the most common still in the wild being 1.0.61025.0. This is often seen in the following references in the web.config...

  <configSections>
    <sectionGroup name="system.web.extensions" type="System.Web.Configuration.SystemWebExtensionsSectionGroup, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
      <sectionGroup name="scripting" type="System.Web.Configuration.ScriptingSectionGroup, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
        <section name="scriptResourceHandler" type="System.Web.Configuration.ScriptingScriptResourceHandlerSection, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="false" allowDefinition="MachineToApplication" />
        <sectionGroup name="webServices" type="System.Web.Configuration.ScriptingWebServicesSectionGroup, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
          <section name="jsonSerialization" type="System.Web.Configuration.ScriptingJsonSerializationSection, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="false" allowDefinition="Everywhere" />
          <section name="profileService" type="System.Web.Configuration.ScriptingProfileServiceSection, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="false" allowDefinition="MachineToApplication" />
          <section name="authenticationService" type="System.Web.Configuration.ScriptingAuthenticationServiceSection, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="false" allowDefinition="MachineToApplication" />
        </sectionGroup>
      </sectionGroup>
    </sectionGroup>
  </configSections>
  <system.web>
    <httpModules>
      <add name="ScriptModule" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
    </httpModules>
    <httpHandlers>
      <remove path="*.asmx" verb="*" />
      <add path="*.asmx" verb="*" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
      <add path="*_AppService.axd" verb="*" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
      <add path="ScriptResource.axd" verb="GET,HEAD" type="System.Web.Handlers.ScriptResourceHandler, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
    </httpHandlers>
    <compilation defaultLanguage="c#" debug="false" batch="false">
      <assemblies>
        <add assembly="System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
        <add assembly="System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=B03F5F7F11D50A3A" />
        <add assembly="System.Web.Extensions.Design, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
      </assemblies>
    </compilation>
  </system.web>

Also if you running on IIS 7.0 and using the new Integrated Mode you might also see the following:

  <!-- IIS 7 Integrated Mode Configuration -->
  <system.webServer>
    <modules>  
      <remove name="ScriptModule"/>
      <add name="ScriptModule" preCondition="managedHandler" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
    </modules>
    <handlers accessPolicy="Read, Write, Script, Execute">
      <remove name="WebServiceHandlerFactory-Integrated"/>
      <remove name="ScriptHandlerFactory"/>
      <remove name="ScriptHandlerFactoryAppServices"/>
      <remove name="ScriptResource"/>
      <add name="ScriptHandlerFactory" verb="*" path="*.asmx" preCondition="integratedMode" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
      <add name="ScriptHandlerFactoryAppServices" verb="*" path="*_AppService.axd" preCondition="integratedMode" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
      <add name="ScriptResource" preCondition="integratedMode" verb="GET,HEAD" path="ScriptResource.axd" type="System.Web.Handlers.ScriptResourceHandler, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
    </handlers>
  </system.webServer>

Unfortunately, with .Net 3.5 and now 4.0 web applications having AJAX support included, issues are cropping up with one version of the .Net AJAX assemblies being used in the main web application and others being used in modules or packages.

Symptoms

The two main errors that I've seen are the following:

When installing Umbraco on a Windows 7 box or Windows Server 2008 you might see the following even though you have a newer version of Systen.Web.Extensions on the box.

Could not load file or assembly 'System.Web.Extensions,  Version=1.0.61025.0,  Culture=neutral, PublicKeyToken=31bf3856ad364e35' or one of its  dependencies.

A stranger issue is when you see something similar the following:

[InvalidCastException:      Unable to cast object of type 'System.Web.Configuration.ScriptingScriptResourceHandlerSection' to type 'System.Web.Configuration.ScriptingScriptResourceHandlerSection'.        

or

... type (System.Web.UI.UpdatePanel) is not  compatible with the type of control (System.Web.UI.UpdatePanel)

What's Going On?

In the first case we simply have a case where the older ASP.Net AJAX 1.0 framework isn't installed on the machine in question but is being referenced somewhere.  You could install it, of course, and you may need to, however once you do, if you have the .Net 3.5 Framework installed  as well, you may one day find yourself dealing with the other symptoms described, so read on to avoid that future headache.

The other two errors (and other similar ones) are version conflicts.  A quick gloss  on this.  A long time ago (in OS years) there was a situation called DLL Hell in which the installation scripts for one program would overwrite dlls needed by another program with newer versions or even versions made for another OS causing unexpected failures.  To help avoid this issue, Microsoft started allowing multiple versions of the same dll to be installed at the same time.  Compiled assemblies reference a specific version of a dll to avoid this versioning issue.

For our specific discussion, this means that you can have two versions of the System.Web.Extensions.dll at the same time.  Therefore in your ASP.Net web application (i.e. Umbraco) you may have components referencing a newer version of a dll than is referenced in the web.config.  This can cause the strange scenario where your external page or control (.aspx / .ascx) references a type and gets the 1.X version but the code behind references the same object but knows about a 3.5 version of the type.  So, as far as the computer knows, the two items are not the same, thus those Type and Cast exceptions.

Solution

Missing DLLs

For the missing dlls issue, you have a couple of things you can try.  The solution for Versioning (below) may be sufficient, especially if you update the machine.config.  Another option, if you have access to the source you can update the references and recompile.  If those aren't viable or don't work, you may have to install the previous version of the ASP.Net AJAX framework, but if you do this, make sure you set up a binding redirect as discussed next.

Versioning

Once you have the proper files you should consider adding entries to either the web.config (to fix this web app) or the machine.config (to bind for all web apps) to bind calls to the System.Web.Extensions and the System.Web.Extensions.Design to the latest assemblies.  To do this add the following to the .config file to make sure that you are using the ASP.Net AJAX 3.5 versions of the files no matter where they are referenced in your web application.

  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="System.Web.Extensions" publicKeyToken="31bf3856ad364e35" />
        <bindingRedirect oldVersion="1.0.0.0-1.1.0.0" newVersion="3.5.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Web.Extensions.Design" publicKeyToken="31bf3856ad364e35" />
        <bindingRedirect oldVersion="1.0.0.0-1.1.0.0" newVersion="3.5.0.0" />
      </dependentAssembly>
    </assemblyBinding>
  </runtime>

As later versions of the .Net Framework gain popularity, you may need to update these references on older applications to keep your front-end and back-end in sync.

For more information on assembly binding see these Microsoft Articles.

http://msdn.microsoft.com/en-us/library/433ysdt1%28v=VS.71%29.aspx

http://msdn.microsoft.com/en-us/library/aa720323%28v=VS.71%29.aspx

1 comment for “Ajax - Don't You Love Me?”

  1. Posted Friday, October 14, 2011 at 4:27:43 AM

    I love to read this type of stuff. Good and attractive information I take from it..Thank you for posting such a nice article.

Post a comment