如何强制设置 IE 的兼容模式从服务器端关闭?

在域控制的环境中,我发现在某些客户端(winXP/Win7,IE8/IE9)上,即使我们提供了 X-UA 标签,也会触发兼容性模式!DOCTYPE 定义和“ IE = Edge”响应头。这些客户机勾选了“在兼容性视图中显示 Intranet 站点”复选框。这正是我想要改写的。

下面是我用来理解 IE 如何决定实际触发兼容性模式的文档。

Http://msdn.microsoft.com/en-us/library/ff406036%28v=vs.85%29.aspx

Http://blogs.msdn.com/b/ie/archive/2009/02/16/just-the-facts-recap-of-compatibility-view.aspx

网站所有者是 一直都是在控制他们的内容。网站所有者可以选择使用 X-UA-Compatible 标签来完全声明他们希望自己的网站如何显示,并将标准模式页面映射到 IE7标准。< em > 使用 X-UA- 兼容标记覆盖客户端的兼容视图。

谷歌的 “定义文档兼容性”,遗憾的是垃圾邮件引擎不让我发布超过2个网址。

这是一个 ASP .NET网络应用程序,主页上包括以下定义:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<head>
<meta http-equiv="X-UA-Compatible" content="IE=Edge" />
</head>

web.config

<system.webServer>
<httpProtocol>
<customHeaders>
<clear />
<add name="X-UA-Compatible" value="IE=Edge" />
</customHeaders>
</httpProtocol>
</system.webServer>

我已经使用 Fiddler 检查头部确实被正确注入。

我的理解是,通过这些设置,我应该能够覆盖“在兼容性视图中显示内部网站”浏览器设置。但是根据客户端的不同,我发现其中一些仍然会触发兼容模式。 它似乎还可以归结为机器级别,而不是策略组设置,因为即使在不同客户机上使用相同的凭据集,我也会获得不同的结果。

禁用“兼容性视图设置”复选框可以解决这个问题。但实际的目的是确保应用程序呈现完全相同的方式,而不管客户端设置如何。

有什么想法和我可能错过的东西吗?有没有可能强制 IE 总是在不触发 Compat 模式的情况下呈现页面?

万分感谢,

Jaume

PS: 该网站目前正在开发中,当然不在微软的兼容列表中,但我也检查了以防万一。

谷歌的 “了解兼容视图列表”,遗憾的是垃圾邮件引擎不让我发布超过2个网址。

143195 次浏览

Update: More useful information What does <meta http-equiv="X-UA-Compatible" content="IE=edge"> do?

Maybe this url can help you: Activating Browser Modes with Doctype

Edit: Today we were able to override the compatibility view with: <meta http-equiv="X-UA-Compatible" content="IE=EmulateIE8" />

Changing my header to the following solve the problem:

<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=Edge" />

I found problems with the two common ways of doing this:

  1. 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.

  2. 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.

  3. Network traffic could be reduced by only sending the X-UA-Compatible header to Internet Explorer clients.

Well-Structured Applications

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.

Legacy Applications

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.

Advantages

  • Overcomes the problems outlined at the start of this answer.

Disadvantages

  • Website admins don't have control over the header value. This could be a problem if a new version of Internet Explorer comes out and adversely affects the rendering of the website. However, this could be overcome by having the module read the header value from the application's configuration file instead of using a hard-coded value.
  • This may require modification to work with ASP.NET MVC.
  • This doesn't work for static HTML pages.
  • The PreSendRequestHeaders event in the above code doesn't seem to fire in IIS6. I haven't figured out how to resolve this bug yet.

For Node/Express developers you can use middleware and set this via server.

app.use(function(req, res, next) {
res.setHeader('X-UA-Compatible', 'IE=edge');
next();
});