Using CallbackHandler with REST Calls

The CallbackHandler is a base JSON Service implementation that allows for remote method calls to be made against the server. The service returns JSON string results. To create a service you simply inherit from CallbackHandler (either in a .ASHX file or by creating a class and registering it as an HttpHandler) and set [CallbackMethod] attributes on each of the methods of this class to expose those methods for remote access.

Any CallbackHandler derived 'service' can be easily accessed via REST calls simply by providing the proper QueryString or POST variables to the server. The handler makes the remote method call and returns a JSON formatted string in response.

The easiest way to access the service is with AjaxMethodCallback control on Page which simply exposes each of the service's methods as Methods on a proxy object. You can simply call Proxy.MyMethod(parm1, parm2, CallbackHandler, ErrorHandler).

However you can also call these services directly with any HTTP tool using plain REST functionality.

Raw Ajax

Calling the handler with raw AJAX is easy as well. You simply call the service URL with the name of the method to invoke. There are several ways that you can specify 'parameters' to the method call:

  • Raw POST buffer
    You can simply pass POST data to the server and do nothing else. In this scenario your server methods can have no parameters and purely rely on POST data to get its input data. You can then use Request.Form to read data out of the Post buffer.

  • JSON Object in POST buffer
    You can pass a single serialized JSON object as a parameter and set the content type to application/json. The handler then converts your JSON object/value into a .NET type and passes it as a parameter to your method. The method must have a matching single parameter signature.

Form Post Variables or Raw POST Data

To make a callback with raw POST data using ww.jquery.js ajaxJson function:

ajaxJson("ClientCallbacks.ashx?Method=CallbackWithPost",
         $.param( { Name: "Rick", Entered: new Date(), Value: 10}),
         function(result) {alert("Message from Server:\r\n" + result) },
         function(error) { alert(error.message); }, 
         { noPostEncoding: true }  );

This passes the raw post data (created with $.param from the object map) to the CallbackWithPost() method on the server. The server can then read the values with Request.Form["Name"], Request.Form["Date"]. You can really specify any kind of data you like here. Note the final parameter of true which indicates using raw POST data as opposed to a JSON object.

The server side method then looks like this:

[CallbackMethod]
public string CallbackWithPost()
{
   string name = Request.Form["Name"];
      int value = int.Parse(Request.Form["Value"]);
      
      return "Hello " + name + ". Value is: " + value.ToString();
}

Note that the response from the server will be JSON (or XML depending on Accept header), not plain text unless you explicitly specify that. You can explicitly specify not to encode the response:

[CallbackHandler(ReturnAsRawString=true,ContentType="text/plain")]

Of course you don't have to use ajaxJson on the client either - any HTTP client that can send POST data to the server will do. So you can just as easily use jQuery with $.post() or $.ajax().

JSON Post Data - Single JSON Object/Value

To pass JSON to the server and treat the value as a single parameter use code like the following:

ajaxJson("StockService.ashx?Method=GetStockQuote",
             "MSFT", 
             function(result) {alert("MSFT Last Price: " + result.LastPrice); },
             function(error)  {alert(error.message);}
             );

The parameter passed here is a string which is ajaxJson converts into a JSON string that is sent to the server. The result returned is an object/value that the method returns.

To handle the server call implement a handler method like this:

[CallbackMethod]
public StockQuote GetStockQuote(string symbol)
{
    StockService service = new StockService();
    return service.GetStockQuote(symbol);  // returns a StockQuoteObject
}

You can pass exactly one parameter to the server, but the parameter can be a complex object. If necessary you can create a parameter object that contains multiple values. For example imagine this type:

public class Person
{
    public string Name = null;
    public int Value = 0;
    public DateTime Date = DateTime.MinValue;
}

and a callback method with this signature:

[CallbackMethod]
public string TestMethod2(Person person)
{
     return person.Name + " " + person.Value.ToString() + " " + person.Date;
}

To pass this value from the client:

ajaxJson("TestService.ashx?Method=TestMethod2",
             { Name:"Rick", Value:10, Date: new Date() }, 
             function(result) {alert("Message from Server:\r\n" + result) },
             function(error) { alert(error.message); } 
            );

The type doesn't have to match exactly - it'll read only matching properties from the JSON value so if you pass only Name (ie. { Name:"Rick" } ) and leave out the other object properties/fields the code still works.

Note that I used ajaxJson from ww.jquery.js here, but it's not required. Any HTTP client that can post JSON data can do this.

**Requirements for JSON POST Data** * Data must be a JSON encoded string * Data must be POSTed to the server * Content type for POST request must be application/json or application/x-javascript

CallbackMethod POST Data Interface

This is the main API that the AjaxMethodCallback Server control uses and we recommend you use this control or the client AjaxMethodCallback class to call services with this. However, for completeness sake here's a discussion of how data is passed from the client to the server. Note that CallbackHandler supports several interfaces as described above and this one is not best suited for REST clients. REST clients will do best with single JSON values or direct POST values. This API is meant for pure RPC style interaction that supports multiple parameters, which is why this slightly more complicated POST encoding scheme that allows for individual parameters to be generically passed to the server is used.

This mechanism relies on regular POST or Querystring values that define the method to call and the parameters to pass. The POST/querystring values for the callbacks are simple and only the following variables need to be supplied:

CallbackMethod (or just Method)
The method in the service handler to call.

CallbackParmCount
The number of JSON parameters passed

Parm1..n
0 or more parameters to be passed to the method called. Note the method must support these parameters. Parameters passed must be JSON encoded in the POST buffer and must be passed in the same order as the method signature. Values can be simple types or complex types as long as the server's input type matches the object signature.

GET Example:

http://site.com/app/jsonHandler.ashx?CallbackParmCount=2&CallbackMethod=HelloWorld&Parm1="Rick Strahl"&Parm2={"x":10,"y":20}

Note that all parameters are JSON formatted (the quotes around a string for example), so you can pass any JSON value to the server as long as it is calling a method that has a signature that expects that signature. Objects are matched based on properties/fields that are updated from matching properties.

POST Data:
The same formatting shown for the GET example can also be applied to POST form urlencoded data. All values in this case should be JSON encoded as well using the same parameter names.

Again, if you are using ww.jquery.js you can use ajaxMethodCallback(), the AjaxMethodCallback() object, or the server controls the AjaxMethodCallback Web Forms control and client class are the easiest way to automate this process.


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