Introduction
In the first and second part of this tutorial on xml-script we introduced the declarative programming model and illustrated how to handle events raised by the client Microsoft Ajax objects. Events can be handled by invoking a global JavaScript function or by using actions; in this third part we'll talk about the InvokeMethod action, which allows calling a method declaratively.
InvokeMethod Action
The InvokeMethod action enables invoking a method exposed in the type descriptor of a client object. In the following example, we'll illustrate this action with the help of an interesting class contained in the Futures CTP: Sys.Preview.Net.ServiceMethodRequest. This class abstracts an asynchronous call to a web service method and exposes a type descriptor that allows using it in xml-script. This means that we can invoke a web method and process its results without writing a single line of JavaScript.
The example
To keep things simple, we will poll (i.e. call at regular intervals) a web method that returns the current time on the web server; then, we'll display it on a label.
The first thing to do is setup the web service; thus, in your Ajax-CTP enabled website, add a new web service called DateTimeService.asmx and copy the following code:
<%@ WebService Language="C#" Class="DateTimeService" %>
using System;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.Web.Script.Services;
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[ScriptService]
public class DateTimeService : System.Web.Services.WebService {
[WebMethod]
[ScriptMethod]
public string GetTimeAsString() {
return DateTime.Now.ToShortTimeString();
}
}
Note that the DateTimeService class is decorated with the ScriptService attribute: this instruct ASP.NET AJAX to generate a client proxy for the web service. The proxy allows invoking all the web methods decorated with the ScriptMethod attribute (like the GetTimeAsString method) from client side, using JavaScript.
Good. Now to the xml-script code; recall that in order to use the xml-script feature you have to reference the Microsoft.Web.Preview.dll assembly in your website. If you are using an Ajax-CTP enabled website, the assembly is already referenced and all you have to do is load the PreviewScript.js file in the ScriptManager.
<%@ Page Language="C#" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Declarative WebService
Call</title>
</head>
<body>
<form id="form1" runat="server">
<asp:ScriptManager ID="ScriptManager1" runat="server">
<Services>
<asp:ServiceReference Path="DateTimeService.asmx" />
</Services>
<scripts>
<asp:ScriptReference Assembly="Microsoft.Web.Preview"
Name="PreviewScript.js" />
</scripts>
</asp:ScriptManager>
<h2>
<span>Time on Web Server: </span>
<asp:Label ID="lblTime" runat="server"></asp:Label>
</h2>
<script type="text/xml-script">
<page xmlns="http://schemas.microsoft.com/xml-script/2005">
<components>
<label id="lblTime" />
<timer id="theTimer" interval="2000" enabled="true">
<tick>
<invokeMethodAction target="timeServiceMethod" method="invoke">
<parameters userContext="" />
</invokeMethodAction>
</tick>
</timer>
<serviceMethodRequest id="timeServiceMethod"
url="DateTimeService.asmx"
methodName="GetTimeAsString">
<completed>
<setPropertyAction target="DateTime"
property="text"
>
<bindings>
<binding dataContext="timeServiceMethod"
dataPath="result"
property="value"
/>
</bindings>
</setPropertyAction>
</completed>
</serviceMethodRequest>
</components>
</page>
</script>
</form>
</body>
</html>
Let's start by looking at the xml-script block. The label element is associated to the span tag, resulting in an instance of the Sys.Preview.UI.Label control being created at runtime. The subsequent element, timer, is used to create an instance of the Sys.Preview.Timer class, which provides a timer that exposes an interval property used to set a time interval that, when elapsed, causes the Timer object to fire a tick event.
More about the InvokeMethod Action
The tick event is handled with an InvokeMethod action, which calls a method called invoke (specified in the method attribute) on an object with the id timeServiceMethod. Inside the invokeMethodAction element we can have a parameters element that is used to specify the parameters passed to the method. To specify a parameter, all we have to do is add an attribute with the name of the parameter and its value. In the example, we are passing a single parameter called userContext and setting its value to an empty string.
The id of timeServiceMethod corresponds to the serviceMethodRequest element, which is parsed to create an instance of the Sys.Preview.Net.ServiceMethodRequest class. The url and methodName attributes specify the path to the web service and the name of the web method to call.
Inside the serviceMethodRequest element we find a completed node. This element represents the completed event raised by the ServiceMethodRequest class when the asynchronous call to the web method succeeds. To handle the event, we are using a SetProperty action to set the label's text to the string returned by the web method, which contains the formatted time on the web server. The ServiceMethodRequest class exposes many other events such as timeout and error, fired when a timeout or an error occur during the processing of the asynchronous request.
Bindings
An interesting thing is the binding element declared inside the setPropertyAction element. Since the string returned by the web method is stored into the result property exposed by the ServiceMethodRequest class, we can't specify it in the value attribute of setPropertyAction; instead, we need to access the result property declaratively.
To do this, we can use a binding, which establishes a relation between two properties of the same or different objects so that when one property changes, the other property automatically reflects the change. If you look at the binding declaration, you'll see that the dataContext attribute points to timeServiceMethod, and the dataPath attribute points to its result property; finally, the property attribute is set to value. What happens is that the value attribute of the setPropertyAction element (or, better, the value property of the SetPropertyAction class) will always have the same value as the result property of the ServiceMethodRequest class. As a consequence, the label's text will be set to the string returned by the result property.
If you are unsure about how bindings work, don't worry because I'll explain them in one of the next parts of this tutorial.
Summary
In this third part of the tutorial we have introduced the InvokeMethod action, which enables calling a method exposed in the type descriptor of a client object. In the example, we have used the InvokeMethod and the SetProperty actions to call a web method at regular intervals and display the returned string in a label, all without writing a single line of JavaScript.
In the next part of the tutorial we'll see how to build custom actions.
References
Xml-script tutorial Part 1
Xml-script tutorial Part 2
Xml-script tutorial Part 3
Xml-script tutorial Part 4
About Alessandro Gallo
 |
Alessandro "Garbin" Gallo is a Microsoft MVP in the Visual ASP/ASP.NET category and a .NET developer/consultant. He is a contributor for the Ajax Control Toolkit project, owned by Microsoft. Alessandro won the Grand Prize at the "Mash-it-up with ASP.NET AJAX" contest held by Micr...
View complete profile
|
Please login to rate or to leave a comment.