使用用户控件从服务器端检查 JavaScript 是否已启用。






4.59/5 (24投票s)
一个 ASP.NET 用户控件,可以检查用户浏览器中是否启用了 JavaScript,然后执行回发以从服务器端执行备用操作,或重定向到没有 JavaScript 的页面。
引言
这是一种替代的设计方法,使用 ASP.NET 用户控件来确定用户是故意还是无意中禁用了浏览器中的 JavaScript,然后提交表单以从服务器端执行某些操作,或导航到另一个没有 JavaScript 的页面。
背景
大多数 ASP.NET/AJAX/JavaScript 开发者都可能遇到过这个问题
"如何检查用户浏览器中是否启用了/禁用了 JavaScript"
答案是,在不从用户浏览器进行回发的情况下,无法检查。虽然 .NET 提供了一种通过使用 'Request.Browser.JavaScript
' 来验证浏览器对 JavaScript 的支持的方法,但这并不能告诉我们 JavaScript 是否已启用。那么,我们如何测试客户端是否启用了 JavaScript 呢?
幸运的是,互联网上有很多答案。网络上大多数可用的技术都使用以下某种形式:使用 JavaScript 更改表单中的值,然后通过 JavaScript 提交表单。提交后,检查该值并与原始值进行比较。如果已更改,则表示 JavaScript 已启用。如果未更改,则表示不支持 JavaScript 或未启用 JavaScript。
然而,我在网上找到的解决方案并未提供以下功能
- 可重用性。
- 与 ASP.NET 集成。
- 其中大多数使用 JavaScript 回发到同一页面,但有时,如果禁用了 JavaScript,则需要导航到没有 JavaScript 的页面,而不是显示同一个损坏的页面。
- 可以在母版页上一次性包含该控件,并在所有页面和用户控件中执行检查。
我想要更优雅的东西。我有两个选择,要么是自定义服务器控件,要么是 ASP.NET 用户控件。我得出的结论是,用户控件将是最佳解决方案,因为它易于自定义和维护。
Using the Code
正如我之前提到的,在第一次请求时,无法从服务器端检查 JavaScript 是否已启用。因此,如果 JavaScript 被禁用,我们必须进行回发,或重定向到一个没有 JavaScript 的页面,使用
<NOSCRIPT>
<meta http-equiv=REFRESH content=0;URL={target url}>
</NOSCRIPT>
在上面的代码中,目标 URL 可以是同一页面或任何其他没有 JavaScript 的页面。
CheckJS.ascx
<%@ Control Language="C#" AutoEventWireup="true"
CodeFile="CheckJS.ascx.cs" Inherits="CheckJS" %>
<asp:HiddenField ID="hfClientJSEnabled" runat="server" Value="False" />
<script type="text/javascript">
document.getElementById('<%= hfClientJSEnabled.ClientID %>').value = "True";
if (document.getElementById('<%= hfClientJSEnabled.ClientID %>').value !=
'<%= IsJSEnabled %>')
{
window.location.href= '<%= GetAppendedUrl(JSQRYPARAM, JSENABLED) %>';
}
</script>
这是 CheckJS.ascx 页面的代码。它包含一个隐藏字段和一个 JavaScript 块。
IsJSEnabled
是一个布尔服务器端控件属性,用于存储和检索 JavaScript 已启用标志。顾名思义,如果 JavaScript 已启用,其值为 true。此属性的默认值为 true。
如果用户在页面已加载时启用了 JavaScript,则上述 JavaScript 将执行。IsJSEnabled
将返回 true。
if (document.getElementById('<%= hfClientJSEnabled.ClientID %>').value !=
'<%= IsJSEnabled %>')
这将导致页面导航到 GetAppendedUrl
返回的 URL。
CheckJS.ascx.cs
using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Collections.Specialized;
using System.Text;
public partial class CheckJS : System.Web.UI.UserControl
{
protected static string JSQRYPARAM = "jse";
protected static string JSENABLED = "1";
protected static string JSDISABLED = "0";
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
bool testJS = IsJSEnabled;
if (Request.QueryString[JSQRYPARAM] != null)
{
IsJSEnabled = Request.QueryString[JSQRYPARAM] == JSENABLED;
}
}
protected void Page_Load(object sender, EventArgs e)
{
}
protected string GetAppendedUrl(string newParam, string newParamValue)
{
string targeturl = string.Empty;
Uri url = (string.IsNullOrEmpty(ResolveUrl(NonJSTargetURL))) ?
new Uri(ResolveUrl(JSTargetURL)) :
new Uri(ResolveUrl(NonJSTargetURL));
if (url == null)
url = Request.Url;
string[] qry = url.Query.Replace("?","").Split('&');
StringBuilder sb = new StringBuilder();
foreach (string s in qry)
{
if (!s.ToLower().Contains(newParam.ToLower()))
{
sb.Append(s + "&");
}
}
if (sb.Length > 0)
{
sb.Remove(sb.Length - 1, 1);
targeturl = string.Format("{0}?{1}&{2}={3}",
url.AbsolutePath, sb.ToString(), newParam, newParamValue);
}
else
{
targeturl = string.Format("{0}?{1}={2}",
url.AbsolutePath, newParam, newParamValue);
}
return targeturl;
}
protected override void OnPreRender(EventArgs e)
{
base.OnPreRender(e);
if (IsJSEnabled)
{
string targeturl = GetAppendedUrl(JSQRYPARAM, JSDISABLED);
HtmlGenericControl ctrl = new HtmlGenericControl("NOSCRIPT");
ctrl.InnerHtml = string.Format("<meta http-equiv=REFRESH " +
"content=0;URL={0}>", targeturl);
Page.Header.Controls.Add(ctrl);
}
else
{
if (NonJSTargetURL != null)
Response.Redirect(NonJSTargetURL);
HtmlGenericControl ctrl = new HtmlGenericControl("NOSCRIPT");
ctrl.InnerHtml = string.Empty;
Page.Header.Controls.Add(ctrl);
}
}
protected bool IsJSEnabled
{
get
{
if (Session["JS"] == null)
Session["JS"] = true;
return (bool)Session["JS"];
}
set
{
Session["JS"] = value;
}
}
protected string JSTargetURL
{
get
{
return Request.Url.ToString();
}
}
public string NonJSTargetURL
{
get
{
return (ViewState["NONJSURL"] != null) ?
ViewState["NONJSURL"].ToString() : string.Empty;
}
set
{
try
{
ViewState["NONJSURL"] = ResolveServerUrl(value, false);
}
catch
{
throw new ApplicationException("Invalid URL. '" + value + "'");
}
}
}
public string ResolveServerUrl(string serverUrl, bool forceHttps)
{
if (serverUrl.IndexOf("://") > -1)
return serverUrl;
string newUrl = ResolveUrl(serverUrl);
Uri originalUri = HttpContext.Current.Request.Url;
newUrl = (forceHttps ? "https" : originalUri.Scheme) +
"://" + originalUri.Authority + newUrl;
return newUrl;
}
}
这是 CheckJS
用户控件的代码隐藏源代码。
OnInit
— 检查请求查询字符串中是否存在 "jse
" 参数。设置IsJSEnabled
的值。NonJSTargetURL
— 此属性是可选的。这是没有 JavaScript 的页面的 URL。如果未指定,它将执行回发到同一页面。GetAppendedUrl
— 此方法返回 URL,附加适当的查询字符串参数以指示 JavaScript 已启用标志。此方法会考虑NonJSTargetURL
来生成 URL。OnPreRender
— 基于IsJSEnabled
标志,此方法将呈现:<NOSCRIPT><meta http-equiv=REFRESH content=0;URL={target url}></NOSCRIPT>
。
请注意,我们不必始终执行重定向。首次请求后,用户信息将存储在会话变量中,直到用户在浏览器中更改设置。
如何使用 JSCheck 用户控件
使用此用户控件非常简单。
以下是步骤:
- 下载 CheckJSEnabledUserControl.zip。
- 将 CheckJS.ascx 和 CheckJS.ascx.cs 复制到您的 controls 文件夹。
- 打开您的母版页,并将此控件添加到页面中。
- 确保将此控件添加到页面控件层次结构中尽可能靠上的位置。这是必需的,因为
IsJSEnabled
属性的初始化是在OnInit
方法中完成的。因此,为了确保JSCheck
的OnInit
在任何其他控件的OnInit
之前执行,JSCheck 控件应尽可能位于控件层次结构的最顶层。 - 现在,要检查 JavaScript 是否已启用或禁用,请调用
CheckJavaScriptHelper.IsJavascriptEnabled
。
public class CheckJavaScriptHelper
{
public static bool IsJavascriptEnabled
{
get
{
if (HttpContext.Current.Session["JS"] == null)
HttpContext.Current.Session["JS"] = true;
return (bool)HttpContext.Current.Session["JS"];
}
}
}
CheckJavaScriptHelper
是一个辅助类,可用于检查 JavaScript 是否已启用或禁用,而无需在每个单独的页面或控件中引用该控件。