Skip to content

Instantly share code, notes, and snippets.

@RichardD2
Created February 5, 2021 08:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save RichardD2/00b1a4f1c1d3e55dc565a7d764d79bfe to your computer and use it in GitHub Desktop.
Save RichardD2/00b1a4f1c1d3e55dc565a7d764d79bfe to your computer and use it in GitHub Desktop.
UrlHelper extension to append a timestamp to a CSS / JS URL
using System;
using System.IO;
using System.Linq;
using System.Web;
using System.Web.Caching;
using System.Web.Hosting;
using System.Web.Mvc;
namespace NBS.Core.Web.Mvc
{
public static class UrlHelperExtensions
{
private const string CachePrefix = "NBS:Fingerprint:";
public static string AppendTimestamp(this UrlHelper url, string rootRelativePath)
{
if (url is null) throw new ArgumentNullException(nameof(url));
if (string.IsNullOrWhiteSpace(rootRelativePath)) return string.Empty;
string cacheKey = CachePrefix + rootRelativePath;
if (!(HttpRuntime.Cache[cacheKey] is string result))
{
string virtualPath = url.Content(rootRelativePath);
string minPath = url.RequestContext.HttpContext.IsDebuggingEnabled ? null : GetMinPath(virtualPath);
result = AppendTimestampCore(minPath, out var absolutePath)
?? AppendTimestampCore(virtualPath, out absolutePath)
?? virtualPath;
if (absolutePath != null)
{
HttpRuntime.Cache.Insert(cacheKey, result, new CacheDependency(absolutePath));
}
}
return result;
}
private static string GetMinPath(string virtualPath)
{
int extensionIndex = virtualPath.LastIndexOf('.');
if (extensionIndex == -1) return null;
if (4 < extensionIndex
&& virtualPath[extensionIndex - 4] == '.'
&& virtualPath[extensionIndex - 3].IsOneOf('M', 'm')
&& virtualPath[extensionIndex - 2].IsOneOf('I', 'i')
&& virtualPath[extensionIndex - 1].IsOneOf('N', 'n'))
{
return null;
}
return virtualPath.Insert(extensionIndex, ".min");
}
private static bool IsOneOf(this char c, [NotNull] params char[] values) => values.Any(v => v == c);
private static string AppendTimestampCore(string virtualPath, out string absolutePath)
{
if (string.IsNullOrWhiteSpace(virtualPath))
{
absolutePath = null;
return null;
}
absolutePath = HostingEnvironment.MapPath(virtualPath);
if (string.IsNullOrWhiteSpace(absolutePath)) return null;
string sep = virtualPath.IndexOf('?') == -1 ? "?v=" : "&v=";
DateTime lastWriteTime = File.GetLastAccessTimeUtc(absolutePath);
return virtualPath + sep + lastWriteTime.Ticks.ToString("x");
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment