Fix the ASP.NET Themes with IE8’s X-UA-Compatible header problem

By Fons Sonnemans, 26-9-2008

If you’ve got a page that doesn’t render correctly in IE8’s new standards mode, you can add a meta tag to the page which requests that IE8 render it in IE7 mode. IE8 only recognizes the X-UA-Compatible header if it’s the first META tag, appearing immediately after the tag.

<!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"> <meta http-equiv="X-UA-Compatible" content="IE=7" /> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <link rel="shortcut icon" href="favicon.ico" /> <title>Test</title> </head> <body>[...]</body></html>

The Problem

The ASP.NET Theme system writes out the theme CSS reference immediately after the <HEAD> tag. This makes it impossible to set the X-UA-Compatible header or to use Stylesheets in your theme folder.

<!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"> <link href="App_Themes/Default/Stylesheet.css" type="text/css" rel="stylesheet" /> <meta http-equiv="X-UA-Compatible" content="IE=7" /> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <link rel="shortcut icon" href="favicon.ico" /> <title>Test</title> </head> <body>[...]</body></html>

The Solution

To fix this problem I have added an implementation for the Application_PreRequestHandlerExecute event in the Global.asax. This method will sort the controls inside the header. It places the X-UA-Compatible metatag on top. I use an anonymous method which is subscribed to the PreRenderComplete event of page. This method uses LINQ to find the metatag. Then removes it from the header and add it again on top.

void Application_PreRequestHandlerExecute(object src, EventArgs e) {
    Page p = this.Context.Handler as Page;
    if (p != null) {
        p.PreRenderComplete += (sender, ee) => {
            // I can't use p, it has no Header set (strange), use sender instead
            Page page = sender as Page; 
            if (page.Header != null) {
                // Find the Compatible Meta tag
                var ctrl = page.Header.Controls.Cast<Control>().FirstOrDefault(
                    c => c is HtmlMeta && ((HtmlMeta)c).HttpEquiv == "X-UA-Compatible");

                // If found remove it and add it on top
                if (ctrl != null) {
                    page.Header.Controls.Remove(ctrl);
                    page.Header.Controls.AddAt(0, ctrl);
                }
            }
        };
    }
}

This results in the correct HTML.

<!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"> <meta http-equiv="X-UA-Compatible" content="IE=7" /> <link href="App_Themes/Default/Stylesheet.css" type="text/css" rel="stylesheet" /> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <link rel="shortcut icon" href="favicon.ico" /> <title>Test</title> </head> <body>[...]</body></html>
Tags: Web, ASP.NET

Leave a Comment

Leave a Comment
Name
Comment
6 + 6 =

0 Comments

All postings/content on this blog are provided "AS IS" with no warranties, and confer no rights. All entries in this blog are my opinion and don't necessarily reflect the opinion of my employer or sponsors. The content on this site is licensed under a Creative Commons Attribution By license.