NovoGeek.com - Krishna's weblog

A technical blog on jQuery, AJAX, JavaScript & modern web technologies

AJAX libraries have simplified developer’s life by providing clean & easy-to-use API. Their usage is so simple that we developers over use it, without realizing the performance impacts. In this article, I would like to explain few scenarios in which AJAX can be an overkill for your web apps.

The motto is to help fellow developers take better design decisions at an early stage, rather than repenting and fine tuning later. Below are real time problems, faced in a large scale ASP.NET/jQuery AJAX based web app, which should be given a serious thought:

(1) AJAX based navigation: 

“Keep DOM manipulations to the minimum” is what every JavaScript library says, but over use of AJAX based navigation defeats this purpose and you may rethink the design, unless your client specifically wants it.

If you are wondering what AJAX based navigation means, check jqGrid demos site. There are no post backs at all even while navigation. Content pages are fetched via AJAX and injected into a parent page, with a huge DOM manipulation.

If the page is small with very less number of DOM elements, AJAX navigation is fine. As the number of elements increase in the page, injecting the page takes longer time and beyond a point, causes ‘stop running script’ error, as discussed in my previous article. Typically, business applications contain hundreds of controls in a page, causing severe performance bottlenecks.

If you see Facebook, the Home, Profile, Account etc links on the top do a full post back and fetch the page, while any other operation is an AJAX call, which is a cooler approach.

Bottom line: AJAX navigation has performance problems when pages are huge. But it can solve problems like maintaining state by storing data in DOM elements, reducing session variables and reducing load on the server. So weigh these choices before taking a call.

You may find the total number of elements in the page using the jQuery code, $(‘*’).length; So be cautious of this count while injecting a page. In a complex page like Yahoo.com, there are about 780 elements (each html tag corresponds to one element). Make sure your page is having not more than 1000 DOM elements. If the count is running into thousands, then split your pages.

(2) Client side templating:

If you liked asp.net repeater and are looking for client side templating, hold on! There is a difference between asp.net repeater and client side templates.

In the case of a repeater, processing takes place on the server and not much load is on the browser. However, in the case of templates, processing as well as injection is on the client. Imagine templating 100 rows, with each row containing 30 elements. You end up having 3000 elements which is alarming!

I can give you the example of twitter.com or facebook.com. Both have a ‘more’ sort of button at the bottom, which fetch more records. What happens if you want to see the posts of last ten days? You end up with thousands of DOM elements and your browser slows down.

Bottom line: In terms of performance, what is apparent to the developer is only the time taken to process the template. But what is hidden is, the time taken for clearing events, handling memory leaks, cleaning missing tags and injecting the template. All this happens in jQuery’s .html() method.

So, if you want to template huge data, make sure you are implementing pagination. Again, as in the above case, $(‘*’).length is the key.

(3) Tabs:

Thanks to this fancy UI technique, which gives a wizard sort of appearance to the content. If you are looking only at the fundo part of it, you are getting into problems! The scenario gets worst when you have AJAX tabs which fetch huge pages.

Let’s say each page has ~700 elements. So if you have 5 tabs, you are having ~3500 elements. Imagine having blur, click, live events for so many elements. It’s a complete mess! Also, you will be running into context related issues, since 2 tabs can have 2 different controls with the same ID. When you are on an active tab, the content of the rest of the tabs is only hidden, but not removed. So your app’s performance is bad yet again.

Bottom line: If you want to use tabs with optimal performance, make sure you are clearing the mark up of the tabs which are not active. At any point of time, make sure your $(‘*’).length is always less than 1000, for better results.

I think I have covered quite a lot. I’m still facing several bottlenecks in my beautiful project and trying to figure out the solutions with my architect. Will cover more scenarios in my next article.

Happy coding :)


Happy to say that I have presented today in Microsoft Virtual Tech Days(VTD) on ASP.NET AJAX Library(BETA)Smile

You can download the presentation here: http://www.slideshare.net/novogeek/introduction-to-asp-net-ajax-librarybeta

I have also uploaded working demos. You can find them here: http://labs.novogeek.com/VTD18Mar2010/index.htm

Regarding the demos, I have converted the aspx files to .htm files, so that you can simply save the demos from the browser. (Same code as shown in VTD).

Please let me know in case of any issues. Thank you once again for the warm response Smile


First of all, my Happy New Year wishes to all netizens! As you journey through 2010, leave a trail of hardwork, innovation, passion and excellence...

Coming to the topic, in web apps, most of the times, we would require adding and removing controls to a web page dynamically. E.g.,adding "Browse" buttons for email attachments(live mail, gmail etc). In a traditional ASP.NET app, we used to build a string containing markup and append it to some control. However, this requires postback. Here is the end result which we would want to achieve:

With the help of jQuery, we can achieve this functionality with ease. Let us see the various ways of implementing this functionality.

1. Using jQuery “clone(true)” function:

Many of us know about jQuery clone() function, which will clone any jQuery selector. But the hidden feature is, it accepts a boolean parameter. When the param is set to true, it will clone DOM elements along with their event handlers.

Though this method can help us achieve the end result, the disadvantage is, it will fail to initialize complex controls like date pickers, auto suggest textboxes etc.

2. Using jQuery “live” event:

jQuery live looks like a perfect choice for this requirement. Live events are added for current as well as future elements in the DOM and hence events for “+”, “-“ buttons can be written only once using Live.

Though this works as expected in simple screens, even this is not a perfect approach! If suppose you are loading pages via AJAX, the events would be bound multiple times. So clicking on “+” will add more than 1 row, as multiple click events are bound. This is because, Live adds events to the document and not to the element. Check this article to see how live works.

3. Using jQuery Event Delegation:

Yup! This will solve the problems caused by above methods. I don’t want to explain about event delegation as there are very good articles already available. Check these:

The concept is very simple. Suppose you have a html table with 100 cells and you need to fire an event when any cell is clicked, instead of writing the below code:

$('#myTable TD').click(function(){
    $(this).css('background', 'blue');
});

you can write code like this:

$('#myTable').click(function(e) {
    var clickedElement = $(e.target);
    clickedElement.css('background', 'blue');
});

So instead of binding 100 events as in case 1, you can achieve the same output by binding only a single event, as in case 2.

This will solve the problem of Live, as the events are not added at document level, but are added to parent container. This will also solve the problem of Clone as date pickers will be initialized properly.

DEMO: Here is a demo for the above functionality using LIVE (Use it only when you are not loading pages via AJAX). I shall very soon come up with a demo using event delegation. This is a real time problem which I faced in a large scale project. So wanted to share immediately, so that others might not fall in the traps in which I fell!

Happy Coding :)


Exception handling is an important feature in any business application. In simple words, it is all about catching ugly errors thrown by server and displaying them in a user friendly manner to the end user. (Of course, logging exceptions/notifications etc may also be a part of exception handling. )

ASP.NET provides API for handling exceptions and displaying them in custom error pages. Custom error pages can also be defined for different HTTP error status codes, which provides good experience to end users in case of exceptions.

However, if you are using AJAX in your ASP.NET application(I’m using jQuery library for AJAX), you would not like to redirect users to a custom error page, as that kills the primary motto of AJAX. You would instead like to display error messages in the same page, as in facebook or twitter. So here is how this can be done using jQuery:

jQuery’s $.ajax method has a special function, $.ajaxSetup, where global settings can be made for handling AJAX requests. If you use this global function, you need not write error callbacks for each of your AJAX requests. All erroneous AJAX requests will be handled by the global error callback in $.ajaxSetup function. We can take advantage of this and write our exception handling wrapper.

$.ajaxSetup({
    error: function(XHR, errStatus, errorThrown) {
 
        if (XHR.status == 0) {
            alert('You are offline!\n Please check your network.');
        } else if (XHR.status == 404) {
            alert('Requested URL not found.');
        } else if (XHR.status == 500) {
            var errorMessage = 'Internal server error';
            try {//Error handling for POST calls
                var err = JSON.parse(XHR.responseText);
                errorMessage = err.Message;
            }
            catch (ex) {//Error handling for GET calls
                $('#divMaster').append('<div id="divErrorResponse" class="DisplayNone">' + XHR.responseText + '</div>');
                errorMessage = 'Page load error: ';
                errorMessage += $('#divErrorResponse').find('h2 i').html();
            }
            alert(errorMessage);
        } else if (errStatus == 'parsererror') {
            alert('Error.\nParsing JSON Request failed.');
        } else if (errStatus == 'timeout') {
            alert('Request timed out..Please try later');
        } else {
            alert('Unknown Error.\n' + XHR.responseText);
        }
    }
});

In the above code, we are checking for status codes(which are self explanatory) and handling error conditions based on these codes. Most of the times, the status code will be “500”, which says “Internal Server Error”. i.e., error in your server side code. Please refer this article from Encosia.com, which explains the core of what I am writing now.

Now, this “500 – Internal Server Error” may arise in both GET as well as POST requests. In POST request, if your web method throws error, it returns a JSON object, which you can parse as explained in the above link. But this does not work in case of GET requests.

Assume that you are loading a remote page into a master page using jQuery AJAX. If your “Page_Load” event throws exception, your response would be in HTML format (unlike the case of POST request, where the response is JSON object), which you cannot parse using JSON.parse or eval(). To differentiate between GET & POST responses, I’m simply using JSON.parse() in try() method. If it throws exception, it is surely due to a GET response, which is html. For better user experience, you may use jGrowl plugin for displaying error messages.

Conclusion: For exceptions in GET requests, you can query the resultant html using jQuery’s DOM selectors and display user friendly messages. For exceptions in POST responses, you can simply parse the resultant JSON object and display user friendly messages. If you feel there could be a better way of handling exceptions in GET requests, let me know.

Hope this article saves the time of folks who are facing similar problems. Happy coding :)


Localization is a very important feature required in medium-large scale business applications. As always, ASP.NET makes developers life easy by providing inbuilt localization mechanism. Using resource files, all the elements in a web page can be localized.

However, if you are building a rich client side app using JavaScript/jQuery, you may need to fetch error messages and other strings from locale specific external file, without post back. In such cases, jQuery localization plugins come to rescue. Below are some of the best jQuery plugins, which help in localization:

  1. http://keith-wood.name/localisation.html
  2. http://codingwithcoffee.com/?p=272
  3. http://sundaymorning.jaysalvat.com/ 

The third one is cool with integrated Google translation API,  The second plugin is used by jqGrid & other plugins for localization. However, I really loved the first one - Keith wood's plugin, which gives a basic but powerful localisation features. All it does is, make synchronous call to the server and load locale specific JS file, which will override the variables of your base file. When you use custom events to change localized messages, the first one is the best, owing to its simplistic nature.

The question now is, how to get the UI culture of user's browser on page load.

Though the plugin is expected to do this, somehow, this is a missing feature. But you need not worry, as ASP.NET does this easily for you.In the "Session_Start" event of global.asax, just use this code:

Response.Cookies("UICultureCookie").Value = Request.UserLanguages(0)

This stores the first preferred UI culture of user's browser in a cookie. Using the information in this cookie is pretty simple using jQuery's cookie plugin. Just say:

var clientCulture = $.cookie("UICultureCookie");
$.localise('JavaScript/Constants/constants', { language: clientCulture }); 

That's it!  Now even your client side messages in ASP.NET can be localized, without postback, using the power of jQuery.

P.S:  I didn't write much about how to use these plugins, as their home pages have clear documentation & demos, which are self explanatory.


I was trying to use jqGrid, an excellent jQuery based grid, for building a zero postback page. It's configuration is very simple, similar to flexigrid, but has many additional features like inline editing, subgrids etc.

What jqGrid expects is a JSON response having few objects and arrays, which are mapped to columns in the grid inside the grid.base.js file, like this.

Though the grid's AJAX call is successful, data is not being bound to thegrid. The reason is, .NET 3.5 returns JSON object which is prefixed with a "d" parameter like this.

So, to map the JSON data to the grid, we have to manually parse the AJAX response and separate the "d" parameter in AJAX success callback. This applies not only to jqGrid, but also to all jQuery plugins which expect JSON response.

I was about to write more on why .Net 3.5 prefixes "d" to JSON response, how it enhances security and how to parse it easily., but incidentally, Dave ward explained the concept excellently in his latest article: http://encosia.com/2009/06/29/never-worry-about-asp-net-ajaxs-d-again

So no more worrying about .Net's "d" again :)


In my previous post, I have explained how to pass complex types using jQuery and JayRock in .NET 2.0 framework. I was digging a bit into Dave’s example (using complex types to make calling services less complex) in .NET 3.5 framework, to find how easier JSON serilaization/deserialization can be made.

When a Web service class is decorated with “ScriptService” attribute, which is in the System.Web.Script.Services namespace in .NET 3.5, the web service returns data in JSON format [MSDN]. Whether the returned value is a string or an object, it will be in JSON format. So no need of writing chunks of code for serializing objects explicitly.

Therefore, all that we need to do is to simply decorate our web service class with “ScriptService” attribute and  return an object from the server. So, to create a JSON object like this:

{"d":{"FirstName":"Krishna","LastName":"Chaitanya","City":"Hyd","State"
:"Andhra","Country":"India"}}

We can simply return a person object like this:

<WebMethod()> _
    Public Function fnFetchDetailsClass() As Person
        Dim objPerson As New Person
        Try
            objPerson.FirstName = "Krishna"
            objPerson.LastName = "Chaitanya"
            objPerson.City = "Hyd"
            objPerson.State = "Andhra"
            objPerson.Country = "India"
        Catch ex As Exception
 
        End Try
        Return objPerson
    End Function

In some situations (like in client side templating), we might need to create custom, complex JSON objects on the fly. In such situations, we can make use of .NET’s “ListDictionary” and “ArrayList” classes.

The above example can be re-written using ListDictionary as:

<WebMethod()> _
Public Function fnFetchDetails() As ListDictionary
    Dim jsonObj As New ListDictionary
    Try
        jsonObj.Item("fname") = "Krishna"
        jsonObj.Item("lname") = "Chaitanya"
        jsonObj.Item("city") = "Hyd"
        jsonObj.Item("state") = "Andhra"
        jsonObj.Item("country") = "India"
        Return jsonObj
    Catch ex As Exception
        jsonObj.Item("Error") = "Error at server"
        Return jsonObj
    End Try
End Function

Thus, using JSON is made easier in .NET 3.5.

Here is a simple demo which makes things clear. (I have used jQuery for making AJAX calls.)

(Note: ListDictionary stores values in Name/Value pairs, which is useful in building JSON Object. Similarly, an ArrayList can be used to build JSON Arrays. Therefore, these two can be used instead of JsonObject and JsonArray classes of Jayrock in my post Converting ASP.NET DataTable to JSON using JayRock.)


  • Share/Save/Bookmark
  • Entries (RSS)
  • Comments (RSS)

About

ProfilePic Hi, My name is Krishna Chaitanya and I'm a web developer from Hyderabad, India.

This is my online abode where I write about various technical topics, my little experiments related to web development in ASP.NET, jQuery etc. More...