Referencing other bundles in BundleConfig.cs in ASP.NET MVC4 app - asp.net-mvc-4

I am working on an MVC4 application where I'm using WebOptimization to do all of my resource handling (cat and min). I have a few pages which are very similar, but need a few varying styles on a page by page basis.
So, I am trying to reference one bundle (base styles) within another bundle (page specific styles) and I'm not having much luck. Here's what I have in my bundle config:
bundles.Add(new StyleBundle("~/bundles/css/search").Include(
"~/Content/css/partials/grid-controls.css",
"~/Content/css/partials/grid.css",
"~/Content/css/views/search.css"));
bundles.Add(new StyleBundle("~/bundles/css/searchtrees").Include(
"~/bundles/css/search",
"~/Content/css/views/search/trees.css"));
On the search trees page I get the trees.css but nothing from the base search CSS bundle.
How can I go about referencing the first bundle in the second? I'm sure there's a way, just not too familiar with bundling yet.

You can reuse the file references instead of referencing another bundle. Something like this:
var baseIncludes = new string [] { "~/Content/css/partials/grid-controls.css", "~/Content/css/partials/grid.css", "~/Content/css/views/search.css" };
// 'base' bundle references the base includes
bundles.Add (new StyleBUndle ("~/bundles/css/search").Include (baseIncludes));
// other bundle references the base includes and some extras
bundles.Add (new StyleBundle ("~/bundles/css/searchtrees").Include(baseIncludes).Include ("~/Content/css/views/search/trees.css"));

Related

ASP.NET Core 6 MVC - access a view (.cshtml) page from a different class library project

We have a scenario where we have to move couple of our view pages away from our Web API project to a separate class library. Where this class library will be be consumed by different Web API projects that needs to load these shared View pages as part of the functionality. I have been looking for a day now but cannot find a way how to do it.
The view pages work with no problems when accessed from within the Web API project but we have now moved these View pages into our existing common library (a class library) and added it as a reference to the Web API project. Basically when we build the application with the common class library containing the views (we changed the property to Content so it gets added on build time), it gets built and copied into the bin folder. So from this, we could say that the view files should be reachable as its just within the project assembly bin folder.
What happens now is that even if setting the web application builder to specify the Content directory to point to this, it still cannot see the View pages and I get an error
The view was not found
Code:
var builder = WebApplication.CreateBuilder(new WebApplicationOptions {
Args = args,
ContentRootPath = PlatformServices.Default.Application.ApplicationBasePath
});
What bugs me is that the same /Views folder is generated when we put back the View pages back to the Web API project. Same structure and files. Only when put to another project, it now cannot recognize it. Having the view pages on the Web API works while putting it to another project does not.
This is a required structure that we need to implement without the use of a RCL but would still work when referenced by different Web APIs. This may seem odd but this is what we need to do and if possible with only minimal changes.
Your help is very much appreciated!
After a few tries, we we're able to do this by setting the resource object to Embedded Resource and implementing the ManifestEmbeddedFileProvider in the common library to virtually map the location when it gets published as a NuGet. In this case, say like we have a folder named /StaticResources in our common lib. In the sample code below, Program refers to your program assembly or any class object within your application.
Code:
// Get embedded file assembly path to allow our static files to be read by the consuming apps
var manifestEmbeddedProvider = new ManifestEmbeddedFileProvider(
typeof(Program).Assembly,
"/StaticResources");
// Sets the `/StaticResources` folder to be servable like a wwwroot folder
app.UseStaticFiles(new StaticFileOptions {
FileProvider = manifestEmbeddedProvider,
RequestPath = "/Resources"
});
// Use it like this
<script src="/Resources/MyScrtipt.js"></script>
For the View() to work, assuming your views are in /StaticResources folder.
var viewsFileProvider = new ManifestEmbeddedFileProvider(
typeof(Program).Assembly,
"/StaticResources");
app.UseStaticFiles(new StaticFileOptions {
FileProvider = viewsFileProvider,
RequestPath = "/Views/Shared"
});
Hope this helps anyone who comes across this issue. Thank you for all of you who have shared their answers.

What is Styles.render equivalent for XSL/XSLT?

In MVC4 you can render CSS stles by using
Styles.Render(path here)
Similarly scripts can be rendered by
Scripts.Render(path here)
But how do render XSL/XSLT stylesheets? Will Styles.Render do the trick?
The reason you do #Styles.Render or #Scripts.Render is because it references a bundle created somewhere in Global.asax, usually in the BundleConfig (look in your App_Start folder). They are created using the code
bundles.Add(new StyleBundle("~/Content/themes/base/css").Include(
"~/Content/themes/base/jquery.ui.core.css",
"~/Content/themes/base/jquery.ui.resizable.css"...
so then you can use them in your views as #Styles.Render("~/Content/themes/base/css"). The framework actually creates a virtual file with the path "~/Content/themes/base/css" to enable this bundling technology.
I dont think the stylebundle can be used with xsl/xslt stylesheets, although I dont know for sure. Here are some relevant question to boot.
How to apply an XSLT Stylesheet in C#
or any of these really
https://stackoverflow.com/questions/tagged/xslt+asp.net-mvc

How can I use different themes for mobile and main versions Yii?

I have Yii project with main and mobile versions. Views files of mobile version has path
modules/mobile/views/nameController/ . For main version created theme, all views loading from path themes/nameTheme. In config writed 'theme' => 'nameTheme', and in controller I use code:
public function init() {
...
Yii::app()->theme = 'mobile';
...
return parent::init();
}
I moved files of mobile versions to new theme. But Yii loaded views from modules/mobile/views/nameController/. I don't know how define theme for mobile versions in config. Can I use other theme for mobile version in my project (together with theme for main version)?
Thank you in advance.
The way I do my dynamic theme switching, I have method within my Controller component that determines what kind of browser the client uses and then set the theme from within the 'init' method. Very similar to what you've done.
I think the difference is in file organization. If you have separate view files for your desktop and mobile themes, I'd suggest that you place the view files withing the respective theme directories.
I usually make use of a single markup for my themes and just modify the style sheets for both the desktop and mobile themes so I have to worry about it once.
Here's how I do it:
public function isMobileBrowser()
{
$useragent=$_SERVER['HTTP_USER_AGENT'];
return preg_match('/android.+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino/i',$useragent)||preg_match('/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|e\-|e\/|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(di|rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|xda(\-|2|g)|yas\-|your|zeto|zte\-/i',substr($useragent,0,4));
}
And this is my Controller::init method :
public function init()
{
if ($this->isMobileBrowser()) {
Yii::app()->theme = "mobile-white-blue";
}
parent::init();
}
If you have multiple view files scattered around your application, Yii looks first for the view files within your theme folder: AppRoot>>Themes>>{theme_name}>>views and if it can't find it there, Yii looks in the primary view folder: AppRoot>>protected>>views or if it's a module view, AppRoot>>protected>>modules>>{module_name}>>views
I hope that's helpful.

ScriptBundle dependencies

I'm having difficulties getting the ScriptBundle to work properly (if this is supposed to work at all). What I'm trying to do is add another bundle (jQuery) as a dependency to my bundle, like so:
bundles.Add(new ScriptBundle("~/js/myscripts")
.Include("~/js/jquery",
"~/Content/scripts/myscript.js"));
~/js/jquery is the "name" (virtual path) of the jQuery bundle, registered as so (before my dependent bundle):
bundles.Add(new ScriptBundle("~/js/jquery")
.Include("~/Content/scripts/jquery-{version}.js"));
When I do #Scripts.Render("~/js/myscripts") in my view, only myscript.js is rendered to the HTML. If I change the virtual path to jQuery from the one in the name of the bundle to the physical, existing one, it works:
bundles.Add(new ScriptBundle("~/js/myscripts")
.Include("~/Content/scripts/jquery-{version}.js",
"~/Content/scripts/myscript.js"));
Also, doing #Scripts.Render("~/js/jquery") in the view, works. It's just referencing the non-existing virtual path (name) of another ScriptBundle that doesn't work. Is this supposed to work at all? If not, I would like to know where I can post a bug report saying that this scenario should throw an exception if it's not supported. If it is supported, where does it say and why doesn't it work?
Going by what your dependency all you have to put in your layout (view) is
#Scripts.Render("~/js/jquery")
#Scripts.Render("~/js/myscripts")
Update after your comment:
You cannot nest bundles, that is you can't Include a bundle within a bundle, that virtual path is most likely not available while the parent bundle is being created.
Typically I have a separate jquery bundle (including some other infrequently changing js) anyway and then one other js bundle for everything else. works well for browser caching.
On a side note, have you looked at requireJS, which is not really needed if you are bundling everything but it does make your js files better documented as it makes the dependencies explicit
It's not supported, but you could come up with your own solution to this, right? Something like:
var jquery = new[] { "~/Content/scripts/jquery-{version}.js" };
var myScripts = jquery.Concat(new[] { "~/Content/scripts/myscript.js" }).ToArray();
var myOtherScripts = myScripts.Concat(new[] { "~/Content/scripts/otherscript.js").ToArray();
bundles.Add(new ScriptBundle("~/js/jquery").Include(jquery));
bundles.Add(new ScriptBundle("~/js/myscripts").Include(myScripts));
bundles.Add(new ScriptBundle("~/js/other").Include(myOtherScripts));
Seems like this is an unsupported feature, so I've reported an issue for it.

ASP.NET MVC 4 ScriptBundle returns empty

Specifically, I am trying to create a ScriptBundle in MVC 4 with already minified scripts, and return this same Bundle whether the project is in Debug or not.
My web project references the MVC Telerik Grid NuGet package. In that package, Telerik only provides the minified JS files. Bundling code is below.
// telerik scripts
bundles.Add(new ScriptBundle("~/scripts/bundles/telerik").Include(
"~/Scripts/2012.1.214/telerik.common.min.js",
"~/Scripts/2012.1.214/telerik.textbox.min.js",
"~/Scripts/2012.1.214/telerik.calendar.min.js",
"~/Scripts/2012.1.214/telerik.datepicker.min.js",
"~/Scripts/2012.1.214/telerik.grid.min.js",
"~/Scripts/2012.1.214/telerik.grid.filtering.min.js"));
Other ScriptBundles run fine, but when my project attempts to reference this bundle, the request appears as: scripts/bundles/telerik?v= Returning nothing.
If I set BundleTable.EnableOptimizations = true, then it DOES return the ScriptBundle and references a specific version, however this solution is unacceptable.
I do not want to forcibly set BundleTable.EnableOptimizations = true, since I want all other Bundles to return the non-minified versions when appropriate.
Anyone have a similar experience and if so, what was the solution?
I think you have the same problem, please look at this link: mvc4 bundler not including .min files
Either rename .min.js to .js or do something like:
public static void AddDefaultIgnorePatterns(IgnoreList ignoreList)
{
if (ignoreList == null)
throw new ArgumentNullException("ignoreList");
ignoreList.Clear();
ignoreList.Ignore("*.intellisense.js");
ignoreList.Ignore("*-vsdoc.js");
ignoreList.Ignore("*.debug.js", OptimizationMode.WhenEnabled);
//ignoreList.Ignore("*.min.js", OptimizationMode.WhenDisabled);
ignoreList.Ignore("*.min.css", OptimizationMode.WhenDisabled);
}