Performance Optimization in ASP.NET Web Sites

Performance is an important aspect of a modern day web application development. Not only it makes sites seamless to use but also increase the scalability and future proof. In this article, we will look at various aspects of improving the performance of web applications. We would only concentrate on the browser/web server side performance as oppose to server/app server/database server performance optimizations.

Before we getting into detail, the first question is, do we really need optimized the web sites?

Amazon.com has performed a test on their web site, and when they slower the site in 100ms, the sales dropped by 1%. As you would imagine a company like Amazon, 1% is a huge lost

Google slower their Search Engine in 500ms, the traffic dropped by 20%

As you can see, it is a very important aspect of modern web site development.

This even becomes more important as nowadays most sites require optimized sites for mobile, tablet devices and other portable devices that often run on low throughput wireless networks.

Below are few tips that you can take to make a better performing website.

Using the right ASP.NET framework

Check your .NET framework. If you can upgrade your site to use .NET 4.5, then it has some great performance optimizations. .NET 4.5 has a new Garbage Collector which can handle large heap sizes (i.e tens of gigabytes). The other improvements are Multi-core JIT compilation improvements, and ASP.NET App Suspension. These optimizations do not require code changes, it either upgrading the framework or changing the configuration i.e IIS etc.

Below is a great article on an overview of performance improvements of .NET 4.5

http://msdn.microsoft.com/en-us/magazine/hh882452.aspx

File compression

There are often requests bloated within the web server with lot of static content. These content can be compressed hence reducing the bandwidth on requests.

The below setting is only available in II7 and later.


<configuration>

<system.webServer>

<urlCompression doStaticCompression="true" doDynamicCompression="true" />

</system.webServer>

</configuration>

The above configuration setting has direct association with IIS and has nothing to with ASP.NET. The urlCompression name sounds strange but it is not really the compressing of URLs. It is compressing or gzipping the content and that sent to the browser. By setting this to true/enabling you can gzip content sent to the browser while saving lot of bandwidth. Also notice that the above settings is not only include static content such as CSS/JS, but also dynamic content such as aspx pages or razor view.
If your webserver running in Windows Server 2008R2 (IIS7.5) these settings are enabled by default. For other server environments, you would want to tweak the configuration as above so you can take the advantage of compression.

Reducing the number of requests to the Server

ASP.NET provides a great way to bundle and minify these static content files. This way the number of requests to the server can be reduced.
There are many ways to bundle and minify files. For example, MSbuild, third party tools, Bundle Configs etc. But the end result is the same.
One of the easiest ways is to use the new Visual Studio Web Essentials Pack. You can download this extention from the below Url.
http://vswebessentials.com/

Once installed, you can create minified and bundled CSS and Script files using the Web Essential Pack as below.

web essentials

The above menu items would create bundled/minified files, and added to your project. Now instead of referencing multiple CSS and JS files, you can simply reference the minified and bundled versions. This would also mean that there will be lesser requests made to the server, which result in less bandwidth and faster responses.
You may also wonder that even if we have bundled all files together, still the total number of Kilobytes remain the same as if we were to server them as individually. This is not necessarily true. For example,

  • The minified process would reduce the size of the files by removing comments, shortening variable, and removing spaces etc.
  • Bundling them together would also remove the additional Http headers that would require for each individual request.

You can also find some great information on the bundling and minification process below.
http://www.asp.net/mvc/tutorials/mvc-4/bundling-and-minification

Get control of your image requests

It is also possible that you can reduce the number of requests for images.
There are couple of ways to do this.

a. You may create an Image Sprite. With image sprite, you can combine multiple different images into a single large image. Then use the CSS to reposition those images within the site.
Below article shows how you would create Image Sprites using web essentials.
http://www.itorian.com/2014/02/creating-image-sprite-in-visual-studio.html

b. Base64 Data URIs
With this you would never make any requests to the server to obtain any images. You can take your smaller images and directly embed them into you CSS/Stylesheet.
code1

This will become.

.main-content {
    background: url('data:image/png;base64,iVBORw0KGgoA………..+ ') 
    padding-left: 10px;
    padding-top: 30px;
}

Setting up expiry headers

By default the static content served by the web server does not have the expiry dates. We can instruct the browser on how to cache the content, and for how long.
image2

If you set the expiration to a future date, the browser would not make a request to the server but instead the static content will be served within browser’s internal cache.
In the web.config, there is a section that you can control these settings.

  <configuration>
      <system.webServer>
        <staticContent>
          <clientCache cacheControlMode="DisableCache" />
        </staticContent>
      </system.webServer>
    </configuration>

We can change these settings to say cache all the static content requested from the server, for instance cache it maximum for a year. Note the expiration is a sliding expiration, which means the content will be serve from the cache from today up to a year.

<configuration>
      <system.webServer>
        <staticContent>
          <clientCache cacheControlMode="UserMaxAge" httpExpires="365.00:00:00" />
        </staticContent>
      </system.webServer>
    </configuration>

Now the web server will automatically add this header to the static files.

image3

(Note : The above Type ‘doc(1)’ would be the Html dynamic file hence the cache settings are not applied.)
This is all good, but what happen if you make a change to your CSS/JS file. With the above settings in place, it will not serve those changes for the entire year. A one way to tackle this issue is to force the browser to refresh the cache. You may also change the URL (i.e add query string, fingerprint/timestamp) to treat the page as a new URL so the cache get refreshed.

Script rendering order

If possible, you can move the script tags >script< to the very bottom of the page. The reason this is important because during the rendering, when browser comes across with a >script< tag, it stops rendering the rest of the page. If you leave the script tags at the bottom of the page, the page/HTML would render faster, the script can execute later on.

Sometimes this not possible due to some DOM elements or CSS requires those scripts to be present so they can be rendered. If that’s the case you could move those scripts further up on the page. However, as a rule of thumb, try to keep the scripts as lower as possible.
Lower positioning of the >script< tag is not the only option but there are other ways you can defer the load of script files.
For example, you can use the defer attribute.

<script src="some.js" defer></script>

By using the defer attribute, you can specify the script not to run until the page has been fully loaded.

Another way is to configure is to run your scripts asynchronously.

<script src="some.js" async></script>

Using the above async tag, the scripts will be run asynchronously as soon as it is available.

Optimizing images

Images are static content and they do take some bandwidth when requested via web server. A one way to solve this is to reduce the size of the images, in other words optimize the images.

Image “Optimize” does not mean that it reduces the quality of the image. But it will re-arrange the pixels and palettes to make the overall size smaller.

Web Definition of “Image Optimization”
“This term is used to describe the process of image slicing and resolution reduction. This is done to make file sizes smaller so images will load faster.”

So how you optimize images?
There are many third-party tools would optimize images. Below VS extension would do the trick for you.
http://visualstudiogallery.msdn.microsoft.com/a56eddd3-d79b-48ac-8c8f-2db06ade77c3

Size of favicon:
This is often ignored but you may have not noticed that sometimes the size of favicon is considerably large.

Caching HTML

If you have pages that never get updated, you can cache those pages for a certain period. For example, if you use Web Forms or ASP.NET MVC you could use ASP.NET Output Caching.
http://msdn.microsoft.com/en-us/library/xsbfdd8c(v=vs.90).aspx
With ASP.NET Web Pages you can modify the response headers for caching. Please see below on some caching techniques on web pages.
http://msdn.microsoft.com/en-us/library/vstudio/06bh14hk(v=vs.100).aspx
http://www.asp.net/web-pages/tutorials/performance-and-traffic/15-caching-to-improve-the-performance-of-your-website
It is important to note that this would only work if you have pages that do not require updates often.

Tooling support for Optimizing Web Sites

I believe that this is the most important aspect of this article, as the right tool goes long way in producing optimized web sites. There are number of tools, but there are 2 tools that always stand out.
a. Yahoo’s YSlow (https://developer.yahoo.com/yslow/)

image4

It is a Firefox Add-On and one of the most popular among web developers.
It has some great feature including a grading system, and instructions to make your site optimized. Most of the content I described in this article is also provided as tips in this tool, so once optimized your grading should go up.
b. Google’s PageSpeed
This is another great chrome browser extension. Once installed this should also be available part of the chrome developer tool bar.

image5

There is no guarantee that you could make all optimisations that these tools suggested. It is all based on the site, and requirements you need to support. But combining both of these tools to measure your site’s performance and applying some of the tips I mentioned before is a great a start.

Summary
In this article, we looked at some of the approaches that you can take to make optimized and better performing web site. This include, reducing number of requests to the server, changes to the .NET framework, compressing techniques and finally some tools that allows you to make better decision on web site performances.
It is also important to consider that whilst these techniques optimize web site/ web server performances, the overall performance can be based on number of other factors. This includes performance of Application Server, Database Server (in a multi-tiered setup). But there is lot of improvements you can gain optimizing sites as described in this article.

CSS Enlightenment with LESS

I have recently started modifying one of my older site’s CSS. Looking at the file gave me a headache as so much duplication. It was harder to figure it what was really going on.

I have also heard about LESS and other CSS pre-processors but really have not had a chance to use it until now.

After using LESS CSS file is much leaner and easier to navigate through. My CSS classes are no longer duplicated and instead they are wrapped in reusable types called mixins (see also mix what?)

There are re-usable variables defined for various styles, and I have reused those variable frequently.

Also  Visual Studio Web Essential 2012 package is a great way to work with LESS. It compiles your .LESS file and upon Save, you can see the CSS output next to your .LESS file.

Let’s take a look at simple example. And of course a real example (not foo, not bar)

In my site I have a CSS class block that have repeated twice like below..

pre

As you see these are styles for a link and should display different colors on the target link based on hover or not. Now if you were to change the font, you would have to change it in two places. With LESS you can introduce a variable which compiles into the same CSS sets.

pre1

This two classes can also be extracted into a maxin, and control the color from the calling CSS class.

premaxin

It is very much like functional programming! Now if we have to modify the styles they all in a single class.

Once you compile, you can see the generated CSS as below.

pregenerated

LESS makes very easier to work with CSS.

 

Getting Started with T4MVC

This post is about T4MVC and how you would use it within your MVC application. T4MVC is a great way to generate strongly typed helpers so you can eliminate the use of literal strings when referring to Actions, Controller, and Views within your MVC application.

How to install T4MVC?

You have 2 options.

a.    Download from MvcContrib CodePlex project.http://mvccontrib.codeplex.com/releases/view/41582

b.    Use NuGet

http://nuget.codeplex.com/wikipage?title=Getting%20Started

 

NuGet Approach      

Open VS2010. Tools,  Library Package Manager, and Package Manager Console. Execute the following command.

PM> install-package T4MVC

This should install 2 files under your app’s root folder.

T4MVC.tt and T4MVC.tt.settings.t4 – These files contain necessary entries which allow you to use T4 strongly typed helpers.

 

Once you install T4MVC, you might also notice couple errors appeared in the Error List window. (Please see below)  image

As you see, there are no auto generated files being added to the solution yet. You would continue to get these errors if you decided to build the solution.

To remove these errors, you need to run Custom Tool on the T4MVC.tt file. (Right click on the file and select “Run Custom Tool”).Now you should be able to see additional auto generated files added to the solution.

 

T4MVC in Action

Below are few examples of the usage of T4MVC.

image (1)

 

As you see T4MVC generates the strings accordingly.

Where to find more information?

T4MVC templates are part of MVCContrib project and developed by David Ebbo. If you would like to know more information please visit the link below.

http://mvccontrib.codeplex.com/wikipage?title=T4MVC_doc&referringTitle=T4MVC

ASP.NET MVC Unit Tests with UnityAutoMoq Container

 

UnityAutoMoq container is a great way to write maintainable Unit Tests. Since the container simplifies faking of dependencies, we can now focus on the actual test itself and spend less time on faking unwanted dependencies

For more info, please refer to the article below.

http://www.dotnetcurry.com/ShowArticle.aspx?ID=767

MVC 3 Filter Ordering

MVC 3 has introduced couple of new approaches related to the run order of filters. In this article, we will look at the order of filters execution.

image

There are different types of filters in MVC. Depending on the type of the Filter, and the scope of the Filter, the order of the execution also changes.

You may already aware that there are different types of filters within MVC framework. They are listed below.

1. Authorization filters

2. Action filters

3. Response/Result filters

4. Exception filters

The above list is ordered as exactly the order they executes within MVC framework. The Authorization filters always run first, and the Exception filters run at the end.

Specifying the Order property for Filters

Within each filter, you may specify the Order property. (All filters are derived from the abstract class FilterAttribute, and this class has an Order property). This property will ensure the filter runs in a specific Order. For an example, let’s say we have 2 Authorization filters, AuthorizationFilterA and AuthorizationFilterB and they are implemented as below.

public class AuthorizationFilterA : AuthorizeAttribute
{
    public override void OnAuthorization(AuthorizationContext filterContext)
    {
         Debug.WriteLine("OnAuthorization : AuthorizationFilterA");   
     }
}


public class AuthorizationFilterB : AuthorizeAttribute
{
     public override void OnAuthorization(AuthorizationContext filterContext)
     {
         Debug.WriteLine("OnAuthorization : AuthorizationFilterB");
     }
}

Now, if I want these two filters to run in a specific order – AuthorizationFilterB to run first, and AuthorizationFilterA to run second, I can simply specify the execution order as below.

[AuthorizationFilterA(Order=2)]
[AuthorizationFilterB(Order=1)]
public ActionResult Index()
{          
    return View();
}

When you run the code, the Output window should display that AuthorizationFilterB runs first, AuthorizationFilterA runs second.

OnAuthorization : AuthorizationFilterB

OnAuthorization : AuthorizationFilterA

Filter Scope

Within each filter type, you can define a scope. For an example, I could scope all my Authorization Filters to run within the Controller Scope, and all Action Filters to run in Global scope (Every Action within the MVC application).

FilterScope.Global is a new scope which was introduced in MVC 3. The existing scopes are First, Controller, Action, and Last. The complete enumeration is defined as below.

namespace System.Web.Mvc {
  public enum FilterScope {
       First = 0,
       Global = 10,
       Controller = 20,
        Action = 30,
        Last = 100,
   }
 }
 

By default, the filters with the lowest scope runs first. For an example, scope Global (10) executes first and scope Controller (20) executes second.

Filter Scope with explicit Ordering

Below example shows, how explicit filter ordering (using Order property) and scope of the filters determine their correct run order.

Let’s add the scope to our existing Authorization Filters – AuthorisationFilterA and AuthorisationFilterB. Please note that we haven’t changed the usage of Order property.

AuthorizationFilterA(Order 2) has the scope Global.

AuthorizationFilterB(Order 1) has the scope Action.

 public class AuthorizationFilterA : AuthorizeAttribute
 {
      public override void OnAuthorization(AuthorizationContext filterContext)
      {
          Debug.WriteLine("OnAuthorization : AuthorizationFilterA (Order: 2) in scope : Global");   
      }
  }

public class AuthorizationFilterB : AuthorizeAttribute
{
    public override void OnAuthorization(AuthorizationContext filterContext)
    {
        Debug.WriteLine("OnAuthorization : AuthorizationFilterB (Order: 1) in scope : Action");   
    }
}

[AuthorizationFilterB(Order = 1)]
public ActionResult Index()
{           
    return View();
}
   
GobalFilters.Filters.Add(new AuthorizationFilterA() { Order = 2});

According to the above Filter Scope enumeration, if we were to specify only the scope but not the Order property, then we would expect AuthorizationFilterA (in Global scope) to run first, and AuthorizationFilterB (in Action scope) to run second. Since we are explicitly specifying the Order property for both filters, AuthorizationFilterB (in Action scope – Order 1) runs first and AuthorizationFilterA (in Global scope – Order 2) runs second.

Output:

OnAuthorization : AuthorizationFilterB (Order: 1) in scope : Action

OnAuthorization : AuthorizationFilterA (Order: 2) in scope : Global

Now let’s add another Authorization filter (AuthorizationFilterC) to Global scope. Also note that we have not specified the Order property.

  
public class AuthorizationFilterC : AuthorizeAttribute
{
      public override void OnAuthorization(AuthorizationContext filterContext)
      {
          Debug.WriteLine("OnAuthorization : AuthorizationFilterC (no Order defined) in scope : Global");
      }
 
    
GlobalFilters.Filters.Add(new AuthorizationFilterC());
   

After running all three filters, you can see the output as below.

Output

OnAuthorization : AuthorizationFilterC (no Order defined) in scope : Global

OnAuthorization : AuthorizationFilterB (Order: 1) in scope : Action

OnAuthorization : AuthorizationFilterA (Order: 2) in scope : Global

For same Filter type, the filters without the explicit ordering (i.e AuthorizationFilterC) take precedence over the filters with explicit ordering (AuthorizationFilterB, AuthorizationFilterA).

Now let’s remove the Order property from both AuthorizationFilterB and AuthorizationFilterA

  
[AuthorizationFilterB]
 public ActionResult Index()
 { 
     return View();
 }
  
 GlobalFilters.Filters.Add(new AuthorizationFilterA());

Output:

OnAuthorization : AuthorizationFilterA (no order defined) in scope : Global

OnAuthorization : AuthorizationFilterC (no order defined) in scope : Global

OnAuthorization : AuthorizationFilterB (no order defined) in scope : Action

As we would expect, the filters with scope Global (AuthorizationFilterA and AuthorizationFilterC) run first and second in order, the scope Action filter (AuthorizationFilterC) runs at the end. 2 Global filters (AuthorizationFilterA and AuthorizationFilterC) run order relies on the order which they were added to the Global Filter collection. In this example AuthorizationFilterA which was added prior to AuthorizationFilterC ,runs first.

For the same filters, when determine the run order, first it sorts them by their order (lowest numbers first), and then by their scope (also lowest numbers first).

Controller as a Filter

In MVC the Controller itself is also a Filter. Controller implements all filters, so Controller can subscribe to all filter events.

  
public abstract class Controller : ControllerBase, 
IActionFilter, IAuthorizationFilter, IDisposable, 
IExceptionFilter, IResultFilter

MVC framework ensures, the Controller always runs first, before any other filters get executed. It has been accomplished by specifying the scope as the First and the order property as Int32.MinValue. By default, an MVC filter has the value for the Order -1. Therefore Int32.MinValue along with the Scope First together ensures the Controller always runs first.

  
public class ControllerInstanceFilterProvider : IFilterProvider {
        public IEnumerable<Filter> GetFilters(ControllerContext controllerContext, ActionDescriptor actionDescriptor) {
            if (controllerContext.Controller != null) {
                // Use FilterScope.First and Order of Int32.MinValue to ensure controller instance methods always run first
                yield return new Filter(controllerContext.Controller, FilterScope.First, Int32.MinValue);
            }
        }
    }

Forward Filter Order and Reverse Filter Order

So far we have discussed the order of filters which get executed based on the explicit ordering (using Order property) and the scope which they can be belong to. However, MVC filters run order, do not only rely only by these two factors. Sometimes filters run in forward order and sometimes filters run in reverse order. Let’s see the below example.

Let’s say I have three Action filters (ActionFilter1, ActionFilter2, ActionFilter3), one Authorization filter (AuthorizationFilter) and two Exception filters (HandleErrorA, HandleErrorB). They are implemented as below.

 
public class ActionFilter1 : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        Debug.WriteLine("Forward Order - OnActionExecuting : ActionFilter1 (Scope Global)");
    }
 
    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        Debug.WriteLine("Reverse Order - OnActionExecuted : ActionFilter1 (Scope Global)");
    }
 
    public override void OnResultExecuting(ResultExecutingContext filterContext)
    {
        Debug.WriteLine("Forward Order - OnResultExecuting : ActionFilter1 (Scope Global)");
    }
 
    public override void OnResultExecuted(ResultExecutedContext filterContext)
    {
        Debug.WriteLine("Reverse Order - OnResultExecuted : ActionFilter1 (Scope Global)");
    }
}

 
public class ActionFilter2 : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
     {
         Debug.WriteLine("Forward Order - OnActionExecuting : ActionFilter2 (Scope Controller)");
     }
  
     public override void OnActionExecuted(ActionExecutedContext filterContext)
     {
         Debug.WriteLine("Reverse Order - OnActionExecuted : ActionFilter2 (Scope Controller)");
     }
  
     public override void OnResultExecuting(ResultExecutingContext filterContext)
     {
         Debug.WriteLine("Forward Order - OnResultExecuting : ActionFilter2 (Scope Controller)");
     }
  
     public override void OnResultExecuted(ResultExecutedContext filterContext)
     {
         Debug.WriteLine("Reverse Order - OnResultExecuted : ActionFilter2 (Scope Controller)");
     }
 }
  
 public class ActionFilter3 : ActionFilterAttribute
 {
     public override void OnActionExecuting(ActionExecutingContext filterContext)
     {
         Debug.WriteLine("Forward Order - OnActionExecuting : ActionFilter3 (Scope Action)");
     }
  
     public override void OnActionExecuted(ActionExecutedContext filterContext)
     {
         Debug.WriteLine("Reverse Order - OnActionExecuted : ActionFilter3 (Scope Action)");
     }
  
     public override void OnResultExecuting(ResultExecutingContext filterContext)
     {
         Debug.WriteLine("Forward Order - OnResultExecuting : ActionFilter3 (Scope Action)");
     }
  
     public override void OnResultExecuted(ResultExecutedContext filterContext)
     {
         Debug.WriteLine("Reverse Order - OnResultExecuted : ActionFilter3 (Scope Action)");
     }
 }
  
  
 public class AuthorizationFilter : AuthorizeAttribute
 {
     public override void OnAuthorization(AuthorizationContext filterContext)
     {
         Debug.WriteLine("Forward Order - OnAuthorization : AuthorizationFilter (Scope Controller)");
     }
 }
  
  
 public class HandleErrorA : HandleErrorAttribute
 {
     public override void OnException(ExceptionContext filterContext)
     {
         Debug.WriteLine("Reverse Order - OnException : HandleErrorA (Scope Action)");
     }
 }
  
 public class HandleErrorB : HandleErrorAttribute
 {
     public override void OnException(ExceptionContext filterContext)
     {
         Debug.WriteLine("Reverse Order - OnException : HandleErrorB (Scope Action)");
     }
 }
 

We will register the above filters as below…

ActionFilter1 has the scope Global, ActionFIlter2 has the scope Controller, ActionFIlter3 has the Scope Action, AuthorizationFilter has the scope Controller, HandleErrorA has the scope Global, and HandleErrorB has the scope Action.

At the beginning of this article I mentioned that the run order of different types of filters. First Authorization filters, then Action Filters, followed by Result filters and at the end the Exception filters. This is true, however within each type of filters, some executes in reverse order and some executes in forward order.

The best way to explain is to examine the generated output.

Forward Order – OnAuthorization : AuthorizationFilter (Scope Controller)

Forward Order – OnActionExecuting : ActionFilter1 (Scope Global)

Forward Order – OnActionExecuting : ActionFilter2 (Scope Controller)

Forward Order – OnActionExecuting : ActionFilter3 (Scope Action)

Home Controller, Index Action

Reverse Order – OnActionExecuted : ActionFilter3 (Scope Action)

Reverse Order – OnActionExecuted : ActionFilter2 (Scope Controller)

Reverse Order – OnActionExecuted : ActionFilter1 (Scope Global)

Forward Order – OnResultExecuting : ActionFilter1 (Scope Global)

Forward Order – OnResultExecuting : ActionFilter2 (Scope Controller)

Forward Order – OnResultExecuting : ActionFilter3 (Scope Action)

Reverse Order – OnResultExecuted : ActionFilter3 (Scope Action)

Reverse Order – OnResultExecuted : ActionFilter2 (Scope Controller)

Reverse Order – OnResultExecuted : ActionFilter1 (Scope Global)

Reverse Order – OnException : HandleErrorB (Scope Action)

Reverse Order – OnException : HandleErrorA (Scope Global)

  • There is only one Authorization Filter in Controller scope and it runs first as expected.
  • The Action Filters run at second. Notice that OnActionExecuting event runs in an order where the order of filter execution is determined by their scope (lowest number first in the enumeration). As you see, Action Filters OnActionExecuting event runs in a forward order.
  • Home Controller’s Index Action executes.
  • Action Filters do not always run in forward order. As you see during OnActionExecuted event, they run in a reverse order.
  • Very similar to OnActionExecuted event, OnResultExecuted event runs in reverse order.
  • Error Handler filters run at last. For each Error Handler filter, OnException event runs in  reverse order. Prior to MVC 3, ErrorHandler’s OnException event ran in forward order. This approach makes MVC exception filters more aligned with .NET exception handlers.

Summary

There are multiple factors involved when deciding the run order of MVC filters. This includes the explicit ordering, the scope they belong to, and the type of the filter. Controller itself is a filter and always run first. By design, MVC executes certain filters in specific order. Some are run in forward order and some are run in reverse order.

For your favourite posts, subscribe to my blog: http://blog.rajsoftware.com

https://blog.rajsoftware.com/post/2011/05/14/MVC3-Filter-Ordering.aspx

Automating QUnit and JSTestDriver within VS2010

I briefly touched based on this during my presentation at Code Camp. There were number of developers who were interested in browser based Unit Testing. This blog post is to provide you with some information on how you would automate browser based Unit Testing with VS2010.

QUnit is a great JavaScript Unit Testing tool which allows you write powerful browser based Unit Tests. You can find more information on QUnit here.

As described in the JSTestDriver Getting Started, you can use the below command to run both Java server and the client using a single command.

java jar <path>/JsTestDriver.jar port 9876browser firefoxpath,chromepath –tests all

Next step is to automate the above command within VS2010. You can easily achieve this by using VS External Tools.

·         VS -> Tools -> External Tools ‘Add new’

·         Specify the Title E.g “Js Unit Tests Run”

·         Specify the Command – C:\Program Files\Java\jre6\bin\java.exe

(This is the path where your java runtime is located)

·         Specify the Arguments

-jar <path>/JsTestDriver.jar –port 9876 –browser  “C:\Program Files\Internet Explorer\iexplore.exe, C:\Program Files\Mozilla Firefox\firefox.exe” –tests all

·         Initial Directory is the path to the directory where the JSTestDriver is located.

·         Ensure you select the “Use Output Window” check box, so you can see the Unit Tests result in the output windows.

Once you run the VS external command, you should be able to see your output similar to below.

image

You can further automate this by running a VS macro, so every time when you save a JS file the above command will run all browser Unit Tests.