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? 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

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.



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



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.

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.

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.

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.

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.

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.

          <clientCache cacheControlMode="DisableCache" />

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.

          <clientCache cacheControlMode="UserMaxAge" httpExpires="365.00:00:00" />

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


(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.

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.
With ASP.NET Web Pages you can modify the response headers for caching. Please see below on some caching techniques on web pages.
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 (


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.


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.

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.

Entity Framework updating (Code First) existing entity using foreign key Id(s) mistakes

Recently we have come across with a scenario like below.

We had an entity (EF bounded), and we wanted to update the entity’s foreign key references from an existing entity. For example, say..

A Person has a Brazilian Passport, and that person need to update the Passport to an American Passport.

The domain/entity model looks like this

 public class Person
   public int Id { get; set; }
   public string Name { get; set; }

   public virtual Passport Passport {get; set; }
   public int PassportId { get; set; }

public class Passport
  public int Id { get; set; }
  public string Number { get; set; }
  public string Nationality { get; set; }

Notice that Person has 2 properties relates to Passport foreign key references. One is a <a href=”; target=”_blank”>Navigational Property</a> and the other is the foreign key id reference. Notice that it uses the {EntityName}Id as the property name. It need to be in this convention for EF to generate the foreign key. If anything other than that EF would create an additional key.

Once you run the <a href=”; target=”_blank”>EF migration</a> you would see the tables generated as below..


Now in order to update the Person’s (only person) passport to an American passport, the code would be something like this..

 using (var dbContext = new PersonContext())
   Console.WriteLine("Update person with passport");
   var person = dbContext.Persons.First();
   var americanPassport = dbContext.Passports.
            Single(x => x.Nationality == "American");

   person.PassportId = americanPassport.Id; //Notice this line


I personally don’t like this approach for couple of reasons.

a. It feels “hacky” that you have set the id explicity to update the FK referece.
b. See the entity model, Passport. There are two properties roughly to achieve the same thing. If you use the Navigational Property you can access the Id right? So why we need another Id property?
c. Suddenly your domain entity become database ‘aware’ of FKs etc.

My preferred approach is to leave entity as it is, and just use the Navigational property. Unless if you really have to no the id property for some other reason, which I can’t think of.

 public class Person
    public int Id { get; set; }
    public string Name { get; set; }

    public virtual Passport Passport {get; set; }

That’s it! EF would generate the Foreign Key for Passport Entity as usual.

Now you can just update the entity using the Navigational Property (not the FK property id)

 using (var dbContext = new PersonContext())
    Console.WriteLine("Update person with passport");

    var person = dbContext.Persons.First();
    var americanPassport = dbContext.Passports.
        Single(x => x.Nationality == "American");
    person.Passport = americanPassport;


This is lot cleaner than setting up ID reference. To perform the update like this you need to make sure your, both entities (Person and Passport), are in unchanged State.

Unchanged: the entity is being tracked by the context and exists in the database, and its property values have not changed from the values in the database