Suppose you have a web application which authenticates clients through a smartcard certificate and everything is working fine, then you decide to move your web application to Windows Server 2008 (which is a good decision in many ways ) but your users are suddenly complaining about slow performance, pages are loading slower than they used to do and you cannot find any explanation on the network infrastructure, everything seems to be properly configured on the client and on the server… what is happening?
Well, as you can imagine this is what happened to a customer I worked with recently. A closer look at the client showed that every time a new object in the page was loaded (images, script files, css…) the smartcard was checked for the certificate, resulting in a major performance loss.
To make the story short, the behavior is controlled by client certificate negotiation, specifically by SSLAlwaysNegoClientCert which in IIS 7 has been moved to http.sys (see http://learn.iis.net/page.aspx/110/changes-between-iis-60-and-iis-7-security/); you can configure the <access> element as described or using netsh with a command such as the following:
netsh http add sslcert ipport=0.0.0.0:$port certstorename=MY certhash=$Certhash appid=$Appnr sslctlidentifier=$CTLlijst sslctlstorename=CA clientcertnegotiation=enable
Carlo
I recently come across an interesting request which read like this:
A simple webapplication with one Textbox and one label. The Textbox has Autopostback=”true” and has an event listener attached to the TextChanged event. In the TextChanged event the label’s text is set to the text in the textbox. A javascript function “formats” the value of the textbox on the keyUp event. The ”problem” The postback is not fired for a textbox if a javascript function sets the value of the textbox in the keyDown or keyUp event. This only occurs in IE (IE 8, IE 7, FF 3.6.8, Opera 10.6 and Chrome 5 has been tested). No javascript errors or any kind of error message, the postback is just not being fired.
And here’s a sample page to reproduce the problem:
<%@ Page Language="vb" AutoEventWireup="false" ValidateRequest="false" EnableEventValidation="false" EnableViewStateMac="false" %><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head runat="server"> <title></title> <script type="text/javascript" language="javascript"> function FormatTextBox(obj) { //This is just a dummy function that adds $ as the first character. var value = obj.value if (value.length > 0 && value.charAt(0) != '$') value = '$' + value; obj.value = value; // This line causes the autopostback not to fire. This only happens if the value of the input // is set in the keyup or keydown event and only in IE. } </script> <script language="vbscript" runat="server"> 'Just to have something happening during the autopostback. Private Sub TextBox1_TextChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles TextBox1.TextChanged Label1.Text = TextBox1.Text End Sub </script></head><body> <form id="form1" runat="server"> <div> <asp:TextBox ID="TextBox1" runat="server" onkeyup="return FormatTextBox(this);" AutoPostBack="true"></asp:TextBox> <asp:Label ID="Label1" runat="server" Text="Label"></asp:Label> </div> </form></body></html>
Type something in the textbox then hit TAB (or click somewhere on the white page) and you’ll see nothing happens, while you should have a postback and the Label should reflect the text you typed (plus the “$” sign added by the FormatTextBox function). Interestingly enough if you type only one character in the TextBox you’ll have the problem, if you type in two or more characters then everything will work. Another interesting effect: if you type the dollar sign (“$”) which happens to be the sign added by javascript, you’ll never have an automatic postback no matter how many “$” you’ll type in.
Why is it happening? Well, any time you type a new character into the TextBox, IE compares the new value to some internal 'initial' value that it it keeping to see if the text has changed. However, when you set the value of the TextBox programmatically, IE makes the assumption that you know what just happened and that it doesn't have to fire the onChange event. So it resets its internal tracking value to be the same as the value you just programmatically set. Then when you tab out of focus, the two values are the same and no onChange event gets fired.
So, how to deal with it? The easiest solution is to use the OnBlur event or,
if you really need to hook on the onkeyup event, is to track the state of the TextBox on your own and force the onchange event to fire, even if you programatically set the TextBox value. Use a TextBox like this:
<asp:TextBox ID="TextBox1" runat="server" onkeyup="FormatTextBoxDirty(this)" onblur="if (this.dirty){this.onchange();}" AutoPostBack="true" />
and javascript like this:
function FormatTextBoxDirty(obj) { obj.dirty = false; // This prevents firing onchange twice in the event that we don't modify the value if (obj.value.length > 0 && obj.value.charAt(0) != '$') { obj.value = '$' + obj.value; obj.dirty = true; } }
<%@ Page Language="vb" AutoEventWireup="false" ValidateRequest="false" EnableEventValidation="false" EnableViewStateMac="false" %><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head id="Head1" runat="server"> <title></title> <script type="text/javascript" language="javascript"> function FormatTextBox(obj) { //This is just a dummy function that adds $ as the first character. var value = obj.value if (value.length > 0 && value.charAt(0) != '$') value = '$' + value; obj.value = value; // This line causes the autopostback not to fire. This only happens if the value of the input // is set in the keyup or keydown event and only in IE. } function FormatTextBoxDirty(obj) { obj.dirty = false; // This prevents firing onchange twice in the event that we don't modify the value if (obj.value.length > 0 && obj.value.charAt(0) != '$') { obj.value = '$' + obj.value; obj.dirty = true; } } </script> <script language="vbscript" runat="server"> 'Just to have something happening during the autopostback. Private Sub TextBox1_TextChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles TextBox1.TextChanged Label1.Text = TextBox1.Text End Sub </script></head><body> <form id="form1" runat="server"> <div> <asp:TextBox ID="TextBox1" runat="server" onkeyup="FormatTextBoxDirty(this)" onblur="if (this.dirty){this.onchange();}" AutoPostBack="true" /> <asp:Label ID="Label1" runat="server" Text="Label"></asp:Label> </div> </form></body></html>
P.s. Thanks to Steve Molloy for this help on this matter.
Quote of the day: Minds are like parachutes: they only work when they are open – Anonymous
Stephen King fans like me for sure know Night Shift, a collection of 19 short stories I first read almost (oh, my…) almost 20 years ago. In Italian the title of this collection has been translated as “A volte ritornano” which literally means Sometimes they come back. This is exactly what I thought yesterday when I got yet another version of the “503 Service Unavailable” error: after I have already written about this error here and here, I’m writing the third post about it. I’m wondering if I’ll end up with a 19 post collection as Night Shift has…
Anyway, here’s the new story: the application pools of this web server were failing with the following error
(eventid 281) The worker process for application pool 'MSExchangeOWAAppPool' encountered an error 'Unrecognized attribute 'precondition' trying to read global module configuration data from file '\\?\C:\inetpub\temp\apppools\MSExchangeOWAAppPool.config', line number '281'. Worker process startup aborted.
As you can see the precondition keyword is mistyped (it should be preCondition, capital “C”) and if we changed the .config file mentioned in the error message we were able to start our application pool but randomly (most of the time after a reboot, though) the problem came back. Interesting to note is the path of the .config file mentioned in the error: C:\inetpub\temp\AppPools\xxxxxx.config
This is where Configuration Isolation stores the application pool specific configuration files:
IIS worker processes do not have Read access to applicationHost.config. How, then, are they able to read any of the configuration set in this file? The answer lies in the configuration isolation feature provided by IIS 7.0, which is always on by default. Instead of enabling IIS worker processes to read applicationHost.config directly when reading the configuration file hierarchy, IIS generates filtered copies of this file and uses these copies as a replacement of applicationHost.config when configuration is read inside the IIS worker process. The reason for doing this is to prevent IIS worker processes from application pool A to be able to read configuration information in applicationHost.config that is intended for application pool B. Because applicationHost.config may contain sensitive information, such as the user name and password for custom application pool identities, as well as user name and password for virtual directories, allowing all application pools to access applicationHost.config would break application pool isolation. WAS is responsible for generating the temporary application pool configuration files that each IIS worker process uses as a replacement of applicationHost.config. These files are placed by default in the %SystemDrive%\Inetpub\Temp\Apppools directory and are named AppPoolName.config. As mentioned earlier, these files are configured to allow access only to the IIS worker processes in the corresponding application pool, by using the IIS APPPOOL\AppPoolName Application Pool SID. Note This process occurs automatically each time applicationHost.config is changed and therefore does not require any manual action from the administrator outside of normal configuration procedures. Each application pool configuration file contains the configuration in applicationHost.config, with the following information removed: All application pool definitions in the system.applicationHost/applicationPools configuration section. Only WAS is required to read this configuration section. Any Web site definitions in the system.applicationHost/sites configuration section for sites that do not have applications in the current application pool. Any configuration in location tags for specific Web sites, applications, or URLs that do not reside inside the applications in the current application pool. Caution All application definitions (and their virtual directory definitions, possibly containing user name and password credentials) for any site that has at least one application in the current application pool will be present in the application pool configuration file. To disable this behavior and include only the application definitions for applications in the application pool, set the IsolationWholeSiteInclude DWORD value to 0 in the HKLM\System\CurrentControlSet\Services\WAS\Parameters key and perform an IISRESET. This may break applications in sites with applications in multiple application pools when they attempt to map physical paths for URLs in other applications. Keep in mind that global configuration settings set in the applicationHost.config (without using location tags to apply them to specific Web sites, applications, or URLs) are not filtered. Each application pool configuration file will contain all of these settings. Configuration isolation is a key part of the application pool isolation strategy in IIS 7.0. It is enabled by default to provide configuration isolation for server-level configuration in applicationHost.config. For strategies on achieving proper application pool isolation, see the section titled "Isolating Applications" earlier in this chapter. Caution Configuration stored in .NET Framework machine.config and root web.config files is not isolated. Only configuration stored in applicationHost.config is isolated.
IIS worker processes do not have Read access to applicationHost.config. How, then, are they able to read any of the configuration set in this file?
The answer lies in the configuration isolation feature provided by IIS 7.0, which is always on by default. Instead of enabling IIS worker processes to read applicationHost.config directly when reading the configuration file hierarchy, IIS generates filtered copies of this file and uses these copies as a replacement of applicationHost.config when configuration is read inside the IIS worker process.
The reason for doing this is to prevent IIS worker processes from application pool A to be able to read configuration information in applicationHost.config that is intended for application pool B. Because applicationHost.config may contain sensitive information, such as the user name and password for custom application pool identities, as well as user name and password for virtual directories, allowing all application pools to access applicationHost.config would break application pool isolation.
WAS is responsible for generating the temporary application pool configuration files that each IIS worker process uses as a replacement of applicationHost.config. These files are placed by default in the %SystemDrive%\Inetpub\Temp\Apppools directory and are named AppPoolName.config. As mentioned earlier, these files are configured to allow access only to the IIS worker processes in the corresponding application pool, by using the IIS APPPOOL\AppPoolName Application Pool SID.
Note This process occurs automatically each time applicationHost.config is changed and therefore does not require any manual action from the administrator outside of normal configuration procedures.
Each application pool configuration file contains the configuration in applicationHost.config, with the following information removed:
Caution All application definitions (and their virtual directory definitions, possibly containing user name and password credentials) for any site that has at least one application in the current application pool will be present in the application pool configuration file. To disable this behavior and include only the application definitions for applications in the application pool, set the IsolationWholeSiteInclude DWORD value to 0 in the HKLM\System\CurrentControlSet\Services\WAS\Parameters key and perform an IISRESET. This may break applications in sites with applications in multiple application pools when they attempt to map physical paths for URLs in other applications.
Keep in mind that global configuration settings set in the applicationHost.config (without using location tags to apply them to specific Web sites, applications, or URLs) are not filtered. Each application pool configuration file will contain all of these settings.
Configuration isolation is a key part of the application pool isolation strategy in IIS 7.0. It is enabled by default to provide configuration isolation for server-level configuration in applicationHost.config. For strategies on achieving proper application pool isolation, see the section titled "Isolating Applications" earlier in this chapter.
Caution Configuration stored in .NET Framework machine.config and root web.config files is not isolated. Only configuration stored in applicationHost.config is isolated.
So, this means the mistyped entry very likely originates from applicationHost.config… We do not know what (or who ) changed this since I have the same roles and features installed on my machine as the customer had on his server, but after fixing the typo in the centralized configuration file the problem disappeared.
Quote of the day: To avoid situations in which you might make mistakes may be the biggest mistake of all. - Peter McWilliams
Lots of stuff kept me busy over the last few months and this blog has been a bit too quiet… let me try to revamp it a bit (new graphic layout will come later).
I recently worked on an interesting case where a simple GridView with pagination enabled was not working as expected: every time we clicked a different page (note, page referred to the GridView pages, not .aspx pages…) we were quickly brought back to the first page: no errors logged anywhere (IIS logs, Fiddler, event viewer… nothing really useful there). Then we decided to make a quick test: we bypassed the ISA proxy and everything started working fine, no way to reproduce the problem again; needless to say, as soon as we reconfigured the proxy in IE the problem came back.
My colleague Alvar works also on ISA cases and suggested the article POST requests that do not have a POST body may be sent to a Web server that is published in ISA Server 2006 and this actually did the trick, problem solved! Thanks Alvar
I’ve been using the new Arc Keyboard for a few weeks now and I’m very pleased with it, I like it especially for typing. But (there is always a “but” )… Unfortunately I have to say this keyboard is not very practical when working with Windbg or Visual Studio (at least with the Italian layout) where you have to type special characters such as tilde (~) or braches ( { } ). Well, it is possible to get braches with the key combination ATL GR+SHIFT+è for the open one and ALT GR+SHIFT++ or ALT+123 and ALT+125 on the numpad if available and despite the weird key combination I got used to press it with only one hand and my typing flow was acceptable, even on a laptop where the numpad cannot be used. Anyway I’ve not been able to find how to get the tilde sign on an Italian keyboard without using the numpad combination (ALT+126), this means I cannot use neither my laptop nor the Arc Keyboard for coding… Should I use two different keyboards, then? No way
Bing came to the rescue and pointed me to the Keyboard Layout Creator that, among other things, allows to modify and extend an existing keyboard layout adding new keys and key combinations, and it’s easy to use, too .
So I started loading the Italian keyboard layout and decided to use the ALT GR key as my function key for my new key combinations: it’s easy to check which keys are already assigned and which are free:
Now just double-click a key on the keyboard to get this dialog:
Now just add the new key in the box with the corresponding control key combination (I chose CTRL+ALT+<key>) to assign it; after some quick tests I came up with the following layout which I’m using on all my machines now:
From the Project menu is possible to validate and test the new keyboard layout and also the Build DLL and Setup Package that creates a MSI setup package to install the new keyboard. Once installed, the new keyboard can be enabled from the Text Services and Input Languages dialog (click on Change keyboard on Region and Language dialog, Keyboarda and Languages tab), choose your custom keyboard layout as the Default input language:
Hope you’ll enjoy your new keyboard layout as I’m doing with mine .
Download it from the IDEVDataCollector page .
Don’t expect too sophisticated coding techniques (at least it gets the job done), let me know what you think, I’m open for suggestions and feature requests .
Quote of the day: ...when you have eliminated the impossible, whatever remains, however improbable, must be the truth. - Sir Arthur Conan Doyle
It took me some time (mostly because of other demanding tasks and commitments I have for my daily job) but finally I have just updated IDEVDataCollector to support IIS 6, it’s available at the tool main page: http://blogs.msdn.com/carloc/pages/idevdatacollector.aspx.
Give it a try and let me know what you think
P.s. Yes, I’m planning to release the source code too, stay tuned!
Over the last couple of months among other things I’ve been working on a tool to automatically the logs and information in my team we usually ask at the beginning of a new Support Call: all standard things such as IIS logs, event logs, .config files etc… Not all of those files are necessary for every case (as usual it depends on the problem at hand), but experience tells me the more information we have about the environment, the more chances we have to spot small inconsistencies, configuration problems etc… that sometimes can lay unnoticed and interfere with our work.
So, enter our guest:
I tried to keep the UI as simple and organized as possible, utilization is very easy, just run it and click the “Collect” button, sit there a couple of minutes (how much exactly will depend on the logs collected) and you’re done . Please note that I’m still working on it, this is just a preview release but I’d love to have your feedback/bug reports/feature requests etc…, keeping in mind that the scope of this tool is to facilitate troubleshooting and data collection for IIS/ASP.NET related problems, I am not interested (and probably do not have the time) to build an omnicomprehensive tool to replace everything else we have today .
So, here is the list of what it collects so far:
Important: it currently works only with IIS 7 (hence on Vista/Windows 7/Windows 2008 and Windows 2008 R2).
Already on the “to do” list:
The dedicated page is http://blogs.msdn.com/carloc/pages/idevdatacollector.aspx, let me know what if think!
I just realized I have not posted anything here over the last couple of months which is definitely not a good thing to keep a blog alive… It’s been a busy period, I’ve been working on the Italian Developer Support Blog with my colleague Raffaele, of course working with our customers on Support Cases, working on a few internal organizational changes (still in progress) and I’ve also been working on a tool to automatically collect logs and information about IIS, ASP.NET and the server itself we’ll (hopefully ) use in our everyday work when troubleshooting customer’s problems.
One of the toughest problems I worked on in this period was actually on my machine… for some reason I could no longer use Silverlight on my office desktop, every time Internet Explorer proposed to install the component but either the setup failed with an error indicating that Silverlight was already installed on my machine (which it really was!) or some other error that inevitably lead to an aborted setup. This seemed to be a machine-wide setting (not just my account) because I got the same problem no matter which account I used to log-on to my machine.
If you quickly need to get your Silverlight working you can do as I did: use the “Reset Internet Explorer Settings” button in the “Advanced” tab to restore some IE settings to their default RTM state; this will not delete your personal data (cookies, forms, InPrivate filters, accelerators etc…) unless you explicitly flag the “Delete personal settings” checkbox:
Anyway I am curios and I managed to collect some data before and after the reset to compare and get the differences and identify which setting is causing the problem (of course I’ll post it when ready), I just wanted to save you and headache in case you have this same issue.
I already wrote a post on this matter some time ago, but this week worked on the same problem on a Windows 2000 Server, of course 32 bit.
Running aspnet_regiis -i did not help so we tried to run the script Tom provides in his post, but we got the error here below:
Line 41 is “Set objIIS = GetObject("IIS://" & strComputer & "/W3SVC/AppPools")”, this path does not exist in IIS 5 metabase, hence the error. To adapt it to IIS 5 we removed the script section that checks for Enable32BitAppOnWin64.
We run the script again and got this message:
PASS: The current value of Restrict_Run is: 0 PASS: Successfully registered mmcaspext.dll PASS: Successfully registered AspNetMMC Microsoft (R) .NET Framework Assembly Registration Utility 2.0.50727.1433 Copyright (C) Microsoft Corporation 1998-2004. All rights reserved. Types registered successfully Assembly exported to 'C:\WINNT\Microsoft.NET\Framework\v2.0.50727\AspNetMMCExt.tlb', and the type library was registered successfully PASS: Successfully registered Assembly Running aspmantst.exe to test the ASP.NET Tab snap-in Attempting to create the object as CLSCTX_LOCAL_SERVER. Create failed. hr: 80070005. QIhr: 80070005. GLE: 1008 Attempting to create the object as CLSCTX_REMOTE_SERVER to <machine_name>. Create failed. hr: 80070005. QIhr: 80070005. GLE: 1008 Attempting to create the object as CLSCTX_INPROC_SERVER. Object created. Attempting to call method. Method succeded. Result: 1.1.4322.0,C:\WINNT\Microsoft.NET\Framework\v1.1.4322\aspnet_isapi.dll,2.0.50727.0,C:\WINNT\Microsoft.NET\Framework\v2.0.50727\aspnet_isapi.dll
Code 80070005 means “Access Denied”, so we do not have enough permission to complete the configuration… The object we are trying to create, which represents the ASP.NET Ta in IIS Manager, is listed in dcomcnfg as Microsoft.Aspnet.Snapin.AspNetManagementUtility.2. In a default Windows 2000 SP4 installation, the Default Access Permission ACL is empty: when you log in as an administrator, if the ACL list is empty then the owner changes to whatever account you are logging on with: this account is the owner and implicitly has access to the COM instantiation works fine. But if the ACL list is not empty (it contains any account or group) the owner does not change at logon and the automatic mechanism just described does not work.
Likely the same missing permission we were already facing, Microsoft.Aspnet.Snapin.AspNetManagementUtility.2 did not show up in our application list… so we add a look at the same kind of permission, but this time we checked the “Default Security” tab:
And here we were! On another working machine this customer had the ACL list was empty, while for some reason on the failing machine the list was not empty, we had an account listed there… in such a situation there are two options:
In our case we cleared the list, run the script again (this time every step completed successfully) and the customer got his ASP.NET Tab available in IIS Manager
Quote of the day: If you develop an ear for sounds that are musical it is like developing an ego. You begin to refuse sounds that are not musical and that way cut yourself off from a good deal of experience. - John Cage
Here’s another interesting crash problem I worked on a few days ago: the application pool was randomly crashing and the following errors were logged:
Event Type: Error Event Source: .NET Runtime 2.0 Error Reporting Event Category: None Event ID: 1000 Date: 21/08/2009 Time: 12:23:12 User: N/A Computer: <computername> Description: Faulting application w3wp.exe, version 6.0.3790.3959, stamp 45d691cc, faulting module kernel32.dll, version 5.2.3790.4062, stamp 462643a7, debug? 0, fault address 0x0000000000027d8d.
Event Type: Warning Event Source: W3SVC Event Category: None Event ID: 1011 Date: 21/08/2009 Time: 12:23:14 User: N/A Computer: <computername> Description: A process serving application pool <AppPoolName> suffered a fatal communication error with the World Wide Web Publishing Service. The process id was xxx. The data field contains the error number.
Even if with some difficulties (we had to disable Error Reporting as described here) we managed to capture a coupe of dumps for this crash; dumping the exception was not very helpful:
0:027> !gleLastErrorValue: (Win32) 0x3f0 (1008) - An attempt was made to reference a token that does not exist.LastStatusValue: (NTSTATUS) 0xc000007c - An attempt was made to reference a token that doesn't exist. This is typically done by referencing the token associated with a thread when the thread is not impersonating a client.0:027> !printexceptionThere is no current managed exception on this thread
0:027> !gleLastErrorValue: (Win32) 0x3f0 (1008) - An attempt was made to reference a token that does not exist.LastStatusValue: (NTSTATUS) 0xc000007c - An attempt was made to reference a token that doesn't exist. This is typically done by referencing the token associated with a thread when the thread is not impersonating a client.
0:027> !printexceptionThere is no current managed exception on this thread
But dumping the very long stack gave some good hint at least about a potential problem (a stack overflow):
0:027> kpLChild-SP RetAddr Call Site00000000`05fcae90 00000642`7f895333 kernel32!RaiseException+0x7300000000`05fcaf60 00000642`78390730 mscorwks!`string'+0x81ef300000000`05fcb130 00000642`780a9522 mscorlib_ni!System.OrdinalComparer.Equals(<HRESULT 0x80004001>)+0x7000000000`05fcb170 00000642`7809822a mscorlib_ni!System.Collections.Hashtable.KeyEquals(<HRESULT 0x80004001>)+0x4200000000`05fcb1a0 00000642`748f8976 mscorlib_ni!System.Collections.Hashtable.get_Item(<HRESULT 0x80004001>)+0x15a00000000`05fcb260 00000642`748ff9bc System_ni!System.Collections.Specialized.NameObjectCollectionBase.FindEntry(<HRESULT 0x80004001>)+0x1600000000`05fcb290 00000642`80580f48 System_ni!System.Collections.Specialized.NameValueCollection.Get(<HRESULT 0x80004001>)+0xc00000000`05fcb2c0 00000642`8058108d MyTest!MyClass.Web.Pages.BasePage.get_Language(<HRESULT 0x80004001>)+0x4800000000`05fcb300 00000642`8058108d MyTest!MyClass.Web.Pages.BasePage.get_Language(<HRESULT 0x80004001>)+0x18d00000000`05fcb340 00000642`8058108d MyTest!MyClass.Web.Pages.BasePage.get_Language(<HRESULT 0x80004001>)+0x18d00000000`05fcb380 00000642`8058108d MyTest!MyClass.Web.Pages.BasePage.get_Language(<HRESULT 0x80004001>)+0x18d00000000`05fcb3c0 00000642`8058108d MyTest!MyClass.Web.Pages.BasePage.get_Language(<HRESULT 0x80004001>)+0x18d00000000`05fcb400 00000642`8058108d MyTest!MyClass.Web.Pages.BasePage.get_Language(<HRESULT 0x80004001>)+0x18d00000000`05fcb440 00000642`8058108d MyTest!MyClass.Web.Pages.BasePage.get_Language(<HRESULT 0x80004001>)+0x18d00000000`05fcb480 00000642`8058108d MyTest!MyClass.Web.Pages.BasePage.get_Language(<HRESULT 0x80004001>)+0x18d00000000`05fcb4c0 00000642`8058108d MyTest!MyClass.Web.Pages.BasePage.get_Language(<HRESULT 0x80004001>)+0x18d00000000`05fcb500 00000642`8058108d MyTest!MyClass.Web.Pages.BasePage.get_Language(<HRESULT 0x80004001>)+0x18d00000000`05fcb540 00000642`8058108d MyTest!MyClass.Web.Pages.BasePage.get_Language(<HRESULT 0x80004001>)+0x18d00000000`05fcb580 00000642`8058108d MyTest!MyClass.Web.Pages.BasePage.get_Language(<HRESULT 0x80004001>)+0x18d00000000`05fcb5c0 00000642`8058108d MyTest!MyClass.Web.Pages.BasePage.get_Language(<HRESULT 0x80004001>)+0x18d00000000`05fcb600 00000642`8058108d MyTest!MyClass.Web.Pages.BasePage.get_Language(<HRESULT 0x80004001>)+0x18d00000000`05fcb640 00000642`8058108d MyTest!MyClass.Web.Pages.BasePage.get_Language(<HRESULT 0x80004001>)+0x18d00000000`05fcb680 00000642`8058108d MyTest!MyClass.Web.Pages.BasePage.get_Language(<HRESULT 0x80004001>)+0x18d00000000`05fcb6c0 00000642`8058108d MyTest!MyClass.Web.Pages.BasePage.get_Language(<HRESULT 0x80004001>)+0x18d00000000`05fcb700 00000642`8058108d MyTest!MyClass.Web.Pages.BasePage.get_Language(<HRESULT 0x80004001>)+0x18d00000000`05fcb740 00000642`8058108d MyTest!MyClass.Web.Pages.BasePage.get_Language(<HRESULT 0x80004001>)+0x18d00000000`05fcb780 00000642`8058108d MyTest!MyClass.Web.Pages.BasePage.get_Language(<HRESULT 0x80004001>)+0x18d00000000`05fcb7c0 00000642`8058108d MyTest!MyClass.Web.Pages.BasePage.get_Language(<HRESULT 0x80004001>)+0x18d00000000`05fcb800 00000642`8058108d MyTest!MyClass.Web.Pages.BasePage.get_Language(<HRESULT 0x80004001>)+0x18d00000000`05fcb840 00000642`8058108d MyTest!MyClass.Web.Pages.BasePage.get_Language(<HRESULT 0x80004001>)+0x18d00000000`05fcb880 00000642`8058108d MyTest!MyClass.Web.Pages.BasePage.get_Language(<HRESULT 0x80004001>)+0x18d00000000`05fcb8c0 00000642`8058108d MyTest!MyClass.Web.Pages.BasePage.get_Language(<HRESULT 0x80004001>)+0x18d[...]
Using the err.exe utility to lookup the exit code of the process when it crashed, we can confirm we had a stack overflow:
Event Type: WarningEvent Source: W3SVCEvent Category: NoneEvent ID: 1009Date: 21/08/2009Time: 13:44:11User: N/AComputer: <computername>Description: A process serving application pool <AppPoolName> terminated unexpectedly. The process id was '5392'. The process exit code was '0x800703e9'.C:\>err 0x800703e9# for hex 0x800703e9 / decimal -2147023895 COR_E_STACKOVERFLOW corerror.h# Is raised by the EE when the execution stack overflows as# it is attempting to ex# as an HRESULT: Severity: FAILURE (1), FACILITY_WIN32 (0x7), Code 0x3e9# for hex 0x3e9 / decimal 1001 ERROR_STACK_OVERFLOW winerror.h# Recursion too deep; the stack overflowed.# 2 matches found for "0x800703e9"
Event Type: WarningEvent Source: W3SVCEvent Category: NoneEvent ID: 1009Date: 21/08/2009Time: 13:44:11User: N/AComputer: <computername>Description: A process serving application pool <AppPoolName> terminated unexpectedly. The process id was '5392'. The process exit code was '0x800703e9'.
C:\>err 0x800703e9# for hex 0x800703e9 / decimal -2147023895 COR_E_STACKOVERFLOW corerror.h# Is raised by the EE when the execution stack overflows as# it is attempting to ex# as an HRESULT: Severity: FAILURE (1), FACILITY_WIN32 (0x7), Code 0x3e9# for hex 0x3e9 / decimal 1001 ERROR_STACK_OVERFLOW winerror.h# Recursion too deep; the stack overflowed.# 2 matches found for "0x800703e9"
In the IIS log the request that lead to the crash was like this:
GET
/MyApp/test.aspx?currentPreferences=2&ParentId=1&ClientDateTime=Wed%20Aug%2019%202009%2009:09:57%20GMT+0100%20(GMT%20Standard%20Time)&TimeZone=-60&Language=undefined&Currency=undefined&OrgUnitId=undefined
Basically some user was using a robot to scrape the web site and the Language parameter (along with a few others) was not correctly set; in this case the customer’s code was not properly validating those parameters (using a browser they are always valid) and this cause the endless recursion that ultimately exhausted the stack.
Needless to say, improving the parameter validation logic resolved the problem
Yesterday my Italian colleagues in Developer Support and I officially inaugurated our new team blog: if you can read Italian then join us at http://blogs.msdn.com/itasupport
If you have a complex solution, with a lot of folders and subfolders, and you are hosting and debugging it on a remote IIS server (not on your local machine), you may get an error similar to the following:
An error occurred loading a configuration file: Failed to start monitoring changes to '<path>' because the network BIOS command limit has been reached. For more information on this error, please refer to Microsoft knowledge base article 810886. Hosting on a UNC share is not supported for the Windows XP Platform
The article mentioned in the error message (810886) suggests to change the MaxCmds and MaxMpxCt values, but when I had the chance to work on this problem this solution does not always work (anyway I suggest you to give it a try before discarding it).
You may find another message in your event log, like the following:
Event Type: Warning Event Source: Srv Event Category: None Event ID: 2021 Date: Time: User: N/A Computer: Description: The server was unable to allocate a work item x times in the last 60 seconds
If you do, give the article 317249 a try (increase the MaxWorkItems value).
The solution I find most useful is the one described in 911272: if your .NET build is at least 2.0.50727.62 you already have the fix mentioned in the article but you may need to activate it:
Registry information To enable this hotfix, you must add the following DWORD value at the following registry key: HKLM\Software\Microsoft\ASP.NET\FCNMode The following table lists possible values for the FCNMode DWORD value and the behavior that is associated with each value. Value Behavior Does not exist This is the default behavior. For each subdirectory, the application will create an object that will monitor the subdirectory 0 or greater than 2 This is the default behavior. For each subdirectory, the application will create an object that will monitor the subdirectory 1 The application will disable File Change Notifications (FCNs) 2 The application will create one object to monitor the main directory. The application will use this object to monitor each subdirectory
Registry information To enable this hotfix, you must add the following DWORD value at the following registry key: HKLM\Software\Microsoft\ASP.NET\FCNMode The following table lists possible values for the FCNMode DWORD value and the behavior that is associated with each value.
I suggest to set FCNMode to 2, so you’ll still have File Change Notifications in place.
I’m back after the summer break (3 weeks spent trying to master the “Do It Yourself” art at home ) and my second day in office I got an interesting problem with remote debugging: after installing the Service Pack 2 for .NET 2.0, when trying to debug our web application (hosted on a remote IIS) we were getting the following error: “Unable to start debugging on the web server. An authentication error occurred while communicating with the web server”. Note, you can get the same error if you install the Service Pack 1 for .NET 3.5: the reason is simple, if you install the SP1 for .NET 3.5 you’ll automatically get the SP2 for .NET 2.0. Another point: you are using host headers in your site.
Anyway, the error is caused by a security change: in .NET 3.5 SP1 (and .NET 2.0 SP2) now defaults to specifying the host name used in the request URL in an SPN in the NTLM authentication package. The NTLM authentication process includes a challenge issued by the destination machine and sent back to the client machine. When Windows receives a challenge it generated itself, authentication will fail unless the connection is a loop back connection. When a Web Site is configured with a host header, the host name is neither the machine name nor the loop back IP address nor the machine's IP address, so the authentication request will fail.
There are two possible solutions:
If you want more information on this matter you have have a look at http://blogs.msdn.com/lukaszp/archive/2008/07/18/reporting-services-http-401-unauthorized-host-headers-require-your-attention.aspx.
My colleague Feliciano has just made me aware of an extraordinary security bulletin we have just released for a new vulnerability discovered in ATL libraries which could allow remote code execution; here are the information I am aware of so far:
The updates to install: