雷达智富

首页 > 内容 > 程序笔记 > 正文

程序笔记

ASP.NET MVC4/5实现asp-append-version为css/js带上版本号

2024-10-13 35

.NET Core MVC/Razor Page中使用TagHelpers的asp-append-version属性就可以为css或者js文件加上版本号。

例如:

<link rel="stylesheet" href="~/css/site.min.css" asp-append-version="true" />

这样输出的Html是这样的:

<link rel="stylesheet" href="/css/site.min.css?v=vSLTk9NafLa61jo5ciF5mRO-U6T-lyeecxK1dVwqCQQ" />

我们可以查看LinkTagHelper的源代码,它是通过FileVersionProvider读取文件,使用SHA256算法计算文件内容的哈希值然后它将对其进行url编码并将其添加到url上。

只有在文件更改时才会重新计算哈希值 ,因为它会添加到缓存中,但具有基于文件观察程序的过期触发器。这里可以看到使用的版本号并不是程序编译后的版本号,而是基于资源文件的内容的。

根据FileVersionProvider的当前实现可以看到,只有url是站内相对路径,才会实现append version,如果是一个远程地址url则不会添加哈希值。

可是在MVC4/5中没有这样的TagHelpers,虽然从MVC4开始推荐使用BundleConfig把资源文件捆绑输出,但是我们可以参考.NET Core asp-append-version的原理自己在ASP.NET MVC4/5中实现这个功能。

我们可以在程序启动的时候读取文件获得哈希值,把它放在缓存里。然后在引用样式或者JS的时候append到url后面。代码如下:

// UrlHelper扩展方法
public static string Version(this UrlHelper me, string path) {
    if (string.IsNullOrWhiteSpace(path))
        return path;
    var hash = GetVersion(path);
    if (string.IsNullOrWhiteSpace(hash))
        return path;
    path = path += "?v=" + HttpUtility.UrlEncode(hash);
    return path;
}
// 获取Version,并写入Cache
private static string GetVersion(string path) {
    var cache = HttpRuntime.Cache.Get(path);
    if (cache != null) 
        return cache.ToString();
    var hash = GetSHA256HashFromString(path);
    HttpRuntime.Cache.Insert(path, hash);
    return hash;
}
// 获取文件SHA256 hash value
private static string GetSHA256HashFromString(string path)
{
    var file = AppDomain.CurrentDomain.BaseDirectory + path;
    if (File.Exists(file))
    {
        var bytes = File.ReadAllBytes(file);
        var sha256 = new SHA256CryptoServiceProvider();
        var hash = sha256.ComputeHash(bytes);
        var sb = new StringBuilder();
        for (int i = 0; i < hash.Length; i++)
        {
            sb.Append(hash[i].ToString("x2"));
        }
        return sb.ToString();
    }
    return string.Empty;
}

在视图上这样引用:

@using 扩展方法所在命名空间

<link rel="stylesheet" href="@Url.Version("/Static/Style/main.css")" />

这里只是示例代码,实际使用还要考虑优化一下,比如url本身是带参数的,读取文件失败等情况也要处理一下。

这样只要文件没有修改,他的version就不会变化了。

更新于:1个月前
赞一波!

文章评论

评论问答