在MVC 4中运行时动态捆绑和缩小

Cyr*_*rom 18 asp.net optimization bundle asp.net-mvc-4 asp.net-optimization

我想知道是否有人可以帮助我使用MVC 4附带的新优化命名空间进行捆绑和缩小.我有一个Multitenant应用程序,我想根据每个用户的设置决定应该加载哪些js文件.一种方法是预先创建所有捆绑包并根据用户的设置更改resolvebundleurl的虚拟路径,但这感觉不是真正正确的方式.另外,我在基于用户设置的cshtml视图中有动态css,我想在运行时缩小它.

有什么建议?在其他问题中我也看到很多反应来检查Requestreduce,但它们都来自同一个用户.

处理这两种情况的最佳方法是什么?

提前致谢!

Jay*_*k84 12

您可以采取的一种方法是在应用程序启动时动态构建捆绑包.因此,如果您的脚本位于~/scripts您可以执行以下操作:

Bundle bundle = new Bundle("~/scripts/js", new JsMinify());

if (includeJquery == true) {     
  bundle.IncludeDirectory("~/scripts", "jquery-*");
  bundle.IncludeDirectory("~/scripts", "jquery-ui*");
} 

if (includeAwesomenes == true) {
  bundle.IncludeDirectory("~/scripts", "awesomeness.js");
}

BundleTable.Bundles.Add(bundle);
Run Code Online (Sandbox Code Playgroud)

然后你的标记看起来像这样

@Scripts.Render("~/Scripts/Libs/js")

注意:我正在使用位于此处的 system.web.optimization(现为Microsoft.AspNet.Web.Optimization)的最新nuget包.斯科特汉塞尔曼有一个很好的帖子.


Ste*_*ong 8

我写了一个辅助函数来动态缩小我的css和js

    public static IHtmlString RenderStyles(this HtmlHelper helper, params string[] additionalPaths)
    {
        var page = helper.ViewDataContainer as WebPageExecutingBase;
        if (page != null && page.VirtualPath.StartsWith("~/"))
        {
            var virtualPath = "~/bundles" + page.VirtualPath.Substring(1);
            if (BundleTable.Bundles.GetBundleFor(virtualPath) == null)
            {
                var defaultPath = page.VirtualPath + ".css";
                BundleTable.Bundles.Add(new StyleBundle(virtualPath).Include(defaultPath).Include(additionalPaths));
            }
            return MvcHtmlString.Create(@"<link href=""" + HttpUtility.HtmlAttributeEncode(BundleTable.Bundles.ResolveBundleUrl(virtualPath)) + @""" rel=""stylesheet""/>");
        }
        return MvcHtmlString.Empty;
    }

    public static IHtmlString RenderScripts(this HtmlHelper helper, params string[] additionalPaths)
    {
        var page = helper.ViewDataContainer as WebPageExecutingBase;
        if (page != null && page.VirtualPath.StartsWith("~/"))
        {
            var virtualPath = "~/bundles" + page.VirtualPath.Substring(1);
            if (BundleTable.Bundles.GetBundleFor(virtualPath) == null)
            {
                var defaultPath = page.VirtualPath + ".js";
                BundleTable.Bundles.Add(new ScriptBundle(virtualPath).Include(defaultPath).Include(additionalPaths));
            }
            return MvcHtmlString.Create(@"<script src=""" + HttpUtility.HtmlAttributeEncode(BundleTable.Bundles.ResolveBundleUrl(virtualPath)) + @"""></script>");
        }
        return MvcHtmlString.Empty;
    }
Run Code Online (Sandbox Code Playgroud)

用法

〜/视图/主页/ Test1.cshtml

〜/浏览/首页/ Test1.cshtml.css

〜/浏览/首页/ Test1.cshtml.js

在Test1.cshtml中

@model object
@{
   // init
}@{

}@section MainContent {
  {<div>@{
     if ("work" != "fun")
     {
        {<hr/>}
     }
  }</div>}
}@{

}@section Scripts {@{
  {@Html.RenderScripts()}
}@{

}@section Styles {@{
  {@Html.RenderStyles()}
}}
Run Code Online (Sandbox Code Playgroud)

但是ofcoz,我把大部分的sripts,样式放在〜/ Scripts/.js,〜/ Content / .css中

并在Appp_Start中注册它们

  • 我喜欢这个解决方案,因为它允许您从 cshtml 文件动态创建包。它不假设您的 cshtml 文件是静态的,并且您提前知道您想要的包。 (2认同)

Hao*_*ung 5

我们在早期考虑过支持动态捆绑,但这种方法的根本问题是多服务器方案(即云)不起作用.如果未预先定义所有捆绑包,则发送到与提供页面请求的服务器不同的服务器的任何捆绑包请求将得到404响应(因为捆绑包定义将仅存在于处理页面请求的服务器上).因此,我建议事先创建所有捆绑包,这是主线方案.捆绑包的动态配置也可以起作用,但这不是完全支持的方案.