简体   繁体   English

自动添加版本到asp.net头内的js文件runat =“server”

[英]Automatically add version to js files inside asp.net header runat=“server”

I'm trying to reload reviewed css/js files automatically to prevent cache. 我正在尝试自动重新加载已审核的css / js文件以防止缓存。 I can loop trough header (which is runat="server") and add a value to link href references but the loop doesn't catch script tags as controls. 我可以循环通过标题(这是runat =“server”)并添加一个值来链接href引用,但循环不会捕获脚本标记作为控件。

if (Page.Header != null)
{
    foreach (var sc in Page.Header.Controls)
    {
        var type = sc.GetType();

        if (type == typeof(HtmlLink))
        {
            ((HtmlLink)sc).Href += "?v=" + Tools.BuildDate();
        }
        else if (type == typeof(HtmlGenericControl))
        {
            ((HtmlGenericControl)sc).Attributes["src"] += "?v=" + Tools.BuildDate();
        }
    }
}

I've tried to add runat="server" to script tags but in this way asp.net tries to compile those files and build fails. 我试图将runat =“server”添加到脚本标签,但这样asp.net尝试编译这些文件并构建失败。 I cannot add version every time because the project has many files. 我不能每次都添加版本因为项目有很多文件。 Also code blocks is not allowed when runat="server" is applied. 当应用runat =“server”时,也不允许使用代码块。

I want to use a commonly accepted solution so I don't have to worry for css/js file versions any more. 我想使用一个普遍接受的解决方案,所以我不必再担心css / js文件版本了。

In MVC Core 1.0 there is a tag helper for this exact purpose. 在MVC Core 1.0中,有一个用于此目的的标记帮助程序。 If you are using a different version of MVC then the previous answers should help. 如果您使用的是不同版本的MVC,那么以前的答案应该有所帮助。

<link rel="stylesheet" src="wherever.css" asp-append-version="true" />

A script tag is not going to be picked up as a Control, so you need to wrap it in a custom control if you want to handle it in the controller. script标记不会被选为控件,因此如果要在控制器中处理script标记,则需要将其包装在自定义控件中。 Or you could just add the timestamp directly in the view: 或者您可以直接在视图中添加时间戳:

<script type="text/javascript" src="path/to/file.js?v=<%= Tools.BuildDate() %>" />

Here is some more info: http://madskristensen.net/post/cache-busting-in-aspnet 以下是一些更多信息: http//madskristensen.net/post/cache-busting-in-aspnet

This should do 这应该做

<script src="ScriptsFolder/ScriptFile.js?v=<%=Tools.BuildDate() %>"></script>
<link href="StylesFolder/StyleFile.css?v=<%= Tools.BuildDate() %>" rel="stylesheet" />

When the value returned by Tools.BuildDate() changes, the browser will be forced to reload the script/style file since the resource url will have changed eg from url/ScriptsFolder/ScriptFile.js?v=1234 to url/ScriptsFolder/ScriptFile.js?v=5678. 当Tools.BuildDate()返回的值发生变化时,浏览器将被强制重新加载脚本/样式文件,因为资源URL已经更改,例如从url / ScriptsFolder / ScriptFile.js?v = 1234更改为url / ScriptsFolder / ScriptFile .js文件?v = 5678。 This by far should be the simplest and fastest solution, since it will only be appending the query string v=value to the resource url. 到目前为止,这应该是最简单和最快速的解决方案,因为它只会将查询字符串v = value附加到资源URL。 The appended querystring will completely be ignored by the server when fetching the resource specified. 获取指定的资源时,服务器将完全忽略附加的查询字符串。

Without knowing what ver of ASP.NET (or MVC) you are using, I can give you an easy way. 如果不知道你使用的是什么版本的ASP.NET(或MVC),我可以给你一个简单的方法。 You can always build a "helper" to do the heavy lifting for you. 你总是可以建立一个“帮手”来为你做繁重的工作。 This is the way that MVC and ASP.NET 5 helpers handle it, but will work with just about any version. 这是MVC和ASP.NET 5帮助程序处理它的方式,但几乎可以使用任何版本。 I generally don't prefer inline code, but a static helper can be made safe to protect against runtime errors. 我通常不喜欢内联代码,但可以使静态帮助程序安全,以防止运行时错误。

First build a static helper utility: 首先构建一个静态帮助器实用程序:

public static class ScriptHelper
{
    public static IHtmlString Render(params string[] paths)
    {
        return RenderFormat(DefaultTagFormat, paths);
    }

    public static IHtmlString RenderFormat(string tagFormat, params string[] paths)
    {
        if (string.IsNullOrEmpty(tagFormat))
        {
            throw new ArgumentException("Tag Format cannot be null");
        }
        if (paths == null)
        {
            throw new ArgumentNullException("Paths cannot be empty");
        }
        if (paths.Any(string.IsNullOrEmpty))
        {
            throw new ArgumentException("paths");
        }
        return BuildHtml(tagFormat, paths);
    }

    private static string defaultFormat = "<script src=\"{0}?ver={1}\"></script>";

    public static string DefaultTagFormat
    {
        get
        {
            return defaultFormat;
        }
        set { defaultFormat = value; }
    }

    private static IHtmlString BuildHtml(string tagFormat, params string[] paths)
    {
        StringBuilder builder = new StringBuilder();
        foreach (string path in paths)
        {
            StringBuilder builder = new StringBuilder();
        foreach (string path in paths)
        {
            // Substitute your logic for version number
            var version = "1234";
            // You could factory this to a concrete type based on file extension etc.
            var fileToOutPut = new VersionedJsFile(path,version,tagFormat);
            builder.Append(fileToOutPut.RenderOutput());
            builder.Append(Environment.NewLine);
        }
        return new HtmlString(builder.ToString());
    }

}

You can add extra logic to wrap around the path, validation of path, virtual paths, etc. Best to create an object with a render method that you can pass in the path (from the helper) and the version. 您可以添加额外的逻辑来包裹路径,验证路径,虚拟路径等。最好使用可以在路径(来自帮助程序)和版本中传递的render方法创建对象。 This is the oop way to do it and is more flexible. 这是完成它的oop方式,并且更灵活。 Doing that you can then have this be a "VersionHelper" instead and have it deal with css/js/etc. 这样你就可以把它变成一个“VersionHelper”而让它处理css / js / etc.

 internal abstract class HtmlFile
{
    public abstract string RenderOutput();
}

internal class VersionedJsFile : HtmlFile
{

    private string _version;
    private string _path;
    private string _format;
    public VersionedJsFile(
        string path, 
        string version,
        string format)
    {
        if (version != null) _version = version;
        if (path != null) _path = path;
        if(!string.IsNullOrEmpty(format))
            _format = format;
    }

    public override string RenderOutput()
    {
        if (!string.IsNullOrEmpty(_path)
            && !string.IsNullOrEmpty(_format))
        {
            string versionedFilePath = string.Format(_format, _path, _version);
            return versionedFilePath;

        }
        return string.Empty;
    }
}

Then add the helper to your page/master page/layout: 然后将帮助器添加到页面/母版页/布局中:

 <%: ScriptHelper.Render("/scripts/bootstrap.js") %>

As you can see, the helper takes a params object so you can apply to multiple files at once. 如您所见,帮助程序使用params对象,因此您可以同时应用于多个文件。

Output: 输出:

<script src="/scripts/bootstrap.js?ver=1234"></script>

The helper can easily be enhanced. 帮手很容易增强。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM