Avoiding JavaScript and CSS Stylesheet Caching Problems in ASP.NET

30 July 2009 (5 years ago)

We frequently run into problems related to caching when building ASP.NET websites. In particular, changes to CSS Stylesheets and JavaScript files on which the sites rely. After a new release our clients often have problems until they manually clear their browser cache. Some of our clients sit behind a proxy server which has its own cache, making the situation even worse.

The problem also extends to our development environment. As more of our UI work is moved into the browser through JavaScript and AJAX, we more frequently run into caching problems ourselves.

So - the solution we sought was to ensure caching when we wanted it, and to avoid it when we didn't!

More specifically, in our development environment, we never want to cache the site's supporting files (as they're likely to be changing quite frequently). In our production environment, we want to cache these files all of the time (for improved performance) - until we make a new release at which point we want to force the clients to pick up the new files.

The Concept

As with all the best things in life (of which this probably isn't one), the concept is simple. All we need to do to force the browser to re-load the file from the server is to give it a different file name. Changing the file name each time we build the site would be a bit of a wrench. Instead, we can add a simple query string to the URL of the file with a new number in it every time we build the site.

As far as the browser is concerned, /scripts/site.js?v=123 is completely different to /scripts/site.js?v=456 - but of course, we know better!

The Implementation

Adding JavaScript files to a page is something that will happen on pretty much every page on the site, so we've added this function to our site's Page base class:

Public Sub RegisterClientJavaScriptFile(ByVal ScriptFilePath As String, Optional ByVal ScriptType As String = "text/javascript")
    Dim ScriptTag As HtmlGenericControl

    ScriptTag = New HtmlGenericControl("script")
    ScriptTag.Attributes.Add("type", ScriptType)

#If DEBUG Then
    ScriptTag.Attributes.Add("src", ScriptFilePath & "?v=" & Now.Ticks)
#Else
    Dim Revision as Integer

    Revision = System.Reflection.Assembly.GetExecutingAssembly().GetName.Version.Revision
    ScriptTag.Attributes.Add("src", ScriptFilePath & "?v=" & Revision)
#End If

    Page.Header.Controls.AddAt(0, ScriptTag)
End Sub

Once this is in place, our page simply needs to call the function with the path to the script file as follows:

Call RegisterClientJavaScriptFile("/scripts/site.js")

When the site is built for DEBUG, a reference to the JavaScript file will be added to the site at run-time which adds the current date in ‘ticks' to the query string. This value changes every millisecond or so, which satisfies our need to never cache the files in our DEBUG environment.

When the site is built for RELEASE, the reference to the JavaScript file gets the current assembly's revision number added to the end. This will stay constant for a given release of the site and fulfils our requirement of allowing the client to cache the files between releases.

Once this is implemented, all you need to do is hook your build process up to your version control system to automatically increment the assembly's revision number every time you build, and you're done!

And Stylesheets...?

It's pretty clear to see where this is going, but for the sake of completeness, here's the function we use for Stylesheets...

Public Sub RegisterClientStyleSheetFile(ByVal StyleSheetFilePath As String, Optional ByVal Media As String = "all")
    Dim LinkTag As HtmlGenericControl

    LinkTag = New HtmlGenericControl("link")
    LinkTag.Attributes.Add("rel", "stylesheet")
    LinkTag.Attributes.Add("media", Media)

#If DEBUG Then
    LinkTag.Attributes.Add("href", StyleSheetFilePath & "?v=" & Now.Ticks)
#Else
    Dim Revision as Integer

    Revision = System.Reflection.Assembly.GetExecutingAssembly().GetName.Version.Revision
    LinkTag.Attributes.Add("href", StyleSheetFilePath & "?v=" & Revision)
#End If

    Page.Header.Controls.AddAt(0, LinkTag)
End Sub

What's Missing?

Unlike .NET's built in RegisterClientScriptInclude method, there's nothing in this system to stop you adding references to the same file more than once. It also adds the entries directly after the opening <head> tag, which you may not want it to. However, adding them at that point does mean that you can write JavaScript in other parts of your <head> block safe in the knowledge that your includes are already in place.

Comments

Zachary

12 February 2013
(1 year ago)
Avatar

Would you like a receipt?

Olivia

15 March 2013
(1 year ago)
Avatar

I came here to work http://www.d-target.com minoxidil generico intercambiable  o Medicines which are blister packed and are hygroscopic or medicines that may

Hen parties

5 October 2013
(1 year ago)
Avatar

There are alxo a lot of night clubs in the toen and never forget the gorgeous casins situated in the town.
There are facilities and arrangements for fun and thrilling
activities here. This is a great role for a younger member of
the wedding party who is old enough to drive, but tooo young to drink.

best hair growth for men

22 May 2014
(5 months ago)
Avatar

Anxiety and depression is common among hair loss sufferers, especially those experiencing total baldness.
A study published in The Journal of Dermatology revealed that
chlorine causes discolouration and a change in hair texture.
She did not seem too enthusiastic about it and claimed that she had just
been to the toilet and did not feel like peeing any more.

Boca Raton firefighter CPAt test

31 May 2014
(4 months ago)
Avatar

But, to a trained cost accountant, it is a quick road
map to help management analyze the business and zero in on areas for improvement.

In a photography business in particular, here are a number of items that are assets to be listed
for your business. As an Accountant with an MBA Degree in you will be able
to use your skills to analyze a company.

igrow golf

7 June 2014
(4 months ago)
Avatar

I couldn't simply hide in my own bedroom until
the balding area disappeared -- if it was still going to vanish.
It can affect the appearance, confidence, and maybe even the self
esteem of a person. Autoimmune problems such as baldness and psoriasis are known to be exacerbated by stress; daytime fatigue and emotional distress are the most commonly
reported symptoms of sleep deprivation.

hcg weight loss oral drops

11 June 2014
(4 months ago)
Avatar

A fetus must have a great deal of energy to keep up with the
speed of growth for a healthy child,and HCH helps
to produce that. It is advisable to test before you expect your next period.

The body demands a specific balance and any deficiency will force the body
to pull its energy from other sources. The pills help in suppressing hunger, so the
user can survive on the 500-calorie diet. Sexually transmitted diseases
affect your baby more grievously than they affect you due to the fact that your baby's immunity is as yet undeveloped.
When women at childbearing age are reminded by morning sickness
that they may be pregnant, they will go for early pregnancy test.
This will give you an accurate day to day comparison. It takes as much as a full week before your
fertilized egg makes its ways into your uterus
and implants itself on your uterine wall. If you
lose more than that and you are following theĀ formula above
just increase your calories a little bit until you are losing consistently, but slowly.
Both zero sugar and high protein bars and shakes can be used, if the calories are low
enough, as snacks and occasional meal replacements.

Leave a Comment