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

时间:2012-05-16 08:11:09

标签: asp.net asp.net-mvc-4 optimization bundle asp.net-optimization

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

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

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

提前致谢!

3 个答案:

答案 0 :(得分: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);

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

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

注意:我正在使用位于here的system.web.optimization(现在是Microsoft.AspNet.Web.Optimization)的最新nuget软件包。关于它,Scott Hanselman有一个很好的post

答案 1 :(得分: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;
    }

使用

〜/视图/主页/ 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()}
}}

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

并在Appp_Start中注册它们

答案 2 :(得分:5)

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