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

Posted

技术标签:

【中文标题】如何从服务器端强制关闭 IE 兼容模式?【英文标题】:How to forcefully set IE's Compatibility Mode off from the server-side? 【发布时间】:2011-09-26 16:02:40 【问题描述】:

在域控制的环境中,我发现兼容模式在某些客户端(winXP/Win7、IE8/IE9)上被触发,即使我们提供 X-UA 标签、!DOCTYPE 定义和“IE=边缘”响应标头。这些客户端勾选了“在兼容性视图中显示 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 标准。 使用 X-UA-Compatible 标签会覆盖客户端上的兼容性视图。

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

这是一个ASP .NET Web 应用程序,在母版页上包含以下定义:

<!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 来检查标头是否确实被正确注入。

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

禁用兼容性视图设置复选框可以解决问题。但实际目的是确保无论客户端设置如何,应用都以完全相同的方式呈现。

有什么想法和我可能遗漏的东西吗?是否有可能强制 IE 始终呈现页面而不触发 Compat 模式?

感谢一百万,

贾梅

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

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

【问题讨论】:

【参考方案1】:

更新:更多有用信息What does <meta http-equiv="X-UA-Compatible" content="IE=edge"> do?

也许这个网址可以帮到你:Activating Browser Modes with Doctype

编辑:今天我们能够覆盖兼容性视图: &lt;meta http-equiv="X-UA-Compatible" content="IE=EmulateIE8" /&gt;

【讨论】:

@Balanivash 实际上这是一本非常好的读物,感谢您的链接。这篇文章让我相信“兼容模式”已启用,因为该站点位于 Intranet 区域内。但是,这种情况并非始终如一地发生,例如: - win7、IE8,在客户端 -> 完全标准模式 - win7、IE8,在具有相同凭据的不同机器上 -> 兼容模式 为了安全起见,我' m 还会启动浏览器的新会话,并在每次测试时将 IE 开发人员工具栏重置为默认值。 也许你可以试试这个:&lt;meta http-equiv="X-UA-Compatible" content="IE=8" /&gt; 另外:如果您希望您的 Web 应用程序告诉 IE8 真正信任您,您需要从您的 Web 服务器发送 X-UA-Compatible 作为 HTTP 标头而不是元标记:social.msdn.microsoft.com/Forums/en-US/iewebdevelopment/thread/… 实际上,今天我们能够覆盖兼容性视图:&lt;meta http-equiv="X-UA-Compatible" content="IE=EmulateIE8" /&gt; 感谢您更新您的答案。我认为如果您的答案指定IE=Edge 会更好,因为问题是关于禁用兼容模式。【参考方案2】:

将我的标题更改为以下解决问题:

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

【讨论】:

我还需要将客户标头添加到 web.config 文件以使其在 Windows 2008 服务器上工作【参考方案3】:

我发现这两种常用方法存在问题:

    使用 web.config 中的自定义标头 (&lt;customHeaders&gt;) 执行此操作允许同一应用程序的不同部署具有不同的此设置。我认为这是另外一件可能出错的事情,所以我认为如果应用程序在代码中指定这一点会更好。另外,IIS6 doesn't support this。

    在 Web 表单母版页或 MVC 布局页中包含 HTML &lt;meta&gt; 标记似乎比上述更好。但是,如果某些页面没有从这些页面继承,则需要复制标签,因此存在潜在的可维护性和可靠性问题。

    仅向 Internet Explorer 客户端发送 X-UA-Compatible 标头即可减少网络流量。

结构良好的应用程序

如果您的应用程序的结构导致所有页面最终都从单个根页面继承,请包含&lt;meta&gt; 标记,如the other answers 所示。

旧版应用程序

否则, 我认为最好的方法是自动将 HTTP 标头添加到所有 HTML 响应中。 One way to do this 正在使用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 表示 IE 应该使用其最新的渲染引擎(而不是兼容模式)来渲染页面。

似乎 HTTP 模块经常注册在 web.config 文件中,但这让我们回到了第一个问题。但是,you can register them programmatically in Global.asax 是这样的:

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);
    

请注意,模块是static 而不是在Init 中实例化很重要,这样每个应用程序只有一个实例。当然,在现实世界的应用程序中,可能应该由 IoC 容器来管理它。

优势

克服了本答案开头列出的问题。

缺点

网站管理员无法控制标头值。如果新版本的 Internet Explorer 出现并对网站的呈现产生不利影响,这可能是一个问题。但是,可以通过让模块从应用程序的配置文件中读取标头值而不是使用硬编码值来克服这个问题。 这可能需要修改才能与 ASP.NET MVC 一起使用。 这不适用于静态 HTML 页面。 上面代码中的PreSendRequestHeaders 事件似乎在IIS6 中没有触发。我还没有想出如何解决这个错误。

【讨论】:

您的答案可能需要一年多的时间才能出现,而我正在开发的实际应用程序现在已被弃用。尽管如此,这绝对是我所希望的最彻底和经过充分研究的答案。等待的人会有好事 :) 谢谢山姆 "这应该确保页面与其他浏览器一致并以符合标准的方式呈现。"对不起,但这至少不是我的经验。现在,我正在处理一个 s-s-rS 报告,它在 IE10 中呈现所有错误,在 Chrome 中很好,在 IE10 兼容模式下也很好。 @BobRodes,我想我之所以这么写是因为后来的 IE 版本应该更符合标准,但我并不是真的从经验中说出来,所以说的很好!我刚刚更新了答案以删除该声明。 微软在与竞争对手的关系中使用了“拥抱、扩展、熄灭”的概念。首先,接受任何类型的标准。然后,用专有特性和功能对标准进行“改进”。然后,在未来的版本中悄悄地放弃对该标准的支持。幸运的是,他们在使用 IE 时遇到了麻烦。 :) 这对我有用,我尝试了几种不同的解决方案,包括元标记并尝试使用 css hack 来解决在 ie 中未正确呈现的网站区域。【参考方案4】:

对于 Node/Express 开发人员,您可以使用中间件并通过服务器进行设置。

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

【讨论】:

以上是关于如何从服务器端强制关闭 IE 兼容模式?的主要内容,如果未能解决你的问题,请参考以下文章

强制关闭 IE 的兼容模式

关闭站点的 IE 8 兼容模式

CSS 多行文本省略(兼容IE)

IE9和IE9兼容性查看浏览器模式的区别

APP多版本共存,服务端如何兼容?

js强制不使用“兼容性视图”