I have the following ScriptBundle defined in BundleConfig.cs-
public class BundleConfig
{
public static void RegisterBundles(BundleCollection bundles)
{
bundles.Add(new ScriptBundle("~/js/yepnope").Include(
"~/Scripts/yepnope.{version}.js"));
}
}
It isn't in fact the only bundle, but that is all in there that is pertinent to the question - the rest is just other bundle definitions.
When in "debug" mode as set in the web.config-
<compilation debug="true" targetFramework="4.5">
Both the full and minified versions of the script are sent to the browser-
<script src="/Scripts/yepnope.1.5.4-min.js"></script>
<script src="/Scripts/yepnope.1.5.4.js"></script>
The script is added using the HTML helper like so-
#section HeadScripts
{
#Scripts.Render("~/js/yepnope")
}
This is an MVC4 project running in Visual Studio 2012 on Windows 7 Professional 64-bit.
Whatever I do I cannot get the {version} wildcard to behave as described in the Microsoft documentation-
Note: Unless EnableOptimizations is true or the debug attribute in the
compilation Element in the Web.config file is set to false, files
will not be bundled or minified. Additionally, the .min version of
files will not be used, the full debug versions will be selected.
For ASP.NET MVC 4, this means with a debug configuration, the file
jquery-1.7.1.js will be added to the bundle. In a release
configuration, jquery-1.7.1.min.js will be added. The bundling
framework follows several common conventions such as:
Selecting “.min” file for release when “FileX.min.js” and “FileX.js”
exist.
Selecting the non “.min” version for debug.
Ignoring “-vsdoc”
files (such as jquery-1.7.1-vsdoc.js), which are used only by
IntelliSense.
The {version} wild card matching shown above is used to
automatically create a jQuery bundle with the appropriate version of
jQuery in your Scripts folder. In this example, using a wild card
provides the following benefits:
Allows you to use NuGet to update to a newer jQuery version without
changing the preceding bundling code or jQuery references in your view
pages.
Automatically selects the full version for debug configurations
and the ".min" version for release builds.
If I add "EnableOptimizations" it seems to behave as expected.
Has anyone else noticed this or found a solution?
MVC4 only knows how to handle a .min.js file. It doesn't recognize -min.js (with a dash).
The way I typically do this, with easy success, is to get rid of any .min.js or -min.js files provided by libraries that provide both a .js and either a .min.js or -min.js. By default, MVC will automatically minify any bundled .js files when you deploy your website, so there's no need to use the provided .min.js or -min.js files.
This isn't necessarily a direct answer to your particular question - it's a way to circumvent the problem entirely.
Related
I created a new .NET 6 Blazor Server-side project and made a couple of changes. I have a couple of files using CSS isolation (like Contact.razor + Contact.razor.css).. In the _Layout.cshtml page the template added the following:
<link href="CustomerPortal.styles.css" rel="stylesheet" />
Where CustomerPortal is my Project Name. I can see the file is generated correctly under "CustomerPortal\CustomerPortal\obj\Debug\net6.0\scopedcss\projectbundle\CustomerPortal.bundle.scp.css" and "C:\Data\Git\WebApps\CustomerPortal\CustomerPortal\obj\Debug\net6.0\scopedcss\bundle\CustomerPortal.styles.css"
BUT when I run the project, both with Kernel or IIS Express, I get a 404 not found for the CSS, if I try to manually navigate to the CSS I also can't find it. Any ideas? My csproj doesn't have any flags that would affect it.
Edit:
There is a new extension as part of the minimal setup in .NET 7, and backported to newer versions of .NET 6 as well.
Both in .NET 7 and .NET 6 you can now do:
builder.WebHost.UseStaticWebAssets();
Old answer:
You've got a couple options here to resolve this depending on the approach you want to take. I think we've figured out why it's happening, but UseStaticWebAssets() seems to not be supported for the new minimal startup code. So, here's your options I can think of off the top of my head.
Migrate your code back to the "old" way of doing application startup. This is still a supported and completely valid approach as there's edge cases that aren't supported (like this one).
Pass a new WebApplicationOptions to the CreateBuilder() method and, depending on environment, look for the static files in a separate (and correct) location. See some examples here.
With the existing builder, check the environment and use the StaticWebAssetsLoader to load static web assets.
A complete example of #3
if (builder.Environment.IsEnvironment("Local"))
{
StaticWebAssetsLoader.UseStaticWebAssets(builder.Environment, builder.Configuration);
}
That being said - I'd imagine they'll plug this hole eventually and provide parity for UseStaticWebAssets(). You can see the progress of this effort in this open GitHub issue.
For anyone else...
I had the exact same issue with a .net 6 blazor server app. For me it came down to the fact that I had changed the project name but the reference to {project}.styles.css in _Layout.cshtml was still pointing to the old project name.
Simply updating {project} here to the correct project name fixed my issue.
When I encountered this error, it was because I'd named my MVC project with a hyphen: htmx-spike.
When I generated the project from a template (dotnet new mvc -o htmx-spike), the tooling renamed the namespace to htmx_spike—with an underscore instead of a hyphen, because hyphens aren't allowed in C# identifiers—and used that modified name as the CSS filename in _Layout.cshtml.
However, it turns out that in this case the CSS location actually still corresponds with the project name, with the hyphen. So the auto-generated code is incorrect, and was causing the 404 to be returned:
Once I renamed the file in the link element to the correct name with the hyphen, everything was fine.
I had the same issue with a component I imported from another project. I solved it by closing all instances of Visual Studio, deleting the hidden folder [.vs] from the project folder, and then restarting the project in Visual Studio. On restart, Visual Studio recreated that folder and imported CSS file(s) were included.
I have a huge web application that bundles and minifies a huge amount of javascript and css files.
When we release a new version, we notice that at the first request of each page (controller + view) the software takes a lot of time to respond. So, I started to search a little bit and find out Bundle Caching and it seems when some .js or .css files are changed, the bundle will create a new token. But I have some doubts about it:
When exactly the join and minification of the files is made? It is when it is called at the first time on a view?
There is a possibility that when the software is build, the files will be joined and minified during that process, so when at the first time the virtual path is called, this process already had occurred and cached?
If the slowly problem about my application is not the bundling and minification of the files, what could be?
Thank you.
Note: I'm talking about the process in a production environment. So,
thinks like putting debug=false in the web.config I already have.
1) I would not bet on this one, but I am pretty sure that this needs to be done upfront provided that the version of the bundle is appended to the path as a query string parameter. Since this value is the hash of the bundle result, this needs to be done before any bundle can be downloaded in order for ASP.NET to even be able to add this parameter when you do something like this:
#Url.Content("~/bundles/yourbundle")
Whether it is calculated the first time the bundle url is rendered into the view or at app startup is something I don't know. I still post this answer because I believe I can give you useful information for the 2) and 3) points.
2) It is possible to bundle your files beforehand. You can either use some Gulp or Grunt task, use the Bundler & Minifier extension, or any tool of your preference. In that case, however, you are not required (or even advised1) to use virtual paths as these tools produce physical files. However, you will need to make sure yourself that they are versioned properly so whenever you change some input file, the clients will be forced to download the new one instead of using the one in their cache.
3) Keep in mind that C# is not compiled to machine code. Initial slowness can, and usually is, caused by something called JITting (which is explained in greater detail here), that is, the process of transforming the IL code into machine code. This is a rather lazy process in that it basically happens just before the actual execution of your code. If, for example, you have a method A, it does not get transformed to machine code up until it is actually invoked. Therefore, the first access of every controller/action is slower than subsequent ones (because after the first run, the resulting machine code is kept).
You can also configure your project to compile your views which will cause your app to be slightly faster at the cost of making the build process slower.
1 It is advisable to use physical paths if the files are actually physically present on the disk because like that, you can skip the virtual path resolving process altogether thus making script loading to be a little bit faster.
Bundling and minification is enabled or disabled by setting the value of the debug attribute in the compilation Element in the Web.config file. In the following XML, debug is set to true so bundling and minification is disabled.+
XML
<system.web>
<compilation debug="true" />
<!-- Lines removed for clarity. -->
</system.web>
To enable bundling and minification, set the debug value to "false". You can override the Web.config setting with the EnableOptimizations property on the BundleTable class. The following code enables bundling and minification and overrides any setting in the Web.config file.
C#
public static void RegisterBundles(BundleCollection bundles)
{
bundles.Add(new ScriptBundle("~/bundles/jquery").Include(
"~/Scripts/jquery-{version}.js"));
// Code removed for clarity.
BundleTable.EnableOptimizations = true;
}
Unless EnableOptimizations is true or the debug attribute in the compilation Element in the Web.config file is set to false, files will not be bundled or minified. Additionally, the .min version of files will not be used, the full debug versions will be selected. EnableOptimizations overrides the debug attribute in the compilation Element in the Web.config file
I'm trying to build a redistributable assembly containing several custom controls (CommonControls).
My environment: MSVC 2010, ASP.NET (WebForms) .NET 2.0/3.0/3.5
The problem: Compiling everything with a Web Deployment Project won't work if I localize CommonControls via App_GlobalResources.
Here is how I build the CommonControls assembly:
I use a WebSite containing the .ascx and .ascx.cs files:
and a Web Deployment Project with the following settings:
This will create "CommonControls.dll".
That assembly is to be used in a different ASP.NET WebApplication as follows:
web.config:
First (minor) problem: Adding CommonControls as a dependency will not automatically copy the satellite assemblies for the languages. Copying them manually to the correct output path seems to work though (for DEBUGGING).
Main problem: The Main web application is also localized via App_GlobalResources and built with a Web Deployment Project:
That build process will fail with
ASPNETCOMPILER : error ASPRUNTIME: Object reference not set to an
instance of an object.
Both deployment projects create a file named "bin\App_GlobalResources.compiled" and I guess those 2 files cannot coexist peacefully within the same output-project.
Is there any elegant solution to localize both CommonContols AND Main using ASP.NET built-in localization?
Note: The project I'm working on has to be compatible with Apache+Mono, so my project-settings (screenshots above) must be exactly like this to work correctly (already tested all other variations).
I fixed it. It was (probably) caused by outdated assemblies in the Bin folder used by the WDP (seems to be a good idea to manually clean that folder from time to time).
I also copied files from "CommonControls\Bin" to the final output (via pre-build event) which is not necessary and causes everything to break (satellite assemblies for translations are automatically copied by MSVC).
While my problem+solution might not be that helpful to others, it's at least a tutorial how to build a re-distributable assembly with some custom-controls out of a bunch of user-controls.
Notes:
All outputs of the custom-control assembly must be merged. Otherwise we will end up with 2 "App_GlobalResources.dll" files (won't work)
It only works with a "Web-site project", not "Web application"
User-controls must use the "CodeFile/Inherit" tags, not the deprecated "CodeBehind" tag (get rid of all those ".designer.cs" files!)
User-controls must have a "ClassName" tag that differs from the control's name (I appended "Internal" and renamed the class(es) in code-behind)
Embedded resources (images, scripts...) are not directly supported in a "Web-site project". I use an additional LIB for that
I have two questions, one about a bug and one about cdn
QUESTION 1: (BUG)
I have just added the new NuGet package: Microsoft ASP.NET Web Optimization Framework 1.0.0.
I'm using ASP.NET MVC 3, and everything seems to be working except for one major bug.
If I use debug="true" in web.config, then no script tags ever get outputted. I checked the view source and there are no tags for that bundle at all.
If I set debug="false" then I get the script tag that points to my minification file.
*Is this a bug? Has anyone else experienced that? *
As a workaround so that I'm at least able to debug my application, I forced optimization on regardless if I'm in debug mode or not BundleTable.EnableOptimizations = true;
QUESTION 2: (CDN)
Also another question I have is about the CDN Support:
bundles.Add(new ScriptBundle("~/bundles/jquery",
jqueryCdnPath).Include(
"~/Scripts/jquery-{version}.js"));
If I want to add another script with CDN support, then I would have to add another bundle, therefore if UseCdn="false", then it will try and load up 2 scripts separately, meaning 2 requests. Is there any way to have CDN support for multiple scripts so that it will combine them into 1 request if UseCdn="false"?
Something like this:
bundles.Add(new ScriptBundle("~/bundles/multiple").Include(
"~/Scripts/jquery-{version}.js", jqueryCdnPath,
"~/Scripts/jquery-ui-{version}.js", jqueryUICdnPath,
));
Regards DotnetShadow
Could you expand on what isn't working on in your MVC3 app, i.e. how are you using the Scripts/Styles.Render methods?
In regards to #2, currently the CDN support is only on a per bundle basis. So you will not be able to do the conditional bundling that you want and use cdn (unless you had access to a CDN which you could upload new content to, then you could just upload your bundle to the CDN)
I have an ASP.NET application which features some server-side includes. For example:
<!--#include virtual="/scripts.inc" -->
These files are not present in my ASP.NET website project because my website starts in a virtual directory:
/path-to-my-application
When I choose Build Web Site, I get this error:
Failed to map the path '/scripts.inc'
Visual Studio cannot resolve these include files that are defined at the root directory level. They are not visible in the website project.
Aside from manually commenting out the #include references, is there any way I can get the website to build? Can I force Visual Studio to ignore those errors and compile the site?
Once the website is pushed out to IIS, there is no problem, because all the #include files are in place.
NOTE - Web Controls are not an option for this application. Please assume #include files are a requirement. Also, I cannot move the include files since they are used by other applications.
Can you make a copy of the includes files, place them in your solution on your dev machine and then tell VS not to copy those on build output (Build Action = None)?
If not, why don't you just hard code the entire link to the scripts.inc file (http://oursite.com/scripts.inc). Sucky work around, but I am pretty sure that you can't just ignore compilation errors (but yes to warnings).
Try using the ~/ syntax to represent the root of your app. e.g.
<!--#include virtual="~/scripts.inc" -->
try this:
Replace the SSI directive in your .aspx file with this:
<asp:Literal runat="server" id="scriptsIncLiteral" />
And put this in your code-behind:
protected override void OnPreRender(EventArgs e)
{
string scriptsFile = Request.MapPath(".") + #"..\scripts.inc";
scriptsIncLiteral.Text = System.IO.File.OpenText(scriptsFile).ReadToEnd();
}
You will of course have to change the number of ..\s if the scripts.inc file is located more than one directory up. You will also have to ensure that your ASP.NET web application has access to this file, otherwise you'll get a System.UnauthorizedAccessException.
You can set up a pre-build task in Visual Studio to copy include file in the project directory each time the project is built before the actual build. Although this is a hack.
A more correct way would be to set up a solution with two projects: one will represent your web-server's root directory/a set of the applications with which your project interacts (through including a shared file). Another will represent your troubled project. Then you should include (as in include as files into the project) your inc file(s) into the first project, for it to make them visible for a second project and allow it to include (as in server-side include in ASPX) them.
It is a way with more hassle, but it mirrors your situation much more closely, no hack, and can bring you some bonus features farther along the road (like easier intergration/representation of connected projects).