Client
Callbacks in ASP.NET Whidbey
Client Callback is a new feature in ASP.NET Whidbey(2.0). It
allows calling server side events asynchronously, without causing
postback. It is possible to do asynchronous
call using XMLHttp Post in ASP.NET 1.0 itself, but in ASP.NET 2.0 a
clean framework is available to do this. This
article describes how Client Callbacks works and also explores how this Client
Callback framework has been implemented in ASP.NET 2.0.
Client Callback Architecture
Consider
in a page you have two dropdown list. First dropdownlist displays authors name
and depending upon the selection of author in first dropdownlist, you need to
display author titles in second dropdownlist. In ASP.NET 1.x, there are two
ways to do this.
1.
After selecting a value from the author dropdownlist. You can do a postback
and get the data for author title and bind it to
the other dropdown. But problem with this method is, it involves a page refresh. All
the controls in the page have to be refreshed and whatever data entered has
to be retained. Major problem with this method is, user has to wait till
the page loads for entering other data in the page.
2. Second option is
to get all the data for author title dropdownlist to the client, and
the depending upon the author dropdownlist selection you can filter the data in client side
using javascript and then show it in author title dropdownlist. In this example, you
need to send lots of data to the client.
In
ASP.NET 2.0 using client callback mechanism you can avoid drawbacks of
the above mentioned methods. Here is the architecture diagram for
Client Callback.
To
avoid page refresh during postback, you need to instantiate
the client callback process from client side and finally you need to update the
page from client side only. Hence you need one client side function to
instantiate the callback and another client side function to get the
results from serverside callback event to update the page. Once the call back is
instantiated, a request will go to server side to call server side events. This
event will return string to client side function which will process this
result.
Generating Client Side Code for Callback
For implementing callback in
client side, a new method "GetCallbackEventReference" in Page Class
is available in ASP.NET 2.0. You can use this method to generate client side
code which is required to instantiate the
asynchronous call to server. In our example, client side code
is generated like this;
Dim callBack As String = Page.GetCallbackEventReference(Me,
"arg", "ClientCallback", "context", "ClientCallbackError")
Me
- The control that implements ICallbackEventHandler(Current Page)
arg
- String to be passed to server side as argument.
ClientCallback
- name of the client side function which will receive the result from server
side event.
context
- String to be passed from one client side function to other client side
function through context parameter
ClientCallbackError
- Name of the client side function which will be called if there is any error
during this process.
String
returned from the GetCallBackReference method will look like this,
WebForm_DoCallback('__Page',arg,ClientCallback,context,ClientCallbackError);
WebForm_DoCallback is another javascript
function comes along with framework which will
does the XMLHttp work for us. This function
is located in the script returned by the WebResource.axd handler. In ASP.NET 1.0, all the
framework client scripts are placed under aspnet_client folder in IIS root
directory. Scripts from this folder are referenced in the
corresponding page wherever it is required. But in ASP.NET 2.0 all the client
side framework scripts are placed inside a dll and these files will
be returned by handler(webresource.axd). For example if you check the source of this aspx page
in browser, you will find the following line.
<script
src="WebResource.axd?a=s&r=WebForms.js&t=632282564448503725"
type="text/javascript"></script>
If you check out the src property of this script
tag,source is pointed to a handler with few parameters. This handler will
return script required for this
page and it is stored in Internet temporary files. If you want to look
at the script generated by this handler, you can go to internet temporary files
folder and then check for files with their name starts with webresoruce.axd . You
will find a file with the name matching the src attribute string mentioned
in script tag. In that file, you can find WebForm_DoCallback javascript function.
The code
snippet for inserting client side code into the page is shown
below.
Sub Page_Load(ByVal sender As Object, ByVal e
As System.EventArgs) Handles Me.Load
If Not IsPostBack And Not IsCallback
Then
Dim
ds As New DataSet
Dim
da As New SqlDataAdapter("select au_id, au_lname + ' ' + au_fname as fullname
from authors",
"<connstr>")
da.Fill(ds)
DropDownList1.DataTextField = "fullname"
DropDownList1.DataValueField = "au_id"
DropDownList1.DataSource = ds
DropDownList1.DataBind()
DropDownList1.Attributes.Add("onchange",
"GetOrders(this.options[this.selectedIndex].value,
'DropDownList1');")
End If
Dim callBack As String
callBack =
Page.GetCallbackEventReference(Me, "arg", "ClientCallback", "context",
"ClientCallbackError")
Dim clientFunction As String
= "function GetOrders(arg, context){ " & callBack & "; }"
Page.ClientScript.RegisterClientScriptBlock(Me.GetType(), "GetOrders",
clientFunction, True)
End Sub
If
you look at this code snippet, you will see a new property called
IsCallBack. This property will return boolean based on call type
(whether it is callback or not). You can use this property to
avoid execution of unnecessary code during call back. In our case, binding
of author dropdownlist is not required during callback or postback as
values of that dropdownlist is retained across postback using viewstate. So you
need to use this property to check whether it is callback or not and then bind
the dropdownlist. Since during a call back, a request will go to server for
executing a server side event. All the events of the Page like Page_load,
Page_init will fire till Page_Prerender event. You should keep this in mind
when you are creating call back page.
As
you have seen earlier, GetCallbackEventReference method is used to generate
code for instantiating
call back and then that is placed inside a client function which has
arg and context as its parameters. This method can be called wherever you
want to do the call back. In our example, you call this in onchange of
dropdownlist to do call back and get the values for second dropdownlist.
RegisterClientScriptblock is used to register this client script in the page.
You can see the difference in how RegisterClientScriptblock is called from
previous release, instead of invoking this method directly from page class. It
is invoked using a new class called ClientScript, which now handles client
script part in ASP.NET 2.0.
Client
script used to instantiate is called in onchange of dropdownlist. SelectedValue
of dropdownlist is passed to client side function as arg value and control name
is passed as context value. Arg value is passed to server side event and
context is passed to call back client side function.
Creating Server Side Event for CallBack
Next
part is in server side. If you want to implement call back in an ASP.NET page.
Then that page has to implement ICallBackEventHandler interface. Basically it
has to have RaiseCallbackEvent function which will be called during callback.
Here is the implementation of server side part for our example,
Partial Class Default_aspx
Implements ICallbackEventHandler
Function RaisePostBackEvent(ByVal eventArgument As String) As String Implements
ICallbackEventHandler.RaiseCallbackEvent
Dim ds As New DataSet
Dim da As New
SqlDataAdapter("select titles.title_id,title from titles inner join titleauthor
on
titleauthor.title_id = titles.title_id where au_id = '" &
eventArgument & "'", "<connstring>")
da.Fill(ds)
Dim str As New
StringBuilder("")
Dim oRow As DataRow
For Each oRow In
ds.Tables(0).Rows
str.Append(oRow("title"))
str.Append("|")
Next
Return str.ToString()
End Function
RaiseCallBackEvent
function will accecpt a string and return a string. Event Arugment is passed
from client side function and return string from this function is passed to
callback client side function which process this result. In our example, we are
getting selectedvalue(author id) as event argument and then with that value we
will fetch author titles. Since we can pass only a string back, we need to do
some string manipulation here to pass all the author title in one string.
Creating Client Call Back Function
Next
part in implementing client call back mechanism is creating a client side
function which will process the result from server side events. This method
has two parameters, result and context. Result is the string from server
side event and context is the string value from the other client side function
which instantiates call back. In our example, it is implemented as shown below.
function ClientCallback(result, context)
{
var dropdown2 =
document.forms[0].elements['DropDownList2'];
dropdown2.innerHTML= "";
var rows = result.split('|');
for (var i = 0; i < rows.length - 1;
++i)
{
var values = rows[i]
var option =
document.createElement("OPTION");
option.value = values;
option.innerHTML =
values;
dropdown2.appendChild(option);
}
}
This function will process the result string and then get the list
of author titles from that string. With that list, it will create option
elements for second dropdownlist. All these things happen without page refresh and
user can continue what he was doing. Now the second dropdownlist is also
populated, he can select any value from this dropdownlist.
Conclusion
Though this callback mechanism is implemented using
XMLHttp Post. It is cross browser friendly, it will
work in netscape also. To verify whether callback mechanism will work
in a browser or not, they have introduced two properties named SupportCallback
and SupportXMLhttppost. In this release, both the property will work in same way. But
in feature release callback can be implemented
without XMLHttpPost, in that case both properties will work in different way. Client
call back will help developers to develop a
very interactive screen without unnecesary postbacks. It can be used for
doing serverside validation, sending some information to server asynchronously.
|