Page History: How Do I Retrieve Data from a Page Method?
Compare Page Revisions
Page Revision: 2010/08/31 01:07
Problem
I have an ASP.NET WebForms page and I want to call an AJAX Page Method without using the ASP.NET AJAX libraries generated proxies using only jQuery.
Solution
Page methods are a special implementation of ASP.NET AJAX service callbacks that can be hosted inside of an ASP.NET WebForms page subclass. Page methods need to be static and like their full blown ASP.NET AJAX ASMX service counterparts take JSON POST input and return JSON result values. Page methods are a simplified way of making callbacks without separately setting up an ASMX or WCF Web Service.
Page Methods are simple RPC methods that take JSON POST data inputs and return a JSON encoded string of the result value from the method call and they can be readily called from jQuery AJAX calls from the client.
The input is a JSON object that contains one property for each parameter passed to the method, and the result returns a root object with a ‘d’ property that contains the actual result value. The reason for the ‘d’ property is security to avoid JSON execution attacks that can be run against JSON arrays.
Setting up a Page Method on the Server
Lets assume we have a simple form on the client with a textbox and a button to retrieve a simple HelloWorld message from the server. The idea is to enter your name, send it to the server and the server responds back with a HelloWorld message string. Here’s the base HTML to work with:
<div class="sample">
<h3>Hello World with Page Methods</h3>
<div class="containercontent">
Enter your name:
<asp:TextBox runat="server" ID="txtName" Text="" />
<input type="button" id="btnHelloWorld" value="Say Hello" />
<div id="divHelloMessage" class="errordisplay" style="display:none"></div>
</div>
</div>
The whole simple UI including the callback message once retrieved looks like this:
To implement the Page Method on the server place a method into CodeBehind Page subclass that handles the callback when the button is clicked. This highly sophisticated HelloWorld method looks like this:
[WebMethod]
public static string HelloWorld(string name)
{
return "Hello " + name + ". Server time is: " + DateTime.Now.ToString();
}
Notice the required
WebMethod attribute (found in the System.Web.Services assembly and namespace) and that the method has to be static. Other than that it’s just a standard .NET method with input parameters and a result type – in this case both strings – which are parsed to and from JSON by ASP.NET AJAX.
Calling a Web Method from the Client
Calling a Page Method (or any service that requires JSON input including ASMX and WCF services) requires that the parameters for the method call are POSTed as a JSON string to the server. jQuery natively doesn’t support JSON encoding and so an additional library may be required to handle JSON encoding. I say ‘may’ as the latest versions of browsers do include native JSON serializers including Internet Explorer 8, FireFox 3.5 and later, Opera 10.5 and later, Chrome 5, Safari 5 and even the iPhone 4’s Safari browser. However, older browsers do not and so you still require a JavaScript library to support non-current browsers.
JSON Serialization Requirements
The most commonly used JavaScript library for JSON encoding and parsing is json2.js by Douglas Crockford. This version is so popular that the native JSON implementations in browsers is based on this API. You can get the latest version of json2.js from here:
http://www.json.org/json2.jsjQuery does support native JSON parsing via $.getJSON() and $.ajax() with the dataType: "JSON" option set, however as we’ll see shortly this deserialization doesn’t deal natively with date values and so custom parsing may still be required if you care about getting dates de-serialized on the client.
Calling a Page Method with the $.ajax() Function
Once you have JSON serialization and parsing covered the next step is to make the AJAX call to the server. jQuery supports making AJAX calls and can retrieve an AJAX result from the server directly using the low level $.ajax() function.
On the client then we have to do a few things to call this method. Start with the script includes for jQuery and json2.js:
<script src="Scripts/jquery-1.4.1.min.js" type="text/javascript"></script>
<script src="Scripts/json2.min.js" type="text/javascript"></script>
It’s also possible to load json2.js conditionally instead of the script include above by dynamically loading the script only if needed:
<script type="text/javascript">
if (!window.JSON)
$.ajax({ type: "GET",url: "Scripts/json2.min.js",dataType: "script"});
</script>
Next let’s hook up the btnHelloWorld click handler in the document ready handler:
$(document).ready(function () {
$("#btnHelloWorld").click(helloWorldCallback);
});
Finally let’s create the actual function that makes the service call using $.ajax() and updates the client display:
function helloWorld() {
var name = $("#txtName").val();
$.ajax({
url: "PageMethods.aspx/HelloWorld", // Current Page, Method
data: JSON.stringify({ name: name }), // parameter map as JSON
type: "POST", // data has to be POSTed
contentType: "application/json", // posting JSON content
dataType: "JSON", // type of data is JSON (must be upper case!)
timeout: 10000, // AJAX timeout
success: function (result) {
$("#divHelloMessage").text(result.d).fadeIn("slow");
},
error: function (xhr, status) {
alert(status + " - " + xhr.responseText);
}
});
}
You can see that there are quite a few options that need to be set on the $.ajax() call. The most important parts are the URL which is the page url plus an extra path that hold the method to call. You also need to pass parameters as a JSON encoded object with each method parameter encoded as a property of the object passed using the JSON objects (native or json2’s stringify() function). The resulting JSON data needs to be posted to the server and the content type has to be set to application/json. To get the result data automatically parsed into a value/object you need to specify the dataType: "JSON" which lets jQuery handle de-serialization of the JSON result and pass it to the callback method.
Finally you need to provide success and error callbacks that are called when the AJAX call completes. The result handler receives the service method’s result as a value/object. Note that the returned value used is result.d to get the result string from the Helloworld call:
$("#divHelloMessage").text(result.d); This is because ASP.NET AJAX (and WCF as well) create response messages that look like this:
{"d":"Hello Rick. Server time is: 8/30/2010 11:55:24 AM"} All .NET JSON service responses include this ‘wrapped’ message format to provide some basic security to prevent JSON hijacking attacks (for more info see
http://tinyurl.com/6xnp8d). Just remember that you need to reference the “d” property to get the result value.
The result value can be something simple like a string in this case, but can also be more complex like a complex nested object or array depending on what the server Page Method returns.
The error handler is a bit more problematic as there is only minimal error handling support in the error function. The function returns only a terse error code about the general failure that occurred (ie. timeout, error, parsererror etc. which isn’t very descriptive) and the XmlHttpRequest object. The latter can be useful to pick up the server response and any error messages the server might have sent since ASP.NET AJAX encodes exception information into the response as an object. More on this later in the document.