在ASP.NET MVC中自动转换CSS/JS?

Tom*_*Tom 14 asp.net-mvc auto-versioning

所以我正在阅读这篇有关CSS/JS文件的ASP.NET MVC中"autoversioning"的stackoverflow帖子,并想知道"最佳"策略是做什么的.

提供的解决方案插入一个程序集编号 - 这意味着每次发布 - 它将更改每个单个文件,这是不理想的,因为如果您只修改1*.css或*.js,那么它将更改每个文件.

1)如何仅针对"单个文件"而不是使用IIS7上的修改日期或其他内容进行站点范围组装?

2)如果我有某种"静态"资产 - 例如http://static.domain.com/js/123.js - 如果有人集成了这个静态,如何使用重写来发送请求的最新文件链接到他们的网站?

http://static.domain.com/js/123.js是链接,当请求到来时 - 检查并发送最新文件?

Run*_*sen 19

我解决这个问题的方法是在AssemblyInfo.cs文件中添加autoversioning到我的MVC项目,如下所示:

Change
[assembly: AssemblyVersion("1.0.0.0")]
to    
[assembly: AssemblyVersion("1.0.*")]
Run Code Online (Sandbox Code Playgroud)

这意味着每次构建项目时,它都会有一个比前一个更高的新程序集版本.现在您拥有唯一的版本号.

然后我创建了一个UrlHelperExtension类,它可以帮助我在我的视图中需要它时获取这些信息:

public static class UrlHelperExtensions
{
    public static string ContentVersioned(this UrlHelper self, string contentPath)
    {
        string versionedContentPath = contentPath + "?v=" + Assembly.GetAssembly(typeof(UrlHelperExtensions)).GetName().Version.ToString();
        return self.Content(versionedContentPath);
    }
}
Run Code Online (Sandbox Code Playgroud)

您现在可以通过以下方式轻松地为视图添加版本号:

<link href="@Url.ContentVersioned("style.css")" rel="stylesheet" type="text/css" />
Run Code Online (Sandbox Code Playgroud)

查看页面源时,您现在可以看到类似的内容

<link href="style.css?v=1.0.4809.30029" rel="stylesheet" type="text/css" />
Run Code Online (Sandbox Code Playgroud)


Mil*_*ler 6

1)改为使用文件修改时间.这是一个例子:

public static string GeneratePathWithTime(string cssFileName)
{
  var serverFilePath = server.MapPath("~/static/" + cssFileName);
  var version = File.GetLastWriteTime(serverFilePath).ToString("yyyyMMddhhmmss");
  return string.Format("/static/{0}/{1}", version, cssFileName);
}
Run Code Online (Sandbox Code Playgroud)

这将为" /static/201109231100/style.css" 生成类似" " 的路径style.css(假设您style.css位于static目录中).然后,您将在IIS中添加重写规则以将" /static/201109231100/style.css" 重写为" /static/style.css".版本号仅在修改css文件时更改,并且仅适用于已修改的文件.

2)您可以通过HttpModule处理对123.js的请求并发送它的最新内容,但我认为您不能保证请求获得最新版本.这取决于浏览器如何处理其缓存.您可以在响应标头中设置较早的过期时间(例如,一分钟前),以告知浏览器始终重新下载文件,但是由浏览器本身决定是否重新下载文件.这就是为什么我们每次更新问题时都需要为修改后的文件生成不同的路径1),如果之前从未访问过URL,浏览器将始终尝试下载文件.

  • 您不需要在IIS中配置重写规则 - MVC导航支持**路由**! (3认同)

Ric*_*rno 6

更新:以前的版本在Azure上不起作用,我在下面进行了简化和更正.(注意,为了在IIS Express的开发模式下工作,您需要从Microsoft http://www.iis.net/downloads/microsoft/url-rewrite安装URL Rewrite 2.0 - 它使用WebPi安装程序,确保首先关闭Visual Studio)

如果您想更改文件的实际名称,而不是附加查询字符串(某些代理/浏览器会忽略静态文件)您可以按照以下步骤操作:(我知道这是一个旧帖子,但我跑了在开发解决方案时跨越它:

操作方法: 每次构建项目时自动增加程序集版本,并将该数字用于要保持刷新的特定资源上的路由静态文件.(所以something.js包含为something.v1234.js,每次构建项目时都会自动更改1234) - 我还添加了一些额外的功能,以确保在生产中使用.min.js文件并使用regular.js文件调试时(我正在使用WebGrease自动化缩小过程)这个解决方案的一个好处是它可以在本地/开发模式和生产中工作.(我使用的是Visual Studio 2015/Net 4.6,但我相信这也适用于早期版本.

步骤1:在构建时在程序集上启用自动增量在AssemblyInfo.cs文件中(位于项目的"属性"部分下面,更改以下行:

[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
Run Code Online (Sandbox Code Playgroud)

[assembly: AssemblyVersion("1.0.*")]
//[assembly: AssemblyFileVersion("1.0.0.0")]
Run Code Online (Sandbox Code Playgroud)

步骤2:在web.config中为具有嵌入式版本slugs的文件设置url重写(参见步骤3)

在web.config(项目的主要<system.webServer>部分)中,在我将其直接放在</httpProtocol>结束标记之后的部分中添加以下规则 .

<rewrite>
  <rules>
    <rule name="static-autoversion">
      <match url="^(.*)([.]v[0-9]+)([.](js|css))$" />
      <action type="Rewrite" url="{R:1}{R:3}" />
    </rule>
    <rule name="static-autoversion-min">
      <match url="^(.*)([.]v[0-9]+)([.]min[.](js|css))$" />
      <action type="Rewrite" url="{R:1}{R:3}" />
    </rule>
  </rules>
</rewrite>
Run Code Online (Sandbox Code Playgroud)

步骤3:设置应用程序变量以读取当前的程序集版本并在js和css文件中创建版本slug.

在Global.asax.cs(在项目的根目录中找到)中将以下代码添加到protected void Application_Start()(在Register行之后)

            // setup application variables to write versions in razor (including .min extension when not debugging)
            string addMin = ".min";
            if (System.Diagnostics.Debugger.IsAttached) { addMin = ""; }  // don't use minified files when executing locally
            Application["JSVer"] = "v" + System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString().Replace('.','0') + addMin + ".js";
            Application["CSSVer"] = "v" + System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString().Replace('.', '0') + addMin + ".css";
Run Code Online (Sandbox Code Playgroud)

第4步:使用我们在Global.asax.cs中设置的应用程序变量更改Razor视图中的src链接

@HttpContext.Current.Application["CSSVer"]
@HttpContext.Current.Application["JSVer"]
Run Code Online (Sandbox Code Playgroud)

例如,在我的_Layout.cshtml中,在我的head部分中,我有以下样式表代码块:

<!-- Load all stylesheets -->
<link rel='stylesheet' href='https://fontastic.s3.amazonaws.com/8NNKTYdfdJLQS3D4kHqhLT/icons.css' />
<link rel='stylesheet' href='/Content/css/main-small.@HttpContext.Current.Application["CSSVer"]' />
<link rel='stylesheet' media='(min-width: 700px)' href='/Content/css/medium.@HttpContext.Current.Application["CSSVer"]' />
<link rel='stylesheet' media='(min-width: 700px)' href='/Content/css/large.@HttpContext.Current.Application["CSSVer"]' />
@RenderSection("PageCSS", required: false)
Run Code Online (Sandbox Code Playgroud)

这里有几点需要注意:1)文件没有扩展名.2)也没有.min.这两个都由Global.asax.cs中的代码处理

同样,在我的javascript部分(也在_Layout.cs中):我有以下代码:

<script src="~/Scripts/all3bnd100.min.js" type="text/javascript"></script>
<script src="~/Scripts/ui.@HttpContext.Current.Application["JSVer"]" type="text/javascript"></script>
@RenderSection("scripts", required: false)
Run Code Online (Sandbox Code Playgroud)

第一个文件是我用WebGrease手动创建的所有第三方库的捆绑包.如果我添加或更改捆绑包中的任何文件(这是罕见的),那么我手动将文件重命名为all3bnd101.min.js,all3bnd102.min.js等...此文件与重写处理程序不匹配,所以将保留在客户端浏览器上的缓存,直到您手动重新捆绑/更改名称.

第二个文件是ui.js(根据你是否在调试模式下运行,将写为ui.v12345123.js或ui.v12345123.min.js)这将被处理/重写.(您可以在Global.asax.cs的Application_OnBeginRequest中设置断点以观察它的工作情况)

对此进行全面讨论:在ASP.NET MVC 5中简化自动版本的Javascript/CSS以停止缓存问题(在Azure和本地工作)有或没有URL重写 (包括一种不用URL重写的方法)