Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to bundle resources for ASP.NET MVC areas?

Tags:

How would you do the resource bundling for asp.net mvc areas? Is this regulated by the ASP.NET MVC framework just like the AreaRegistration for routes?

I could make a BundleConfig class inside the area and call this from the global BundleConfig inside the App_Start folder but this doens't feel good to me.

I can't find any information on this subject. Any help our thoughts are appreciated.

like image 490
Martijn B Avatar asked Nov 11 '12 21:11

Martijn B


People also ask

How do we implement bundling in MVC?

To enable bundling and minification, set the debug value to "false". You can override the Web. config setting with the EnableOptimizations property on the BundleTable class. The following code enables bundling and minification and overrides any setting in the Web.

Can you explain MVC bundling?

Bundling and Minification are two performance improvement techniques that improves the request load time of the application. Most of the current major browsers limit the number of simultaneous connections per hostname to six. It means that at a time, all the additional requests will be queued by the browser.

What are the different ways for bundling and minification in asp net core?

Bundling and minification are two techniques you can use in ASP.NET to improve page load performance for your web application. Bundling combines multiple files into a single file. Minification performs a variety of different code optimizations to scripts and CSS, which results in smaller payloads.

How does bundling increase performance in MVC?

The bundling reduces the number of requests to the Server, while the minification reduces the size of the requested assets. Most browsers process six requests simultaneously to each Website, which is why additional requests will be queued by the Browsers.


2 Answers

I was hoping this was somehow more regulated - but after diving into the framework code the answer to this is negative.

What I decided to do is the following:

Solution Structure

  • Areas:
    • Admin
      • 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);                 }        } 
like image 55
Martijn B Avatar answered Nov 04 '22 02:11

Martijn B


Your question implies that you have separate scripts & css folders for each area? This is unconventional (though perfectly plausible). Or perhaps you have a single scripts folder at the route level and you have split that into sub folders for each Area? Either way you will have to do something only slightly different to get Area specific bundles.

MVC4 applications come with a static BundleConfig class that lives in the App_Start folder. The bundle is then initialized from the Global.asax. If you are not working with a MVC4 project either upgrade or just start an out of the box MVC4 project to observe the layout of these files.

Bundles are configured simply by declaring a virtual path, (from which the bundle can be referenced) then specifying the files you wish to be bundled. The files to be bundled can be specified by listing the filename explicitly, filename character matching, or specifying a directory in which all files should be included.

To begin with, I would just use this global BundleConfig to specify bundles for all of your areas. If this does not scale for you or becomes unwieldy, you can always break it out later.

Specify which files should be included. You should prefix the bundle's virtual path with the Area that it is for. Then it will be easy to reference using the Area name from your views - most likely your _Layout.cshtml.

For example, here we have two Areas each with distinct scripts: User and Group.

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"));     } } 

You can then use the Scripts.Render() on your main _Layout.cshtml to render the correct Area bundle, depending on which area the user is currently viewing. To do this you first need to get the current Area like so:

Views/Shared/_Layout.cshtml:

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

EDIT

If you really want to manage your bundle from within your Area, then the Area registration would be a good place to do so. The BundleTable static property referenced in the BundleConfig is global so it can be referenced anywhere. This code compiles but I haven't tested it. It is for an Area called 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"));     } 
like image 23
Nick Avatar answered Nov 04 '22 02:11

Nick