Cyber Security & Dot Net Security

Thursday, November 18, 2010

How to use the Client Script Manager

How to use the Client Script Manager

The ClientScriptManager class is used to manage client scripts and add them to Web applications. You can get a reference to the ClientScriptManager class from the ClientScript property of the Page object. You can add a client script to a Web page declaratively by including the script in the HTML markup of the page. 
This embedded script would look like this on the aspx page:








<script type="text/javascript">
            function changePostalCodeLabel(selectedValue)
            {
                        var lblZipPostalCode = document.getElementById("lblZipPostalCode");
                        if(selectedValue == 'US'){
                                    lblZipPostalCode.innerHTML = 'Zip Code'
                        } else {
                                    lblZipPostalCode.innerHTML = 'Postal Code'
                        }
            }
</script>
However, there are situations when adding client script dynamically is needed. To add a script dynamically, use the RegisterClientScriptBlock method (to inset a dynamically created block of script into the page), the RegisterClientScriptInclude method (to dynamically insert a reference to an external script file into the page), the RegisterStartupScript method (to dynamically insert a script that will execute during start-up), or the RegisterOnSubmitStatement method(to dynamically insert a script that will execute on form submission)
The ClientScriptManager class uniquely identifies scripts by a key String and a Type. Scripts with the same key and type are considered duplicates. Using the script type helps to avoid confusing similar scripts from different user controls that might be in use on the page.

One of the biggest advantages to using dynamic scripts is the ability to access the ClientID of various controls on the web page as the page is being loaded.  As the simple script listed at the top will work on a simple page when master pages are implemented .NET does some name mangling under the covers and the previous script would not work.  With master pages the correct script would be more along the lines of the following:
<script type="text/javascript">
            function changePostalCodeLabel(selectedValue)
            {
                        var lblZipPostalCode = document.getElementById("ctl00_MainContent_lblZipPostalCode");
                        if(selectedValue == 'US'){
                                    lblZipPostalCode.innerHTML = 'Zip Code';
                        } else {
                                    lblZipPostalCode.innerHTML = 'Postal Code';
                        }
            }
</script>

There is no way of knowing at design time, in a guaranteed fashion, what the control name will be.  By using the client script manager we can create the script on the fly and have the page provide us with the client id that it will be implementing.

The following example uses a simple drop-down containing three countries.  The idea behind the script is that if the selected country is the United States then the text box label will show Zip Code, for any other country it will display Postal Code. 
The code for the aspx page is:
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="ClientScriptManagerExample.aspx.cs" Inherits="ClientScriptManagerExample" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>Client Script Manager Example Page</title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <asp:DropDownList ID="ddlCountry" runat="server" Height="19px" Width="184px" onChange="changePostalCodeLabel(this.value)">
        </asp:DropDownList>
        <asp:Label ID="lblZipPostalCode" runat="server" Text="Zip/Postal Code"></asp:Label>
        <asp:TextBox ID="txtZipPostalCode" runat="server"></asp:TextBox>
    </div>
    </form>
</body>
</html>
The Code-Behind is this:
using System;
using System.Text;
using System.Web.UI;
using System.Web.UI.WebControls;

public partial class ClientScriptManagerExample : Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            // Add a few countries to the drop-down list
            ListItem liUS = new ListItem("United States", "US", true);
            ListItem liUK = new ListItem("United Kingdom", "UK", true);
            ListItem liCA = new ListItem("Canada", "CA", true);
            ddlCountry.Items.Add(liUS);
            ddlCountry.Items.Add(liUK);
            ddlCountry.Items.Add(liCA);
            // Create and register the script
            SetPostalCodeJavascript();
            // Set an initial value for the label
            if (ddlCountry.SelectedItem.Text.Equals("United States"))
            {
                lblZipPostalCode.Text = "Zip Code";
            }
            else
            {
                lblZipPostalCode.Text = "Postal Code";
            }
        }
    }
    private void SetPostalCodeJavascript()
    {
        // Define the name and type of the client scripts on the page.
        const string csname = "PostalCodeLabelScript";
        Type cstype = GetType();

        // Get a ClientScriptManager reference from the Page class.
        ClientScriptManager cs = Page.ClientScript;

        // Check to see if the client script is already registered.
        if (!cs.IsClientScriptBlockRegistered(cstype, csname))
        {
            StringBuilder cstext = new StringBuilder();
            cstext.AppendFormat("<script type=\"text/javascript\">{0}", Environment.NewLine);
            cstext.AppendFormat("\tfunction changePostalCodeLabel(selectedValue) {0}", Environment.NewLine);
            cstext.AppendFormat("\t{{{0}", Environment.NewLine);
            // lblZipPostalCode.ClientID is the important part here
            cstext.AppendFormat("\t\tvar lblZipPostalCode = document.getElementById(\"{0}\");{1}", lblZipPostalCode.ClientID, Environment.NewLine);
            cstext.AppendFormat("\t\tif(selectedValue == '{0}'){{{1}", "US", Environment.NewLine);
            cstext.AppendFormat("\t\t\tlblZipPostalCode.innerHTML = 'Zip Code' {0}", Environment.NewLine);
            cstext.AppendFormat("\t\t}} else {{ {0}", Environment.NewLine);
            cstext.AppendFormat("\t\t\tlblZipPostalCode.innerHTML = 'Postal Code' {0}", Environment.NewLine);
            cstext.AppendFormat("\t\t}} {0}", Environment.NewLine);
            cstext.AppendFormat("\t}}{0}", Environment.NewLine);
            cstext.Append(Environment.NewLine);
            cstext.AppendFormat("</script>{0}", Environment.NewLine);
            cs.RegisterClientScriptBlock(cstype, csname, cstext.ToString(), false);
        }
    }
}

By using the ClientScriptManager we can really leverage javascript on the client-side where appropriate, reducing round trips to the server, providing a better user experience as well as consuming less server time.  A win-win situation

No comments: