4

嗨,我正在使用 mvc4 应用程序并使用包来呈现脚本和 css

以下是我创建捆绑包的方式:

bundles.Add( new StyleBundle( "~/Content/css" ).Include(
                    "~/Content/bootstrap/css/bootstrap.css",
                    "~/Content/bootstrap/css/bootstrap-responsive.css",
                    "~/Content/site.css" ) );

现在它像我在浏览器源代码中看到的那样生成这样的包:

<link href="/Content/css?v=8HZAB6C8ZnrIPYNFzMQKt0AR4AUsUYBjxPPkbGSRIZo1" rel="stylesheet">

我想要的是删除链接中版本的“v”查询字符串。

谢谢

4

4 回答 4

6

我为 mvc-bundling 创建了一个扩展,它使您能够将查询字符串部分移动到 url 内。它可以生成这样的网址

/bundles/css/20130315191550.css

/bundles/css/_NNIf4XxdPCITzjlKPMgZwHMSUsPyxxGaNCIe6mgAkg1

代码可在http://github.com/unger/Bundling.Extensions

也许这可以给你一些关于如何解决它的想法?

于 2013-10-03T20:29:42.203 回答
5

我最终做了以下事情:

BundleResolver首先我用这个实现改变了默认值

public class ReplaceQueryStringBundlerResolver : IBundleResolver
        {
            private readonly IBundleResolver _resolver;

            public ReplaceQueryStringBundlerResolver(IBundleResolver resolver)
            {
                _resolver = resolver;
            }

            public IEnumerable<string> GetBundleContents(string virtualPath)
            {
                return _resolver.GetBundleContents(virtualPath);
            }

            //The important part, modifies the generated Url
            public string GetBundleUrl(string virtualPath)
            {
                var bundleUrl = _resolver.GetBundleUrl(virtualPath);
                bundleUrl = bundleUrl.Replace("?v=", "/v/");
                return bundleUrl;
            }

            public bool IsBundleVirtualPath(string virtualPath)
            {
                return _resolver.IsBundleVirtualPath(virtualPath);
            }
        }

这可以像这样在RegisterBundles方法中注册。

 BundleResolver.Current = new ReplaceQueryStringBundlerResolver(BundleResolver.Current);

这基本上指示当前解析器使用我们需要的Url格式。

这个解决方案更好,因为我们不必更改Styles.RenderScripts.Render调用调用代码中的任何地方。

由于我们需要将这些新捆绑映射Urls到捆绑表,我尝试对当前的 Api 做类似的事情,但我无法让它工作,因此作为临时解决方案,我在 web.config 中添加了重写规则,以便我们可以重写/v/?v=. 理想情况下,优化模块应该这样做,因为重写规则限制我们遵循一些命名约定,而我的是所有包虚拟路径都应该以"~/bundles/"

<rule name="RewriteBundlesWithNoQueryStrings" stopProcessing="true">
  <match url="^bundles/(.*)/v/(.*)" />
  <action type="Rewrite" url="/bundles/{R:1}?v={R:2}" />
</rule>
<rule name="RewriteBundlesWithNoQueryStringsToDefault" stopProcessing="true">
  <match url="^bundles/(.*)/(.*)" />
  <action type="Rewrite" url="/bundles/{R:1}" />
</rule>

如果我可以在处理捆绑请求的类中挂钩某些东西BundleHandler,我会提出更新。

于 2016-07-26T14:43:51.833 回答
2

不,因为那时浏览器会缓存你的包的陈旧版本,因为该查询字符串是内容更改时的指纹。

我们的积压工作中确实有一个项目可以自定义指纹在 url 中的显示方式,但目前无法将其关闭。

一个简单的解决方法是显式地渲染出你的包的路径,因为如果你不想要查询字符串,这不会改变。

于 2013-01-10T18:53:56.510 回答
1

只需编写一个像这样的简单扩展:

public enum RenderType{Css, Js}
public static class _Extentions
{
    public static string RemoveQueryString(this IHtmlString _HtmlString, RenderType _RenderType){
        string Render = _HtmlString.ToHtmlString().Replace(Environment.NewLine, "").Replace("?v=", "/v/");
        Render = Render.Replace(_RenderType == RenderType.Css ? "\" rel=" : "\"></script>", _RenderType == RenderType.Css ? ".css\"  rel=" : ".js\"></script>");
        return Render;
    }      
}

并像这样使用url重写:

<rule name="rewrite css" enabled="true" stopProcessing="true">
<match url="^css/v/(.+).css"/>
<conditions logicalGrouping="MatchAll" trackAllCaptures="false"/>
<action type="Rewrite" url="/css?v={R:1}"/>
</rule> 
<rule name="rewrite js" enabled="true" stopProcessing="true">
<match url="^js/v/(.+).js"/>
<conditions logicalGrouping="MatchAll" trackAllCaptures="false"/>
<action type="Rewrite" url="/js?v={R:1}"/>
</rule> 

并以这种方式使用它:

<%=Styles.Render("~/css").RemoveQueryString(RenderType.Css)%>
<%=Scripts.Render("~/js").RemoveQueryString(RenderType.Js)%>

请注意,Render 函数中的虚拟路径和 url 重写中的虚拟路径必须匹配:

Scripts.Render("~/ js ").RemoveQueryString(RenderType.Js)

匹配 url="^ js /v/(.+).js"

于 2015-06-15T15:00:16.193 回答