JumpStart # 8 – Making Client CallBacks by Implementing ICallBackEventHandler Interface

 

Before looking at the code, Read about – What is JumpStart?

NOTE:-
  1. CallBacks plays a crucial role at times when we don’t need to go around to the server in round trips (to prevent unnecessary postbacks).
  2. CallBacks are also useful to preserve the client state (say if there is a state maintained in Javascript for example), which we loose in case of postbacks.
  3. There are some alternatives to the callbacks, say AJAX, Async WebServices.

In the following example code, we first create a Database and store the necessary details of the Images like ImageName, ImagePath (physical directory path in relative URL), ImageDescription etc. Then we display these images on the web page using a Repeater in combination with SqlDataSource. After this we use Client CallBack to display the details of corresponding image on which mouse is hovered. CallBacks are accomplished by implementing ICallBackEventHandler.

NOTE:-
  1. I tried my best (in short time) to make things look understandable with lot of comments and pre-description (above).
  2. I kindly request the reader to bear with me in the style this tutorial has been written.
  3. For better understanding purpose, I took the names of the variables from MSDN (as I thought those are wonderfully appropriate). For detailed info – MSDN Reference

================================================================================================

Database Details

Database details which are used to accomplish this tutorial are furnished in this section.

================================================================================================

Database Name :- Example

Database Table :- Images

Database Definition :-

 Untitled

Database sample data :-

Untitled1

ConnectionString entry in the Web.Config file (inside the <Configuration> tag) would look like (kindly change it to your systems corresponding) :-

  <connectionStrings>
    <add name="ExampleConnectionString" connectionString="Data Source=RAMILU-PC\SQLEXPRESS;
          Initial Catalog=Example;Integrated Security=True"  providerName="System.Data.SqlClient" />
  </connectionStrings>

================================================================================================

Page.aspx

We implement ICallBackEventHandler interface in this page to change the images dynamically with ‘onmouseover’ event of html Image control.

================================================================================================

<%@ Page Language="C#" %>

<!-- For Inline aspx model, we got to Implement ICallBackEventHandler interface to make callbacks -->
<%@ Implements Interface="System.Web.UI.ICallbackEventHandler" %>

<!-- The below namespaces are required for basic database and file operations (which we intended to perform in the code -->
<%@ Import Namespace="System.Data.SqlClient" %>
<%@ Import Namespace="System.Data" %>
<%@ Import Namespace="System.IO" %>

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

<script runat="server">
    
    // returnValue -> is the value returned from the server to client on CallBack
    protected string returnValue = "";
    protected DataSet ds;
    
    
    protected void Page_Load(object sender, EventArgs e)
    {
        /* Below code is responsible to make the CallBacks (means important code), which first gets the CallBackReference (which
         * conveys the javascript method to be called on CallBack, here it is - ReceiveServerData(arg)). And then induces the 
         * reference to the clientside call function - CallServer().
         */
        String cbReference = Page.ClientScript.GetCallbackEventReference(this, "arg", "ReceiveServerData", "context");
        String callbackScript;
        callbackScript = "function CallServer(arg, context)" + "{ " + cbReference + ";}";
        Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "CallServer", callbackScript, true);

        
        
        /* Below code connects to the the database (which we created as shown prior in this tutorial), and then gets the content
         * of the database into a dataset (which we use to filter and display images on mouse over). We use a SqlDataAdapter to
         * fill the dataset.
         */
        SqlConnection conn = new SqlConnection("Data Source=RAMILU-PC\\SQLEXPRESS;Initial Catalog=Example;Integrated Security=True");
        string command = "select * from Images"; 
        
        SqlDataAdapter sda = new SqlDataAdapter(command,conn);
        ds = new DataSet();
        
        sda.Fill(ds,"Images");
    }

    
    // This page event registers the event reference for validation. so that we can use ValidateEvent() for cross checking script attacks.
    protected override void Render(HtmlTextWriter writer)
    {
        Page.ClientScript.RegisterForEventValidation(imgDisplay.UniqueID);
        base.Render(writer);
    }

    
    
    // This is the event actually raised on CallBack back at server.
    public void RaiseCallbackEvent(String eventArgument)
    {
        try
        {
            /* ValidateEvent is used to cross check that the client CallBack is not because of a script attack of a malicious user.
             * If the callback is malicious, then the code breaks here and takes us to the catch block.
            */
            Page.ClientScript.ValidateEvent(imgDisplay.UniqueID);
            
            
            /* Below code takes the image path of the image on which mouse is hovered. Then based on that particular image details
             * we get the remaining details of the image like ImageDescription, ImageName etc from the Dataset which we used in Page_Load.
             * Then we concatenate the details to a string with a seperator, say here - '$$/' (its just a random one) to the returnValue - 
             * then returnValue is thrown back to the javascript RecieveServerData function.
             */
            string imgPath = Path.GetFileName(eventArgument);

            foreach (DataRow dr in ds.Tables[0].Rows)
            {
                if (Path.GetFileName(dr["ImagePath"].ToString()) == imgPath)
                {
                    returnValue += dr["ImagePath"].ToString() + "$$/" + dr["ImageDescription"].ToString() + "$$/" + dr["ImageName"].ToString();
                }
            }
        }
        catch (Exception ex)
        {
            returnValue += "error$$/error$$/error";
        }
    }
    
    
    // This is the function which is used to return the result of a CallBack.
    public String GetCallbackResult()
    {
        return returnValue;
    } 
</script>

<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
    <title></title>
      <script type="text/javascript">

          // Raise the callback event here. We Pass src of the Image control in the Repeater as an argument to this method (for image identification).
          function ClientCallbackRaise(event) {
              CallServer(event, "");
          }

          // Process the return value from the server here....
          function ReceiveServerData(rValue) {
              var originalString = rValue;

              // we split the returnValue string to substrings, and then display those details in corresponsing controls using Javascript.
              var spltString = originalString.split('$$/');
              document.getElementById('imgDisplay').src = spltString[0];
              document.getElementById('News').innerHTML = spltString[1];
              document.getElementById('imgName').innerHTML = spltString[2];
          }
  </script>
</head>
<body>
    <form id="form1" runat="server">
    <div>

       <!-- We use SqlDataSource and repeater to display the initial images (say for example as thumbnails) -->
        <asp:SqlDataSource ID="SqlDataSource1" runat="server" 
            ConnectionString="<%$ ConnectionStrings:ExampleConnectionString %>" 
            SelectCommand="SELECT [ImagePath] FROM [Images]"></asp:SqlDataSource>
        <br />
        <asp:Repeater ID="Repeater1" runat="server" DataSourceID="SqlDataSource1">
        <ItemTemplate>
            <asp:Image ID="Image1" runat="server" Height="50" Width="50" onmouseover="ClientCallbackRaise(src)" ImageUrl='<%# Eval("ImagePath") %>' />
        </ItemTemplate>
        </asp:Repeater>

        <br />

        <!-- The bottom section is used to display the callback results. -->
        <asp:Panel ID="Panel1" runat="server">
            Image :- <img id="imgDisplay" runat="server" alt="" src="" height="200" width="200" /><br />
            Image Description :- <span id="News" runat="server"></span><br />
            Image Name :- <span id="imgName" runat="server"></span>
        </asp:Panel>
    </div>
    </form>
</body>
</html>

================================================================================================

OUTPUT

================================================================================================

 

Disclaimer:

All coding and suggestions made in the above discussion is strictly in point of view of the author. It is neither mentioned any where nor even concluded that this is the only possible way to go with, as there will be always a chance for a new approach in achieving the same requirement (in context of programming). The above mentioned code is strictly written and explained for the sake of new comers to C# and ASP.NET world.

You may also like...