Saturday, October 3, 2009

ASP.Net Callback, Anthem and ViewState

Call backs and anthem are two important tools in AJAX library which have ability to fetch data from server without having to post the whole page.

I expect the readers to have some knowledge of ASP.NET to understand this article.

What happens in traditional ASP.NET:

Let us first recapitulate few things to proceed further. In traditional ASP.NET, client makes a request to server (say user has clicked a button on the page), a series of events get called and finally HTML is sent back to client. During this process, the whole page is re-drawn. This results in page flickering and whitening of whole page. Since web is stateless, so ASP.NET takes special care to maintain state by virtue of ViewState, which is prepared on server and stored on client.

Advent of AJAX:

To solve the issue of complete page being redrawn, Microsoft invented AJAX and call back is one of the tools in AJAX library. Before finally taking callback into account let us discuss UpdatePanel (One of the tools in AJAX library) a bit. Update panel leads to partial rendering which means whole page is not redrawn.

Only the markup written inside update panel tag is refreshed. But here also whole data is posted back and viewstate is also restored. Update panel is quite vast subject and we will not delve more into it. Now we will talk of callbacks.

Let’s now talk Call backs in detail:

A callback gives us flexibility of calling and fetching server data without having to make a full page postback. Server response is also at developer’s choice (which generally is very small). What areas on the page will be updated is decided by script function, which means whole page is not redrawn. So, end user gets the response very fast. So, the important benefits of callback approach are:

  • Whole page is not posted
  • Complete page is not redrawn. Rather a script function decides what mark up to refresh
  • Response is small, so it is quite fast.
  • User experience is very good. No flickering of the page. Response comes as soon as the request is fired.

HTML rendering is not decided by ASP.NET. Rather it is user driven.


Callback in Action:

Till now we have gathered theoretical knowledge of callback. Let us now talk about implementation level details. AJAX (Asynchronous JavaScript and XML) is based on xmlHttpRequest object and client side callbacks are dot Net way of wrapping xmlHttpRequest object. Client side callback feature is available in .NET 1.1. and 2.0 onwards.

The following example will show how to call the server (to get the date time from the server) and have that date time show up on the screen without any postbacks.

  • First create your website and go to the code behind of your default.aspx.
  • Implement the System.Web.UI.ICallbackEventHandler on the class.
  • This interface will produce two methods (RaiseCallbackEvent and GetCallbackResult). Make sure both of these methods get implemented.
  • The RaiseCallbackEvent method will be the first method called when the Callback starts. This method takes in an argument, which you can store as a member variable on your class to use in the GetCallbackResult. The GetCallbackResult method is the method in which you will build the arguments to pass back to the client side JavaScript.
  • Implement the code within the RaiseCallbackEvent and GetCallbackResult methods:

Following Code snippet will help you implement callback

private string _argument = string.Empty;

/// The RaiseCallbackEvent is the first place to receive the

/// callback from the client's browser when 'CallServer' is

/// triggered.

public void RaiseCallbackEvent(string eventArgument)

{

/// Stores the argument in a local variable so we can use it in

/// the GetcallbackResult" method later on if necessary.

_argument = eventArgument;

}

/// The GetCallbackResult method is the second call triggered by

/// the 'CallServer()'on the client side. This is the place to

/// prepare a string that can be placed as html on the page.

public string GetCallbackResult()

{

/// run the code to add the html to the javascript callback

/// method

if (_argument == "getServerTimeUserControl")

{

//return the response

return System.DateTime.Now.ToString();

}

else

{

return string.Empty;

}

}

Next, implement the following code in Page_Load event. Don’t forget to implement System.Web.UI.ICallbackEventHandler interface in the code behind class.

protected void Page_Load(object sender, EventArgs e)

{

/// Only need to register once, so don't register when a

/// callback is being performed

if (!Page.IsCallback)

{

//Register the Ajax client script to the client's broswer

string eventReference = String.Empty;

eventReference=

Page.ClientScript.GetCallbackEventReference(this,

"arg", "ReceiveServerData", "context");

string callbackScript = "function CallServer(arg,context)" + "{ " + eventReference + "} ;";

Page.ClientScript.RegisterClientScriptBlock(this.GetType()

,"CallServer", callbackScript, true);

}

}

Following client side code complements above callback code written in the code behind

<script type="text/javascript" language="javascript">

function GetServerTime(argument)

{

//Send the request to server

CallServer(argument, "");

}

function ReceiveServerData(argument){

document.getElementById("serverTimeUserControlArea").innerHTML =

argument;

}

The ReceiveServerData is the javascript method we registerd in the page_load of the code behind, so that is the method that the client side callback will eventually write back to. The GetServerTime is our javascript method we are going to call to kick off the client side callback functionality.

Build the html. This will just consist of a button to start the client side callback and a div to fill in when the information is retrieved from the server:

<input type= “button”

onclick=”javascript:GetServerTime(’getServerTimeUserControl’);”

id=”Button1″ />

<div runat=”server” id=”serverTimeUserControlArea”>div>

That’s it. We are done with firing the callback. This was a very simple example. Though in

‘RaiseCallbackEvent’ we can do whatever we feel like. Fetching data from database is another useful thing that can be done using callback without any page flicker.

Some Facts worth knowing

The above discussion and code snippet might have given you the impression that a javascript function calls a server method, which in turn returns response to another receiver script method, which is in fact right. But here one thing is worth mentioning that events in page life cycle are also called. So if you put a break point at any statement in Page_Load method, it will be hit while debugging. Try fetching the value of say a textbox ( suppose user has input some value in a textbox) in a callback scenerio in say Page_Load method. It will be either empty or any value user had provided at design time, but not the posted value ???

The reason is it is a callback and not a postback, so postdata is not available. But if you want to access postdata, there is a way to do that. Just copy and paste following lines in your javascript function before making server call (through callback ofcourse J)

__theFormPostCollection.length=0;
__theFormPostData="";
WebForm_InitCallback();

//Now...do the callback with your method CallServer("", "");

Basically issue is that with callbacks the data to post to the server is gathered in __theFormPostData by WebForm_InitCallback() method when the Page loads. So we call this method again to update __theFormPostData with the actual posted values.

Another issue with callback is that viewstate is not refreshed. Although callbacks are generally used for small operations where we don’t really need to maintain viewstate. But if you wish to refresh viewstate between cycles there is a hack available for that.

Update “GetCallbackResult” with following code

public string GetCallbackResult()

{

string callBackReturnValue = String.Empty;

//Run the code to add the html to the javascript callback

// method

if (_argument == "getServerTimeUserControl")

{

//return the response

callBackReturnValue = System.DateTime.Now.ToString();

}

else

{

callBackReturnValue = string.Empty;

}

System.Reflection.MethodInfo mi=

typeof(Page).GetMethod("SaveAllState",

System.Reflection.BindingFlags.Instance|
System.Reflection.BindingFlags.NonPublic);

mi.Invoke(this.Page, null);

// Get serialized viewstate from Page's ClientState

System.Reflection.PropertyInfo stateProp =

typeof(Page).GetProperty("ClientState",

System.Reflection.BindingFlags.Instance |

System.Reflection.BindingFlags.NonPublic);

string state = stateProp.GetValue(this.Page, null).ToString();

return callBackReturnValue + ";" + state;

}

Also modify ReceiveServerData as follows

function ReceiveServerData(argument){

var argumentArray = argument.split(";");

var userResponse = argumentArray[0];

var state = argumentArray[1];

document.getElementById("serverTimeUserControlArea").innerHTML

= userResponse;

document.getElementById('__VIEWSTATE').value = state;

}

But my recommendation is to use such hacks with due care as these hacks are not totally fool proof.

Even if we maintain postdata and viewstate in callbacks, it is still quite lighter than normal postback or postback using updatepanel. As in callback the biggest step of HTML rendering is avoided as opposed to a postback scenerio. The HTML rendering as we have seen is performed by the script function.

Anthem framework

Anthem is basically an open source project created by Jason Diamond's. Anthem is compatible on most of the browsers like IE, Firefox and Safari. Anthem supports both .NET 1.1 and .NET 2.0 and has a number of built in AJAX enabled controls. It is based upon callbacks rather than postback and its core is of course xmlHttpRequest object. It supports viewstate, so you can get control states and page info back in callbacks. It works seamlessly with web user controls, and master pages; and it is reasonably stable.

Getting Started

First, you need to download Anthem.NET 1.0. You can download it from http://anthem-dot-net.sourceforge.net/ Unfortunately, the DLL is not precompiled, so you will need to extract the projects and compile them to get the DLL. Assuming you've done this and have created the DLL, all you need to do to install Anthem.NET in a web application is add the DLL as a reference to your web application. You can then make the Anthem controls available by creating a new tab in the Toolbox, and use the right-click menu "Choose Items" - click Browse and locate the Anthem DLL. All the Anthem controls derive from ASP.NET controls, so you can use them on a web page just as you would a normal ASP control.

Also provide register directive at the top like

<%@ Register Assembly="Anthem" Namespace="Anthem" TagPrefix="cc1" %>

Simple Demo

Create a simple web application. In default.aspx page, drag and drop two anthem controls Linkbutton and a panel from anthem toolbox. Set the 'Text' property of LinkButton1 to "Click". Now place two ASP.NET textboxes inside the panel Panel1.Using an Anthem Panel control is the simplest way of providing AJAX updates to non-Anthem controls, if needed. Now the magic! Double-click the LinkButton on the designer. You should now be in the code editor, with a template LinkButton1_Click function. This is not a postback but a callback function.

Anthem will:

a. create the necessary JavaScript on the client,

b. bind it to the control's OnClick event,

c. receive the XMLhttprequest on the server, and

d. call the LinkButton1_Click in your server-side code.

Put following code in LinkButton1_Click callback event handler

protected void lnkLogin_Click(object sender, EventArgs e)

{

TextBox2.Text = TextBox1.Text;

// tell Anthem to update this control

this.pnlContainer.UpdateAfterCallBack = true;

}

Now, try running this. In first Textbox enter some value say ‘Test Value’ and click linkbutton. This value will be copied to second textbox.

This ensures the value is properly posted without writing any JavaScript code. Good thing is that viewstate is also restored.

Let’s analyze UpdateAfterCallBack property. Any anthem control will be updated if this property is set to true. Since Anthem panel is a container control. So once we set UpdateAfterCallBack property of anthem panel, it will be applied to all controls inside the panel. Now comment this line and again try running above code. This time the second text box value will be empty. So only those controls will be updated for which UpdateAfterCallBack property is set to true. Of course, this property can be set for individual anthem controls.

So, this gives user flexibility which portion of HTML he wants to update.

Another refinement: what if we have a slow connection? The user might click linkbutton to get the page, but a second or two's delay might make them think nothing has happened (especially if the server is loaded). They might click it again. Anthem controls like LinkButton and Button have two useful properties: TextDuringCallBack and EnabledDuringCallBack. If we set EnabledDuringCallback to false, the button is disabled during the callback processing time. To give the user some feedback, you can also set TextDuringCallBack=Wait so they know something's happening. If you run this on a local IIS, it's so quick you won't see it, so let's add a delay so it's easier to see:

Set TextDuringCallBack="Wait" EnabledDuringCallBack="false" on Anthen link button control i.e.

<cc1:LinkButton ID="lnkLogin" runat="server" Text="Login" OnClick="lnkLogin_Click" TextDuringCallBack="Wait" EnabledDuringCallBack="false" >cc1:LinkButton>

Add a delay by adding changing Linkbutton click hanlder as follows

protected void lnkLogin_Click(object sender, EventArgs e)

{

TextBox2.Text = TextBox1.Text;

System.Threading.Thread.Sleep(2000)

// Tell Anthem to update this control

this.pnlContainer.UpdateAfterCallBack = true;

}

Using anthem controls is simple. They expose events and properties the same way as normal ASP.NET controls. Like in the above case, the click event handler signature for an anthem linkbutton is same as that for normal ASP.NET linkbutton. After all, all anthem controls are derived from respective ASP.NET controls. The major difference in the way call is made. Anthem relies on callbacks. So in the above method, we are making a callback and not a postback.

Creation of necessary scripts and bundling xmlHttp functionality is taken care of by anthem framework.

If you view source of above demo, the linkbutton onclick event will be generated as onclick= “AnthemLinkButton_Click”, with some parameters. It also crates scripts and variables.

Adding Controls Dynamically

Anthem supports creating and adding controls dynamically.

If you expect your dynamic controls to fire events during call backs, you need to create them during or before the Load event. (Note that page life cycle executes the same way here as with normal ASP.NET controls).

Let’s take following code piece to understand creation of anthem controls dynamically.

protected void Page_Load(object sender, EventArgs e)

{

Anthem.LinkButton linkButton = new Anthem.LinkButton();

linkButton.Text = "Added Dynamically";

linkButton.Click += new System.EventHandler(linkButton_Click);

pnlContainer.Controls.Add(linkButton);

}

pnlContainer is the panel control in aspx page.

Now, write the linkbutton_click event handler as follows.

private void linkButton_Click(object sender, EventArgs e)

{

TextBox2.Text = TextBox1.Text;

// tell Anthem to update this control

this.pnlContainer.UpdateAfterCallBack = true;

(sender as Anthem.LinkButton).Text = "Modified";

}

Execute this code and it will work as you would have expected J

Anthem library provides you host of other controls in addition to simple controls which you can use. Let’s talk of databound controls.

Simple Controls: It supports mostly all simple controls like LinkButton, TextBox, Label, RadioButton, CheckBox, HiddenField, Hyperlink, Image, Imagebutton etc. Good thing is that it also supports File Upload, Multiview and FormView Control control.

Databound Controls: Datagrid, DataList, GridView, Repeater, CheckBoxList, RadioButtonList etc.

Validators: It supports all validators which are supported by ASP.NET viz. RequiredFieldValidator, RangeValidator, RegularExpressionValidator, CompareValidator, CustomValidator, ValidationSummary etc.

More Controls: It also supports some more controls like Calendar, Ad rotator, Bulleted List, Timer and WebPartZone etc.

Above all the panel control, which acts as a container for anthem and non- anthem controls. It has ability to provide anthem functioality to non- anthem controls. As we have already seen, any HTML inside anthem panel will only update in a callback scenerio, if panel’s UpdateAfterCallBack property is true.

Conclusion

Anthem is a modern AJAX library to speed up your applications. Based on callback framework, it provides a nice working model for ASP.NET developers. We can use anthem controls the same way as we use ASP.Net controls. All the necessary JavaScript is taken care of by smart Anthem. It provides a nice wrapper over xmlRequest and xmlResponse objects. Developer has nothing to worry about marshaling and de-marshaling of data. Above all it supports viewstate and multiple browsers.

For detailed documentation on Anthem please visit the following link.

http://anthem.talloaksoftware.com/

No comments: