Intro
The ASP.NET project I am on currently has spanned 5 years and has undergone many upgrades. The latest upgrade was made necessary by the Internet Explorer 9 (IE9) push by Microsoft in Windows Update. Our users started getting it and things that used to work started breaking. I was given the task to find and repair these issues. This post details my findings. I am posting the two that I felt would be most relevant to developers. Note that one of the issues (the second one) is related to ASP.NET alone but the first one is important for all web developers.
Content (or custom) Attribute Changes
Before IE9, content attributes could be get or set using JavaScript object DOM ‘expando’ properties. With the introduction of IE9, that is no longer the case. A content attribute is an attribute that is specified in the HTML source or, with ASP.NET, in the server side Control.Attributes collection. There are pre-defined HTML content attributes like ‘value’ or ‘id’. There are also user-defined content attributes (I call them ‘custom’ attributes), and that’s what I’ll be talking about in this post. Expando properties are defined from MSDN as follows: All objects in JavaScript support "expando" properties, or properties that can be added and removed dynamically at run time. (See http://msdn.microsoft.com/en-us/library/89t1khd2(v=vs.94).aspx)
Before IE9 the custom attributes were implied with the same name expando properties (i.e. javaObject.customAttr was valid in JavaScript.) With IE9, that is no longer the case. Note that the pre-defined content attributes will still be available as expando properties.
FIX -- The fix is to use the getAttribute and setAttribute functions of the JavaScript object instead of the expando properties.
See the MSDN explanation of this IE9 change here: http://msdn.microsoft.com/en-us/library/ie/gg622931(v=vs.85).aspx
Example 1 – Content Attribute As HTML Source
This example will show what happens in IE9 and compatibility mode when we set a custom attribute in the HTML source.
Here is the ASP.NET code:
<asp:Button ID="ContentAttrBtn" runat="server" Text="Get Custom Content Attribute"
OnClientClick="attrAsContentAttribute(); return false;" />
<asp:TextBox ID="TextBox2" runat="server" helloWorld="content attribute!" />If you aren’t familiar with ASP.NET, this is the HTML that is generated:
<input type="submit" name="ctl00$MainContent$ContentAttrBtn"
value="Get Custom Content Attribute" onclick="attrAsContentAttribute(); return false;"
id="MainContent_ContentAttrBtn" />
<input name="ctl00$MainContent$TextBox2" type="text" id="MainContent_TextBox2"
helloWorld="content attribute!" />
Here is the JavaScript:
function attrAsContentAttribute() {
var txt = document.getElementById('<%= TextBox2.ClientID %>');
alert('TextBox2 helloWorld attribute (expando) = ' + txt.helloWorld);
alert('TextBox2 value attribute (expando) = ' + txt.value);
alert('TextBox2 helloWorld attribute (getAttribute) = ' + txt.getAttribute("helloWorld"));
}
When this is run in IE9, we get the following alert boxes:
…Note that this is undefined in IE9 now.
…I entered “textbox value” into the textbox.
…works with getAttribute.
When this is run in IE9 Compatibility Mode, the following alert box changes (the 1st one):
…works in compatibility mode.
Example 2 – Content Attribute Added in ASP.NET Code Behind (on server)
This example will show what happens in IE9 and compatibility mode when we set a custom attribute in the ASP.NET code behind.
Here is the ASP.NET code:
<asp:Button ID="ServerAttrBtn" runat="server" Text="Get Custom Server Attribute"
OnClientClick="attrSetOnServer(); return false;" />
<asp:TextBox ID="TextBox1" runat="server" />
If you aren’t familiar with ASP.NET, this is the HTML that is generated:
<input type="submit" name="ctl00$MainContent$ServerAttrBtn"
value="Get Custom Server Attribute" onclick="attrSetOnServer(); return false;"
id="MainContent_ServerAttrBtn" />
<input name="ctl00$MainContent$TextBox1" type="text" id="MainContent_TextBox1"
helloWorld="hello from server!" />
This is the code-behind to the page where I am setting the helloWorld attribute:
TextBox1.Attributes.Add("helloWorld", "hello from server!");
Here is the JavaScript:
function attrSetOnServer() {
var txt = document.getElementById('<%= TextBox1.ClientID %>');
alert('TextBox1 helloWorld attribute (expando) = ' + txt.helloWorld);
alert('TextBox1 id attribute (expando) = ' + txt.id);
alert('TextBox1 helloWorld attribute (getAttribute) = ' + txt.getAttribute("helloWorld"));
}
When this is run in IE9, we get the following alert boxes:
…Note that this is undefined in IE9 now.
…id of the TextBox or input element.
…works with getAttribute.
When this is run in IE9 Compatibility Mode, the following alert box changes (the 1st one):
…works in compatibility mode.
AjaxControlToolkit CalendarExtender
This issue is more specific to ASP.NET applications that are using the AjaxControlToolkit (November 2011 Release). I noticed in my app that when I selected a date using the calendar extender (the calendar image that allows you to choose a date from a visual calendar), and the date had one digit in the month and/or day, it was formatted in the TextBox as follows: 4/9/2012
It should have formatted it this way: 04/09/2012
Note that I never set the CalendarExtender.Format value. I just took the default.
Why do I care, you may ask? Because the validation in the control doesn’t work correctly when it is formatted without leading zeroes. What I noticed in my app was that I would get a “Date required” error message when a date was already in the TextBox control.
FIX -- The fix is to set the CalendarExtender.Format explicitly to "MM/dd/yyyy".
I logged this bug as an issue on CodePlex and you can follow it if you are interested here: http://ajaxcontroltoolkit.codeplex.com/workitem/27137