I found problems with the two common ways of doing this:
Doing this with custom headers (<customHeaders>
) in web.config allows different deployments of the same application to have this set differently. I see this as one more thing that can go wrong, so I think it's better if the application specifies this in code. Also, IIS6 doesn't support this.
Including an HTML <meta>
tag in a Web Forms Master Page or MVC Layout Page seems better than the above. However, if some pages don't inherit from these then the tag needs to be duplicated, so there's a potential maintainability and reliability problem.
Network traffic could be reduced by only sending the X-UA-Compatible
header to Internet Explorer clients.
If your application is structured in a way that causes all pages to ultimately inherit from a single root page, include the <meta>
tag as shown in the other answers.
Otherwise,
I think the best way to do this is to automatically add the HTTP header to all HTML responses. One way to do this is using an IHttpModule
:
public class IeCompatibilityModeDisabler : IHttpModule
{
public void Init(HttpApplication context)
{
context.PreSendRequestHeaders += (sender, e) => DisableCompatibilityModeIfApplicable();
}
private void DisableCompatibilityModeIfApplicable()
{
if (IsIe && IsPage)
DisableCompatibilityMode();
}
private void DisableCompatibilityMode()
{
var response = Context.Response;
response.AddHeader("X-UA-Compatible", "IE=edge");
}
private bool IsIe { get { return Context.Request.Browser.IsBrowser("IE"); } }
private bool IsPage { get { return Context.Handler is Page; } }
private HttpContext Context { get { return HttpContext.Current; } }
public void Dispose() { }
}
IE=edge
indicates that IE should use its latest rendering engine (rather than compatibility mode) to render the page.
It seems that HTTP modules are often registered in the web.config file, but this brings us back to the first problem. However, you can register them programmatically in Global.asax like this:
public class Global : HttpApplication
{
private static IeCompatibilityModeDisabler module;
void Application_Start(object sender, EventArgs e)
{
module = new IeCompatibilityModeDisabler();
}
public override void Init()
{
base.Init();
module.Init(this);
}
}
Note that it is important that the module is static
and not instantiated in Init
so that there is only one instance per application. Of course, in a real-world application an IoC container should probably be managing this.
PreSendRequestHeaders
event in the above code doesn't seem to fire in IIS6. I haven't figured out how to resolve this bug yet.