4

I have some pages on my site that use certain CSS and JS resources - but they are the only page(s) to use that css or js file - so I don't want to include that CSS and JS reference in every page. Rather than modify each View to reference the CSS/JS it needs, I thought I could create a bundle in the Controller and add it to the Bundles that are already registered, and then it would be included in the bundle references, but this does not appear to be possible, or maybe I'm just going about it the wrong way.

In my Controller for a registration page for example, I thought I could write this:

Bundle styleBundle = new Bundle("~/bundles/registrationStyleBundle");
styleBundle.Include("~/Content/Themes/Default/registration.css");
BundleTable.Bundles.Add(styleBundle);

And then have this in my /Views/Shared/_Layout.cshtml:

@foreach(Bundle b in BundleTable.Bundles)
 {
     if (b is StyleBundle)
     {
            <link href="@BundleTable.Bundles.ResolveBundleUrl(b.Path)" rel="stylesheet" type="text/css" />
     }
     else if (b is ScriptBundle)
     {
            <script src="@BundleTable.Bundles.ResolveBundleUrl(b.Path)" type="text/javascript"></script>
     }
 }

But this does not work - the only bundles to get rendered to my page end up being the ones I specified in RegisterBundles (in /App_Start/BundleConfig.cs)

Any idea how to achieve this kind of "dynamic" or "runtime" bundling?

EDIT: Following Jasen's advice, what I ended up doing was taking the bundle creation/registration code out of the controller and adding it to RegisterBundles() in /App_Start/BundleConfig.cs. This way, the bundle is already available and the contents get minified. So:

bundles.Add(
new StyleBundle("~/bundles/registrationStyleBundle")
.Include("~/Content/Themes/default/registration.css"));

Then, in my view, I added this:

@section viewStyles{
    <link href="@BundleTable.Bundles.ResolveBundleUrl("~/bundles/registrationStyleBundle")." rel="stylesheet" type="text/css" />
}

Then, in /Views/Shared/_Layout.cshtml, I added this:

@RenderSection("viewStyles", required: false)

1 Answer 1

6

Use the @section Scripts { } block to conditionally add bundles.

_Layout.cshtml

<body>
    ...
@RenderSection("Scripts", required: false)
</body>

FooView.cshtml

@section Scripts {
    @Scripts.Render("~/bundles/foo")
}

KungFooView.cshtml

@section Scripts {
    @Scripts.Render("~/bundles/kungfoo")
}

In my BundleConfig I typically group resources

bundles.Add(new ScriptBundle("~/bundles/Areas/Admin/js").Include(...);
bundles.Add(new StyleBundle("~/bundles/Areas/Admin/css").Include(...);
bundles.Add(new ScriptBundle("~/bundles/Areas/Home/js").Include(...);
bundles.Add(new StyleBundle("~/bundles/Areas/Home/css").Include(...);

Now I can either define multiple layout files or just selectively add bundles to the views.

Sign up to request clarification or add additional context in comments.

8 Comments

While that does work (I just tried it) - it requires adding a @section to each view/.cshtml page - I was hoping to be able to avoid that and define the resources needed in the controller using a bundle to take advantage of the minification provided by bundling.
That kind of defeats the purpose of bundling and minification if you dynamically build bundles right before a view is rendered. You lose the browser caching on that bundled resource.
How frequently do your bundles change? Do your bundles change at runtime? Do you have enough permutations that you can't define a bundle while designing your views?
Well, no I know which css and js files will be needed by each view ahead of time. I'm playing with this a little now and am just trying to figure out how to get the bundle to minify the contents of the CSS file. If I can do that, this solution will be usable.
I'm trying this in my View in conjunction with the Controller code, but the result is not minified for some reason. @section styles{<link href="@BundleTable.Bundles.ResolveBundleUrl("~/bundles/registrationStyleBundle")" rel="stylesheet" type="text/css" />}
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.