在域控制的环境中,我发现即使我们提供了X-UA标记、!DOCTYPE定义和"IE=Edge"响应头,也会在某些客户端(winXP/win7、IE8/IE9)上触发兼容模式.这些客户端勾选了"在兼容视图中显示Intranet站点"复选框.这正是我想要推翻的.

以下是我用来try 理解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

网站所有者有always人控制他们的内容 网站所有者可以 Select 使用X-UA-Compatible标签,以绝对声明他们希望网站的显示方式,并将标准模式页面映射到IE7标准.Use of the X-UA-Compatible tag overrides Compatibility View on the client.

不幸的是,垃圾邮件引擎不允许我发布超过2个URL.

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

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

我已经使用Fiddler判断了报头是否确实被正确注入.

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

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

有什么 idea 和我可能错过的吗?有没有可能强迫IE在不触发Compat模式的情况下始终呈现页面?

非常感谢,

豪梅

该网站目前正在开发中,当然不在微软的兼容性列表中,但我也判断了一下,以防万一.

不幸的是,垃圾邮件引擎不允许我发布超过2个URL.

推荐答案

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

  1. 使用web中的自定义标题(<customHeaders>)执行此操作.config允许同一应用程序的不同部署使用不同的设置.我认为这是另一件可能出错的事情,所以我认为应用程序最好在代码中指定这一点.还有,IIS6 doesn't support this.

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

  3. 只向Internet Explorer客户端发送X-UA-Compatible报头可以减少网络流量.

struct 良好的应用程序

如果应用程序的 struct 使所有页面最终都从一个根页面继承,请包含<meta>标记,如the other answers所示.

遗留应用程序

否则

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上注册.配置文件,但这让我们回到第一个问题.然而,像这样的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中触发.我还没有找到解决这个问题的方法.

Asp.net相关问答推荐

属性包含破折号的 ServiceStack 请求对象?

如何在没有 Select 按钮的情况下在 GridView 中实现全行 Select ?

IIS HTTP 错误 500.19

httpCompression 和 urlCompression 有什么区别?

IIS Request.UserHostAddress 返回 IPV6 (::1),即使禁用了 IPV6

有条件地在 Gridview 中隐藏 CommandField 或 ButtonField

ASP.NET 平台是否有与 Heroku 等价的工具?

异步编程与线程有什么不同?

从 IIS 7/8 中的静态内容中删除服务器标头

如何将 Web 应用程序项目转换为类库项目

Windows 运行 ASP.NET 的 IIS 替代方案

判断邮箱地址是否对 System.Net.Mail.MailAddress 有效

.NET 上的 HTTP/2(HTTP2 或 SPDY)

MVC 4 - Razor - 将变量传递到 href url

由于文件路径太长,网站发布失败

如何防止aspxerrorpath作为查询字符串传递给 ASP.NET 自定义错误页面

ASP.Net 无法创建/卷影复制

将字典绑定到中继器

如何解决我的 ASP.Net MVC 应用程序中的 iisreset 后发生的 AntiForgeryToken 异常?

以编程方式滚动到锚标记