Click here to Skip to main content
Click here to Skip to main content

Cleaner, Faster AJAX in ASP.NET

, 6 May 2009
Rate this:
Please Sign up or sign in to vote.
This article gives a quick overview of how AJAX helps with the slow parts of web applications, and highlights one of the new approaches in ASP.NET.

Introduction

Many web application firms spend substantial time and effort doing market research, analyzing requirements, and coming up with sophisticated ways to provide their users with more value than their competitors. But business value alone doesn’t guarantee a high adoption rate. Your app needs to perform - nobody wants something that’s slow and difficult to use. This article gives a quick overview of how AJAX helps with the slow part, and highlights one of the new approaches in ASP.NET.

Overview

Providing the right user experience for many web apps often means making them work very much like the good old desktop applications to which we’ve become accustomed. Developers have been giving their users desktop-like functionality and behavior with the use of AJAX (Asynchronous JavaScript and XML) technologies.

As web applications are becoming more sophisticated and even more data intensive, many web apps using the standard ASP.NET AJAX technologies find that although these technologies offer clear advantages from a usability perspective, they often provide less than satisfactory performance for web applications that need to process and display a relatively large amount of data.

AJAX

ASP.NET offers a few ways to use AJAX functionality, but the idea behind each is similar. Rather than refreshing the users’ web page or redirecting them to a different page after the user does something, AJAX allows web pages to connect to the web server behind the scenes. Instructions are sent and new information is received for consumption by the interface - whether it’s to display a message or change the view.

The two most common AJAX approaches in ASP.NET web apps make use of the UpdatePanel and partial postbacks. Both offer easy implementations and a rich feature set. Although these can be ideal for relatively small web pages, both approaches transfer large amounts of data over the wire with every call. This can result in fairly bad performance for web pages that make frequent use of AJAX to send and receive data.

While ASP.NET provides different flavors of AJAX implementations, such as the two above, most are covered extensively on the web and can be found with Google. So for this article, I want to focus on the less known (yet highly effective) web service-like approach to AJAX called PageMethods.

PageMethods

PageMethods allow any ASP.NET page to define web service-like methods that can be called directly without sending a large amount of data back and forth between the browser and the server. This avoids the typical overhead of maintaining a web page’s state in an ASP.NET postback.

Well, you might be asking yourself, “I’m already doing this, what’s new here?” The main difference is that this mechanism does not execute in the context of the ASPX page, and doesn’t use postbacks to perform the AJAX operation. This greatly reduces the amount of data being submitted over the wire by only including what’s needed for the Web Service method, which offers a great performance boost compared to the UpdatePanel and partial postbacks.

The Good and the Bad

Since the PageMethods approach does not persist web pages on the server, calling these methods has little overhead beyond the parameters required by the method and whatever data is eventually sent back to the browser. This means better performance and a more responsive web app.

Unfortunately, PageMethods do have a cost for the improved performance. Using these methods means that your server code is called outside of the page context, which means that many of the utilities and persistence features that we have all learned to love about the ASP.NET page object are not available.

In fact, PageMethods are required to be static (Shared in VB.NET), and can only operate on the information that was provided to them from the browser, possibly in conjunction with the user’s Session data. So, although page methods can be a great way to improve AJAX performance in many ASP.NET web applications, it’s important to weigh the performance benefits versus the inherent added complexity of their use.

Implementation

Implementing PageMethods is fairly straightforward, and involves taking the following steps:

  • Page Method - Define a static method on the relevant ASPX page and set it with the WebMethod attribute.
  • ScriptManager – Add a script manager to the ASPX page and enable it for page methods.
  • JavaScript Asynchronous Methods – Define two JavaScript methods. One to be called upon successful execution of the AJAX call, and the other to be called upon failure.
  • Using PageMethods – Call the ASPX static method we defined earlier, from the client-code using JavaScript.

To get going, we need to define a static method that would be called from our client-code using JavaScript, which might look something like this:

[WebMethod]
public static string GetData(string text)
{
  return text + "-" + DateTime.Now.ToString();
}

In order to use PageMethods, we need to use the ASP.NET AJAX object, ScriptManager. Add the ScriptManager to the web form and set the EnablePageMethods attribute to true.

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

Since the PageMethods calls are done asynchronously, we need to define a function that would be called once the AJAX call is done. (Note that we’re not actually doing anything with the data, just showing an alert message in this example.)

function OnGetDataComplete(result, userContext, methodName) {
    alert(result);
}

We also need to define a function that’s called when there’s a failure, such as when there’s a connection failure or there’s an exception in the server code.

function OnGetDataError(error, userContext, methodName) {
    if (error != null) {
        alert(error.get_message());
    }
}

Finally, we can use this infrastructure to retrieve data. The JavaScript function below will call the page’s Web Service and the appropriate JavaScript function with the result.

function GetData() {
    PageMethods.GetData('this is my data', 
                OnGetDataComplete, OnGetDataError);
}

Advanced Implementation

One of the immediate questions that might come up at this point is how to send complex data types, such as objects with multiple properties, back to the client code with PageMethods. Well, this can be done with JSON (JavaScript Object Notation). Complex objects can be converted to their JSON representation and can then be sent back to the calling client and used like any normal object. We can convert any object to JSON using the following function:

public static string SerializeJsonObject<T>(T obj) where T : class
{
    DataContractJsonSerializer serializer = 
             new DataContractJsonSerializer(typeof(T));
    using (MemoryStream ms = new MemoryStream())
    {
       serializer.WriteObject(ms, obj);
       ms.Flush();
                
       byte[] bytes = ms.GetBuffer();
       string json = Encoding.UTF8.GetString(bytes, 0, 
                              bytes.Length).Trim('\0');

       return json;
    }
}

For example, our object has a property named Data. We can modify the OnGetDataComplete JavaScript function that was defined earlier. We convert the JSON string into an object, which then allows us to simply access its properties. In this case, it happens to be the Data property:

function OnGetDataComplete(result, userContext, methodName) {
   var myObject = eval('(' + result + ')');
   alert(myObject.Data);
}

Conclusion

ASP.NET PageMethods might be somewhat more involved than other AJAX approaches, but their improved performance can make your web app much more responsive. And, faster is always better, right?

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Gil Shabat
Chief Technology Officer Novologies LLC
United States United States
Gil Shabat is a co-founder and one of the managing directors of Novologies LLC (www.novologies.com), a small web development consulting firm located in the NYC metro area that focuses on helping various companies to plan & build their own powerful web applications, as well as on advising development teams on complex web development challenges.
 
Gil was one of the key people to architect and build Scopings (www.scopings.com), a new type of web product in the recruiting space, now in beta, and has helped to make it the powerful platform it is today.

Comments and Discussions

 
GeneralMemoryStream PinmemberKevinAG14-May-09 11:06 
You need to review your usage of the MemoryStream object.
 
First, a call to MemoryStream.Flush() doesn't do anything.
 
http://msdn.microsoft.com/en-us/library/system.io.memorystream.flush.aspx
 
Secondly, you can avoid having to do the .Trim('\0') operation by passing in 'ms.Length' instead of 'bytes.Length' to the UTF8.GetString() method.
 
Otherwise, good article and good use of a generic method there.

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web01 | 2.8.140721.1 | Last Updated 6 May 2009
Article Copyright 2009 by Gil Shabat
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid