Quantcast
Viewing all articles
Browse latest Browse all 33

How to force to update JavaScript and CSS files after deploying new version of ASP.NET MVC application.

Usually after each deployment my ASP.NET MVC (Razor view) site I have a little mess with cached JavaScript and CSS files. Sometimes user's browsers show unappropriated view or some client functionality doesn't work.
Yeah, it is very easy to fix - just clear browser cache or reload JavaScript and CSS files (press CTRL+F5). But I want user to avoid this annoying action moreover not all users are so familiar with PC to know this trick.
My friend Mykhailo found nice solution for this. If I add parameter to JavaScript's url and will change parameter's value after each deployment. Browser will recognize it as other script and will update file.
So now I should add something like "?v=xxxx" to all links of CSS and JavaScript files in my project and keep in mind it for future links. Looks not really smart solution doesn't it?
First of all I want to say that I set JavaScript and CSS files in "Razor" style. For instance:


<link href="@Url.Content("~/Content/Site.css")" rel="...

In this case I just need to find way override "Content" method. Ok I've done it:

public class UrlHelperEx : UrlHelper
{
#region Constants
private const string c_VERSION_FORMAT = "{0}?v={1}";
#endregion

#region Initialization
public UrlHelperEx(RequestContext requestContext)
base(requestContext)
{
}
#endregion

#region Public methods
public new string Content(string contentPath)
{
var content = base.Content(contentPath);
Version version = WebHelper.GetVersion();
return string.Format(c_VERSION_FORMAT, content
, version.Build.ToString(
CultureInfo.InvariantCulture));
}
#endregion
}

Please, pay attention - I've used "new" key world for "Content" method.
Razor's view bases on "WebViewPage" and "WebViewPage<T>" classes. So I extended to use new "UrlHelper" class them.
public abstract class WebViewPageEx : WebViewPage
{
#region Properties
public new UrlHelperEx Url
{
get;
set;
}
#endregion

#region Public methods
public override void InitHelpers()
{
base.InitHelpers();
Url = new UrlHelperEx(ViewContext.RequestContext);
}
#endregion
}
public abstract class WebViewPageEx<T> : WebViewPage
{
#region Properties
public new UrlHelperEx Url
{
get;
set;
}
#endregion

#region Public methods
public override void InitHelpers()
{
base.InitHelpers();
Url = new UrlHelperEx(ViewContext.RequestContext);
}
#endregion
}
Pay attention - I've used "new" key  again. So I've replaced method and properties from base classes and I don't need to do any changes in my views.
Now I need to replace base classes for views in my project. How to do it I've found in the this great article - "Changing Base Type Of A Razor View". So I replaced next line in Web.config that is located in Views folder.

<pagespageBaseType="System.Web.Mvc.WebViewPage">
 
with 
<pagespageBaseType="MyNamespace.WebViewPageEx">
 
And version of current build is added to each CSS and JavaScript's url in my project now.
It was "pros" and now a few words about "cons". I have a lot of "default" CSS and JavaScript files. For instance of jQuery, third part components and so on. I don't change this files from build to build but they are updated after build. It is possible to implement some extra logic in "Content" method for skipping such files or use old school way adding url. for instance:


<link href="../../css/custom-theme/jquery-ui-1.8.5.custom.css" rel="...

But in my opinion it is whims and current implementation is enough.

PS: I'm pretty sure that it is possible to do something like for any view engines in ASP.NET MVC.

Viewing all articles
Browse latest Browse all 33

Trending Articles