在现代的网络应用中,JavaScript和Cookie是实现许多功能的基础。大多数情况下,用户的浏览器默认启用了这些功能,因此一切正常。然而,如果用户的浏览器禁用了JavaScript或Cookie,而应用程序没有相应的处理代码,用户可能会遇到问题,不知道发生了什么,甚至可能会报告一些奇怪的问题,这可能会浪费开发者大量的时间去排查,最后发现问题并非出自应用程序本身,而是用户的浏览器设置。
为了提高用户体验并节省开发者的时间,有时需要检查用户的浏览器设置,并在JavaScript或Cookie被禁用时采取一些措施。这听起来很简单,但当深入研究这个问题时,会发现实际上并不容易。
没有办法直接检测浏览器的客户端配置。确实,可以使用HttpRequest::Browser来检查浏览器的能力,但这对没有任何帮助。
对于Cookie,唯一的方法是创建一个Cookie,然后尝试读取它。如果能读取,这意味着它被启用了;否则,它被客户端禁用了。在代码中,使用了相同的原理。
对于JavaScript,可以使用<noscript>
标签为用户提供备用内容,这些用户在浏览器中禁用了脚本或使用不支持客户端脚本的浏览器。但使用<noscript>
标签只是一种机制,用于显示客户端JavaScript的不可用性,除此之外什么也做不了,服务器端仍然不知道。
因此,想法是使用用户控件或自定义控件让服务器能够知道用户的设置。更喜欢自定义控件,因为它可以轻松地在不同的项目中重用。在网上搜索,没有找到现成的控件,既能检查JavaScript又能检查Cookie。所以决定自己创建一个。
代码相当简单。在文件"BrowserChecker.cs"中定义了一个名为BrowserChecker的组件。
网页表单"Default.aspx"是一个演示如何使用这个组件的示例。在这个网页表单上有一个按钮,点击时除了提交表单外什么也不做。按钮下方的标签用于在客户端禁用JavaScript或Cookie时显示信息。进行检查的时间是在页面加载和回发时(见下面的代码)。
protected void Page_Load(object sender, EventArgs e)
{
if (IsPostBack)
CheckBrowser();
}
从控件的属性BrowserJavaScriptStatus和BrowserCookieStatus,可以知道客户端是否禁用了JavaScript或Cookie(见下面的代码)。
private void CheckBrowser()
{
StringBuilder error = new StringBuilder();
if (this.BrowserChecker1.BrowserJavaScriptStatus == BrowserStatus.Disabled)
error.Append(BrowserCheckJavaScript);
if (this.BrowserChecker1.BrowserCookieStatus == BrowserStatus.Disabled)
error.Append(BrowserCheckCookie);
if (error.Length > 0)
this.lblMessage.Text = error.ToString();
}
以下是在禁用JavaScript时点击按钮后的结果。使用了Internet Explorer 7,并使用Internet Explorer开发者工具栏禁用了JavaScript。
以下是在禁用Cookie时点击按钮后的结果。使用了Internet Explorer 7,并使用Internet Explorer开发者工具栏禁用了Cookie。
也可以在Firefox中运行应用程序。在Firefox中,禁用JavaScript或Cookie要容易得多,如果不知道如何操作,只需Google一下就能找到答案。
这里只显示了消息。在实际使用中,可以将检查代码放在Web应用程序的登录页面甚至母版页面中,当用户禁用JavaScript或Cookie时,将用户重定向到指定页面。
如果想在另一个项目中重用这个组件,只需复制并包含文件"BrowserChecker.cs"到项目中,然后构建应用程序。现在在工具箱中,会发现控件,只需将其拖放到Web表单上,就可以使用它了。
代码非常直观。但想提一下以下几点。
对于检查Cookie的可用性,它在呈现时尝试写入一个Cookie,并在回发时再次读取它。
对于检查JavaScript的可用性,它在呈现时将一个隐藏的输入和一个启动JavaScript块放入页面。JavaScript将被执行以设置隐藏输入的值。因此,当页面回发时,服务器可以通过检查隐藏输入的值来知道JavaScript是否被客户端禁用。
控件继承了Control而不是WebControl,以使其尽可能简单。
if (DesignMode)
return;
RegisterScript();
SetCookie();
否则,在调用SetCookie时,设计视图中会出现错误,因为HttpContext在这种情况下不可用。