65.9K
CodeProject 正在变化。 阅读更多。
Home

配置 ASP.NET 2.0 以正确识别和识别 Google Chrome 浏览器

starIconstarIconstarIconstarIconstarIcon

5.00/5 (4投票s)

2012年1月6日

CPOL

10分钟阅读

viewsIcon

39593

downloadIcon

514

本文旨在解释如何更新您的 ASP.NET 2.0 站点以正确识别和识别 Chrome。

引言

如果您开发或维护了 ASP.NET 2.0 网站,您可能会发现 ASP.NET 2.0 无法正确识别和识别 Google Chrome 浏览器。本文旨在解释如何更新您的 ASP.NET 2.0 站点以正确识别和识别 Chrome。

背景

ASP.NET 开发人员通常依赖 .NET HttpBrowserCapabilities 对象的属性,该对象由 HttpRequest 对象的 Browser 属性引用。例如,要获取浏览器的名称和版本,您可以使用类似这样的代码

BrowserName.Text = Request.Browser.Browser;
BrowserVersion.Text = Request.Browser.Version;

BrowserName.Text = this.Context.Request.Browser.Browser;
BrowserVersion.Text = this.Context.Request.Browser.Version; 

问题

问题在于 ASP.NET 2.0 无法正确识别 Chrome。在标准的(未修复的)ASP.NET 2.0 Web 应用程序中,Chrome 被识别为“AppleMAC-Safari”版本 5.0。这不足为奇,因为 ASP.NET 2.0 是在 Chrome 开发之前发布的。

许多开发人员通过编写自己的代码来解析 HttpRequest 对象的 UserAgent 属性来解决此缺陷,而浏览器和浏览器版本信息最终都来自此处。对于我目前使用的 Chrome 版本,User-Agent 字符串是

"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.7 (KHTML, like Gecko) Chrome/16.0.912.63 Safari/535.7"

看到 User-Agent 字符串,很容易理解为什么 ASP.NET 会将 Chrome 浏览器识别为 Safari,因为该代码是在 Chrome 存在之前发布的。

现在您可以自己解决这个问题,但事实证明,Microsoft 开发人员创建了一个相当复杂的系统来处理浏览器识别,我决定对我来说,最好的方法是修复已有的系统。事实证明这相当简单。

解决方案

只需一个简单的五步过程即可让 ASP.NET 2.0 正确识别 Chrome,最重要的是,这甚至不需要更改代码。

第一步:确定您的 .NET Framework 版本及其目录

在我的例子中,我使用的是 64 位框架,因此我的框架目录是:C:\Windows\Microsoft.NET\Framework64\v2.0.50727。如果我使用的是 32 位框架,它将是:C:\Windows\Microsoft.NET\Framework\v2.0.50727。在本文的其余部分,我将此目录称为“框架目录”。

第二步:复制或获取 chrome.browser 文件并将其放置在框架目录的 CONFIG\Browsers 目录中

当您查看框架目录的 CONFIG\Browsers 目录时,您可能会震惊地看到所有 .browser 文件。这些 .browser 文件是我之前提到的复杂系统的组成部分。如果您检查文件,您会发现它不过是一个 XML 配置文件,它使用正则表达式从 User-Agent 字符串中识别浏览器并设置浏览器功能。如果您仔细查看,您会发现它巧妙地使用正则表达式,不仅可以确定浏览器,还可以直接从 User-Agent 字符串中获取版本。

如果您的网站托管计算机上安装了 .NET 4.0,您可以简单地将 4.0 框架的 chrome.browser 文件从 4.0 Config\Browsers 目录复制到您的框架目录的 CONFIG\Browsers 目录中。

如果您没有安装 .NET 4.0,我有一个稍微修改过的 chrome.browser 文件可供下载。下载并解压缩它,然后将其放置在您的框架目录的 CONFIG\Browsers 目录中。

第三步:决定是否要将 Chrome 的版本仅报告为主版本和次版本(例如 16.0)或完整版本(例如 16.0.912.63)

.NET 4.0 chrome.browser 文件(未修改)在版本号中仅包含主版本和次版本。所以对于我正在使用的 Chrome 版本 16.0.912.63,它将版本报告为“16.0”。这对我来说是不够的,因为我想要完整的版本号。如果您使用本文附带的 chrome.browser 文件,我已经修改了它以报告完整的版本号。

以下是我附加的 chrome.browser 文件中的相关行。您可以看到第一个 userAgent 元素已被注释掉。这是标准 .NET 4.0 chrome.browser 文件中的原始行,导致版本仅报告为主版本和次版本“16.0”。第二个 userAgent 元素是我添加的,它会导致整个版本号被报告为版本“16.0.912.63”。

<browser id="Chrome" parentID="Mozilla">
    <identification>
     <!--userAgent match="Chrome/(?'version'(?'major'\d+)(\.(?'minor'\d+)?)\w*)" /-->
        <userAgent match="Chrome/(?'version'(?'major'\d+)(?'minor'\.[.\d]*))" />
    </identification>

如果您使用我附加的 chrome.browser 文件并想要完整的版本,只需保持文件原样。如果您只想报告主版本和次版本,请取消注释已注释掉的 userAgent 元素,并注释掉未注释的 userAgent 元素。

如果您使用的是自己的 .NET 4.0 chrome.browser 文件,并且只想报告主版本和次版本,请保持文件原样。如果您想报告完整的版本号,请注释掉现有的 userAgent 元素,并添加示例中的元素。

不用担心注释行会对性能产生负面影响,因为我在这里采取的方法不会影响系统的运行时性能。

第四步:编辑 mozilla.browser 文件

虽然我们现在有了一个 chrome.browser 配置文件来帮助 ASP.NET 识别 Chrome 浏览器,但不幸的是,现有的 mozilla.browser 文件会造成干扰。我们需要对其进行两处修改。

4.1. 备份现有的 mozilla.browser 文件

我只是在同一个目录中复制了文件,并将其命名为 mozilla.browser.bak,这似乎不会产生任何不良影响。

4.2. 更新 Gecko 部分

找到 id 属性设置为“Gecko”的 browser 元素。这将开始识别 Gecko 浏览器的配置部分。在 browser 元素内将有一个 identification 元素,在其内部将有一个 userAgent 元素,其 match 属性设置为“Gecko”。严格来说,这意味着如果您在 User-Agent 字符串中找到“Gecko”字符串,这就是 Gecko 浏览器。如果您检查 Chrome 提供的 User-Agent 字符串(本文顶部附近有记录),您会发现它确实包含 Gecko 字符串,这将导致它被(错误地)识别为 Gecko 浏览器。简单的解决方案是在现有元素下方添加另一个 userAgent 元素,并设置一个 nonMatch 属性为“Chrome”。这将告诉系统要成为 Gecko,User-Agent 字符串必须包含“Gecko”但不能包含“Chrome”。这是您添加新的 userAgent 元素后,mozilla.browser 文件中该部分应有的样子

<browser id="Gecko" parentID="Mozilla">
    <identification>
        <userAgent match="Gecko" />
        <userAgent nonMatch="Chrome" />
    </identification>

4.3. 更新 Safari 部分

找到 id 属性设置为“Safari”的 browser 元素。这将开始识别 Safari 浏览器的配置部分,而 Chrome 目前(错误地)被识别为此浏览器。请注意,在该部分更靠下的位置有一个名为 browser 的功能,其值为“AppleMAC-Safari”。这就是为什么 Chrome 被识别为“AppleMAC-Safari”的原因。现在开始变得有意义了,您不觉得吗?

在 Safari browser 元素内将有一个 identification 元素,在其内部将有一个 userAgent 元素,其 match 属性设置为“AppleWebKit/(?'webversion'\d+)”。严格来说,这意味着如果您在 User-Agent 字符串中找到“AppleWebKit/”字符串,这就是 Safari 浏览器。如果您检查 Chrome 提供的 User-Agent 字符串(本文顶部附近有记录),您会发现它确实包含“AppleWebKit/”字符串,这将导致它被(错误地)识别为 Safari 浏览器。简单的解决方案是在现有元素下方添加另一个 userAgent 元素,并设置一个 nonMatch 属性为“Chrome”。这将告诉系统要成为 Safari,User-Agent 字符串必须包含“AppleWebKit/”但不能包含“Chrome”。这是您添加新的 userAgent 元素后,mozilla.browser 文件中该部分应有的样子

<browser id="Safari" parentID="Gecko">
    <identification>
        <userAgent match="AppleWebKit/(?'webversion'\d+)" />
        <userAgent nonMatch="Chrome" />
    </identification>

如果不修改 mozilla.browser 文件,您会发现最初,Chrome 会被识别为 Safari,这是最初的问题。如果您仅更新 Safari 部分以在 User-Agent 字符串包含“Chrome”时排除它,那么该浏览器将随后被(错误地)识别为 Gecko。这就是为什么我们必须修改 mozilla.browser 文件的两个部分。

第五步:运行 aspnet_regbrowsers.exe 程序

之前我说过,在 .browser 文件中保留注释不会影响运行时性能。原因在于这些 .browser 配置文件不会在每次浏览器发出 HTTP 请求时读取。要使其生效,我们必须运行 aspnet_regbrowsers.exe 程序,该程序将实际解析它们并构建一个程序集,然后该程序集将在运行时链接。

因此,打开命令提示符并 cd 到您的框架目录。在其中,您会找到 aspnet_regbrowsers.exe 程序。只需运行该程序并附加 -i(安装)参数。这将创建并安装 ASP.BrowserCapsFactory.dll 程序集,该程序集会在您收到 HTTP 请求时填充 HttpBrowserCapabilities 对象。

您应该知道,运行 aspnet_regbrowsers.exe 程序将导致 IIS 重启。

C:\Windows\Microsoft.NET\Framework64\v2.0.50727>aspnet_regbrowsers.exe -i
Utility to compile ASP.Net browser files.
Copyright (C) Microsoft Corporation. All rights reserved.
The browser capabilities assembly ASP.BrowserCapsFactory.dll has been successfully installed.

结果

运行 aspnet_regbrowsers.exe 程序后,您应该会发现 Chrome 被识别为 Chrome,并且根据您在第三步中的决定,被识别为相应的版本。在我的例子中,该浏览器现在被识别为 Chrome 16.0.912.63,这正是我想要的。

风险

这种方法存在一些风险。如果您有一个现有的应用程序已支持 Chrome,您可能会发现这会带来麻烦。现有的代码,例如第三方服务器控件,可能期望 Chrome 被识别为“AppleMAC-Safari”,并可能自己检查 User-Agent 字符串以确定浏览器是 Chrome。通过系统现在将 Chrome 识别为 Chrome,其代码可能会出现故障。在我的例子中,我的应用程序不支持 Chrome,所以我没有这个风险。

此外,当您以这种方式更新系统时,它将影响使用相同版本的 .NET Framework(在同一服务器上)的所有 Web 应用程序。因此,您可能会在修复自己的 Web 应用程序时破坏其他 Web 应用程序。

限制和替代方案

显然,这种方法要求您完全控制服务器。在共享服务器环境中,您可能没有这种程度的控制。不过,您可以采取另一种方法来解决此问题。您可以将 .browser 文件添加到项目中的 App_Browsers 目录。

我没有尝试过这种方法,所以我不了解详细信息,但我想分享这个选项,以防您无法控制服务器,或者您不想冒着破坏服务器上其他 Web 应用程序的风险。如果我对这种方法感兴趣,我会想知道以下问题的答案

每次发出 HTTP 请求时都会解析 .browser 文件吗?它们是如何使用的?换句话说,运行 aspnet_regbrowsers.exe 程序会构建一个程序集一次。而将 .browser 文件直接放入 App_Browsers 目录又有什么作用?

根据上一个问题的答案,在 .browser 文件中保留注释会影响性能吗?如果每次请求都会解析它们,那么它们就会。如果每次请求都会影响性能,我可能想删除这些注释。

系统如何响应将框架 mozilla.browser 文件编译到 ASP.BrowserCapsFactory.dll 程序集中,同时在 App_Browsers 目录中有一个修改过的 mozilla.browser 文件?您的配置会正确覆盖 ASP.BrowserCapsFactory.dll 程序集中的配置吗?

结论

有很多替代方法和技巧可以确定浏览器是否为 Chrome,但既然 Microsoft 创建了这样一个精细的系统来做到这一点,为什么不使用它呢?这种方法比大多数方法更干净,并且不需要任何代码更改。只需确保更新所有必要的服务器,包括开发、暂存、测试和生产环境中的服务器。

© . All rights reserved.