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

时间:2011-07-01 10:30:46

标签: asp.net internet-explorer ie8-compatibility-mode x-ua-compatible

在域控制的环境中,我发现在某些客户端(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兼容标记来绝对声明他们的喜好他们的网站显示和标准模式页面映射到IE7标准。 使用X-UA兼容标记会覆盖客户端上的兼容性视图。

谷歌“定义文档兼容性”,遗憾的是SPAM引擎不允许我发布超过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检查标头是否确实正确注入。

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

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

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

感谢百万,

乌梅

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

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

4 个答案:

答案 0 :(得分:44)

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

  1. 通过web.config中的自定义标头(<customHeaders>)执行此操作,可以对同一应用程序的不同部署进行不同的设置。我认为这是一个可能出错的事情,所以我认为如果应用程序在代码中指定它会更好。另外,IIS6 doesn't support this

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

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

  4. 结构良好的应用程序

    如果您的应用程序的结构导致所有网页最终都从单个根页继承,请包含<meta>标记,如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中没有触发。我还没弄清楚如何解决这个bug。

答案 1 :(得分:39)

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

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

答案 2 :(得分:17)

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

也许这个网址可以帮助您:Activating Browser Modes with Doctype

编辑:今天我们可以用以下方式覆盖兼容性视图: <meta http-equiv="X-UA-Compatible" content="IE=EmulateIE8" />

答案 3 :(得分:0)

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

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