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
How to Save Dlls in a Different Folder When Compiling in Visual Studio
How to Join 2 or More .Wav Files Together Programmatically
Spawn a New Thread to Open a New Window and Close It from a Different Thread
Execute SQL Script on SQL Server Using C#
How to Avoid Page Refresh After Button Click Event in Asp.Net
How to Check If a Given Value Is a Generic List
List<T> Readonly with a Private Set
Insert into SQL Db a String That Contain Special Character '
Why Is "Null" Present in C# and Java
Capturing Count from an SQL Query
Rijndael 256 Encrypt/Decrypt Between C# and PHP
Best Practice: Direct SQL Access VS. Web Service
C# Linq to SQL: Refactoring This Generic Getbyid Method
When Do You Use Extension Methods, Ext. Methods VS. Inheritance