When your site grows in complexity, it makes sense to keep it maintainable by using components, such as partial views, DisplayTemplates and EditorTemplates.
You can solve this to some extent by using MVC areas, but those are used mainly to create sub-sites.
Dynamic Bundles is an extension of the Razor view engine and MVC bundles. It greatly improves maintainability and code reuse of ASP.NET MVC sites:
- Provides the same minification and file combining as standard MVC bundles.
Lets compare the file structure of a classic MVC site with one that uses Dynamic Bundles.
- Long brittle urls from CSS files to background images.
- The view engine included in Dynamic Bundles lets you put partial views and layout files in their own sub directories.
- Short simple image background image urls in your CSS.
- Co-locating all assets that make up a component makes reuse much easier.
Lets compare the way that bundles are created with a classic MVC site with one that uses Dynamic Bundles.
- You have to create and maintain bundles yourself.
- You have to make sure to include the correct files, and in the right order.
public static void RegisterBundles(BundleCollection bundles)
// Need to create bundles yourself, in code. To make any change,
// you have to recompile. Must always make sure to include the
// right files in the right order.
- Bundles are auto generated. No need to create bundles yourself.
- Optimizes client side caching, by combining files into bundles by area, controller, shared and layout.
public class BundleConfig
public static void RegisterBundles(BundleCollection bundles)
// No need to register bundles in BundleConfig
@*Nominate where to load the bundles.
The bundles themselves are automatically generated.*@
- Install Dynamic Bundles
- Add view engine to global.asax
- Add layout container
- Update Web.config for views
- Co-locate assets
- Create explicit dependencies
1. Install Dynamic Bundles
Install the DynamicBundles package from NuGet:
2. Add view engine to global.asax
Update your global.asax.cs or global.asax.vb, to add the DynamicBundles view engine:
public class MvcApplication : System.Web.HttpApplication
protected void Application_Start()
// Add DynamicBundles view engine. This functions the same as the Razor view engine,
// but can find views sitting in their own directories, such as ~/Views/Home/Index/Index.cshtml
// Note: this leaves the other view engines in place, so they can still be used.
3. Add layout container
In classic MVC sites, pages sit within a _Layout.cshtml or _Layout.vbhtml file, which contains shared headers, footers, etc.
To make this separation happen, create a new file _LayoutContainer.cshtml (you'll see the content in a moment). This and the _Layout.cshtml go into their own directory. The result looks like this:
Contents of _LayoutContainer.cshtml
@*Nominate where to load the bundles. The bundles themselves are automatically generated.*@
Changes to _Layout.cshtml
- Set Layout to _LayoutContainer.cshtml, which acts as the overall container of the site.
- Remove the doctype and html tags.
- Remove all style and script rendering, including rendering of script sections.
// Add _LayoutContainer as the container for the _Layout.cshtml file itself.
Layout = "../_LayoutContainer/_LayoutContainer.cshtml";
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
<title>Dynamic Bundles for ASP.NET MVC</title>
@RenderSection("scripts", required: false)
4. Update Web.config for views
In addition to the Web.config file in the root directory of your site, each MVC site also has a Web.config file in its Views directory. If your site uses areas, each area has a Views directory as well, with its own Web.config file.
The Web.config files in the Views directories need to be updated to:
- Install the Dynamic Bundles page base type. This gets each view to register the assets it needs, so bundles with the right files can be generated.
The BlockViewHandler blocks all requests. In classic MVC sites, it is used to block all requests for files from
we only want to block requests for the view files.
<!-- Replace path="*.cshtml" with path="*.vbhtml" if you use Visual Basic. -->
<add name="BlockViewHandler" path="*.cshtml" verb="*" preCondition="integratedMode" type="System.Web.HttpNotFoundHandler" />
5. Co-locate assets
- Move all assets that are shared throughout the site in the _LayoutContainer directory.
- Move all assets that are shared by all views for a controller into that controller's directory.
- If there are assets specific to a single view file, create a sub directory for that view file and put all assets (including the view itself) into that sub directory. Be sure to name the sub directory the same as the view file, without the extension.
- Dynamic Bundles will add both the assets in the sub directory and those in its parent directory(s), less specific assets first. In the example below, when /Product/List is loaded, first the assets in ~/Views/Product and then those in ~/Views/Product/List are added.
This works for both controller specific views and shared (partial) views. Dynamic Bundles makes sure that assets are only ever added once to a bundle.
6. Create explicit dependencies
You can specify these dependencies with .nuspec files. These have the same structure as their NuGet counterparts (definition).
If Dynamic Bundles finds a nuspec file in a directory, it will find the directories specified in that nuspec file and add the assets in those directories to the bundles. If those directories have nuspec files themselves, Dynamic Bundles processes those nuspec files as well, etc. This is a fully recurrent process.
To create a dependency from a directory X to some other directories, include a .nuspec file in directory X that looks like this:
<dependency id="../AccountDetailsAssets" />
<dependency id="~/Views/Shared/DetailsAssets" />
- The name of the .nuspec file doesn't matter, as long as it has the extension .nuspec.
- You can specify root relative paths (starting with ~/) and paths relative to the .nuspec file, but not absolute paths (such as C:\Dev\Views\Accounts).