84

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

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

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

<!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 for "Understanding the Compatibility View List",遗憾的是垃圾邮件引擎不允许我发布超过 2 个网址。

4

4 回答 4

45

我发现这样做的两种常见方法存在问题:

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

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

  3. X-UA-Compatible仅将标头发送到 Internet Explorer 客户端可以减少网络流量。

结构良好的应用程序

如果您的应用程序的结构导致所有页面最终都从单个根页面继承,请包含其他答案<meta>中所示的标记。

旧版应用程序

否则,我认为最好的方法是自动将 HTTP 标头添加到所有 HTML 响应中。一种方法是使用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 文件中注册的,但这让我们回到了第一个问题。但是,您可以像这样在 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 中触发。我还没有想出如何解决这个错误。
于 2013-05-21T00:18:35.210 回答
39

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

<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=Edge" />
于 2012-04-04T13:19:58.260 回答
17

更新:更多有用信息<meta http-equiv="X-UA-Compatible" content="IE=edge"> 有什么作用?

也许这个 url 可以帮助你:Activating Browser Modes with Doctype

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

于 2011-07-01T11:33:02.310 回答
0

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

app.use(function(req, res, next) {
  res.setHeader('X-UA-Compatible', 'IE=edge');
  next();
});
于 2017-06-10T09:46:49.400 回答