Sunday, February 2, 2014

Implementing asynchronous callbacks in asp.Net 4

Internet application development can be seen as the a stateless client-server programming using a thin client.In case that we don't like this approach, we have several methods to change it.
The cause of such adaptations most often stems from specific business needs and rules.

Sometimes, software engineers want to make the client a bit more thick. They usually do this by adding code to the client side, i.e. JavaScript, vb-script, etc. Other times, want to make UI more... feasible. By 'feasible' I mean that it is not necessary to post-back a whole page just for a very simple calculation. One solution to this issue is to put simple calculations to the client side (using JavaScript). But again, what if the operands are members of  some more generic object that cannot be transferred to the client, such as a large database table? Is then the post-back a one-way solution? Well, no. The answer can be called AJAX or in other words (a more MS oriented ones) Asynchronous Callbacks.

 In this post, I will show the MS asp.Net 4 way to implement asynchronous callbacks using a very simple paradigm. I will create a VS 2012 Web project that will just calculate the sum and the product of two integers. The actual calculation will be done on the client and the result will be send to the server without post-back but by "callbacking" the functions that performed the actual calculations. Please note that the code make use of this features, tips or tricks:
  • I pass to the CallbackEvent many arguments (from client).
  • I use two call back events (one for each operation - sum and product)
  • The same code can be used in case that data can be calculated, called or retrieved from a database.
  • I use VB.Net but (of course) C# can be used as well.
  • For clarity reasons I did not put any exception handling code.

Program Flow

On Page_Load I just create the JS functions that will be called by the client (code) when the corresponding button, responsible for the calculation, is pressed.  I pass 3 arguments to the Client CallBack function using concatenation, delimetered by comma: "p1, p2, p3".
p1 is the type of action ('sum' or 'product') and the rest p2,p3 are the operands.

The default.aspx file is the following:

   1:  <%@ Page Language="VB" AutoEventWireup="false" CodeFile="Default.aspx.vb" Inherits="_Default" %>
   2:   
   3:  <!DOCTYPE html>
   4:    
   5:   <html xmlns="http://www.w3.org/1999/xhtml">
   6:    
   7:   <head id="Head1" runat="server">
   8:       <title>AJV Callback02</title>
   9:    
  10:       <script type="text/javascript">
  11:           // The Sum //////////////////////////////////////
  12:           function GetSum() {
  13:               var args = "sum" + "," + document.forms[0].TextBox1.value + "," + document.forms[0].TextBox2.value;
  14:               CallbackFromJS_sum(args);
  15:           }
  16:   
  17:           function PutSumToTheClient(theSum) {
  18:               document.forms[0].TextBox3.value = theSum;
  19:           }
  20:           // The Product ///////////////////////////////////
  21:           function GetProduct() {
  22:               var args = "product" + "," + document.forms[0].TextBox4.value + "," + document.forms[0].TextBox5.value;
  23:               CallbackFromJS_product(args);
  24:           }
  25:   
  26:           function PutProductToTheClient(theProduct) {
  27:               document.forms[0].TextBox6.value = theProduct;
  28:           }
  29:       </script>
  30:    
  31:   </head>
  32:    
  33:    
  34:   <body>
  35:       <form id="form1" runat="server">
  36:           <div>
  37:               <h2>Implementing asynchronous callbacks in asp.Net 4</h2>
  38:               Calculate the sum and the product of 2 integers using asynchronous callback. <br />
  39:               I pass 3 arguments to the Client CallBack function using concatenation, delimetered by comma: "<i>p1, p2, p3</i>".<br />
  40:               <i>p1</i> is the type of action ('sum' or 'product') and the rest <i>p2,p3</i> are the operands.<br />
  41:               <i>Please note that for clarity reasons I did not put any exception handling code...</i> ;)
  42:               <br /><br />
  43:           </div>
  44:           <div>
  45:           Enter Interger 1:<asp:TextBox ID="TextBox1" Runat="server"></asp:TextBox>
  46:           <br />
  47:           Enter Interger 2:<asp:TextBox ID="TextBox2" Runat="server"></asp:TextBox>
  48:           <br /><br />
  49:           <input id="Button1" type="button" value="Calculate Sum" onclick="GetSum()" />
  50:           <br /><br />
  51:           The sum is <asp:TextBox ID="TextBox3" Runat="server" ReadOnly="true"></asp:TextBox>
  52:           </div>
  53:           <hr />
  54:           <div>
  55:           Enter Interger 1:<asp:TextBox ID="TextBox4" Runat="server"></asp:TextBox>
  56:           <br />
  57:           Enter Interger 2:<asp:TextBox ID="TextBox5" Runat="server"></asp:TextBox>
  58:           <br /><br />
  59:           <input id="Button2" type="button" value="Calculate Product" onclick="GetProduct()" />
  60:           <br /><br />
  61:           The product is <asp:TextBox ID="TextBox6" Runat="server" ReadOnly="true"></asp:TextBox>
  62:           </div>
  63:    
  64:       </form>
  65:   </body>
  66:   </html>


And the corresponding code behind default.aspx.vb is the following:

   1:   
   2:  Partial Class _Default
   3:      Inherits System.Web.UI.Page
   4:   
   5:      Implements System.Web.UI.ICallbackEventHandler
   6:   
   7:   
   8:      Dim iRet_Result As String = Nothing 'Holds the result of the operation.
   9:   
  10:      Protected Sub Page_Load(sender As Object, e As EventArgs) Handles Me.Load
  11:          'Create the JS function that will be called when the Sum button is pressed. 
  12:          Dim cbJSFunction As String =
  13:              "function CallbackFromJS_sum(arg) { " + _
  14:                              Page.ClientScript.GetCallbackEventReference(Me, "arg", "PutSumToTheClient", "") + _
  15:             "; }"
  16:   
  17:          ' Put the function on the client.
  18:          Page.ClientScript.RegisterClientScriptBlock(Me.GetType(), "CallbackFromJS_sum", cbJSFunction, True)
  19:   
  20:          '------------------------------------
  21:   
  22:          'Create the JS function that will be called when the product button is pressed. 
  23:          Dim cbJSFunction_product As String =
  24:              "function CallbackFromJS_product(arg) { " + _
  25:                              Page.ClientScript.GetCallbackEventReference(Me, "arg", "PutProductToTheClient", "") + _
  26:             "; }"
  27:   
  28:          ' Put the function on the client.
  29:          Page.ClientScript.RegisterClientScriptBlock(Me.GetType(), "CallbackFromJS_product", cbJSFunction_product, True)
  30:   
  31:   
  32:      End Sub
  33:   
  34:      Public Sub RaiseCallbackEvent(ByVal eventArgument As String) Implements System.Web.UI.ICallbackEventHandler.RaiseCallbackEvent
  35:          ' Convert the "p1, p2, p3" arguments into an array.
  36:          ' p1 is the type of action ('sum' or 'product') and the rest p2,p3 are the operands.
  37:          Dim strArrayOfParameters() As String
  38:          strArrayOfParameters = Split(eventArgument, ",")
  39:   
  40:          Select Case strArrayOfParameters(0)
  41:              Case "sum"
  42:                  iRet_Result = CType(strArrayOfParameters(1), Integer) + CType(strArrayOfParameters(2), Integer)
  43:              Case "product"
  44:                  iRet_Result = CType(strArrayOfParameters(1), Integer) * CType(strArrayOfParameters(2), Integer)
  45:              Case Else
  46:                  iRet_Result = "Invalid Parameters"
  47:          End Select
  48:   
  49:   
  50:      End Sub
  51:   
  52:      Public Function GetCallbackResult() As String Implements System.Web.UI.ICallbackEventHandler.GetCallbackResult
  53:          Return iRet_Result
  54:      End Function
  55:   
  56:  End Class
Happy programming guys!

No comments:

Post a Comment