Detecting and Upleveling ASP.NET Pages for IE11

It’s considered best-practice to do browser detection based on features rather than the more error-prone detection based on the user-agent. For example, see this Microsoft browser identification best practices article for how they suggest you structure your Internet Explorer detection scripts by making user of the ASP.NET HttpBrowserCapabilities Object.

If you are interested in reading more about the problems ASP.NET has recently had with IE10 and IE11, please check out my related article on the subject

A User-Agent and Feature-Detection Double Failure

With the recent release of IE11, and its associated detection problems, Microsoft has made quite a mistake. In IE11, Microsoft has intentionally changed the user-agent string to NOT include MSIE and the addition of like Gecko. Based on best practices one would (mistakenly) assume this was a justification for not identifying browsers based on the user-agent string.

Browser detection based on features, has been problematic with IE11, and also with IE10 prior to that. In certain conditions such as on a Windows 2003/IIS6 Web server, IE11 will not be detected properly by the .NET 4 engine. This means that IIS will serve a page assuming a completely disabled browser rather than a fully functioning IE11, so a feature detection script would do just as poorly as a user-agent based detection script.

Bottom line here is a double-failure with IE11: the response for feature-based detection will show a completely disabled browser, and the user-agent string intentionally is not signed MSIE.

Basically, if you wrote your browser detection script based on user-agent, you’d be better off than if you had written it based on feature detection. For user-agent, you’d just have to parse like Gecko to know that you are dealing with IE11, while with a feature detection script, there is no way that you can tell that you are dealing with IE11. Using only one or the other is probably not as safe as it should be, so a best case fix would include combining both techniques to get a specific ID of the browser and it’s status.

It’s worthwhile mentioning that previously IE10 had similar problems, but patches were quickly released that cleared up these issues… until an IE10 critical patch broke things again a few months later. Rather than using a definition file fix or temporary patch, which has failed in the past, I suggest using a code-based fix that will be properly future-proof.

The User-Agent Signature of IE11

Here is an example of the user-agent signature of IE11 that is not running in compatibility view:

Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko

Here is an example of the user-agent signature of IE11 that IS running in compatibility view:

Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/7.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E)

Detecting and Upleveling Only IE11 Browsers

You can see from the user-agent strings above that IE11 has a very different signature based on how it is running. Likewise, you can see from the results of the browser feature tests below (using the .NET HttpBrowserCapabilities object), that IE11 can be served completely disabled pages by default.

As I mentioned in an article about correcting the pages served to IE11; to get your Web server to serve fully functional pages to IE11, you need to set the Page.ClientTarget attribute for your .NET pages to uplevel rather than the default downlevel.

However, you will want to make sure that the Page.ClientTarget setting is only applied to users coming to your site with IE11, since this setting can cause unpredictable behavior in third party components. For example, one commenter on my blog mentioned that setting the Page.ClientTarget to uplevel would cause problems with the Telerik RadEditor control for FireFox users.

For further reading, in case you are interested, Microsoft has published a good article about the compatibility changes in IE11 including Legacy features and their replacements at the following URL: http://msdn.microsoft.com/en-us/library/ie/bg182625(v=vs.85).aspx#utf8 

The Example Code:

I would suggest keying your detection script off a combination of the user-agent string and the detected browser features. Here is an example script that keys off the like Gecko signature that IE11 now identifies itself as as well as the Trident keyword, combined with a zero as the majorVersion browser feature of the HttpBrowserCapabilities object.

Note that this is only an example, and you should adjust this script to use a regex against the user-agent string and probably include more zero or null browser features from the HttpBrowserCapabilities object:

string strAgent = Request.UserAgent;
 HttpBrowserCapabilities myBrowserCapabilities = Request.Browser;
 Int32 majorVersion = myBrowserCapabilities.MajorVersion;
 if (strAgent.Contains("like Gecko") && strAgent.Contains("Trident") && majorVersion==0){
 Page.ClientTarget = "uplevel";
 }

So as a fully functional example of the detection snippet above, here is a C# Web Form that outputs either IE11 or NOT IE11 to a label field depending on your browser. Try it out, it’s actually quite fun:

<%@ Page Language="C#" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script runat="server">
 protected void Page_Load(object sender, EventArgs e)
 {
 string strAgent = Request.UserAgent;
 HttpBrowserCapabilities myBrowserCapabilities = Request.Browser;
 Int32 majorVersion = myBrowserCapabilities.MajorVersion;
 if (strAgent.Contains("like Gecko") && strAgent.Contains(Trident") && majorVersion==0){
 Label1.Text = "IE11";
 }else{
 Label1.Text = "NOT IE11";
 }

 }
</script>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
 <title></title>
</head>
<body>
 <form id="form1" runat="server">
 <div>
 <asp:Label ID="Label1" runat="server" Text="Label"></asp:Label>
 </div>
 </form>
</body>
</html>

A Simple C# Web Form Listing the Browser Features

Here is an example Web Form in C# that will populate a GridView with the HttpBrowserCapabilities collection

Below this example code, I give two outputs:

  1. Output of IE11 not being detected and being served a non-functional page
  2. Output of IE11 running in compatibility mode
<%@ Page Language="C#" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script runat="server">
 protected void Page_Load(object sender, EventArgs e)
 {
 HttpBrowserCapabilities myBrowserCapabilities = Request.Browser;
 SortedList<string, string> myBrowserCapabilitiesList = new SortedList<string, string>();
 foreach (System.Collections.DictionaryEntry dctEntry in myBrowserCapabilities.Capabilities){
 myBrowserCapabilitiesList.Add(dctEntry.Key.ToString(), (dctEntry.Value == null ? "" : dctEntry.Value.ToString()));
 }
 myGridView.DataSource = myBrowserCapabilitiesList;
 myGridView.DataBind();
 }
</script>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
 <title></title>
</head>
<body>
 <form id="form1" runat="server">
<asp:GridView ID="myGridView" runat="server">
 </asp:GridView>
 </form>
</body>
</html>

 

IE11 running in Edge mode on a Windows 2003/IIS6 Server

Key Value
Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko
activexcontrols false
aol false
backgroundsounds false
beta false
browser Mozilla
canCombineFormsInDeck true
canInitiateVoiceCall false
canRenderAfterInputOrSelectElement true
canRenderEmptySelects true
canRenderInputAndSelectElementsTogether true
canRenderMixedSelects true
canRenderOneventAndPrevElementsTogether true
canRenderPostBackCards true
canRenderSetvarZeroWithMultiSelectionList true
canSendMail true
cdf false
cookies false
crawler false
defaultSubmitButtonLimit 1
ecmascriptversion 0.0
frames false
gatewayMajorVersion 0
gatewayMinorVersion 0
gatewayVersion None
hasBackButton true
hidesRightAlignedMultiselectScrollbars false
inputType keyboard
isColor true
isMobileDevice false
javaapplets false
javascript false
jscriptversion 0.0
majorversion 0
maximumHrefLength 10000
maximumRenderedPageSize 300000
maximumSoftkeyLabelLength 5
minorversion 0
mobileDeviceManufacturer Unknown
mobileDeviceModel Unknown
msdomversion 0.0
numberOfSoftkeys 0
platform WinNT
preferredImageMime image/gif
preferredRenderingMime text/html
preferredRenderingType html32
rendersBreakBeforeWmlSelectAndInput false
rendersBreaksAfterHtmlLists true
rendersBreaksAfterWmlAnchor false
rendersBreaksAfterWmlInput false
rendersWmlDoAcceptsInline true
rendersWmlSelectsAsMenuCards false
requiredMetaTagNameValue
requiresAbsolutePostbackUrl false
requiresAdaptiveErrorReporting false
requiresAttributeColonSubstitution false
requiresContentTypeMetaTag false
requiresControlStateInSession false
requiresDBCSCharacter false
requiresFullyQualifiedRedirectUrl false
requiresLeadingPageBreak false
requiresNoBreakInFormatting false
requiresOutputOptimization false
requiresPhoneNumbersAsPlainText false
requiresPostRedirectionHandling false
requiresSpecialViewStateEncoding false
requiresUniqueFilePathSuffix false
requiresUniqueHtmlCheckboxNames false
requiresUniqueHtmlInputNames false
requiresUrlEncodedPostfieldValues false
requiresXhtmlCssSuppression false
screenBitDepth 8
supportsAccesskeyAttribute false
supportsBodyColor true
supportsBold true
supportsCacheControlMetaTag true
supportsCallback false
supportsCss true
supportsDivAlign true
supportsDivNoWrap true
supportsEmptyStringInCookieValue true
supportsFileUpload false
supportsFontColor true
supportsFontName true
supportsFontSize true
supportsImageSubmit true
supportsIModeSymbols false
supportsInputIStyle false
supportsInputMode false
supportsItalic true
supportsJPhoneMultiMediaAttributes false
supportsJPhoneSymbols false
SupportsMaintainScrollPositionOnPostback false
supportsMultilineTextBoxDisplay false
supportsQueryStringInFormAction true
supportsRedirectWithCookie true
supportsSelectMultiple true
supportsUncheck true
supportsVCard false
tables false
tagwriter System.Web.UI.Html32TextWriter
type Mozilla
vbscript false
version 0.0
w3cdomversion 0.0
win16 false
win32 true

IE11 running in Compatibility View mode on a Windows 2003/IIS6 Server

Key Value
Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/7.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E)
activexcontrols true
aol false
backgroundsounds true
beta false
browser IE
canCombineFormsInDeck true
canInitiateVoiceCall false
canRenderAfterInputOrSelectElement true
canRenderEmptySelects true
canRenderInputAndSelectElementsTogether true
canRenderMixedSelects true
canRenderOneventAndPrevElementsTogether true
canRenderPostBackCards true
canRenderSetvarZeroWithMultiSelectionList true
canSendMail true
cdf false
cookies true
crawler false
defaultSubmitButtonLimit 1
ecmascriptversion 3.0
ExchangeOmaSupported true
extra ; Windows NT 6.1; WOW64; Trident/7.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E
frames true
gatewayMajorVersion 0
gatewayMinorVersion 0
gatewayVersion None
hasBackButton true
hidesRightAlignedMultiselectScrollbars false
inputType keyboard
isColor true
isMobileDevice false
javaapplets true
javascript true
javascriptversion 1.5
jscriptversion 5.7
layoutEngine Trident
layoutEngineVersion 7
letters
majorversion 7
maximumHrefLength 10000
maximumRenderedPageSize 300000
maximumSoftkeyLabelLength 5
minorversion 0
mobileDeviceManufacturer Unknown
mobileDeviceModel Unknown
msdomversion 7.0
numberOfSoftkeys 0
platform WinNT
preferredImageMime image/gif
preferredRenderingMime text/html
preferredRenderingType html32
rendersBreakBeforeWmlSelectAndInput false
rendersBreaksAfterHtmlLists true
rendersBreaksAfterWmlAnchor false
rendersBreaksAfterWmlInput false
rendersWmlDoAcceptsInline true
rendersWmlSelectsAsMenuCards false
requiredMetaTagNameValue
requiresAbsolutePostbackUrl false
requiresAdaptiveErrorReporting false
requiresAttributeColonSubstitution false
requiresContentTypeMetaTag false
requiresControlStateInSession false
requiresDBCSCharacter false
requiresFullyQualifiedRedirectUrl false
requiresLeadingPageBreak false
requiresNoBreakInFormatting false
requiresOutputOptimization false
requiresPhoneNumbersAsPlainText false
requiresPostRedirectionHandling false
requiresSpecialViewStateEncoding false
requiresUniqueFilePathSuffix false
requiresUniqueHtmlCheckboxNames false
requiresUniqueHtmlInputNames false
requiresUrlEncodedPostfieldValues false
requiresXhtmlCssSuppression false
screenBitDepth 8
supportsAccesskeyAttribute true
supportsBodyColor true
supportsBold true
supportsCacheControlMetaTag true
supportsCallback true
supportsCss true
supportsDivAlign true
supportsDivNoWrap true
supportsEmptyStringInCookieValue true
supportsFileUpload true
supportsFontColor true
supportsFontName true
supportsFontSize true
supportsImageSubmit true
supportsIModeSymbols false
supportsInputIStyle false
supportsInputMode false
supportsItalic true
supportsJPhoneMultiMediaAttributes false
supportsJPhoneSymbols false
SupportsMaintainScrollPositionOnPostback true
supportsMultilineTextBoxDisplay true
supportsQueryStringInFormAction true
supportsRedirectWithCookie true
supportsSelectMultiple true
supportsUncheck true
supportsVCard true
supportsXmlHttp true
tables true
tagwriter System.Web.UI.HtmlTextWriter
type IE7
vbscript true
version 7.0
w3cdomversion 1.0
win16 false
win32 true
About these ads

4 thoughts on “Detecting and Upleveling ASP.NET Pages for IE11

  1. Pingback: ASP.NET Doesn’t Detect IE11 « Justin Cooney

  2. This detection and fix works great. Since every web page on all my sites descend from a single base page class, I only had to make the change in the shared assembly and then dump the new assembly out to the sites. I knew that would pay off one day :-)

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s