How to bundle different js and css files per controller action/view? - asp.net-core

I have site-wide js file (site.js) that goes out with every request.
I have 2 actions on the controller: Action1 and Action2. Each of these actions has a view. Each view references a view-specific js (action1.js and action2.js).
I would like to bundle site.js with action1.js when Action1 method is executing. And when Action2 method, I want to bundle site.js with action2.js.
The bundling should be done at build time.
Is this possible with .Net Core 1.x?

It's possible, but there's a lot of menial work involved, because you'll need to manually describe each view's bundle.
Everything you need to know can be found in the official documentation, but here's the gist of it:
Action1.cshtml
I assume that for debugging purposes, you want to include both files on your dev box, while you only want the bundle in production. In your view, you add the following tags:
<environment names="Development">
<script src="site.js"></script>
<script src="action1.js"></script>
</environment>
<environment names="Staging,Production">
<script src="view1.js" asp-append-version="true"></script>
</environment>
When in development, your two files will be included as is, while in production, the bundled file view1.js will be included.
asp-append-version is part of the cache busting mechanism: it will append the file's version to each request to that file (details here).
Create your bundled view1.js
There's a number of various possibilities to create the bundle, but they all revolve around the bundleconfig.json file. The simplest solution uses he BuildBundlerMinifier NuGet package, and simply requires you to add it to your project.
bundleconfig.json would look like this:
[
{
"outputFileName": "wwwroot/js/view1.js",
"inputFiles": [
"wwwroot/js/site.js",
"wwwroot/js/action1.js"
]
},
]
Repeat for each view
This is where things get boring, because you'll need to repeat this for each view.

Related

ABP - How does abp.auth being evaluated when starting a project?

I added a side-bar menu and maybe twisted a little, somehow the abp.auth isn't working anymore.
I checked the abp.js, all I found is
abp.auth = abp.auth || {};
abp.auth.allPermissions = abp.auth.allPermissions || {};
So where does abp.auth or abp get the value in the first place?
I checked the role application service, no breakpoint is entered.
Then how can I trace this? Is it done inside the ABP framework? If so , how can I debug the abp.dll or whatever abp.XXX.dll in the template?
Many thanks!
abp.auth is initialized in ~/lib/abp-web-resources/Abp/Framework/scripts/abp.js.
That's included in _Layout.cshtml
by default:
<environment names="Development">
<script src="~/lib/abp-web-resources/Abp/Framework/scripts/abp.js" asp-append-version="true"></script>
</environment>
<environment names="Staging,Production">
<script src="~/view-resources/Views/_Bundles/shared-layout.min.js" asp-append-version="true"></script>
</environment>
Since it's a JavaScript library and not a .dll, it can be updated in package.json using yarn/npm.
abp = abp || {}. So where does the abp at the right come from?
It doesn't necessarily come from anywhere. It's done like this so that you can define abp and add your properties to the object even before abp.js loads, and this avoids replacing it.
Where does abp.auth get its value then?
abp.auth is just a JavaScript object. If you mean the allPermissions property, see #2569.
It's populated in AuthorizationScriptManager.
how to debug this library?
To enable debugging, change Visual Studio (2017+) Debugging options like in the docs:
Uncheck "Enable Just My Code"
Check "Enable source server support"
Check "Enable source link support"
abp.auth is being set after successful login. It makes GET request to http://mywebsite.com/AbpUserConfiguration/GetAll
The result of AbpUserConfiguration/GetAll action is AbpUserConfigurationDto.
There's Auth property in this result.
Search your solution for GetAll. You can find the client-side code.

Knockout JS SPA + RequireJS - bundle path issue

I have generated a knockout JS yeoman template using the knockout generator 'generator-ko' written by Steve Sanderson. It generates a ready made setup for an single page application and includes requireJS optimization configuration support in the included gulp file using Steve's own gulp-requirejs-bundler.
The bundler plugin creates .js files for each bundle you set in the optimizer config in the output folder.
The issue I'm having is that requireJS will ALWAYS try to load these bundle JS files from the current path instead of the root site path. Remember that I'm using an SPA, so folders are not "real".
eg if you access:
www.mysite.com/event/dashboard
then it will try to load event-dashboard.js (the bundled module) from: www.mysite.com/event/event-dashboard.js
Obviously that location doesnt exist being a SPA so it fails.
I need a way to control where requireJS loads these bundles from but I dont know where this can be configured.
Having looked under the hood of Steve's gulp-requirejs-bundler plugin, I'm thinking the problem may lie in the way requireJS loads the bundles.
Here's the issue raised on the gulp plugin:
https://github.com/SteveSanderson/gulp-requirejs-bundler/issues/4#
It doesnt seem that there's alot of activity going on around this so not sure if i'll get a reply anytime soon there.
I'm wondering if anyone has experienced this or has any advice.
Note: the only modification I have made is swapped out hasher for History.js so that urls dont use a hashbang to control the client side page routing.
Thanks in advance.
I have found a solution though it's not ideal using this:
https://github.com/jrburke/requirejs/wiki/Fine-grained-URL-control
In the index.html file, I can override the requireJS.load() function to modify the url from a relative path (ie beginning with "./") to the root path (ie "/")
<!-- build:js /scripts.js -->
<script src="/app/require.config.js"></script>
<script src="/bower_modules/modernizr/modernizr.js"></script>
<script src="/bower_modules/requirejs/require.js"></script>
<!-- endbuild -->
<script>
(function () {
var load = requirejs.load;
requirejs.load = function (context, moduleId, url) {
//modify url here, then call original load
return load(context, moduleId, url.replace("./", "/"));
};
//Now load code.
require(['app/startup']);
}());
</script>
Note that I also had to remove the data-main="app/startup" from the require.js script tag.
Still think there's surely a better way than doing this though.

Bundles Not Loading in ASP.NET MVC 4

I added the bundle in BundleConfig.cs as shown below:
bundles.Add(new ScriptBundle("~/bundles/angular").Include("~/Scripts/angular.min*"));
In the _Layout.cshtml I have the following:
<body>
#RenderBody()
#Scripts.Render("~/bundles/jquery")
#Scripts.Render("~/bundles/angular")
#RenderSection("scripts", required: false)
</body>
</html>
In the network traffic it does not show the angular file.
Bundling in ASP.NET MVC is quite clever in that it understands *.min and when to use or no to use it. So if you do this in your bundle:
bundles.Add(new ScriptBundle("~/bundles/angular").Include("~/Scripts/angular.js"));
In debug-mode, it will send a request for "/scripts/angular.js" and in release-mode it will send a request to "/scripts/angular.min.js"
In order to benefit from this, you should put both the original and the minified file in your scripts folder. That way, when you're debugging you have full access to the uncompressed source and in your production environment, the optimized file will be loaded
you have given incorrect file name
~/Scripts/angular.min*
instead it should be
~/Scripts/angular.js
.min would automatically be added in the production mode\
Bundler not including .min files
in my case the problem was with Global.asax.cs
you need to have
BundleConfig.RegisterBundles(BundleTable.Bundles);
in your Application_Start()

Why is resource bundling being redirected in my ASP MVC4 app?

I'm using the RC and I've checked everything is up to date via NuGet.
In my global.asax.cs ive got:
BundleTable.Bundles.AddDefaultFileExtensionReplacements();
BundleTable.Bundles.AddDefaultIgnorePatterns();
BundleTable.Bundles.AddDefaultFileOrderings();
Bundle scripts = new Bundle("~/Scripts");
scripts.IncludeDirectory("~/Scripts", "*.js");
BundleTable.Bundles.Add(scripts);
Bundle css = new Bundle("~/Content/css");
css.IncludeDirectory("~/Content/css", "*.css", false);
BundleTable.Bundles.Add(css);
I've tried a few different configurations of this with no improvement.
Then in my layout ive got:
<link href="#BundleTable.Bundles.ResolveBundleUrl("~/Content/css")" rel="stylesheet" type="text/css" />
<script src="#BundleTable.Bundles.ResolveBundleUrl("~/Scripts")"> </script>
When the page loads its got decent looking urls:
<link href="/Content/css?v=QAsFYXHCbnaU70oGVxpgi9py9iKQrT9C4BVNdHa7xoI1" rel="stylesheet" type="text/css" />
But that url redirects to:
/Content/css/
Which returns a 404 not found error...
Anybody got any ideas?
The bundle module logic that decides whether or not to handle a request, will not takeover requests to existing files or directories. So that's why your bundle requests don't work when they live at the same virtual path as an existing directory (or file).
The ~/Scripts and ~/Content/css virtual-path already exists on disk, so you need to make them some virtual-url, lets say ~/Scripts/js, and ~/Content/styles that's it, it's fine now.
Bundle scripts = new Bundle("~/Scripts/js");
scripts.IncludeDirectory("~/Scripts", "*.js");
BundleTable.Bundles.Add(scripts);
Bundle css = new Bundle("~/Content/styles");
css.IncludeDirectory("~/Content/css", "*.css", false);
BundleTable.Bundles.Add(css);
Also in MVC4 the Routing, Bundles, and Filters configuration has been moved to the
~/App_Start/(RouteConfig, BundleConfig, FilterConfig).cs
so check that you have those, if so then write your configurations there.

Including local (JS and CSS) files in local Sinatra Development

I've been trying out Sinatra on my local Windows machine. I want to include some local CSS and JS files. This is how the code looks in layout.erb
<script src="jquery.js" type="text/javascript">
</script>
<link rel="stylesheet" href="reset.css" type="text/css" />
All my files are in the same folder as app.rb
This is my app.rb
require 'rubygems'
require 'sinatra'
get '/' do
erb :index
end
For some reason, I cant see these files included in my pages. When I view the source code and click on the file(JS/CSS) I see that - "Sinatra doesn't know this ditty"- error.
What am I doing wrong here?
Move your static files(css/js) into a folder named public. Sinatra looks there with default settings.
If you want to change that behaviour have a look at this: Static Files
By default Sinatra will look for static files in your public folder. You just need to make a folder called public in the same directory as your Ruby file, and place your JS and CSS files there.

Resources