Basic Page Callbacks using AjaxMethodCallback

Using the AjaxMethodCallback control makes it extremely easy to create AJAX callback on a page.

The steps are:

  • Add a AjaxCallbackMethod to the page
  • Create a method in your server page (or control) class that is to be called from the client
  • Mark the method with the [CallbackMethod] attribute
  • Set up your client event handler to handle the response and error callbacks
  • Implement the client handlers
  • Call the proxy object and server method:
    Proxy.HelloWorld("Rick",HelloWorldCallback,OnPageError);

Let's walk through it. First make sure the control is registered with the page - if you drop the control from the toolbox then this is automatic - otherwise you have to manually add it like this:

<%@ Register Namespace="Westwind.Web.Controls" Assembly="Westwind.Web" TagPrefix="ww" %>

The add a AjaxMethodCallback control to the page you can drop it from the toolbox or or using code like this:

<ww:AjaxwMethodCallback ID="Proxy" runat="server"  />

In its default configuration as shown the control routes callbacks to methods on the currently executing ASP.NET Page. You can also point at an external URL and customize how data is posted to the server:

<ww:AjaxwMethodCallback ID="Proxy" runat="server"  
		ServerUrl="StockService.ashx"
		PostBackMode="PostMethodParametersOnly" />

which fires the callbacks at the specified handler that should derive from the CallbackHandler class.

External Http Handlers
Using an external HttpHandler is akin to using a 'service' and provides much better performance than page level callbacks. Page level callbacks have access to the executing page so you can potentially - depending on the PostBackMode and whether POST data includes form data - access controls on the page with their postback data. Callback handlers do not have accecss to the calling Page in any way.

If you use an external handler rather than Page Callback methods, you need to add one more line of code into the page to render a client side proxy class (which is optional but easier) and add it the Init() or Load() events of the page:

protected void Page_Load(object sender, EventArgs e)
{    
    // assign type so we can generate a proxy
    this.Proxy.ClientProxyTargetType = typeof(StockService); // name of the CallbackHandler class
}

Methods with [CallbackMethod] do the Work
Either way the implementation of the 'service' interface consists solely of creating methods in a class - either a handler, the page or even in user or custom server controls.

You're now ready to start calling remote methods. For now lets stick to page level methods for simplicity. So lets set up the server side method. What else than a Helloworld method?

[CallbackMethod]
protected string HelloWorld(string Name)
{
    return "Hello " + Name + ". Server Time: " + DateTime.Now.ToString();
}
[CallbackMethod]
protected decimal AddNumbers(decimal x, decimal y)
{
    return x + y;
}

Very simple. You just create your method and have it return normal parameter types. Make sure you mark up each method with the [CallbackMethod] Attribute. This is done so that you can control which methods are callable since the client code can be declarative and dynamic and so the control can create a client class wrapper for only the exposed methods.

On the client you now need to hook up the call to some sort of client side action. Let's use a textbox and button for our Helloworld sample:

Enter your name:
<asp:TextBox ID="txtName" runat="server" Width="178px">John Doe</asp:TextBox>
<input id="btnSubmit" type="button" value="Say Hello" 
                   onclick="HelloWorld();" />

Next create the HelloWorld function that handles this operation (you could also do this directly in the onclick handler, but i like to break it out for clarity):

function HelloWorld()
{
    // 'Proxy' is a the generated object with the same name as your control
    Proxy.HelloWorld($("#txtName").val(),
	function(result) { alert(result); },
	function (error){ alert("Error: " + result.message); }
}

So the onclick fires the Helloworld function. This function is the kick off point for the AJAX callback and it uses the Proxy class that was generated by the AjaxMethodCallback control. AjaxMethodCallback generates a proxy object instance with the same name as the control (Proxy in this case) which can then be used to call the HelloWorld method directly. Each client proxy method matches the server method's parameter signature (here the name as a string), plus two additional parameters for the Callback handler when the call completes and an error handler if the call fails.

You can also create a new instance manually at any time with:

var myProxy = Proxy_GetProxy();

<yourControlId>_GetProxy() is generated automatically and always available and creates an instance of the client AjaxMethodCallback control and assigns the server control specified settings. Think of it as an easy factory method.

The Proxy class is generated based on the server control's GenerateClientProxyClass property. It's true by default, but if you choose you can omit the proxy and manually call server methods using code like the following:

var myProxy = Proxy_GetProxy();
myProxy.callMethod("HelloWorld",
	[ ($("#txtName").val() ],
	function(result) { alert(Result); },
	function (error){ alert("Error: " + Result.message); }

This is the low level syntax and uses the AjaxMethodCallback client class and it's callMethod() method to make the server call. Instead of a proxy method that mirrors the server this generic method takes the name of the method plus an array of parameters, plus the callback and error handler functions. This approach gives you full control and allows to remove the overhead of generating the proxy at the cost of a little more verbose syntax.

In both proxy or 'manual' operation, if the call succeeds the callback handler is called with the result value. The result value is typed the same as the return value of the server method. So if you return a string a string is passed. If you return an int it'll be a JavaScript number. If you return an object you get a JavaScript object. On success the result is passed and you can use the result as you want.

If the callback fails - due to invalid signatures, a method execution error, or connectivity or other HTTP problem the error handler is called instead. This handler is passed a single error object which has a message property that contains error information. The error object contains message and detail properties.

That's really all there's to it. It's extremely easy to implement this functionality!

Calls are asynchronous by default

All remote method calls are made asynchronously. This means when you call the method in question control returns to you immediately but you don't get a result back. All results are returned only to callback handlers.

Multiple callbacks can be made on the same control simultaneously. For example:

Proxy.HelloWorld($("#txtName").val(),Helloworld_Callback,OnPageError);
Proxy.HelloWorld2($w("#txtName2").val(),Helloworld_Callback,OnPageError);

will result in two calls that are executing basically side by side, and there's no guarantee that one or the other will execute first.


© West Wind Technologies, 1996-2016 • Updated: 02/09/12
Comment or report problem with topic