Other Links

Category: JQuery

I like the AjaxControlToolkit, but using those controls without a real knowledge of what is happening behind the scenes can be dangerous. We have a simple page that shows a list of objects of type A; for each line there is a button called â€œAssociateâ€, that opens a modal-like dialog where the user can search objects of type B. Each result of this search show a button call â€œSelectâ€ to associate that object to the A object. The page was written with ModalPopupExtender; for each line a User Control (that implements search and association) was included and managed by a ModalPopupExtender, a few lines of code behind, an updatePanel and the game is done, whoa, success

The page was cool, thanks to updatepanel and partial rendering the user does not see page to flicker and thanks to modalPopupExtender all the logic is reduced to very few lines of code. This experience makes programmers loving those kind of controls, until the number of users grow and people start to complain about slow performance. Letâ€™s examine only the bandwidth consumed by this page and do not check other possible performance issue.

Request

Bytes uploaded

Bytes downloaded

Open the page

0

74,918

Press Associate button

0

0

Search Objects

136,275

196,682

Press Select to associate an object

136,323

196,770

Press Close Button to close the modal

136,171

446,582

WHAT!!!!!! these are pretty big numbers for such a simple operation (search and asosciate), but here is what is happening. First of all we use a custom HttpModule that compress the page before sending back to the caller, but it creates problems with the UpdatePanel, so each request made by an update panel (partial rendering) does not get compressed, and this is the reason why the page size is much bigger on subsequent requests. Then we have a big upload payload due to the huge viewstate of the page (there are a lot of other stuff in the page) and each operation issue a full POST roundrip to the serverâ€¦. a lot of traffic

The solution is using a real Ajax technique, I created a separate page to render the grid, and with a little bit of jQuery moved all this logic into a true Partial Rendering Ajax page. The page that manage the association only accepts GET request with all needed parameters and only render the grid. Now I did the same sequence of operation and look at the different result.

Request

Bytes uploaded

Bytes downloaded

Open the page

0

48,414

Press Associate button

0

1,744

Search Objects

0

1,662

Press Select to associate an object

1,658

247

Press Close Button to close the modal

0

0

The original request is much smaller because I removed all those Panels that were handled with ModalPopupExtender, so the whole page is smaller.

When the user press the Associate Button the page issue a GET request to the other page that renders a small bunch of HTML (a texbox to search and a button inside a div), and when the user press the Search Button I returned only resulting data formatted in a simple Table. Finally when the user press Select I call an asmx webservice thanks to Ajax.Net to create the association in the database, and finally pressing the close button simply removes all partial rendering content with javascript, so no roundtrip is needed.

This big improvement in performance was paid by more time needed to develop the solution, by the gain in performance and scalability is tremendous, and since this is one of the most common operation the user to with this web application, the overall improvement worth the time spent on it and the slightly more complicated code on the UI.

This kind of problems happen because using the Update Panel or other similar control (like the ModalPopupExtender) gave the programmer the sense of creating a real Ajax application, quite often I heard people telling me that the concept of ajax is only â€œavoid refreshing the whole pageâ€ so an update panel is the only control they need.

Such kind of problems arise because developers are used to test application locally, where size of the page does not impact on perceived performance. I strongly suggest you to constantly test your web application with tools capable of simulating various Bandwidth scenario, just to avoid to find problems only when you deploy the application on the production server just to verify that your server bandwidth is completely saturated by the app.

In an old project I have a particular user control dedicated to identify data stored in a tree. The user can type some letters, and press â€œSearchâ€ button to find all the elements that match the search, or it can use a series of DropDownList to navigate from the higher element down to the hierarchy. It is used extensively in the site, and is used even to select location, from a table where location are stored in Nations, Region, Province and Location.

The control was designed as a user control, wrapped in an update panel, it works well, but it is really inefficient for high number of operations, so we decided to make a different version in jQuery. It tooks me about one day to recreate the control, mainly to maintain all the functionality it has in the past. Since the older version have already a decoupled DAL, I can reuse all server functions to search, manage the tree etc, and I need to write less code.

The old code was spread in four user control whose length is: 356, 557, 367 and 310 lines of code. This is mainly due to the fact that I decided to create two controls, one for the free text search, and the other for the DropDownList navigation, and other two controls that wire everything up. This kind of structure was chosen, because in some page we want to display only the DDL, in other only the search, and having each functionality in its own user control was simple to manage, I have only to change visibility.

Now we are testing the new control, it seems to work excepts some minor bugs that needs to be corrected, but Iâ€™m able to give you some numbers.

The control now is contained in only two server files and one javascript file. The first server control is the one used to render HTML and is 293 lines length (it is composed only by properties and some little logic, so it has really logic to mantain), the other file is an aspx page that stream json result data to the caller, and is 141 lines long, the js file is 192 lines and it is composed mainly by comments that explain how the script work. Iâ€™m happy because I reduced a lot server code, and the overall structure is simplier. Now it is time to look at request and response length. I recorded with fiddler a little section in witch I first search and select an option, then I use DropDownList part to select in a four level tree. I recorded both old version and new one in a real complex page of the program, here is the result.

Operation

Download

Upload

Download

Upload

First search

3684

0

133202

15432

Selection

0

0

133414

15560

First combo

8342

0

0

0

Already loaded into the page

second combo

661

0

15435

35721

third combo

158

0

15652

36228

fourth combo

5387

0

15804

37672

Selection

0

0

15959

37836

TOTAL

18232

0

329466

178449

I immediately notice is that the old version does a lot of traffic. Since the new version only does GET reques it reduces the upload payload from 178k to zero !!!!! The download is also reduced and is about 6% of the original size. These numbers makes me think a lot, because Asp.Net is a great environment that can be used to do RAD developement, but sometimes it is not so efficient. Thanks to jQuery we can still use asp.net optimizing some critical part with client logic.

jQuery has really a lot of interesting plugins, but the one I like most is a template engine called jtemplates. Basically it consist of a jQuery extension that is capable of rendering html with javascript on client machine. You really have a lot of flexibility on how to specify a template, basically you can embed it into an hidden textarea, the one you see in the above sample is created in this way

As you can see jtemplates has a simple syntax to render data where $T identify the object that contains data to be rendered. The template engine supports many constructs: foreach, if, and many other ones. To actually render something you need to assign the above template to a div:

$(".jTemplatesTest").setTemplateElement("template");

Assigning a template is just a matter of selecting a wrapped-set and then assign the template passing the id of the textarea that contains the template. Now the div has a template assigned, to render something you need only to fire the template engine passing it the object that contains data to be rendered. It is accomplished with the function processTemplate(data). The data is a simple javascript object that will be substituted to the $T object inside the template.

This is not the only way to set a template, the other one is using setTemplateURL and processTemplateURL that actually gets the template from an URL and render it with a json object returned from the url passed to processTemplateURL. If this sounds you interesting, think to asp.net mvc, where you can create a controller that manages templates, and other controllers that returns data with JsonResult. If you structure the site in this way, you can maximize performance passing only json data with the server. You only need to render the page with empty divs, assign template to the div, and finally gets data to be rendered from the server.

Actually Iâ€™m experimenting with the PhotoAlbum application I did for the jQuery workshop of our usergroup DotNetMarche, as soon as possible Iâ€™ll begin to post some concrete code that works with client-side rendering, showing you pratical example that uses this technique.

Iâ€™ve found this exceptional component to do file upload with jQuery and ajax call. I have a page where I need to edit a domain entity that have a property of type List<FileAttach>, and I need to permit to the user to easily add and remove attachments. The asp.net webform where this control resides is quite complex, so I really want to avoid a full page postback each time the user want to Add, remove or download an attachment.

My technique is quite simple, I created a page called AttachmentAjaxAction.aspx, this pages have two main functions, the first is to render a grid with all the attachments of related entity, the other is to add or remove an attach from the list. It accepts some parameter in post, and it does all the work in the load event.

The code is really simple, all parameters are passed in post variables, when the action is â€œaddâ€ I need to check the request.Files collection because this indicates that a file was uploaded to the server, when the action is â€œdelâ€ I simply delegate to the service the task to delete the attach. Finally after all operations are completed the page renders the whole grid. Files are stored in its binary form directly in the database (to use full text search). Now in the main page, I simply place a div where I want this grid to be shown.

I simply create an header, a div and an html button both with the attribute relid equal to the id of the entity we are managing. Now it is time for jQuery to wire everything with a simple script. In the first part I wireup the plugin used to upload the file

Thanks to the ajax-upload plugin, uploading a file is a breeze, first of all in the onSubmit I call one of my extension named setwait, that greys out the div containing the list of attachment, command is â€˜addâ€™ and when the calls succeded the funcion onComplete clear the waiting gif, parse the result of the page (remember that my AttachAjaxAction.aspx renders the grid after it performed desidered action.), filter to find the div with id â€˜the contentâ€™ and substitute all html into the div that shows the grid. The rewire function is used to wire up some events. The last line calls a funcion named loadAttachmentAjax to load the grid the first time.

These two function are really simple, the first one simply uses the load jQuery function to load the grid the first time, the rewire simply adds click functionality to the image used to remove attachment.

The result is a much more interactive page, where the user can add, remove and download attachments without a single postback.

Iâ€™m porting a sample application from asp.net to MVC, I used this app to make my session during last DotNetMarche event dedicated to JQuery. Now Iâ€™m writing the same sample pages in asp.net mvc to compare both technologies. In an Asp.Net page I showed how to use jQuery to do â€œEdit in placeâ€ of some Photo Description in an application that manages photo album. At a certain point my jQuery script will communicate with the server through an asmx webservice exposed with a ScriptManager.

Now that Iâ€™m working in asp.net MVC Iâ€™m asking if the same approach is valid, so the question is â€œI really need the ScriptManager to dialogate with the server?â€ and clearly the answer is â€œNOâ€. Iâ€™m not happy of the Script manager, because it generates a lot of Javascript code to create the infrastructure to make the SOAP request to the webserver. If it is possible I really prefer to avoid these external scripts and thanks to ASP.Net mvc this is possible. Here is the original call to the web service.

With this code Iâ€™m calling the ChangePhotoDescription method of the PhotoManager webService, as usual I pass parameters, then the two callback (success and failure) and the contex. Now that Iâ€™m in asp.net MVC all this infrastructure is completely unnecessary, first of all I write this action in the PhotoManagerController.

I declare that this action accepts only post, I inserted a sleep for demo purpose (Actually I shows that when the server needs time to answer, the ui shows a waiter gif), then I call my business logic (behind a Service) and return the result to the caller as a JSonResult. Iâ€™ve completely eliminated the asmx webservice, now here is the code to call this controller.

Thanks to jQuery I simply use the ajax method to make a call to the server, the url is composed by /ControllerName/ActionName, with the data parameter I set POST data, that will be passed to the controller action (pay attenction to the name), then I setup the various callback, and finally I insert into ajax options object a custom property called mycontext that contains the actual span Iâ€™m modifying.

Thanks to the JsonResult ASp.Net Mvc permits to call controllerâ€™s action from client code really in a breeze.