Bootstrap and font-awesome in MVC4 - asp.net-mvc-4

I am using MVC4 and have added Bootstrap and Font Awesome via nuget.
I can see how Bootstrap gets bundled in via BootstrapBundleConfig.cs (which was added by the nuget package) below:
public static void RegisterBundles()
{
BundleTable.Bundles.Add(new ScriptBundle("~/bundles/bootstrap").Include("~/Scripts/bootstrap*"));
BundleTable.Bundles.Add(new StyleBundle("~/Content/bootstrap").Include("~/Content/bootstrap.css", "~/Content/bootstrap-responsive.css"));
}
I have the following questions:
For font-awesome, I don't see similar bundling code to the above for registering the required css files, is there any, or do i just link to the stylesheet in the content directory <link href="~/Content/font-awesome.min.css" rel="stylesheet" /> - what is the proper way?
For bootstrap, if I do not want a responsive layout, would I just comment out the bootstrap-responsive.css from Include("~/Content/bootstrap.css", "~/Content/bootstrap-responsive.css"))?

You can read more about how bundling works on the asp.net site.
It seems that the BootStrap nuget package has made some bundles for you. You could modify this to include Font Awesome in the existing bundle, or make it it's own bundle
e.g.
public static void RegisterBundles()
{
BundleTable.Bundles
.Add(new ScriptBundle("~/bundles/bootstrap")
.Include("~/Scripts/bootstrap*"));
// Either add it to the existing bundle
BundleTable.Bundles
.Add(new StyleBundle("~/Content/bootstrap")
.Include("~/Content/bootstrap.css",
"~/Content/bootstrap-responsive.css",
"~/Content/font-awesome.css"));
// Or make it it's own bundle
BundleTable.Bundles
.Add(new StyleBundle("~/Content/font-awesome")
.Include("~/Content/font-awesome.css"));
}
Then, you need to make sure that your _layout.cshtml renders these bundles (the Bootstrap nuget may not have done this for you).
e.g.
#Styles.Render("~/Content/bootstrap")
// Or, if you made it it's own bundle
#Styles.Render("~/Content/font-awesome")
If you don't want to include ~/Content/bootstrap-responsive.css in your bundle, simple delete this string from the Include method.

Related

Multiple Aurelia Instances - Aurelia Webpack Plugin - aureliaApp option - "module not found"

I am composing my web app as a number of Aurelia "feature" apps - although I'm not using Aurelia features as such. Consequently in my html markup I have two entry points pointing to different apps:
<!-- Top Navigation Bar -->
<div aurelia-app="topnav"></div>
<!-- Main App-->
<div aurelia-app="main"></div>
I am using webpack and everything works perfectly using the single "main" app. Webpack generates a JS file "main.bundle.js" which I include in the src tag.
Things are not so straightforward when I added the "topnav" app. In webpack I tell the plugin to use a different aureliaApp name:
new AureliaPlugin({ aureliaApp: "topnav"}),
and, as you can see my HTML entrypoint also calls "topnav". Webpack generates a JS file "topnav.bundle.js" which I also include. I have a file called "topnav.ts" which contains the aurelia Cionfigure function which ends:
aurelia.start().then(() => aurelia.setRoot(PLATFORM.moduleName("nav")));
And a pair of files "nav.ts", "nav.html" which constitute my viewmodel and view.
When I run the app aurelia loads and the "nav" module code executes. But I then get an error - see below.
The module which it reports that it cannot find is the one entered into the HTML markup.
Should this work? Have I missed something?
I should add, everything seems to work. I can create and update properties in the viewmodel and these are bound to the view. It's just that this error is thrown.
You are doing nothing wrong, just unsupported scenario. Per official doc-wiki: https://github.com/aurelia/webpack-plugin/wiki/AureliaPlugin-options#aureliaapp
You can have only 1 auto entry module with aureliaApp configuration. To solve this, you just need to add PLATFORM.moduleName('topnav') to your main.ts (and put it on root level)
Another way to do is to bootstrap manually:
// in your index.ts
import { bootstrap } from 'aurelia-bootstrapper';
// bootstrap top nav application, with one instance of Aurelia
bootstrap(aurelia => {
// do your configuration
aurelia
.start()
.then(() => aurelia.setRoot(
PLATFORM.moduleName('topnav'),
document.querySelector('#topnav')
);
});
// bootstrap main application, with another instance of Aurelia
bootstrap(aurelia => {
// aurelia.use.standardConfiguration();
// ...
aurelia
.start()
.then(() => aurelia.setRoot(
PLATFORM.moduleName('app'),
document.querySelector('app')
)
});

Is there a way to package an ASP.NET Core app area as a NuGet package?

I'm working on an ASP.NET Core app that I would love to publish as a NuGet package that you can add to any Core web project. The app is actually entirely confined to an area (i.e., /Areas/MyArea) in the project, including controllers, views, service classes, models, views, etc., except for a few pieces. Really, these are the pieces that I'd love to magically add to an existing web app:
The area and everything in it
Its CSS and JS in wwwroot/lib/myapp
Entries in the Startup class
MyApp.json in the root
I know NuGet will restore the package dependencies, but I'm not sure how it would also consider the client-side packages.
Any suggestions? Is NuGet the wrong tool for this?
currently afaik it is not possible to deliver files into the web app from a nuget package. I think there is some discussion and work going on about making that possible in the future.
The way I'm handling that in my projects is to embed the views and the needed static js and css resources which is done like this in project.json:
"buildOptions": {
"embed": [ "Views/", "js/", "css/**" ]
},
I created a controller to serve my static resources:
public class cscsrController : Controller
{
private ContentResult GetContentResult(string resourceName, string contentType)
{
var assembly = typeof(cscsrController).GetTypeInfo().Assembly;
var resourceStream = assembly.GetManifestResourceStream(resourceName);
string payload;
using (var reader = new StreamReader(resourceStream, Encoding.UTF8))
{
payload = reader.ReadToEnd();
}
return new ContentResult
{
ContentType = contentType,
Content = payload,
StatusCode = 200
};
}
[HttpGet]
[AllowAnonymous]
public ContentResult bootstrapdatetimepickercss()
{
return GetContentResult(
"cloudscribe.Core.Web.css.bootstrap-datetimepicker.min.css",
"text/css");
}
[HttpGet]
[AllowAnonymous]
public ContentResult momentwithlocalesjs()
{
return GetContentResult(
"cloudscribe.Core.Web.js.moment-with-locales.min.js",
"text/javascript");
}
}
then I link to the controller action in the views where I need to load the js and/or css.
To make the embedded views work I created an extension method of RazorViewEngineOptions:
public static RazorViewEngineOptions AddEmbeddedViewsForCloudscribeCore(this RazorViewEngineOptions options)
{
options.FileProviders.Add(new EmbeddedFileProvider(
typeof(SiteManager).GetTypeInfo().Assembly,
"cloudscribe.Core.Web"
));
return options;
}
and this must be called from ConfigureServices in the web app Startup like this:
services.AddMvc()
.AddRazorOptions(options =>
{
options.AddEmbeddedViewsForCloudscribeCore();
})
;
this technique should work the same for areas. Note that one cool thing is that users can download the views and install them locally and that will override the use of the embedded views making it easy to customize some or all views. By overriding the views it is also possible to then manually install the js and css locally if desired and change the views to link to those local files if customization is needed. The end result is my nuget has everything it needs so there is just some startup configuration to get things working.
Years later, this is possible in ASP.NET Core > v2.x, by using a Razor class library.

asp.net mvc-4 and grunt-uglify

How to manage .min files generated by grunt-uglify and "debug" version?
If I set
BundleTable.EnableOptimizations = true;
or at web.config
<compilation debug="false" />
apparently the bundle concat all files by itself and don't use the min files generated by grunt.
All debug version has their own minify version at the same folder ex:
Folder A
testA.js
testA.min.js
...
Folder B
testB.js
testB.min.js
...
PS: I'm not referencing minified files in bundleConfig.cs.
What is the best solution to handle it? I need to use ONLY minified files generated by GRUNT at the release moment, and still using debug version when in development.
BundleTable.EnableOptimizations = true;
This code works only if you're using BundleConfig.cs
I think that the best way for you is to create a custom UrlHelper that can build JS scripts url according to if you're in debug mode or not (this is pseudo-code) :
public static class UrlHelper
{
public static string JsScript(this UrlHelper urlHelper, string baseFileName) {
return HttpContext.Current.IsDebuggingEnabled
? urlHelper.Content(baseFileName + '.js')
: urlHelper.Content(baseFileName + '.min.js');
}
}
And for example, if you want to use it in your Razor view :
<script src="#Url.JsScript("~/js/folderA/testA")"></script>

MVC 4 Bundling causes missing image in Kendo UI

I have created a new MVC 4 application and am trying to migrate an existing MVC 3 application over. Everything works fine until I try to use the new Bundling feature and when I bundle Kendo css files the arrow on dropdowns and numeric textboxes disappear. They function ok, just missing the images. The files seem to bundle just fine. I have researched extensively and have tried renaming the files to remove the "min" and still have the same issue.
Here are the files I am trying to bundle:
<link href="#Url.Content("~/Content/kendo/kendo.common.min.css")" rel="stylesheet" type="text/css" />
<link href="#Url.Content("~/Content/kendo/kendo.default.min.css")" rel="stylesheet" type="text/css" />
<link href="#Url.Content("~/Content/kendo/kendo.blueopal.min.css")" rel="stylesheet" type="text/css" />
When I bundle them like so the issues appear :
bundles.Add(new StyleBundle("~/Content/cssBundle").Include(
"~/Content/kendo/kendo.common.min.css",
"~/Content/kendo/kendo.default.min.css",
"~/Content/kendo/kendo.blueopal.min.css"
));
I faced the same problem.
CssRewriteUrlTransform should do the trick:
.Include("~/Content/kendo/2014.1.318/kendo.common.min.css", new CssRewriteUrlTransform())
First off, there is no need to minify files that have already been minified. The StyleBundle class will try to minify the Kendo .min files again, which is unnecessary. Use the Bundle class instead.
Secondly, the .Include() method takes a second parameter of params IItemTransform[] transforms. You can pass new CssRewriteUrlTransform() as that parameter, so your CSS will have the right paths.
Example:
bundles.Add(new Bundle("~/Content/cssBundle")
.Include("~/Content/kendo/kendo.common.min.css", new CssRewriteUrlTransform()),
.Include("~/Content/kendo/kendo.default.min.css", new CssRewriteUrlTransform()),
.Include("~/Content/kendo/kendo.blueopal.min.css", new CssRewriteUrlTransform())
);
I know it's a pain, but I usually just modify the .css files and do a find/replace to get the correct paths.
Otherwise, you can set the bundle to be the same directory that Kendo is in, like this:
bundles.Add(new StyleBundle("~/Content/kendo").Include(
"~/Content/kendo/kendo.common.min.css",
"~/Content/kendo/kendo.default.min.css",
"~/Content/kendo/kendo.blueopal.min.css"
));
I was able to correct this problem by configuring routes in my application for the problem locations.
// Route for bundles problem.
routes.MapRoute("ResourcesFix", "bundles/{folder}/{path}",
new { controller = "Redirect", action = "Index" });
// Redirect for requests.
public class RedirectController : Controller
{
public ActionResult Index(String folder, String path)
{
return Redirect("~/Content/kendo/" +
WebConfigurationManager.AppSettings["KendoVersion"] + "/" + folder + "/" + path);
}
}
Add the following class extension,
public static class BundleConfigExt
{
public static Bundle CustomCssInclude(this Bundle bundle, params string[] virtualPaths)
{
foreach (var virtualPath in virtualPaths)
{
if (virtualPath.IndexOf("~/Content/kendo/") > -1) //OR
//// if (virtualPath.IndexOf("~/Content/kendo/") > -1 || virtualPath.IndexOf("~/Content/ExternalCss/") > -1)
{
bundle.Include(virtualPath, new CssRewriteUrlTransform());
}
else
{
bundle.Include(virtualPath);
}
}
return bundle;
}
}
Call .CustomCssInclude() extension method instead of .Include(),
bundles.Add(new StyleBundle("~/Bundles/AllArabicCss").CustomCssInclude(
"~/Content/bootstrap.min.css",
"~/Content/kendo/kendo.common.*",
"~/Content/kendo/kendo.default.min.css",
//...
"~/Content/kendo/kendo.bootstrap.min.css",
"~/Content/ExternalCss/custom.css",
"~/Content/ExternalCss/tab-responsive.css",
"~/Content/ExternalCss/mobile-responsive.css"));

MVC4 Internet Application template bundle enabled by default?

I am using Mvc 4 project from Internet Application template. Why bundle feature does not enabled by default or am I missing something?
There is no such methods like this in Mvc4 as mentioned by other post:
BundleTable.Bundles.RegisterTemplateBundles();
BundleTable.Bundles.EnableDefaultBundles();
Update: This how to enable bundle in debug mode
BundleTable.EnableOptimizations = true;
after registering bundles.
Bundles are registered and enabled by default. When you run in Release mode (debug="false") in your web.config the #Script.Render helper will concatenate and minify the resources into a single file. If you run in Debug mode then each script will be rendered separately.
I run into a similiar issue and my solution is this:
public class bundleConfig
{
public static void RegisterBundles(BundleCollection bundles)
{
// bundle as usual
#if(!DEBUG)
BundleTable.EnableOptimizations = true;
#endif
}
}
This way, when I launch it in Release mode, it does minification and bundling but if I launch it in Debug mode, it doesn't.