返回
ASP.NET MVC4/5实现asp-append-version为css/js带上版本号
2022-12-23
1599 0.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就不会变化了。
您可能感兴趣:
网友点评
提交
相关阅读
.NET Core记录请求处理时间的中间件
如何在传统MVC网站使用react
ASP.NET MVC View视图 .cshtml文件中创建方法
ASP.NET Core 使用Razor code blocks替代@helper
IL源码解读,理解MVC里面Filter这个AOP的实现原理
EF Core在非MVC项目中需要手动释放吗?
Asp.Net Core进程内托管 和 进程外托管的区别
.NET6 AutoFac在非MVC中的用法
ASP.NET Core微服务架构中使用RabbitMQ实现CQRS模式
MVC跨域问题 Response for preflight has invalid HTTP status code 405