I have two script bundles defined:
bundles.Add(new ScriptBundle("~/scripts/common").Include(
"~/Scripts/jquery-1.11.1.js",
"~/Scripts/jquery-ui-1.10.4.custom.min.js",
"~/Scripts/jquery.validate.js"));
bundles.Add(new ScriptBundle("~/scripts/sectionCommon").Include(
"~/Scripts/A.js",
"~/Scripts/B.js",
"~/Scripts/C.js"));
I have one set on my master layout page:
#Scripts.Render("~/scripts/common")
And one set on a subset of my pages where it is used:
#Scripts.Render("Scripts/sectionCommon")
So far so good and this works.
When I run my site using debug compilation, the JS files from the first bundle are rendered to the markup as individual script links per file, whereas the second bundle remains as a single minified bundle:
<script src="/siteRoot/Scripts/jquery-1.11.1.js"></script>
<script src="/siteRoot/Scripts/jquery-ui-1.10.4.custom.min.js"></script>
<script src="/siteRoot/Scripts/jquery.validate.js"></script>
<script src="/siteRoot/Scripts/sectionCommon"></script>
Does anybody have any idea why this might be happening? Bit of a pain while debugging.
Figured this out while I was writing the question. Thought I would answer it in case this bites anybody else. The difference between the two was using the tilda to get a site relative url:
#Scripts.Render("~/scripts/common")
#Scripts.Render("Scripts/sectionCommon")
Both of these render out the script as intended, but only the top one (using the site relative URL) was rendering out the individual script references in debug.
Related
I have a Durandal 2 app based on ASP.NET MVC 5 and Web API, with the initial Index.cshtml (on HomeController) being served through the MVC router. From then on it's all regular html views being handled by the Durandal router.
Anyway, I'm trying to use gulp-useref to concatenate all css and js files. I've got everything working and gulp-useref drops the newly concatenated files and an index.cshtml with the updated script and stylesheet references in a dist folder.
Of course, for the application to work I need the updated index.cshtml back in Views/Home/. I have created a "copy" task with gulp that does just that; it overwrites the original index.cshtml and fixes the paths to the concatenated js and css files.
That works as well, but since useref removes the html comments that mark the spot where it should insert the references to the concatenated files, the process is not repeatable.
Let me illustrate with some code.
In my Index.cshtml I have:
<html>
<head></head>
<body>
<!-- build:js js/lib.js-->
<script src="/bower_components/numeral/languages.js"></script>
<script src="/scripts/bootstrap.js"></script>
<script src="/scripts/typeahead.js"></script>
<script src="/scripts/knockout-bootstrap.js"></script>
<script src="/scripts/knockout-extenders.js"></script>
<!-- endbuild -->
</body>
</html>
This is where gulp-useref will place the updated script reference so it will end up looking like this:
<html>
<head></head>
<body>
<script src="/js/lib.js"></script>
</body>
</html>
As you can see, useref removes the html comments so if I overwrite the original index.cshtml with this file, useref will not know where to place the updated script tag. And if I don't overwrite the original index.cshtml, the application will not be using the concatenated files.
I'm new to gulp so I might be going at this in the completely wrong way, but how can I make sure that my /Views/Home/index.cshtml uses the concatenated files in an automated manner?
Or, alternatively, is there a better approach for what I'm trying to do, namely, get everything ready for deployment?
Here are my relevant gulp tasks, for reference:
gulp.task("optimize-for-deployment", function () {
var assets = $.useref.assets({ searchPath: "./" });
var cssFilter = $.filter("**/*.css");
var jsFilter = $.filter("**/*.js");
return gulp
.src(config.index)
.pipe($.plumber())
.pipe(assets)
.pipe(cssFilter)
.pipe($.csso())
.pipe(cssFilter.restore())
.pipe(jsFilter)
.pipe($.uglify())
.pipe(jsFilter.restore())
.pipe(assets.restore())
.pipe($.useref())
.pipe(gulp.dest(config.appDist));
});
// copy the updated index.cshtml to Views/Home/
gulp.task("copy-for-deployment", ["optimize-for-deployment"], function () {
return gulp.src(config.appDist + "index.cshtml")
.pipe($.replacePath(/js\/lib.js/, "/app/dist/js/lib.js"))
.pipe($.replacePath(/style\/app.css/, "/app/dist/style/app.css"))
.pipe(gulp.dest(config.indexLocation));
});
Don't know if this is 'better' approach or the best solution but you could use something like a template for your index file. So you would have an Index-template.cshtml with al your html comments which you use to create your Index.cshtml every time in your gulp tasks.
This way you can overwrite your Index.cshtml and keep your template with al your html comments.
I am new to .net mvc and trying to do the exact thing Sergi. If you modified the default view location scheme to include your dist folder (How to change default view location scheme in ASP.NET MVC?), would .net know to include the dist folder and compile those .cshtml files?
When I create an MVC project that uses Razor, the following lines are generated:
#Scripts.Render("~/bundles/jquery")
#RenderSection("scripts", false)
What is the difference between these lines ? Is it the case that #Scripts.Render generates a <scripts> section and then #RenderSection("scripts", false) renders it ?
The first one renders out a bundle, which is a group of related Javascript files. For instance, you might want to bundle jQuery and jQuery UI together. Bundles also get the benefit of bundling and minification when a solution is compiled in release mode. ref: http://www.asp.net/mvc/tutorials/mvc-4/bundling-and-minification
#RenderSection indicates that a page that uses the layout in question can inject markup in a particular spot in the layout. Sections are in effect a placeholder (and work much like the ContentPlaceHolder server control from web forms if you are familiar with that). That reference is probably right before the closing body tag, where it is believed by some to be the best spot to put scripts. You could have a section called scripts, or head, or footer, it is completely arbitrary and sections don't necessarily have anything to do with scripts at all. ref: http://weblogs.asp.net/scottgu/asp-net-mvc-3-layouts-and-sections-with-razor
These are completely different things.
The #Scripts.Render("~/bundles/jquery") is rendering a group of scripts for you, creating all the <script> tags. in the BundleConfig.cs file you are able to create bundles of scripts and css files.
One of its advantages allow you to group multiple files that are commonly used together. Instead of including each of these files explicitly you can include all of them using explicit Scripts.Render(groupName).
You can read more about Bundling and Minification here.
The #RenderSection("scripts", false) is about rendering a section in the view.
A section allow you to specify a region of content within a layout. It expects one parameter which is the name of the section. If you don’t provide that, an exception will be thrown.
Here is a good article explaining about Layouts, RenderBody, RenderSection and RenderPage in ASP.NET MVC.
The first parameter to the “RenderSection()” helper method specifies
the name of the section we want to render at that location in the
layout template. The second parameter is optional, and allows us to
define whether the section we are rendering is required or not. If a
section is “required”, then Razor will throw an error at runtime if
that section is not implemented within a view template that is based
on the layout file (which can make it easier to track down content
errors). If a section is not required, then its presence within a
view template is optional, and the above RenderSection() code will
render nothing at runtime if it isn’t defined.
Is it possible to force ASP.NET MVC 4 bundle to render links with full domain address?
I mean a bundle like this: ~/bundle/jquery render to http://domain.com/bundle/jquery instead of this one: /bundle/jquery.
UPDATE:
I think I should explain more. By render I mean the rendered url, not the page. e.g. I have a bundle with this key: ~/bundle/jquery. OK. It will be rendered as
<script src="/bundle/jquery" type="text/javascript"></script>
Right? Well, I want this one instead:
<script src="http://sub.domain.com/bundle/jquery" type="text/javascript"></script>
Do you exactly say it "render"?? yes, then ASP.NET MVC 4 renders them as you have asked for.You can notice this by going to the source code of the page RENDERED by a view in ASP.NET MVC 4.0.
You don't have to force it as such , it automatically does it for you...!!
EDITED:
You can do so by deleting Bundle.cs file in the App_Start folder and removing the BundleConfig.RegisterBundles(BundleTable.Bundles); line from Global Application Class. But you will have to add paths to your required files manually. this is cumbersome. Moreover, this will reduce your application's performance as you will be adding the plain HTML on View Page.
I understand and fully appreciate the new bundle wildcard {version} regex, as it will continue to pick up your script and style libraries even after updating, etc. The problem is that I cannot get it to work effectively.
I had previously use the following notation to pick up my jQuery scripts:
bundles.Add(new ScriptBundle("~/bundles/jquery").Include(
"~/Scripts/jquery-1.*"));
and it would pick up all files matching the asterisk wildcard.
But when I tried the following:
bundles.Add(new ScriptBundle("~/bundles/jquery").Include(
"~/Scripts/jquery-{version}.js"));
I noticed that the jQuery file was not written out to the _Layout.cshtml page.
NOTE - I am indeed using the following HTML code for both examples:
#Scripts.Render("~/bundles/jquery")
When I use the first example above (" * ") notation the following is written to the page:
<script src="/Scripts/jquery-1.7.2.js" type="text/javascript"></script>
However when I use the "{version}" notation, there is merely an empty space where the library should be written. This pertains to both jquery files as well as the associated CSS stylesheets.
It does not matter whether I am compiling for DEBUG or RELEASE mode. The results are the same. Obviously in release mode I'll get the optimized version when using the "*" notation:
<script src="/bundles/jquery?v=VUv2YOeuOgHad-FHZ-vGMDu9wN1j9VZGifI1SBUUSMs1" type="text/javascript"></script>
So being the perfectionist that all developers are, I would greatly like to see the {version} notation work for me, as I do keep up to date on new releases and would like this control on my deployments.
Any insight into what I may be doing wrong is greatly appreciated.
Thanks in advance,
Dan
Try updating Microsoft.AspNet.Web.Optimization and related NuGet packages: Microsoft.Web.Infrastructure, WebGrease, Antlr. Check not just "nuget.org" tab, but also "All".
I have a javascript application that runs in a view (index.cshtml).
Problem:
The problem is all relative paths are relative to the current url, which would be ok in a simple html webapp but not in asp mvc. The js-app shouldn't have to bother whether it's served in a normal html file or via a asp mvc page.
I.e. http://www.domain.com/<controller>/<action>/ contains a script test.js. This script loads an external xml file searching relative to it ie. "data/data.xml". The resulting url reads http://www.domain.com/<controller>/<action>/data/data.xml. This isn't found.
Question:
Is there a way to route static files (images,..., maybe even js files) to the content folder like "~/Content/controller/action/<pathToFile>/"?
Any help appreciated!
Lg
warappa
PS: I know about Url.Content() but that doesn't fit here.
The solution doesn't require mapping - just a simple html tag in the header:
<base href="#(Request.Url.GetComponents(UriComponents.SchemeAndServer, UriFormat.Unescaped) +
Url.Content("~/content/controller/action/"))" />
Lg
warappa
EDIT
Some browsers need an absolute url - sample updated.
In you can use absolute URL addresses to access you static resources:
$('img').attr('src', '/Content/Pictures/picture1.png');
or
<script src="/Scripts/script.js"></script>
This way you will allways get the same resources relative to the page base address, no matter if you load the script in a /{Controller}/{Action}/{View}, {Area}/{Controller}/{Action}/{View}, a custom route or even in a static script html page.
Or perhaps what you're looking for is the use of css files, since CSS's url('<path>') resolves the addresses relative to the CSS file's location. You would just need to import the one CSS file that had all the resource (image?) file paths. Then the scripts could reference the distinct class names, thus not being location aware at all. This is what libraries like jQuery UI do. But again this would require a fixed folder structure relative to the CSS document.