Archive
HowTo: Reset browser cache of CSS files upon ASP.net MVC app publish
On an ASP.net MVC webapp I’m maintaining, I had the issue that due to caching of older CSS (stylesheet) files in the browser, if the user didn’t press F5/refresh, it wasn’t showing you some message (since I had added the class .center-horiz-vert in the CSS that didn’t exist in the older cached css the browser had).
Instead of changing web.config to stop cachine of CSS files (in which case it would bring the CSS on every page load which is an overkill), I expanded on an idea mentioned by Maxim Kornilov on SO (https://stackoverflow.com/a/12992813/903783), on making the CSS URLs webapp version specific.
I added a fake version parameter to the URLs with the build number as value so that till I publish a new build the browser caches the CSS, but when I upload a new build it brings the new one since it cache with the url as a key (that now includes the build number as a dummy url parameter that the webserver will ignore and just fetch the CSS file when requested)
Maxim’s example was in ASP/ASP.net WebForms syntax instead of MVC’s and Razor Pages’ newer Razor syntax), so I contributed my solution for the case of an ASP.net MVC webapp that wants to serve a fresh copy of CSS files on every new build that you publish (will do this whether the CSS file has changed or not) so that browsers don’t use older cached copies of the file. Obviously this expands to any kind of files you link/load into your webpages via a URL.
1) Added to the webapp’s main class (was called MvcApplication) in Global.asax.cs
#region Versioning
public static string Version =>
typeof(MvcApplication).Assembly.GetName().Version.ToString();
//note: syntax requires C# version >=6
public static DateTime LastUpdated =>
File.GetLastWriteTime(typeof(MvcApplication).Assembly.Location);
#endregion
the someProperty => someReadOnlyExpression syntax is just shorthand for someProperty { get { return … ;} } possible since C# 6
2) in its Content/_Layout.cshtml file I used to have the following to show build number and build datetime (based on the webapp’s main assembly) on the page footer:
Version @ViewContext.Controller.GetType().Assembly.GetName().Version
(@string.Format("{0:yyyy/MM/dd-HH:mm:ss}",
@File.GetLastWriteTime(ViewContext.Controller.GetType().Assembly.Location)))
which I changed to the simpler:
Version @somewebappname.MvcApplication.Version
(@string.Format("{0:yyyy/MM/dd-HH:mm:ss}",
somewebappname.MvcApplication.LastUpdated))
3) it was loading the CSS via hardcoded link in _Layout.cshtml (still refactoring it) which I changed to:
<link href='@Url.Content("~/Content/Site.css?version=" +
somewebappname.MvcApplication.Version)' rel="stylesheet" type="text/css" />
so if one right-clicks in the webpage and they do view source they see:
<link href='/Content/Site.css?version=2.1.5435.22633'
rel="stylesheet" type="text/css" />
that is the CSS url is version specific thanks to the dummy parameter version
If a random number was used instead it would fetch the CSS at every page load which is usually undesired, especially if you are already pushing a new webapp build instead of individual page changes to the web server (so that you do have access to a build number that you can inject into URLs).
Note that to achieve auto-incrementing of build number, at Properties/AssemblyInfo.cs I have (see How to have an auto incrementing version number (Visual Studio)?):
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Revision
// and Build Numbers by using the '*' as shown below:
[assembly: AssemblyVersion("1.0.*")]
//[assembly: AssemblyFileVersion("1.0.*")]
// don't use boh AssemblyVersion and AssemblyFileVersion with auto-increment
HowTo: Display version information on WinForm title
This is my contribution to
http://stackoverflow.com/questions/7178725/version-number-in-winform-form-text
I’m using the following at the WinForm of the WebCapture tool I’m making for ClipFlair:
public MainForm()
{
InitializeComponent();
Version version = Assembly.GetExecutingAssembly().GetName().Version;
Text = Text + " " + version.Major + "." + version.Minor +
" (build " + version.Build + ")"; //change form title
}
Not showing revision number to the user, build number is enough technical info
Make sure your AssemblyInfo.cs ends in the following (remove the version it has there by default) for VisualStudio to autoincrement build and revision number. You have to update major and minor versions yourself at every release (update major version for new features, minor version when you do just fixes):
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build
// and Revision Number by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.*")]
Update: Since now WebCapture is ClickOnce-deployed from the web (also has nice autoupdate support thanks to ClickOnce) and I want to avoid user confusion by showing the published version of the app (as the ClickOnce installation page does) on the WinForm titlebar, I now use the following code instead, based on a relevant post I found on the web:
public MainForm()
{InitializeComponent();
ShowVersion();
}
private void ShowVersion()
{Version version = (ApplicationDeployment.IsNetworkDeployed)?
ApplicationDeployment.CurrentDeployment.CurrentVersion :Assembly.GetExecutingAssembly().GetName().Version;
//if network deployed show published version (as the web install page)
Text = Text + " " + version.Major + "." + version.Minor + "."+ version.Build + "." + version.Revision;
//change form title
}
BTW, speaking of ClickOnce, I noticed that if at the autoupdate dialog shown when you launch the app from its desktop shortcut (and there’s a new version available) you press “Skip”, it won’t offer you this update anymore when you launch an app (I hope that when an even newer update is there it will prompt you), but you can override that behaviour by going to the installation page for your ClickOnce app (where you installed it from in the first place) and press the “Install” button there.