August Madness - A tale of Classic ASP, Two CLRs, IIS, and COM Interop
UPDATE: Here is how we solved this problem.
So, this is bizarre. The idea is this:
We want to share FormsAuth cookies between two ASP.NET sites on the same box. No biggie, right? However, one of the ASP.NET sites also has some Classic ASP pages in it. Still, no worries, right?
- The Classic ASP pages happen to use .NET objects that expose themselves to Classic ASP via COM Interop…
- If ASP.NET pages are hit ONCE in both sites (pools/appdomains) to 'bootstrap' the CLR, all is well and FormsAuthTickets will be sharable and jointly decryptable.
- .NET 1.1 and .NET 2.0 are installed on the systems
- Both ASP.NET applications/vdirs are configured to use .NET 1.1 in IIS
PROBLEM: If the site that creates the FormsAuthenticationTickets instead has the CLR 'bootstrapped' into the process/pool/domain by hitting a Classic ASP page that calls the COM-interop DLL, it causes later FormsAuthentication crypto to produce tickets that can't be decrypted by the other application.
QUESTION: What's going on? Both sites have web.config files with synchronized machinekeys (the machinekey is used by FormsAuth).
PARTIAL ANSWER: Turns out that if the Classic ASP page (that uses the .NET object that is used via COM) is hit first then .NET 2.0 gets loaded up inside that IIS Managed Application even if the ASP.NET application is set to use .NET 1.1!
Am I missing something? Does this mean that I can't have two classic ASP apps that use .NET objects via Interop, one using 1.1 and one using 2.0 on the same computer? Seems like it.
The issue is that ASP.NET doesn't start up the CLR because it's not hit first. The Classic ASP page is hit first, and apparently can't control the CLR version it gets! By the time someone hits an ASP.NET page, the CLR is already loaded up with a different version.
HERE'S THE KICKER: I don't yet understand why (on Win2k3, in our tests) the problem only happens when the anonymous identity for the web site is a domain account. If the anonymous identity was left as the default IUSR_xxxx, the CLR loaded is still 1.1 when a CCW is created. (!)
OUR WORKAROUND: We just let .NET 2.0 load up anyway and run our 1.1 application. We have to synchronize the machinekeys in BOTH CLR versions' machine.config files though.
Kudos to Peter Wong for figuring this stuff out. Now the question is - is there a good workaround or better explanation? My guess is we'll hear "functions as designed" but it seems to me that even though you can't indicate in the COM Registration stuff in the Registry what CLR Version to use (it's listed in the Registry, but the values are ignored) there should be some way.
Repro attached. Unzip this file into a c:\inetpub\wwwroot\wong test and make an IIS Application (isolated, or in its own AppPool in IIS). Get Process Explorer from SysInternals and hit x.asp after a fresh reset.
File Attachment: NET11_NET20_ASP.zip (894 bytes)