Too many scripts will slow us down

by ishaih 3/1/2009 9:01:00 AM

I’ve been ‘away’ from this blog for a while. It’s been a very interesting year for me but I’ve been neglecting this blog for too long.

If you’ve read the previous posts, you can see I’m not a big fan of the Asp.Net postbacks and update panels. Too much information is sent back and forth for small actions that can be easily done in javascript.

As I’ve shown before, there are hugh performance benefits to using client side rendering in a web app. Instead of sending the entire HTML for every request, we load javascript code for creating that HTML once and after that we just send the data for subsequent requests.

One of the side effects of moving from server side rendering is that you start getting more and more javascript files. I’ve been using JQuery for a while, there are a lot of great plugins for JQuery, but loading all of those include files introduces some problems:

  1. More scripts = more requests = more loading time
  2. Managing includes can become messy

Using a Script Combiner to reduce the number of requests
Ideally you want to have only one js file and one css file, but you don’t want to have your files merged while you’re developing, a hugh file will be a pain to work with. The solution is to merge all the scripts into one big file later, either in the build process or at run time.
if you use the same scripts for all pages in your app (or if you have a one page app), merging during the build process is a good solution but I needed different files for different pages.

Asp.Net AJAX 3.5
If you’re using Asp.Net AJAX 3.5, achieving this is very simple. The scripts from Microsoft will already be combined by default and to add your own scripts all you need to do is include your scripts using the ScriptManager.

<asp:ScriptManager runat="server" ID="ScriptManager1" >
    <CompositeScript>
        <Scripts>
            <asp:ScriptReference Path="~/JScript1.js" />
            <asp:ScriptReference Path="~/JScript2.js" />
        </Scripts>
    </CompositeScript>
</asp:ScriptManager>

Script Combiner - The Other Solution
If you don’t use Asp.Net AJAX and don’t want those scripts loaded (or you’re still using 2.0) you can create your own handler to combine scripts.
Here’s a project I foundby Omar Al Zabir (Who wrote the excellent book Building a Web 2.0 Portal with ASP.NET 3.5 and co-founded PageFlakes)
You might want to change the way you decide which scripts to load, I use an xml configuration file to specify the location of each script file and which js files should be loaded based on the page name that’s passed to the handler. (I use the page name as the key for now). I also have a separate path for the minified version and the debug version, and based on a config I use the right one

<ClientScripts>
   <Script name=”jquery” minPath=”Scripts/JQuery/jquery.1.2.6.min.js” debugPath=”Scripts/JQuery/jquery.1.2.6.js”/>
   <Script name=”jqvalidation” minPath=”Scripts/JQuery/plugins/jquery.validate.min.js” debugPath=”Scripts/JQuery/plugins/jquery.validate.js”/>
</ClientScripts>
<Pages>
   <Page name=”home” Scripts=”jquery,jqvalidation” />
</Pages>

There are several benefits when using this custom handler

  • You can use it for css files too
  • It compresses the js files using gzip
  • The files are only read from the file system once and are then cached on the server for subsequent requests
  • You can easily add versioning to the handler and set client side caching to never expire.
Digg It!DZone It!StumbleUponTechnoratiRedditDel.icio.usNewsVineFurlBlinkList

Currently rated 3.7 by 3 people

  • Currently 3.666667/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: ,

AJAX | Asp.Net | Javascript

Upgrading ASMX web services to WCF

by ishaih 6/15/2008 9:21:00 AM
There is a lot of information on the web on using WCF for JSON, but I figured I’ll writing something short on the way I use it.

When I decided to try WCF, the first thing I noticed was how simple it was to upgrade. All you need to do is add a new WCF Service to the web project, copy the code from the ASMX service, change the [ScriptService] to [ServiceCntract] and the [WebMethod] tags to [OperationContract] and add some definitions in the web.config file.
You’re supposed to use a separate Interface to define the service contract, but it’s not a must and you can add the tags to the actual class with the implementation.

The second thing I noticed is that I can get JSON by changing some configuration settings.
When I was working on the AJAX search page, WCF was not around (it was by the time I posted the series on it here). I used XSLT to transform data to JSON and arrays. It was another step I had to do on the server side but it’s worth it, JSON is smaller than XML and very easy to work with in JavaScript.
With WCF I just change a small definition and I get the results in JSON, no need for the XSLT transformation.

Another thing we get with WCF is Data Contracts. The way I’m using it in this sample, it’s pretty much the same as using the .Net AJAX GenerateScriptType.
All I had to do is add a [DataContract] tag to the class and [DataMember] tags to each property.
I think it’s better to define this on the exposed class itself instead of adding some register definition in a web service.

The attached project is the same search page sample with the WCF service. The changes to look for are:
  • The new DataService.svc file
  • The Entities.QueryParameters classes now have the DataContract tags
  • web.config has the new serviceModel section at the end, that defines the service as an HTTP JSON enabled service
  • default.aspx – the service defined in the ScriptManager was changed to the svc file and the path was updated in the javascript Search method

WcfAjaxSearchSample.rar (883.99 kb)

Digg It!DZone It!StumbleUponTechnoratiRedditDel.icio.usNewsVineFurlBlinkList

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: , ,

AJAX | Asp.Net | WCF

Ajax Data Controls (Repeater, Data List and Grid View)

by ishaih 2/18/2008 1:14:00 PM

ADC is a set of data controls that try to mimic the Asp.Net controls using Asp.Net AJAX Extensions.

I'm looking at the GridView in particular, although I never really liked the Asp.Net control, the AJAX version might work well for my search pages.
For the current project I'm working on I won't be using the server side wrapper, just the client side code.

The grid view control supports paging, sorting, column dragging, links, checkboxes and in-place editing.

I'm going to try it out, see if it takes the places of my upgraded WebFXColumnList...

check it out at Ajax Data Controls - Home

Digg It!DZone It!StumbleUponTechnoratiRedditDel.icio.usNewsVineFurlBlinkList

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:

AJAX | Asp.Net | Javascript

You should never forget your (browser) history

by ishaih 2/18/2008 10:44:00 AM

One of the most annoying things in AJAX based applications is clicking the back button and going back to a previous url and not the previous state of the application.
Users are trained at clicking the back button if they went to the wrong place and need to get back to the last place they were at. Even when I know I'm using an AJAX app, I would click it by mistake.

What happens when uses click the back button in your AJAX application?
I've worked on a lot of back office web applications and when an application uses AJAX with only one real page (in the same way gmail does), clicking back will usually take you to the login screen, and that's not where you wanted to go.

Adding History to an AJAX application
Fortunately, this problem has been solved. You can manipulate the browser history and control what happens when a user clicks the back button.
Even better, Microsoft’s AJAX library adds easy support for setting history points and going back to them, so you don't have to write the code yourself.

Let’s take a look at the AJAX search sample, where we had next and previous buttons to navigate the search results.

Whenever a results page is shown I want to add a history point.

Here's the code I'll use to set a history point in JavaScript:

Sys.Application.addHistoryPoint({showPage:pager.CurrentPageIndex},'MyTakeOnNet - Search Results - Page ' + pager.CurrentPageIndex);


Sys.Application.addHistoryPoint takes two parameters, the first one can be any object you want, you will use this object to decide what to do when the user goes back to this history point. the second parameter is the title of the page.

If you add this line of code to the pager's ShowPage method, you'll see the history button's drop down will have a new entry for each page.


Handling the history navigation
Every time a user navigates through the browsers history by clicking the back button or selecting a history point from the back buttons drop down, the MS AJAX library raises an event.
To subscribe to this event, add the following line of code when the page loads.

Sys.Application.add_navigate(onNavigate);

and add the onNavigate function to handle the event
function onNavigate (sender, e) {    //get state and make change to application    var state=e.get_state();    if (typeof(state.showPage) != 'undefined') {        if (pager.CurrentPageIndex != state.showPage)            pager.ShowPage(state.showPage);    }}

The get_state() call will return the object you saved as the first parameter of the history point, you can then use this parameter to show the page.

Pretty simple, right?
It does get more complicated if you remember that a user might execute several searches and page through them, so the search parameters should be saved as well with the history point.
You have to make sure you cover the entire state of you AJAX enabled page to make sure you can re-create that state when the user clicks the back button, but at least you don't have to write the code to deal with the browser's history
Digg It!DZone It!StumbleUponTechnoratiRedditDel.icio.usNewsVineFurlBlinkList

Currently rated 4.7 by 3 people

  • Currently 4.666667/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:

AJAX | Asp.Net | Javascript

My take on implementing searches with AJAX (Part 5)

by ishaih 2/15/2008 4:39:00 PM
So far in this series of posts I created a search page that uses AJAX to fetch the results and display them using a modified version of the WebFX ColumnList control.
The only thing left to do to meet the requirements is add support for paging and sorting.

We already have the paging and sorting parameters in the SearchParameters object, so we're sending these parameteres and returning onlt the first page of the results.
Now we need to add paging buttons and enable users to view the other pages.
We also want to cache pages and support prefetching of the next page.


The Pager Control
I wanted to make a reusable paging control that I can use whenever I need paging support.

The main method of the pager control is ShowPage, this method is called with the page index and if the page is not in the cache it will call the server side method to get that page.
Before calling the ShowPage method we need to set some parameters to let the pager know what we want to do.
-ServerSideMethod - the name of the method to call
-ServerMethodType - 1 for a web service method, 2 for PageMethods
-UsePredictiveFetching - when true, the next page will be fetched and cached
-ShowPageCallback - a reference to a method for showing the page (needed because fetching a page is done asynchronously and the pager can be used by different classes)
-SearchParameters - a SearchParameters object that will be sent to the server side method, the pager control will set the paging and sorting parameters every time the ShowPage method is called, but the search specific parameters won't change between pages.

The Pager JavaScript Class:

Pager.js.txt


In the updated Search function the Pager class is created the first time the function is called, the SearchParameters are set and the ShowFirstPage method is called (this method simply calls ShowPage with the value 1).
The pager variable is declared outside of the function because we need it later for showing other pages (and if we created it every time, there will be no point for the page caching).

The updated Search function:
var pager = null;

function Search() {
var fc = new FormController();
var searchParams = fc.CollectFormValues("searchFormContainer");
searchParams.PageSize=20;
searchParams.SortColumn="FirstName";
searchParams.SortOrder="ASC";
searchParams.QueryName="SearchClients";
searchParams.ColumnCollectionName="ClientsSearchResults";

if (pager==null) {
pager = new Pager();
pager.ServerMethodName = 'IshaiHachlili.MyTakeOnDotNet.WebServices.ContentsWS.DoSearch';
pager.ServerMethodType = 1;
pager.ShowPageCallBack = showGrid;
pager.UsePredictiveFetching = true;
}

pager.SearchParams = searchParams;

pager.ClearCachedPages();
pager.ShowFirstPage();
}

var searchResultsObject;
function showGrid(result) {
eval(result);

if (typeof(aColumns)!="undefined") {
if (TotalPages>0) {
pager.TotalPages=TotalPages;
}

var el =$get("searchResultsContainer"); //the element that will contain the grid
if (searchResultsObject == null) {
var searchResultsObject = new WebFXColumnList();
searchResultsObject.SortingCallback = pager.Sort.bind(pager);
searchResultsObject.create(el, aColumns);
} else {
searchResultsObject.clear();
}

searchResultsObject.addRows(aData);
} else {
alert('No results returned');
}
}

I renamed the onComplete method to reflect that it is now used to show the grid and not as the onComplete call back to the server side call.
You can also see that I moved the searchResultsObject declaration outside of the function. The reason for doing that is to keep the same positions and widths for columns (If the ColumnList is created everytime a page is shown any changes the user made to the widths and positions of columns will be reset).


The Pager class has two methods that can be used for next/previous paging, the ShowNextPage and ShowPreviousPage. It also has two methods for showing the first and last pages.
Adding buttons to control the paging is easy, you can also use the TotalPages value to create direct page links.


Sorting when there's more than one results page.
If there's only one results page the WebFX control can be sorted on the client side, but when there's more than one page we need to change the sorting paramters in SearchParameters and execute the search again.
If you take a look at the Pager class, you can see the Sort method and all it does is change the sorting parameters, clear the page cache and call the ShowFirstPage method.

The Sort method should be called from the grid, when a column header is clicked. Since the WebFX control already support sorting, all I had to do is add a call from the WebFXColumnList.sort function to the Pager's Sort method.
I also wanted to cancel the client side sorting if there's more than one page, no reason to sort on the client side and then replace the whole grid with the new sorted data from the server side.
I added a property to the ColumnList called SortingCallback, and in the showGrid function I set the value of this property to the pager's sort method.



Let's see what we have so far
1. A search page with support for paging, pre-fetcing the next page and caching previous pages.
2. A grid that supports column dragging, resizing, and formatting and links in the cell contents.
3. Easy maintainance. Adding a new search parameter requries only a simple update to the HTML form and the stored procedure, no need to touch the server side code at all.
4. Better performance. Because we only transfer the page data instead of refreshing the entire page (or loading the whole grid's HTML with an update panel), the size of the download is much smaller. Also, caching saves more requests for the same data and pre-fetching gives the user a better experience by having the next page ready faster.

and, best of all, with this implementation I just saved myself a lot of work. From now on, the DBA and designer can create search pages without me being involved. I actually made it even easier by moving the search function inside another class, and the only code that needs to be written is a call to a function with the values for some properties.


What's next? Some advanced features...
This framework will allow you to create pages easily without having to recompile you code but there are some other features that can be added to make it even cooler.

Saved Searches
Allowing users to saves their favorite and most used searches is a great feature that will be easy to implement.
By using the FormController's CollectFormValues to get a JSON of the search parameters and saving these parameters with some name, it should be easy to load the values back to the form later.
Most of the work will be the function that sets the values for the form elements. Apart from that we need to add some HTML for saving and loading searches, a text box with a button for saving and a drop down with a button for loading. Should'nt be too hard.

New search results alerts
Once we have the JSON saved on the server side we can execute this searches at any time, we just need to deserialize the JSON back to the SearchParameters object and execute a search.
It should be very easy to create a service that executes searches periodically and sends a notification when new results are found.

Grid Personalization
Different users might use the same search pages for different things and it might be easier for each user to get the results grid he way they want it. Since we already have a grid that supports setting the widths and positions of columns, we can save this properties for each user and load them back.
In my implementation of this feature I simply saved the column ids, positions and widths for each user and after the default grid is created I just ran over the columns and re-set this properties.

Dynamically created forms
By adding support for dynamically created forms, I can move the whole process of adding a new search page to the database layer. Add a stored procedure, add the data query, columns and form input controls in the database, and open a generic search page with the name of the form to load. Now you don't even need to upload an HTML file.
Of course, getting to a place where these forms look good enough and support all the layout requirements might be too hard to make it worth it.


Files:
 
AjaxSearchSamplePart5.zip (935.70 kb)
This zip file contains all the code shown in this series and some additional code that was mentioned.
Digg It!DZone It!StumbleUponTechnoratiRedditDel.icio.usNewsVineFurlBlinkList

Currently rated 3.7 by 3 people

  • Currently 3.666667/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: ,

AJAX | Javascript

Powered by BlogEngine.NET 1.3.1.0
Theme by Mads Kristensen

About the author

Name of author Ishai Hachlili
I've been developing web applications using Microsoft technologies for over 10 years. This is my way of doing things, it might be a little different...

E-mail me Send mail

Calendar

<<  July 2010  >>
MoTuWeThFrSaSu
2829301234
567891011
12131415161718
19202122232425
2627282930311
2345678

View posts in large calendar

Pages

    Recent comments

    Authors

    Disclaimer

    The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.

    © Copyright 2010

    Sign in