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

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

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.59/5 (24投票s)

2008 年 5 月 27 日

CPOL

4分钟阅读

viewsIcon

174900

downloadIcon

2077

一个 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 用户控件的代码隐藏源代码。

  1. OnInit — 检查请求查询字符串中是否存在 "jse" 参数。设置 IsJSEnabled 的值。
  2. NonJSTargetURL — 此属性是可选的。这是没有 JavaScript 的页面的 URL。如果未指定,它将执行回发到同一页面。
  3. GetAppendedUrl — 此方法返回 URL,附加适当的查询字符串参数以指示 JavaScript 已启用标志。此方法会考虑 NonJSTargetURL 来生成 URL。
  4. OnPreRender — 基于 IsJSEnabled 标志,此方法将呈现:<NOSCRIPT><meta http-equiv=REFRESH content=0;URL={target url}></NOSCRIPT>

请注意,我们不必始终执行重定向。首次请求后,用户信息将存储在会话变量中,直到用户在浏览器中更改设置。

如何使用 JSCheck 用户控件

使用此用户控件非常简单。

以下是步骤:

  1. 下载 CheckJSEnabledUserControl.zip
  2. CheckJS.ascxCheckJS.ascx.cs 复制到您的 controls 文件夹。
  3. 打开您的母版页,并将此控件添加到页面中。
  4. 确保将此控件添加到页面控件层次结构中尽可能靠上的位置。这是必需的,因为 IsJSEnabled 属性的初始化是在 OnInit 方法中完成的。因此,为了确保 JSCheckOnInit 在任何其他控件的 OnInit 之前执行,JSCheck 控件应尽可能位于控件层次结构的最顶层。
  5. 现在,要检查 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 是否已启用或禁用,而无需在每个单独的页面或控件中引用该控件。

© . All rights reserved.