Weird ASP.NET AJAX Bug / 32-bit to 64-bit

2020-06-19 03:36发布

问题:

I'm getting a weird error from my sites ever since upgrading to Windows 2008 64-bit. I have most of my app pools running in 64-bit mode (all but one, used for a legacy ASP.NET 1.1 application). On the sites that are running on 64-bit, I've been getting errors from ASP.NET AJAX.

Exception information:
   Exception type: System.NotSupportedException
   Exception message: Assembly "AjaxControlToolkit, Version=3.0.20820.16598, Culture=neutral, PublicKeyToken=28f01b0e84b6d53e" does not contain a script with hash code "e2e86ef9".

Request information:
   Request URL: http://site.com/page.aspx?_TSM_HiddenField_=ctl00_ctl00_elScripto_HiddenField&_TSM_CombinedScripts_=%3B%3BAjaxControlToolkit%2C+Version%3D3.0.20820.16598%2C+Culture%3Dneutral%2C+PublicKeyToken%3D28f01b0e84b6d53e%3Afr-FR%3A707835dd-fa4b-41d1-89e7-6df5d518ffb5%3Ae2e86ef9%3A9ea3f0e2%3A9e8e87e9%3A1df13a87%3Ad7738de7

Thread information:
   Thread ID: 21
   Thread account name: NT AUTHORITY\NETWORK SERVICE
   Is impersonating: False
   Stack trace:    at AjaxControlToolkit.ToolkitScriptManager.DeserializeScriptEntries(String serializedScriptEntries, Boolean loaded) in c:\AjaxControlToolkit_Admin\Release\AjaxControlToolkit\ToolkitScriptManager\ToolkitScriptManager.cs:line 534
  at AjaxControlToolkit.ToolkitScriptManager.OutputCombinedScriptFile(HttpContext context) in c:\AjaxControlToolkit_Admin\Release\AjaxControlToolkit\ToolkitScriptManager\ToolkitScriptManager.cs:line 264
  at AjaxControlToolkit.ToolkitScriptManager.OnInit(EventArgs e) in c:\AjaxControlToolkit_Admin\Release\AjaxControlToolkit\ToolkitScriptManager\ToolkitScriptManager.cs:line 198
  at System.Web.UI.Control.InitRecursive(Control namingContainer)
  at System.Web.UI.Control.InitRecursive(Control namingContainer)
  at System.Web.UI.Control.InitRecursive(Control namingContainer)
  at System.Web.UI.Control.InitRecursive(Control namingContainer)
  at System.Web.UI.Control.InitRecursive(Control namingContainer)
  at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)

The error appears to be a known issue in CodePlex but that doesn't help me much. Here's a link explaining the issue: http://dotnetdebug.net/2008/05/25/ajaxcontroltoolkit-toolkitscriptmanager-stringgethashcode-and-mixing-32bit-and-64bit-machinesprocesses/

I am not using load balancing and am wondering why my application would be switching between 32-bit and 64-bit modes.

Could it be that the DLLs must be compiled for a 64-bit architecture or something like that? Are there any weird issues I should be aware of that could be causing this issue for me?

回答1:

It looks like the String.GetHashCode() result changes based on what instruction set the dll has been compiled for. I can't explain why this happens within the framework when your .NET 2.0+ app pools are all 64-bit but there's a solution you can try if you're willing to grab the latest source off codeplex and change a few lines in the ToolkitScriptManager.

I don't know why an official fix hasn't been submitted based on the comments available--maybe because all the solutions are as ugly as mine?

I've attempted to fix it by using the SHA1 hash routine as described in one of the comments--so first I created a static instance of the SHA1Managed provider in the ToolkitScriptManager class as shown below:

public class ToolkitScriptManager : ScriptManager
{
    private static System.Security.Cryptography.SHA1Managed s = new System.Security.Cryptography.SHA1Managed();

...

then there are two places where the string hash code was being used that I commented out and replaced--once in the SerializeScriptEntries function:

//serializedScriptEntries.Append(scriptEntry.Name.GetHashCode().ToString("x", CultureInfo.InvariantCulture));
serializedScriptEntries.Append(Convert.ToBase64String(s.ComputeHash(System.Text.Encoding.UTF8.GetBytes(scriptEntry.Name))));

and then once in the DeserializeScriptEntries function:

//string hashCode = resourceName.GetHashCode().ToString("x", CultureInfo.InvariantCulture);
string hashCode = Convert.ToBase64String(s.ComputeHash(System.Text.Encoding.UTF8.GetBytes(resourceName)));

Maybe a simpler method would allow us to just access the 64-bit GetHashCode method for serializing this string so that we get the same results for 32-bit and 64-bit calls...