Visual Studio 2012 Conditional Bundling

Visual Studio 2012 Conditional Bundling

My suggestion:

Goto Global.asax. Ensure the method Application_Start contains following line:

protected void Application_Start()
{
...
BundleConfig.RegisterBundles(BundleTable.Bundles);
}

Find or create class BundleConfig as follows, preferrably in folder App_Start:

public class BundleConfig
{
public static void RegisterBundles(BundleCollection bundles)
{
...

bundles.Add(new StyleBundle("~page1").Include(
"~/Styles/site.css",
"~/Styles/page1.css"));

bundles.Add(new StyleBundle("~page2").Include(
"~/Styles/site.css",
"~/Styles/page2.css"));

...

bundles.Add(new StyleBundle("~pageN").Include(
"~/Styles/site.css",
"~/Styles/pageN.css"));

}
}

Now use corresponding bundle in every appropriate page:

<link rel="stylesheet" type="text/css" href="Styles/page1" />

Or better from code:

@Styles.Render("~/Styles/page1")

(this is cshtml, but aspx syntax is for sure very similar).

Note that you must have a separate bundle per page. You should not modify one and the same bundle on the fly. Bundles have virtual Urls. In your example it is just css. These are cached by browsers, so regardless weather you have changed the content of bundle on the fly a browser might think this is the same and do not re-fetch it.


If you do not want to take care about adding each and every page manually to the method above. You could automate it. Following code could give you an idea how:

public class MyStyleHelper
{
public static string RenderPageSpecificStyle(string pagePath)
{
var pageName = GetPageName(pagePath);
string bundleName = EnsureBundle(pageName);
return bundleName;
}

public static string GetPageName(string pagePath)
{
string pageFileName = pagePath.Substring(pagePath.LastIndexOf('/'));
string pageNameWithoutExtension = Path.GetFileNameWithoutExtension(pageFileName);
return pageNameWithoutExtension;
}

public static string EnsureBundle(string pageName)
{
var bundleName = "~/styles/" + pageName;
var bundle = BundleTable.Bundles.GetBundleFor(bundleName);
if (bundle == null)
{
bundle = new StyleBundle(bundleName).Include(
"~/styles/site.css",
"~/styles/" + pageName + ".css");
BundleTable.Bundles.Add(bundle);
}
return bundleName;
}
}

Usage:

<link rel="stylesheet" type="text/css" href="<%: MyStyleHelper.RenderPageSpecificStyle(Page.AppRelativeVirtualPath) %>" />

ASP.NET's Conditional bundling - real world implementation?

One way is to use DynamicBundleFolder

If you can have a directory structure like

Scrtips
-- /Permissions
-- /1
-- a.js
-- b.js
-- /2
-- a.js
-- b.js
-- c.js
-- /3
-- c.js
-- d.js

where 1,2,3 are the restriction levels, then in your RegisterBundles add a DynamicBundle

bundles.Add(new DynamicFolderBundle("userScripts", "*.js",new JsMinify()));

And then in your _layout.cshtml, you can do

@{
var userPermissionLevel = 2; // grab your user permission level, from session maybe
}

@Scripts.Render("~/Scripts/Permissions/"+ @userPermissionLevel +"/userScripts")

and that will render all the scripts in that directory. You dont have to create bundles for each page then. And if you need to add new permission based file, just add to respective permission folder.

Update: This will work fine if you have unique js files for each permission level. For shared files, updating them will be quite a work. So what you can do is create bundle according to permission levels like

    // Bundle for permission level 1
bundles.Add(new ScriptBundle("~/bundles/permissions/1").Include(
"~/Scripts/a.js")
.Include("b.js"));

// Bundle for permission level 2
bundles.Add(new ScriptBundle("~/bundles/permissions/2").Include(
"~/Scripts/b.js")
.Include("c.js"));

// and so on for each level 3,4,5 include specific level files

and then again you can add them to page throught _layout.cshtml

@{
var userPermissionLevel = 2; // grab your user permission level, from session maybe
}

@Scripts.Render("~/bundles/permissions/"+userPermissionLevel)

Visual Studio setup project: bundle prerequisites into one installer

Some developers use a zip-type program for this. Basically you add the setup.exe, prerequisites and MSI into a self-extracting exe that will run setup.exe after it unpackes everything. I think IExpress will do this, as well as 3rd party tools like WinZip.

Other setup authoring tools have their own bootstrappers which can include all the installation files.

Bundling css/js only in debug mode

To check if debugging is enabled you can use this:

HttpContext.Current.IsDebuggingEnabled

provided that the HttpContext is accessible. If not, the longer approach would be this one:

var isDebug =(System.Web.Configuration.CompilationSection)ConfigurationManager.GetSection("system.web/compilation").Debug;

Both these suggestions come from this article: How do I check if Debug is enabled in web.config.

What I would do to actually add modules conditionally would be to start off by creating a Dictionary<string, bool> of script paths and whether or not they should be added in release mode.

When you call the program, if debugging is false then simply filter the dictionary into a collection of elements:

var includes = dict.Where(x => x.Value).Select(x => x.Key);

And then pass the result to your Include statement.

Is it possible to use conditional compilation symbols in VS build events?

I finally found an answer. The following works perfectly:

if "$(DefineConstants.Contains('DEBUG'))" == "True" <command>

This works for any constants defined in the build, but note that the constant is case-sensitive ('DEBUG' != 'Debug').

The type or namespace name 'BundleCollection' could not be found (are you missing a using directive or an assembly reference?)

There is no clear answer for this question.
I managed to fix the project only by re-creating it, and then downloading all the DLLs in a different order, closing and re-opening the visual studio several times while doing it.

Aparently there was some conflict between some of the packages, but that was impossible to guess until I had re-created the project from scratch again.

Running Install-Package Microsoft.AspNet.Web.Optimization did solve the problem after the clean install however, so I recommend it.

I thank everyone for the help.

How do I output conditional information in-place using ASP.net MVC4?

Use Html.Raw helper for plain text output:

@for (int i = 1; i <= 20; i++)
{
<ul class="leader @Html.Raw(i % 2 == 0 ? "light" : "dark")">
<li class="rank">@i</li>
<li class="challenger"><img alt="Photo" src="~/Content/Textures/Photo/temp-face.jpg" /> James Winters</li>
<li class="date">01 Sept 2012</li>
<li class="venue">NSW - Woolloomooloo Bay Hotel</li>
<li class="points">2999</li>
</ul>
}


Related Topics



Leave a reply



Submit