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

JSa*_*cho 84 asp.net internet-explorer ie8-compatibility-mode x-ua-compatible

在域控制的环境中,我发现在某些客户端(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标准.使用X-UA-Compatible标记会覆盖客户端上的兼容性视图.

谷歌的"定义文档兼容性",遗憾的是SPAM引擎不允许我发布超过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>
Run Code Online (Sandbox Code Playgroud)

web.config

<system.webServer>
  <httpProtocol>
    <customHeaders>
      <clear />
      <add name="X-UA-Compatible" value="IE=Edge" />
    </customHeaders>
  </httpProtocol>
</system.webServer>
Run Code Online (Sandbox Code Playgroud)

我已经使用Fiddler来检查标头是否确实被正确注入.

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

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

任何想法和我可能会错过的东西?是否有可能强制IE始终渲染页面而不触发Compat模式?

太感谢了,

乌梅

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

谷歌"了解兼容性视图列表",遗憾的是SPAM引擎不允许我发布超过2个网址.

Sam*_*Sam 45

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

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

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

  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() { }
}
Run Code Online (Sandbox Code Playgroud)

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意,模块的static实例化非常重要,Init因此每个应用程序只有一个实例.当然,在实际应用程序中,IoC容器应该可以管理它.

好处

  • 克服本答案开头列出的问题.

缺点

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

  • 你的答案可能需要一年多的时间才能到来,而我正在处理的实际应用程序现已弃用.尽管如此,这绝对是我所希望的最全面和最好研究的答案.那些等待的人会有好的东西:)谢谢Sam (2认同)

小智 39

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

<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=Edge" />
Run Code Online (Sandbox Code Playgroud)


And*_*rew 17

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

也许这个网址可以帮助您:使用Doctype激活浏览器模式

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

  • 实际上今天我们能够覆盖兼容性视图:`<meta http-equiv ="X-UA-Compatible"content ="IE = EmulateIE8"/>` (2认同)
  • 感谢您更新答案.我认为如果您的答案指定为"IE = Edge"会更好,因为问题是关于**禁用**兼容模式. (2认同)