Friday, July 18, 2008

RegisterStartupScript and RegisterClientScriptBlock

         There two powerful methods available in dotnet two include JavaScript on page from code behind. Normally we write the JavaScript functions on aspx page however in some case we have to dynamic script which we can not write on aspx page for many reasons like the script require some data which we have to fetch from database or require some operations that can only be done from code behind. In this case we can use RegisterStartupScript or RegisterClientScriptBlock function to include the JavaScript from code behind.

         Both function does the same thing, just emits your JavaScript to the page, however the difference lies in position where they emits the scripts on page. RegisterStartupScript emits your JavaScript at the end of the page just before </form> tag (before the <form> tag ends). While RegisterClientScriptBlock emits the JavaScript just after the <form> tag starts. Look at the code shown below,

   1: protected void Page_Load(object sender, EventArgs e)
   2: {
   3:         
   4:     if(!ClientScript.IsClientScriptBlockRegistered("RegisterClientScriptBlock"))
   5:         Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "RegisterClientScriptBlock", "document.write('RegisterClientScriptBlock');", true);
   6:  
   7:  
   8:     if (!ClientScript.IsStartupScriptRegistered("StartupScriptRegistered"))
   9:         ClientScript.RegisterStartupScript(this.GetType(), "StartupScriptRegistered", "document.write('StartupScriptRegistered');", true);
  10: }

Fig - (1) Code behind file Default.aspx.cs



   1: <%@ Page Language="C#" AutoEventWireup="true" CodeFile="UseIComprer.aspx.cs" Inherits="IseIComprer" %>
   2:  
   3: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
   4:  
   5: <html xmlns="http://www.w3.org/1999/xhtml">
   6: <head runat="server">
   7:     <title>Untitled Page</title>
   8: </head>
   9: <body>
  10:     <form id="form1" runat="server">
  11:     <div>
  12:         <table>
  13:             <tr>
  14:                 <td>
  15:                     Page Content
  16:                 </td>
  17:             </tr>
  18:         </table>
  19:     </div>
  20:     </form>
  21: </body>
  22: </html>

Fig - (2) Default.aspx page


    Now when you run this page the output will be,



   1: RegisterClientScriptBlock 
   2: Page Content 
   3: StartupScriptRegistered 

Fig - (3) Output of the Default.aspx page


      You can see that the script we have register using RegisterStartupScriptBlock renders first and the statement document.write writes "RegisterClientScriptBlock" to the page then we have the Page Content and finally the "StartupScriptRegistered".  If you see the view source,



   1: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
   2:  
   3: <html xmlns="http://www.w3.org/1999/xhtml">
   4: <head><title>
   5:     Untitled Page
   6: </title></head>
   7: <body>
   8:     <form name="form1" method="post" action="UseIComprer.aspx" id="form2">
   9: <div>
  10: <input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPDwUJNzgzNDMwNTMzZGT4JJog3qP93QeYemlckRLadGZVuw==" />
  11: </div>
  12:  
  13:  
  14: <script type="text/javascript">
  15: //<![CDATA[
  16: document.write('RegisterClientScriptBlock');//]]>
  17: </script>
  18:  
  19:     <div>
  20:         <table>
  21:             <tr>
  22:                 <td>
  23:                     Page Content
  24:                 </td>
  25:             </tr>
  26:         </table>
  27:         
  28:     
  29:     </div>
  30:     
  31:  
  32: <script type="text/javascript">
  33: //<![CDATA[
  34: document.write('StartupScriptRegistered');//]]>
  35: </script>
  36: </form>
  37: </body>
  38: </html>

Fig - (4) View Source for Default.aspx


      As you can see at lines 14 to 17 we have the script registered using "RegisterStartupScript" and at lines 32 to 35 we have the script registered using "RegisterStartupScript".


      Now you can easily identify when you have to use RegisterStartupScript and when to use RegisterClientScriptBlock. If you want to assign any value or property  or want to get the value or property from any element you should use RegisterStartupScript. If you use RegisterClientScriptBlock you will get error object undefined as the particular object is not being rendered yet. 


Happy Programming !!!

Wednesday, June 25, 2008

Access Cache object of one application from another application OR share Cache object between Applications

       Recently while reading some forum I found an interesting question Can we share the cache object between two different applications ? More specifically can we access cache data of one application from another application ? I thought its a good topic to study and share.

       The answer is yes you can share the cache data between two application or you can access cache data of one application in another. There may be plenty of options to achieve this. The way I found and like is to serialize the cache data and transfer it between two applications.

       In the example which I will show here, I have created a two applications. First application has two pages Default.aspx and SerializeCacheData.aspx. The second application has only one page GetSerializedCacheData.aspx. The logic is, we will add the data in Cache on Default.aspx. SerializeCacheData.aspx page receives the name of the cache object we want to share between two applications. GetSerializedCacheData.aspx call the SerializeCacheData.aspx page and passes the name of the cache data that it wants from first application in querystring.

      On Default.aspx page I am creating an object of Person class (I have created a class in App_Code folder and will store the object of that class in cache) and string it is Cache. To store the object in Cache that object must be serializable. So I have marked my Person class as [Serializale]. Below is the Person class,

   1: using System;
   2: using System.Data;
   3: using System.Configuration;
   4: using System.Linq;
   5: using System.Web;
   6: using System.Web.Security;
   7: using System.Web.UI;
   8: using System.Web.UI.HtmlControls;
   9: using System.Web.UI.WebControls;
  10: using System.Web.UI.WebControls.WebParts;
  11: using System.Xml.Linq;
  12:  
  13: /// <summary>
  14: /// Summary description for Person
  15: /// </summary>
  16: [Serializable]
  17: public class Person
  18: {
  19:     public Person()
  20:     {
  21:         //
  22:         // TODO: Add constructor logic here
  23:         //
  24:         Name = "Chirag";
  25:         Address = "Ahmedabad";
  26:         Id = 1;
  27:         strPrivateData = "chirag";
  28:     }
  29:  
  30:     public string Name { get; set;}
  31:     public string Address { get; set; }
  32:     public int Id { get; set; }
  33:  
  34:     private string strPrivateData;
  35:  
  36: }

Fig - (1) Person class, we are going to store its object in Cache


       On Default.aspx page we will store the object of person class in cache as shown below,



   1: using System;
   2: using System.Configuration;
   3: using System.Data;
   4: using System.Linq;
   5: using System.Web;
   6: using System.Web.Security;
   7: using System.Web.UI;
   8: using System.Web.UI.HtmlControls;
   9: using System.Web.UI.WebControls;
  10: using System.Web.UI.WebControls.WebParts;
  11: using System.Xml.Linq;
  12:  
  13: public partial class _Default : System.Web.UI.Page 
  14: {
  15:     protected void Page_Load(object sender, EventArgs e)
  16:     {
  17:         if (!Page.IsPostBack)
  18:         {
  19:             Person objPerson = new Person { Name = "Dipak", Address = "USA", Id = 2 };
  20:             Cache.Insert("TestData", objPerson);
  21:         }
  22:     }
  23: }

Fig - (2) Storing data in Cache.


        On SerializeCacheData.aspx page we will serialize the cache data in byte array.  We will get the name of cache data in querystring.  As you can see in code below we will get the querystring parameter "data" on this page. We will retrieve the values from cache using querystring parameter and serialize it in Memory Stream. There is no need to store value in ViewState however I have specifically stored in ViewState as I need to do some operations on postback which I have not covered in this article. Look at the code below,



   1: using System;
   2: using System.Collections;
   3: using System.Configuration;
   4: using System.Data;
   5: using System.Linq;
   6: using System.Web;
   7: using System.Web.Security;
   8: using System.Web.UI;
   9: using System.Web.UI.HtmlControls;
  10: using System.Web.UI.WebControls;
  11: using System.Web.UI.WebControls.WebParts;
  12: using System.Xml.Linq;
  13: using System.Runtime.Serialization;
  14: using System.Runtime.Serialization.Formatters.Binary;
  15: using System.IO;
  16:  
  17: public partial class SerializeCacheData : System.Web.UI.Page
  18: {
  19:     public MemoryStream objMemoryStream
  20:     {
  21:         get
  22:         {
  23:             if (ViewState["objMemoryStream"] == null)
  24:                 ViewState["objMemoryStream"] = new MemoryStream();
  25:             return (MemoryStream)ViewState["objMemoryStream"];
  26:         }
  27:  
  28:         set
  29:         {
  30:             ViewState["objMemoryStream"] = value;
  31:         }
  32:     }
  33:     
  34:  
  35:     protected void Page_Load(object sender, EventArgs e)
  36:     {
  37:         if (!Page.IsPostBack)
  38:         {
  39:             string strValueToSerialize = string.Empty;
  40:  
  41:             // Get the name of Cache data from querystring
  42:             if (Request.QueryString["data"] != null)
  43:                 strValueToSerialize = Request.QueryString["data"].ToString();
  44:  
  45:             if (strValueToSerialize != string.Empty)
  46:             {
  47:                 // Serialize the data in Memory Stream
  48:                 IFormatter objIFormatter = new BinaryFormatter();
  49:                 objIFormatter.Serialize(objMemoryStream, Cache[strValueToSerialize]);
  50:                 objMemoryStream.Position = 0;
  51:  
  52:                 // Generate the byte array from Memory Stream
  53:                 byte[] objByte = new byte[objMemoryStream.Length];
  54:                 objMemoryStream.Read(objByte, 0, Convert.ToInt32(objMemoryStream.Length));
  55:                 Response.BinaryWrite(objByte);
  56:                 objMemoryStream.Position = 0;
  57:                 Response.End();
  58:             }
  59:             
  60:         }
  61:         
  62:     }
  63: }

Fig - (3) SerializeCacheData.aspx.cs


      Now in second application from GetSerializedCacheData.aspx page we will call SerializCacheData.aspx page and retrieves the value. Look at the code below,



   1: using System;
   2: using System.Collections;
   3: using System.Configuration;
   4: using System.Data;
   5: using System.Linq;
   6: using System.Web;
   7: using System.Web.Security;
   8: using System.Web.UI;
   9: using System.Web.UI.HtmlControls;
  10: using System.Web.UI.WebControls;
  11: using System.Web.UI.WebControls.WebParts;
  12: using System.Xml.Linq;
  13: using System.Net;
  14: using System.IO;
  15: using System.Runtime.Serialization;
  16: using System.Runtime.Serialization.Formatters.Binary;
  17:  
  18: public partial class GetSerilizedCacheData : System.Web.UI.Page
  19: {
  20:     protected void Page_Load(object sender, EventArgs e)
  21:     {
  22:         if (!Page.IsPostBack)
  23:         {
  24:             // Generate WebRequest to SerializeCacheData.aspx page
  25:             WebRequest objWebRequest = WebRequest.Create("http://localhost:1083/SerializationEx/SerializeCacheData.aspx?data=TestData");
  26:             WebResponse objWebResponse = objWebRequest.GetResponse();
  27:             Stream objStream = objWebResponse.GetResponseStream();
  28:  
  29:             // Deserialize the value
  30:             IFormatter objIFormatter = new BinaryFormatter();
  31:             Person objPerson = (Person)objIFormatter.Deserialize(objStream);
  32:             Response.Write(objPerson.Name);
  33:             
  34:         }
  35:     }
  36: }

Fig - (4) GetSerializedCacheData.aspx.cs


     As shown in above code, we are retrieving the Person class object in second application and writing the Name value in response. You must have to have Person class in both application. In real time you can pass anything which can be serialized like DataTable, DataSet or any custom object.


Happy Programming !!!