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