using System.Web.Optimization can I mix css and .less files in the same bundle? - asp.net-optimization

It does not look like this is possible because LessTransform will be applied only once all the files have been merged and minified.
public class LessTransform : IBundleTransform
{
public void Process(BundleContext context, BundleResponse response)
{
response.Content = LessWeb.Parse(response.Content, (DotlessConfiguration) ConfigurationManager.GetSection("dotless"));
response.ContentType = "text/css";
}
}
Is there a way to preprocess the less files in some way at Bundling time?

I recently had the same needs and wrote a blog post about the solution that I finally came up with. Here
This can be done relatively easy with a nuget package/some web.config changes (detailed after the package installs so excluding here)/a new transformer in your bundling config.

Related

Failed to load local data with Angular 6 and ASP.NET MVC5

For security reason, we have to stick to ASP.NET MVC5. That's why we have to build the frontend Angular app and use BundleConfig to package and grab everything. For the view, we established a view placeholder for our Angular App.
Yes, I agree that it's ugly. However, it seems it is a best solution for us.
Here is the problem: When I try to load the static files. (e.g. images, json files) we have to grab them from the mvc5 backend.
I tried to move the static files to the angular assets folder, and everything got successfully compiled and copied to the dist folder. However, using relative path, Angular cannot recognize them.
Here is the error:
As you may know that the root of our angular app is: http://localhost:1220/client
and the absolute json file location is: 'http://localhost:1220/client/dist/assets/data/UiData.json'
This is my Angular service:
import { Injectable } from '#angular/core';
import { HttpClient } from '#angular/common/http';
import { Observable } from 'rxjs/observable';
#Injectable()
export class LocalDataService {
private staticDataURL = '../../../assets/data/UiData.json';
// private staticDataURL = 'assets/data/UiData.json';
constructor(private http: HttpClient) { }
public getJSON(): Observable<any> {
return this.http.get(this.staticDataURL);
}
}
both path '../../../assets/data/UiData.json' and 'assets/data/UiData.json' won't work for this case, because the server won't recognize the frontend Angular App.
This is the BundleConfig from our MVC5 backend:
public class BundleConfig
{
// For more information on bundling, visit https://go.microsoft.com/fwlink/?LinkId=301862
public static void RegisterBundles(BundleCollection bundles)
{
bundles.Add(new ScriptBundle("~/script/bundle").Include("~/Scripts/dist/bundle.js"));
bundles.Add(new StyleBundle("~/style/main").Include("~/Scripts/dist/style.css", new CssRewriteUrlTransform()));
// Angular build artifacts
bundles.Add(new ScriptBundle("~/script/report-bundle").Include(
"~/client/dist/runtime.*",
"~/client/dist/polyfills.*",
"~/client/dist/scripts.*",
"~/client/dist/main.*"
));
bundles.Add(new StyleBundle("~/style/report-style")
.Include(
"~/client/dist/styles.*",
new CssRewriteUrlTransform()
));
}
}
Is there any way to load the local json file using relative path in this case?
Thanks in advance!
We have a very similar environment (for security reasons also).
I'm hoping I can help answer your question by explaining what I 'think' would be the standard way to handle this...
I think the main thing is to just know / decide on a folder to treat as your "web root folder".
In older versions of MVC, it was the /Content folder.
In asp.net core versions, it is the /wwwroot folder.
And then put all of your scripts and assets in that folder.. As long as they are all relative to each other it should work..
So basically, you'll want to edit your output dir of your angular-cli to output your angular app to something like
/Content/js/dist/your files
All of your assets will be in something like
/Content/images/your images
and
/Content/static/your static files
something like that.
in other words, you'll put all your assets in that "web root folder" and also make sure to output your /dist folder to that same folder.
hope that helps!

Using ES6 `import` with CSS/HTML files in Meteor project: bug or feature?

I am currently learning Meteor and I found out something that intrigued me.
I can load HTML and CSS assets from a JS file using the import statement.
import '../imports/hello/myapp.html';
import '../imports/hello/myapp.css';
import * as myApp from '../imports/hello/myapp.js';
This was a surprise to me so I ran to google but could not find this behavior documented in the specification for ES6 import or in Meteor's Docs.
So my questions are:
Can I rely on this behavior to build my apps?
Will my app will break when Meteor gets around to fix it -- if it's a bug --?
Notes
I am using Meteor v1.3, not sure if this works also with previous versions.
You can download the app to see this behavior from Github
After going through the implementation of the built files for my app
I found out why this works.
HTML
Files are read from the file system and their contents added to the global Template object, e.g.,
== myapp.html ==
<body>
<h1>Welcome to Meteor!</h1>
{{> hello}}
</body>
results in the following JS code:
Template.body.addContent((function () {
var view = this;
return [
HTML.Raw("<h1>Welcome to Meteor!</h1>\n\n "),
Spacebars.include(view.lookupTemplate("hello"))
];
}));
Which is wrapped in a function with the name of the file as it's key:
"myapp.html": function (require, exports, module) {
Template.body.addContent((function () {
var view = this;
return [
HTML.Raw("<h1>Welcome to Meteor!</h1>\n\n "),
Spacebars.include(view.lookupTemplate("hello"))];
}));
Meteor.startup(Template.body.renderToDocument);
Template.__checkName("hello");
Template["hello"] = new Template("Template.hello", (
function () {
var view = this;
return [
HTML.Raw("<button>Click Me</button>\n "),
HTML.P("You've pressed the button ",
Blaze.View("lookup:counter",
function () {
return Spacebars.mustache(view.lookup("counter"));
}), " times.")
];
}));
},
So all of our HTML is now pure JS code which will be included by using require like any other module.
CSS
The files are also read from the file system and their contents are embedded also in JS functions, e.g.
== myapp.css ==
/* CSS declarations go here */
body {
background-color: lightblue;
}
Gets transformed into:
"myapp.css": ["meteor/modules", function (require, exports, module) {
module.exports = require("meteor/modules").addStyles("/* CSS declarations go here */\n\nbody {\n background-color: lightblue;\n}\n");
}]
So all of our CSS is also now a JS module that's again imported later on by using require.
Conclusion
All files are in one way or another converted to JS modules that follow similar rules for inclusion as AMD/CommonJS modules.
They will be included/bundled if another module refers to them. And since all of them are transformed to JS code
there's no magic behind the deceitful syntax:
import '../imports/hello/myapp.html';
import '../imports/hello/myapp.css';
They both are transpiled to their equivalent forms with require once the assets have been transformed to JS modules.
Whereas the approach of placing static assets in the imports directory is not mentioned in the official documentation,
this way of importing static assets works.
This seems to be at the core of how Meteor works so I'd bet this functionality is going to be there for a long while.
I don't know if to call this a feature maybe a more appropriate description is unexpected consequence but that would
only be true from the user's perspective, I assume the people who wrote the code understood this would happen and perhaps even
designed it purposely this way.
One of the features in Meteor 1.3 is lazy-loading where you place your files in the /imports folder and will not be evaluated eagerly.
Quote from Meteor Guide:
To fully use the module system and ensure that our code only runs when
we ask it to, we recommend that all of your application code should be
placed inside the imports/ directory. This means that the Meteor build
system will only bundle and include that file if it is referenced from
another file using an import.
So you can lazy load your css files by importing them from the /imports folder. I would say it's a feature.
ES6 export and import functionally are available in Meteor 1.3. You should not be importing HTML and CSS files if you are using Blaze, the current default templating enginge. The import/export functionality is there, but you may be using the wrong approach for building your views.

Moving Sitemesh3.xml to a different folder

I'm practicing web programming by using Spring 3.1, Hibernate and SiteMesh3.
I want to move 'sitemesh3.xml' file to other directory as WEB-INF/spring/ (not in WEB-INF directly). I've tried it, but sitemesh didn't work. Is it possible to move it? If it is, what properties, if any, should I add on other files like web.xml?
(I've read http://wiki.sitemesh.org/wiki/display/sitemesh3/Configuring+SiteMesh+3, which says "The configuration file should live in /WEB-INF/sitemesh3.xml in your web-application.")
Consider using java config, you can get rid of xml configuration totally.
Follow Sitemesh Java Config
Create a filter like this and register it in your web.xml or in java configuration file.
#WebFilter(urlPatterns = "/*")
public class ConfiguredSiteMeshFilter extends ConfigurableSiteMeshFilter {
#Override
protected void applyCustomConfiguration(SiteMeshFilterBuilder builder) {
builder.addDecoratorPath("/*", "/WEB-INF/decorators/defaultDecorator.jsp");
}
}

Why are my ServiceStack.Razor pages not refreshing until I rebuild my app?

I've got an API project hosted in ServiceStack (3.9), and I've added a /docs folder containing two Razor files, _layout.cshtml and default.cshtml
I have configured no caching; my AppHost class looks like this:
public class AppHost : AppHostBase {
public AppHost()
: base("My API", typeof(UserService).Assembly, typeof(GetUserDto).Assembly) {
}
public override void Configure(Container container) {
ServiceExceptionHandler +=
(req, request, exception) => {
Elmah.ErrorSignal.FromCurrentContext().Raise(exception);
return DtoUtils.HandleException(this, request, exception);
};
JsConfig.EmitCamelCaseNames = true;
Plugins.Add(new RazorFormat());
Plugins.Add(new SwaggerFeature());
}
public static void Start() {
new AppHost().Init();
}
}
My Razor pages are working fine - going to localhost/api/docs shows the default page and uses the supplied layout - but if I make a change to the Razor code, I need to recompile the app before it's visible in a browser.
My understanding was that ServiceStack views worked like ASP.NET MVC views - they're interpreted at request time, and any changes to the view code show up immediately, and if you want to cache your rendered views you'll need to configure that explicitly. Have I missed a config setting, or is there something else I need to do to get ServiceStack pages to recompile without needing to rebuild the project?
You need to set the AppHost config to debug mode:
SetConfig(new EndpointHostConfig {
DebugMode = true,
});
For performance reasons changes are only monitored for in Debug mode. See here for more information.
Automatic reload of modified views, layout templates and partials (in Debug mode)
The best way to avoid the Start-Up penalty is to avoid having to restart the AppDomain in the first place. So in Debug Mode we'll also do this where a background file system watcher monitors all pages, partials and Layout templates for modifications and recompiles and auto-reloads them on the fly, all-ready to deliever instant response time once the page is requested.

Bundling scripts are not getting rendered

I am having a problem with script bundling and minification with ASP .NET
I have tried all popular solution found on internet but still having the same problem.
My BundleConfig.cs looks like
namespace MYPROJ{
public class BundleConfig
{
public static void AddDefaultIgnorePatterns(IgnoreList ignoreList)
{
if (ignoreList == null)
return;
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);
}
public static void RegisterBundles(BundleCollection bundles)
{
bundles.IgnoreList.Clear();
AddDefaultIgnorePatterns(bundles.IgnoreList);
bundles.Add(new ScriptBundle("~/bundles/jquery").Include(
"~/Scripts/jquery-{version}.js"));
…
…
//bundles.Add(new ScriptBundle("~/Scripts").Include("~/Scripts/jquery.unobtrusive-ajax.min.js", "~/Scripts/kendoui/kendo.all.min.js", "~/Scripts/kendoui/kendo.combobox.min.js", "~/Scripts/kendoui/kendo.grid.min.js"));
//bundles.Add(new ScriptBundle("~/Scripts").Include("~/Scripts/kendoui/kendo.all.min"));
//bundles.Add(new ScriptBundle("~/Scripts").Include("~/Scripts/kendoui/kendo.combobox.min"));
//bundles.Add(new ScriptBundle("~/Scripts").Include("~/Scripts/kendoui/kendo.grid.min.js"));
bundles.Add(new ScriptBundle("~/Scripts").IncludeDirectory("~/Scripts", "*.js").IncludeDirectory("~/Scripts/kendoui", "*.js"));
……
BundleTable.EnableOptimizations = true;
}
}
}
And in master view:
#Scripts.Render("~/Scripts")
Now after all this when I runs I get this tag:
<script src="/Scripts?v=ZnxC8dcoc3fJ-hfKQHLiTe19PjJFHwPhwHPUncuBtzE1"></script>
And upon using chrome code inspector I found out that the status code for the above resource is Status Code: 302 Found And for Scripts/ it is Status Code: 404 Not Found
And I also cannot access the script file by clicking it in the view source, so looks like nothing is loaded however all files and directories are rightly placed.
Just for the info, my styleSheets bundling is working fine.
Kindly help Thank you.
You can't give your bundle a name that is also the name of an existing directory. Rename the bundle or add a /js to make it work correctly:
bundles.Add(new ScriptBundle("~/Scripts/js").IncludeDirectory("~/Scripts", "*.js").IncludeDirectory("~/Scripts/kendoui", "*.js"));
and
#Scripts.Render("~/Scripts/js")
Any other name that doesn't exist would work as well, e.g.
bundles.Add(new ScriptBundle("~/ScriptMonkey").IncludeDirectory("~/Scripts", "*.js").IncludeDirectory("~/Scripts/kendoui", "*.js"));
...assuming you don't have /ScriptMonkey directory.
Have you tried using non existing directory in Bundle's virtual path?
Like
...new ScriptBundle("~/bundle/Scripts")...
The accepted answer did not work for me. I use MVC 4.0 on Visual Studio 2010 SP1. I had a js file named "jquery-ui.min.js" file and was not getting loaded. My Bundle.config code was:
bundles.Add(new ScriptBundle("~/bundles/jqueryui").Include(
"~/Scripts/jquery-ui.min.js"));
I renamed the file to jquery-ui.js and updated my code as
bundles.Add(new ScriptBundle("~/bundles/jqueryui").Include(
"~/Scripts/jquery-ui.js"));
I got this information from here.
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).