A closer look at Page methods
Live Demo Source Code
The Atlas framework allows to send asynchronous HTTP requests to a web server without reloading the current page and also to perform other tasks while waiting for the response to arrive from the server.
By using Atlas, it is possible to send such an asynchronous request to invoke a method defined in an ASP.NET page. The use of a page method is an alternative to invoking a web service method when we need to perform a task without rendering anything on the page nor exposing any data publicly. Plus, when using a page method, we run into the Page's full lifecycle and are able to handle events raised by server controls, since the ViewState of the page is sent in the asynchronous request and loaded on server-side (from another perspective, this could be a disadvantage since a massive ViewState leads to a bigger request's payload, so the ability to choose if sending the ViewState in the request is desirable).
To declare a page method, we have to perform the following steps:
- Import the namespace System.Web.Services.
- Declare the page method as a public method.
- Add a WebMethod() attribute to the page method.
For example, let's declare a page method that returns back the string sent as an argument:
[WebMethod]
public string Echo(string toEcho)
{
return toEcho;
}
By enabling Atlas in the page (i.e. by adding a ScriptManager control) we are able to call the Echo method on client-side with a simple JavaScript statement:
var request = PageMethods.Echo('Hello World!');
There are a couple of things to notice in the above statement. First of all, every page method is accessed through a special reference called PageMethods. Then, what the call returns is not the return value of the Echo method (the echoed string), but a reference to a Sys.Net.WebRequest object, that represents the asynchronous request that we made to the web server to invoke the page method. So when can we access the returned string?
In the asynchronous programming model, when we call a method that performs an asynchronous operation, we also pass to it a list of methods to call when the operation completes and also a special object, called the context, when we store all the references needed to process the results of the asynchronous task. In the Atlas framework we do a similar thing, by invoking the page method with the following syntax:
PageMethods.Echo('Hello World!', onComplete, onTimeout, onError, onAbort, context, timeout, priority);
First of all, we must pass all the arguments that the page method is accepting, separated by a comma; in this case, the Echo method accepts one argument, the string to echo. After the list of the server method's arguments, we can pass the references to three methods to call when the page method returns:
- onComplete, is a function that will be called if the page method returns with no errors.
- onTimeout, will be called if the page method doesn't return a value within the specified timeout interval.
- onError, will be invoked if an error occurs during the process of the asynchronous request (for example, an Exception being raised on server-side).
- onAbort, is invoked when the asynchronous request is aborted. This can be done by calling the abort() method on the WebRequest object returned with the call to PageMethods.Echo().
- context, is the state object that will be passed to the callbacks when processing results.
- timeout, specifies the timeout before an asynchronous request is dropped. A response must arrive before the timeout occurs.
- priority, is a number that specifies the priority of the asynchronous request.
Let's pass to the callbacks. The onComplete function (you can obviously give it the name you prefer) should be declared as follows:
function onComplete(result, response, context)
{
// . . . process result . . .
}
- The result parameter contains the page method's return value. In our example, this will be the echoed string. You can easily verify it with an alert or a call to debug.trace(result).
- The response parameter contains a reference to the Sys.Net.WebResponse instance that encapsulates the response sent from the web server to the asynchronous request.
- The context parameter is the context object that we passed to PageMethods.Echo when starting the asynchronous call.
The onError function receives an instance of the Sys.Net.MethodRequestError class, that contains useful informations about the error that happened while processing the request:
function onError(objError)
{
// Display the error message.
debug.trace(objError.get_message());
}
The onTimeout and onAbort functions are called when a response never arrives, due to a timeout or an explicit abort action.
function onTimeout(request, context)
{
}
function onAbort(request, context)
{
}
As you can see from the above snippet, both the onTimeout and onAbort callbacks are called passing the object that encapsulates the request sent to the server (it is a Sys.Net.WebRequest instance) and the context object.