Welcome to AspAdvice Sign in | Join | Help

Alessandro Gallo

.NET & Beyond
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.

Sponsor
Posted: Wednesday, August 23, 2006 11:58 AM by Garbin

Comments

Luis Abreu said:

Here's something which might look good at first sight...only for a few seconds though :)

their performance sucks since all the fields are sent back and you only get a result back (if i recall correctly, all viewstate changes aren't persisted and updated on the client, like happens when you use the updatepanel control).

I still haven't found a place where they make sense...

# August 24, 2006 8:03 PM

Garbin said:

Luis: I understand your point, but I prefer to have another way of going through the page lifecycle asynchronously with Atlas(I'm not considering the ASP.NET callbacks), otherwise I'll have to always rely on the UpdatePanel for this kind of task.

I know that a web service would be more performant in many cases, but a web service and a page method have two different scopes and this could be relevant when designing the app.

Regarding the stateful nature of the page methods, I agree that being able to switch to a stateless call would be a nice feature and would increase the number of handled scenarios, so I hope the Atlas team will consider it.

# August 25, 2006 6:47 AM

Matthias Hertel said:

Page methods together with some client-script ave a big advantage over the updatepanel: There is only one call to the server - no two in many cases.

Sample: if you open a calendar control within the update panel you get one call for opening the calendar and another for closing it.

A better solution is pulling a calendar control from the server and use it on the client with a client-side show/hide logic. You can even reuse the control (or any other data) you've fetched.

I wonder why MS tags the methods with a [WebMethod] attribute but doesn't use a true SOAP based WebService protocol. Re-inventing the wheel. one more time...

# August 25, 2006 1:24 PM

Amit Lohogaonkar said:

Ok it's cool.But can you fire same events on server button control.In your code its done on html control.

# September 5, 2006 9:04 AM

Garbin said:

Amit: sure, just replace the input element with an asp:Button and use the OnClientClick attribute to call the JavaScript function.

# September 5, 2006 5:20 PM

Amit Lohgaonkar said:

Thanks.

I just want to make it sure that you are writing web method in aspx page & calling it in javascript & atlas script manager.Nothing more or any other page or service.

# September 7, 2006 1:42 AM

Amit Lohogaonkar said:

Also where you have put txtToEcho.get_text() function.I could not find it.I am currently working on atlas updatepanels.Is it possible to make async calls to server method written in aspx pages without using updatepanel & only with scriptmanager.Can you load dataset in webmethod & populate grid without postback & without updatepanel just scriptmanager,aspx page with webmethod to fill dataset.

# September 7, 2006 1:46 AM

FletchSOD said:

Well, what you're describing is a comparision of apple and orangle.  In this case, I would use Atlas via window.onerror to detect JavaScript error and send me an email.

# September 7, 2006 10:23 AM

Garbin said:

@Amit: get_text() is a method (a getter) exposed by the Atlas  TextBox control to retrieve its value. In the JavaScript code, I've wrapped the input control with a Sys.UI.TextBox control (look inside the application_Load() function).

# September 8, 2006 2:07 PM

Amit Lohogaonkar said:

Hi,

It works.I am using it for calling some small values from database via web methods without postback.But is it possible to use it with gridview or to bind it with dataset etc.

# September 12, 2006 3:28 AM

jim said:

-- static method is REQUIRED NOW.

What is the diff. and advantage or disadvantage of using PageMethods and asmx (through the <services> in ScriptManager)???

# July 24, 2008 12:58 PM

SHERYAR NIZAR said:

<asp:ScriptManager ID="ScriptManager1" runat="server" EnablePageMethods="true">

     </asp:ScriptManager>

//Speak is a method in CS file.

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

function Test(this)

{

  PageMethods.Speak(cbTest);

}

function cbTest(result)

{

 alert(result);

}

</script>

--

SHERYAR NIZAR

http://www.sheryar.net

# August 4, 2008 2:02 AM

predictive dialer software said:

WebSphere Communications Enabled Applications Add a Comment Recommend this entry More Actions Notify other users Flag as inappropriate Notify Other Users People to notify: Description: Cancel Flag as inappropriate Issue: Human Resources issue Legal issue

# July 1, 2009 9:06 PM
New Comments to this post are disabled