如何从服务器端强制关闭 IE 的兼容模式? [英] How to forcefully set IE's Compatibility Mode off from the server-side?

查看:27
本文介绍了如何从服务器端强制关闭 IE 的兼容模式?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在域控制的环境中,我发现即使我们提供 X-UA 标签、!DOCTYPE 定义和IE=Edge"响应头.这些客户端勾选了在兼容性视图中显示 Intranet 站点"复选框.这正是我想要覆盖的内容.

In a domain-controlled environment I'm finding that the compatibility mode is triggered on certain clients (winXP/Win7, IE8/IE9) even when we are providing a X-UA tags, a !DOCTYPE definition and "IE=Edge" response headers. These clients have the "display intranet sites in compatibility view" checkbox ticked. Which is precisely what I'm trying to override.

以下是我用来尝试了解 IE 如何决定实际触发兼容模式的文档.

The following is the documentation that I've used to try understand how IE decides to actually trigger the compatibility mode.

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 个网址.

Google for "Defining Document Compatibility", sadly the SPAM engine doesn't let me post more than 2 urls.

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

This is an ASP .NET web app and includes the following definitions on the master page:

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

I've used Fiddler to check that the header is indeed being injected correctly.

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

My understanding is that with these settings I should be able override the "Display intranet sites in Compatibility View" browser setting. But depending on the client I've found that some of them will still trigger compatibility mode. It also seems to be down to the machine level rather a policy group setting, since I obtain different results even when I use with the same set of credentials on different clients.

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

Disabling the Compatibility View Settings checkbox does the trick. But the actual purpose is to make sure that the app is rendered exactly the same way regardless of the client settings.

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

Any thoughts and what I could be possibly missing? Is it possible at all to force IE to always render the pages without triggering Compat mode?

感谢一百万,

杰姆

PS:该站点目前正在开发中,当然不在 Microsoft 的兼容性列表中,但我也进行了检查以防万一.

PS: the site is currently in development and is of course not in Microsoft's compatibility list, but I've also checked just in case.

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

Google for "Understanding the Compatibility View List", sadly the SPAM engine doesn't let me post more than 2 urls.

推荐答案

我发现这两种常见的方法有问题:

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

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

  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.

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

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.

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

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

结构良好的应用程序

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

否则,我认为最好的方法是自动将 HTTP 标头添加到所有 HTML 响应中.一种方法是使用IHttpModule:

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 表示 IE 应该使用其最新的渲染引擎(而不是兼容模式)来渲染页面.

IE=edge indicates that IE should use its latest rendering engine (rather than compatibility mode) to render the page.

似乎HTTP模块经常被注册在web.config文件中,但这又让我们回到了第一个问题.但是,您可以在 Global 中以编程方式注册它们.asax 像这样:

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

请注意,模块是 static 并且不在 Init 中实例化很重要,因此每个应用程序只有一个实例.当然,在现实世界的应用程序中,IoC 容器可能应该对此进行管理.

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.

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

这篇关于如何从服务器端强制关闭 IE 的兼容模式?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆