Introduction
This is an alternate design approach using an ASP.NET user control to determine if the users have either purposely or inadvertently disabled JavaScript on their browsers, and either submit the form to perform some actions from server-side or navigate to another non-JavaScript page.
Background
Most ASP.NET/AJAX/JavaScript developers must have faced this issue:
"How to check if JavaScript is enabled/disabled in the user's browser"
The answer is, you cannot, without doing a postback from the user's browser. Although .NET provides a way to verify browser support for JavaScript through the use of 'Request.Browser.JavaScript
', it does not tell us if JavaScript is enabled. So, how do we test if the client has JavaScript enabled?
Fortunately, there are many answers on the Internet. Most techniques available on the Web use some form of the following: Use JavaScript to change a value in a form and then submit the form via JavaScript. After submitting, check the value and compare it to the original. If it has changed, then JavaScript is enabled. If it hasn't changed, then either JavaScript isn't supported or JavaScript isn't enabled.
However, the solutions I found on the Internet do not provide the following:
- Reusability.
- Integration with ASP.NET.
- Most of them use JavaScript to postback to the same page, but sometimes, it is required to navigate to a non-JavaScript page if JavaScript is disabled, instead of displaying the same broken page.
- Ability to include the control once on the master page and do the check in all the pages and user controls.
I wanted something more elegant. I had two choices, either a custom server control, or an ASP.NET user control. I came to the conclusion that the user control would be the best solution as it would be easy to customize and maintain.
Using the Code
As I have already mentioned, there is no way of checking if JavaScript is enabled from the server-side on the first request. So, if JavaScript is disabled, we have to do a postback, or redirect to a non JavaScript page, using:
<NOSCRIPT>
<meta http-equiv=REFRESH content=0;URL={target url}>
</NOSCRIPT>
In the above code, the target URL can be the same page or any other non-JavaScript page.
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>
This is the code in the CheckJS.ascx page. This contains a hidden field and a JavaScript block.
IsJSEnabled
is a boolean server-side control property which stores and retrieves the JavaScript enabled flag. As the name indicates, its value is true if JavaScript is enabled. The default value of this property is true.
If the user turns on the JavaScript while the page has already loaded, the above JavaScript will execute. The IsJSEnabled
will return true.
if (document.getElementById('<%= hfClientJSEnabled.ClientID %>').value !=
'<%= IsJSEnabled %>')
This will cause the page to navigate to the URL returned by GetAppendedUrl
.
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;
}
}
This is the source code for the code-behind for the CheckJS
user control.
OnInit
— Check the Request query string for the parameter "jse
". Set the value of IsJSEnabled
.NonJSTargetURL
— This property is optional. This is the URL to a non-JavaScript page. If not specified, then it will do a submit to the same page.GetAppendedUrl
— This returns the URL, appending the appropriate query string parameters for the JavaScript enabled flag. This method takes NonJSTargetURL
into account for generating the URL.OnPreRender
— Based on the IsJSEnabled
flag, this method renders: <NOSCRIPT><meta http-equiv=REFRESH content=0;URL={target url}></NOSCRIPT>
.
Please note that we do not have to do the redirect always. After the first request, the information about the user's browser is stored in the session variable until the user changes the settings in the browser.
How to Use the JSCheck User Control
It's really easy to use this user control.
Here are the steps:
- Download CheckJSEnabledUserControl.zip.
- Copy CheckJS.ascx and CheckJS.ascx.cs to your controls folder.
- Open your Master page and add this control to the page.
- Make sure this control is added to the page control hierarchy as high as possible. This is required because the initialization of the
IsJSEnabled
property is done in the OnInit
method. So, to make sure that JSCheck
's OnInit
fires before any other control's OnInit
, the JSCheck control should be on top of the control hierarchy as far as possible. - Now, to check if JavaScript is enabled or disabled, call
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
is the helper class which can be used to check if JavaScript is enabled or disabled without actually referencing the control on each individual page or control.