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

发布于 2024-11-17 22:49:58 字数 1674 浏览 0 评论 0原文

在域控制环境中,我发现即使我们提供 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 标记会覆盖客户端上的兼容性视图。

这是一个 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 code>

<system.webServer>
  <httpProtocol>
    <customHeaders>
      <clear />
      <add name="X-UA-Compatible" value="IE=Edge" />
    </customHeaders>
  </httpProtocol>
</system.webServer>

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

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

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

有什么想法以及我可能会错过什么吗?是否有可能强制 IE 始终渲染页面而不触发兼容模式?

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

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.

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

Site owners are always in control of their content. Site owners can choose to use the X-UA-Compatible tag to be absolutely declarative about how they’d like their site to display and to map Standards mode pages to IE7 Standards. Use of the X-UA-Compatible tag overrides Compatibility View on the client.

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>

and web.config

<system.webServer>
  <httpProtocol>
    <customHeaders>
      <clear />
      <add name="X-UA-Compatible" value="IE=Edge" />
    </customHeaders>
  </httpProtocol>
</system.webServer>

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

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.

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?

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

一萌ing 2024-11-24 22:49:58

我发现执行此操作的两种常见方法存在问题:

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

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

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

结构良好的应用程序

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

遗留应用程序

否则,
我认为最好的方法是自动将 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);
    }
}

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

优点

  • 克服了本答案开头概述的问题。

缺点

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

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

  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.

  2. 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.

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

Well-Structured Applications

If your application is structured in a way that causes all pages to ultimately inherit from a single root page, include the <meta> tag as shown in the other answers.

Legacy Applications

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 indicates that IE should use its latest rendering engine (rather than compatibility mode) to render the page.

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

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.

Advantages

  • Overcomes the problems outlined at the start of this answer.

Disadvantages

  • 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.
佼人 2024-11-24 22:49:58

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

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

Changing my header to the following solve the problem:

<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=Edge" />
岁月静好 2024-11-24 22:49:58

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

您可以使用以下方法覆盖兼容性视图:

更多有用信息做什么?

Maybe this URL can help you: Activating Browser Modes with Doctype

You can override the compatibility view with:
<meta http-equiv="X-UA-Compatible" content="IE=Edge" />

More useful information What does <meta http-equiv="X-UA-Compatible" content="IE=edge"> do?

无戏配角 2024-11-24 22:49:58

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

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

For Node/Express developers you can use middleware and set this via server.

app.use(function(req, res, next) {
  res.setHeader('X-UA-Compatible', 'IE=edge');
  next();
});
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文