如何为ASP.NET MVC区域捆绑资源?

21

如何为asp.net mvc区域进行资源捆绑?这是否像路由的AreaRegistration一样由ASP.NET MVC框架来管理?

我可以在区域内创建一个BundleConfig类,并从全局App_Start文件夹中调用它,但这让我感觉不好。

我找不到任何关于这个问题的信息。任何帮助或想法都将不胜感激。

2个回答

37

我原本希望这个问题得到更好的规范 - 但在深入研究框架代码后,答案是否定的。

我决定采取以下措施:

解决方案结构

  • 区域:
    • 管理者
      • RouteConfig.cs
      • BundleConfig.cs
      • AdminAreaRegistration.cs

RouteConfig.cs

internal static class RouteConfig
{
    internal static void RegisterRoutes(AreaRegistrationContext context)
    {
        //add routes
    }
}

BundleConfig.cs

internal static class BundleConfig
{
    internal static void RegisterBundles(BundleCollection bundles)
    {           
        //add bundles
    }
}

AdminAreaRegistration.cs

public class AdminAreaRegistration : AreaRegistration
{
    public override string AreaName
    {
        get
        {
            return "Admin";
        }
    }

    public override void RegisterArea(AreaRegistrationContext context)
    {
        RegisterRoutes(context);
        RegisterBundles();
    }

    private void RegisterRoutes(AreaRegistrationContext context)
    {
        RouteConfig.RegisterRoutes(context);
    }

    private void RegisterBundles()
    {
        BundleConfig.RegisterBundles(BundleTable.Bundles);            
    }       
}

24

您的问题暗示着您为每个区域有单独的脚本和CSS文件夹?这是不寻常的(但完全可行)。或者您在路由级别有一个单独的脚本文件夹,并将其拆分为每个区域的子文件夹?无论哪种方式,您都需要做一些微不足道的事情来获取特定于区域的包。

MVC4应用程序配备了一个静态的BundleConfig类,该类位于App_Start文件夹中。然后从Global.asax初始化捆绑包。如果您不使用MVC4项目,则升级或只需启动MVC4项目以观察这些文件的布局。

通过声明虚拟路径(从中可以引用捆绑包),然后指定要捆绑的文件来简单配置捆绑包。要捆绑的文件可以通过显式列出文件名、文件名字符匹配或指定包含所有文件的目录来指定。

首先,我会使用这个全局的BundleConfig来为您所有的区域指定包。如果这对您来说不可扩展或变得笨重,您随时可以稍后再进行拆分。

指定要包括哪些文件。您应该在捆绑包的虚拟路径前缀中加上它所属的区域。然后,可以在视图中使用该区域名称轻松引用它 - 最有可能是_Layout.cshtml

例如,这里有两个具有不同脚本的区域:UserGroup

App_Start/BundleConfig.cs

public class BundleConfig
{
    public static void RegisterBundles(BundleCollection bundles)
    {
        /// Bundle For User Area
        bundles.Add(new ScriptBundle("~/user/bundles/scripts").Include(
                    "~/Scripts/User/myuserscript1.js",
                    "~/Scripts/User/myuserscript2.js"));

        /// Bundle For Group Area
        bundles.Add(new ScriptBundle("~/group/bundles/scripts").Include(
                    "~/Scripts/Group/mygroupscript1.js",
                    "~/Scripts/Group/mygroupscript2.js"));
    }
}

您随后可以在主要的_Layout.cshtml上使用Scripts.Render()来呈现正确的区域绑定包,具体取决于用户当前正在查看哪个区域。要做到这一点,您首先需要获取当前的区域,如下所示:

Views/Shared/_Layout.cshtml:

<head>
    @{
        var currentArea = (ViewContext.RouteData.DataTokens["area"]
                              ?? String.Empty).ToString().ToLower();
    }
    @Scripts.Render("~/" + currentArea + "/bundles/scripts")
</head>

编辑

如果您真的希望在您的区域内管理捆绑包,那么区域注册可能是一个很好的地方。在BundleConfig中引用的BundleTable静态属性是全局的,因此可以在任何地方引用它。这段代码可以编译,但我还没有测试过。它是针对一个名为Test的区域的:

Areas/Test/TestAreaRegistration.cs

    public override void RegisterArea(AreaRegistrationContext context)
    {
        context.MapRoute(
            "Test_default",
            "Test/{controller}/{action}/{id}",
            new { action = "Index", id = UrlParameter.Optional }
        );

        BundleTable.Bundles.Add(new Bundle("~/test/bundles/scripts").Include(
                    "~/Areas/Test/Scripts/jquery.js"));
    }

谢谢您的回答,但这不是我想要的。我不想使用全局BundleConfig来为区域进行绑定。我还没有决定将CSS和JS资源放在哪个区域。这与放置捆绑配置的责任的位置是一个独立的问题。我更倾向于将CSS和JS资源放在区域本身内,这对我来说更自然。再次感谢! - Martijn B
我已经更新了答案,并尝试在区域命名空间内配置一个包(bundle)。 - Nick
+1 你的编辑。我决定采用我自己答案中的解决方案。这个解决方案或多或少相同,但它不违反SRP(单一职责原则)。 - Martijn B
我更喜欢这个答案(编辑版)。我已经尝试了两天不同的方法。最终这个解决了我的问题。在我的情况下,除了TestAreaRegistration.cs中的BundleTable之外,我还必须将(test)添加到_Layout.cshtml文件中的@Styles.Render("~/test/Content/css")。谢谢。 - reaz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接