我目前正在研究浏览器功能,并尝试测试.NET 4.0附带的浏览器定义文件。要做到这一点,我使用Firefox的附加组件来更改用户代理,我有一个简单的页面报告以下内容:
Request.UserAgent
Request.Browser.Id
Request.Browser.Browser
Request.Browser.MajorVersion
Request.Browser.MinorVersion
Request.Browser.Platform
Request.Browser.IsMobileDevice
Request.Browser.MobileDeviceManufacturer
Request.Browser.MobileDeviceModel
通常,这会根据默认浏览器定义文件中的注释中提供的示例提供正确的信息。但是我不时会看到奇怪的结果,我无法解释。
在iphone.browser
定义文件中获取示例iPhone用户代理,如下所示:
Mozilla/5.0 (iPhone; U; CPU like Mac OS X; en) AppleWebKit/420+ (KHTML, like Gecko) Version/3.0 Mobile/1A543a Safari/419.3
这应该将浏览器作为Safari返回。这取决于将Safari作为父级的IPhone网关,它与术语Safari
匹配。
稍微更改用户代理,以便在iPhone上模拟邮件客户端的用户代理,意味着删除用户代理的末尾部分,如下所示:
Mozilla/5.0 (iPhone; U; CPU like Mac OS X; en) AppleWebKit/420+ (KHTML, like Gecko)
现在应该将Mozilla作为浏览器返回,因为它无法匹配术语Safari
。但是,在第一次报告错误信息后立即对此进行分析,并仍然指示浏览器为Safari。
使用.browser
文件夹添加自定义App_Browsers
文件然后修改它似乎会强制它暂时正确,几乎就像缓存的定义或规则并没有在每个请求上完全运行。
这也是另一种方式,如果你从第二个示例用户代理开始,那么在分析第一个用户代理时,它将报告为Mozilla而不是Safari。
任何人都可以解释这种行为或解决方法吗?它是否尝试进行某种(不那么)聪明的缓存,它根据类似的用户代理进行假设?
感谢。
答案 0 :(得分:1)
比起寻找字符串“Safari”还有更多的匹配。如果你看看Mono的ASP.Net实现所使用的user agent database,你会发现你的第一个更具体的用户代理字符串将匹配一个更具体的规则,并且将设置浏览器版本。但即使修剪后的用户代理字符串仍然符合规则,将其标识为“iPhone”的某种变体,后来将其称为“Safari”。
微软的ASP.Net最有可能使用一个非常相似的数据库,我只是以Mono为例,因为该代码可以在网上找到。
所以,我重新回答了我的回答,并意识到我完全误解了这个问题!你是对的:缓存就在这里。 .NET Framework尝试节省解析用户代理字符串的时间。解析UA字符串后,结果将保存在哈希表中。关键是UA字符串,截断。
默认情况下,此密钥长度为64个字符,这就是为什么当您更改长UA字符串的末尾时,您看不到任何更改。此设置由UserAgentCacheKeyLength
的属性HttpCapabilitiesDefaultProvider
控制。为了验证,我添加了
<browserCaps userAgentCacheKeyLength="512" />
到我的测试项目中的Web.config中的<system.web>
元素。通过这个快速解决方案,问题就消失了。