ASP.NET bundling - default virtual paths? - asp.net

As far as I can tell (because frankly documentation on System.Web.Optimization is very sparse), the way bundling works in ASP.NET is that you register a set of files (Javascript or CSS, corresponding with ScriptBundle and StyleBundle), and associate them with a virtual path; for example, ~/bundles/jqueryui for all the jQuery UI scripts. Later, ASP.NET can minify these files when you're running in non-debug mode, and the minified version will be made available at the virtual path you specified for the bundle.
The default bundle setup registers some script bundles with ~/bundles/... as the virtual path, and some CSS with ~/Content/css as the virtual path. My question is, isn't this inconsistent? Wouldn't it make more sense to have something like ~/bundles/js/... and ~/bundles/css/...? In fact, the ~/Content directory actually exists as a real directory, so there's even the chance of a name collision. I'd have thought you'd want your virtual bundle paths to be directories that don't exist by default, and are not meant to be created on the actual filesystem. Is there some reason why ~/Content/css is used for the CSS bundle virtual paths that I'm not understanding?

Great question, and the short story is that in general it doesn't matter at all. However, some script files and CSS depend on their physical location on disk because they use relative paths to reference other content. For example, of you look at the default jQuery UI bundle in new ASP.NET 4.5 project you see it has a rather long path. That's because jQuery's CSS has relative references to some image files. To get those to resolve correctly the paths matter or else things like ".." will not go up to the right parent directory.

Related

Serving static content outside the WAR with Embedded Jetty

I have a WAR (being served through Embedded Jetty) that I'd like to include static files outside the WAR. My goals are:
Serve static files from a path outside the WAR, relative to the directory the Embedded Jetty is running. So, if I invoke the jar in /srv/app, I'd like to configure a URL of http://myapp.com/static/js/my.js to serve /src/app/public/js/my.js.
Secure: No directory listings or ../ path escapes
Not reinvent the wheel: I don't want to write a new Servlet, but rather harness existing capabilities
Ideally (not required): Shadow the static content in the WAR, so that if I have a /src/app/public/index.html, that file will be served, and, if not existent, the WAR's index.html will be served.
Here's what I examined, and where I'm stuck:
DefaultServlet: Seems ideal, but, I can't find any way to have it serve files outside the WAR. Is there a way for the DefaultServlet to serve static content outside the WAR, with paths relative to the app's pwd?
Configuring Jetty, as described in https://www.eclipse.org/jetty/documentation/current/static-content-deployment.html ; this would seem to be ideal, but, when copied in, didn't seem to do anything (it was a NOOP).
ResourceHandler: Is this the right way to do it? I wasn't able to figure out how to use this to make my goals
ResourceHandler: Is this the right way to do it? I wasn't able to figure out how to use this to make my goals
Don't use ResourceHandler, its inferior to DefaultServlet.
Configuring Jetty, as described in https://www.eclipse.org/jetty/documentation/current/static-content-deployment.html ; this would seem to be ideal, but, when copied in, didn't seem to do anything (it was a NOOP).
This only works if you don't share the same contextPath as your deployed webapp.
Is there a way for the DefaultServlet to serve static content outside the WAR, with paths relative to the app's pwd?
Yes, and this has been documented on stackoverflow in a few different ways.
Key is, you'll use extra DefaultServlet entries, defined with their own "Resource Base Path" (which has to be a fully qualified path entry, no relative paths), on different url-patterns.
See:
Serving static files from alternate path in embedded Jetty

CSS/JS bundle in single file in mvc when publish with release option

I have created MVC application. When I publish the application on Azure with release option, all css and js file load in a single bundle in page. (Open view source of page then displays a single link for css).
When I publish a site with Debug option in publish profile then all CSS load individual.
My problem is when publish site with release option theme not load correctly, but with debug option theme loads correctly. I want to publish my application with Release option only. If anyone face this issue before and get any solution then please help me.
I have experienced this before when using bundling.
Say for instance your css file is located at: /Content/css/css.css
This css file then makes a reference to another file, or for example an image at /Content/images/image1.png via url('../images/image1.png').
You then set up your css bundle # /bundles/css.
All appears great in debug mode. However, when you set <compilation debug="false" .... in your web.config, suddenly the references made in the css file breaks. If you open your console in Firebug/Chrome dev tools and check the network tabs, you'll see resources failing to load, from an incorrect URL.
This happens because when debug mode is off, all the files are bundled and minified like they would be in production. In this case, the CSS file would be bundled and served from the URL /bundles/css. This results in the relative URL reference breaking. Where it once referenced /Content/images/image1.png, it now references /images/image1.png.
You have a few options to solve this:
Serve your bundled css files from the same folder as the actual css files. eg. /Content/css/cssbundle. This can become very tedious quickly.
Change all relative references in your css files to absolute references. eg. ../images/image1.png would become /Content/images/image1.png. This does mean you can't use a lot third party CSS bundled out of the box, you would have to check/change relative references if you wanted to bundle them.
Use the BundleTransformer nuget package. It automatically transforms relative urls to absolute ones during the bundling process.
The main differences of StyleTransformer and ScriptTransformer classes from a standard implementations: ability to exclude unnecessary assets when adding assets from a directory, does not produce the re-minification of pre-minified assets, support automatic transformation of relative paths to absolute in CSS-code (by using UrlRewritingCssPostProcessor), etc.
I personally recommend 3 as it is the easiest to maintain long term.

How do I get the ASP.NET content relative path

Doing a project between multiple people, and a few components (web app, services app and some others). We will be storing some information inside the Content folder of the web app so it can be accessed directly from the web server with an href, however other components outside of the web app need to access this folder as well, and since we are sharing the project between multiple people using an absolute path is not an option. What options do we have?
EDIT: Trying to explain it a little better.
What i have exactly is, a web project, a "data project" which is just a dll, a "logic" project which is another dll and a services project which is an exe/service.
Both the web project and service project consumes the methods from the logic, and the logic from the data project. Being the last one the responsable for storing data (in a database) and also in the file system.
This "filesystem" path should be configurable, and we are aiming to put it into the content folder of the web project so multimedia files can be accessed directly rather than doing a byte stream.
Now in the web.config(config file of the web app), and app.config(config file of the services app) i could set the absolute path to web/content (the same for both config files) and the data dll would use it without problems. Now the main problem is that we cannot put an absolute path in the config file because each person works on a different computer with obviously different file paths. So if i could just write something like: ~/project/Web/Content rather than C:/myfolder/stuff/blabla/project/web/content in the config files, with ~ resolving the path to the project, this is what i want! Or maybe better ideas about how to share a folder with these apps without adding absolute paths hardcoded somewhere.
What you want to use is:
Server.MapPath("/Content/filepath.ext");
This will give you the absolute path of a file based on it's position within the website, in this case, from the /Content directory.
For a program external to the website, you have a couple options;
The easiest to implement might be a simple configuration value in the external program which points to the directory. My guess is you've already decided that's not ideal, but it may be the quickest way.
Alternatively, there's a Microsoft .NET assembly which gives you easy access to IIS information (I can't recall its name off the top of my head!). You could use this assembly to find the appropriate website, and retrieve its root directory. I'll see if I can find it and get an example, or maybe someone else will see this and post an answer with that information.
Please check the following method "ResolveClientUrl"
MSDN
Use the ResolveClientUrl method to return a URL string suitable for use by the client to access resources on the Web server, such as image files, links to additional pages, and so on.
http://msdn.microsoft.com/en-us/library/system.web.ui.control.resolveclienturl.aspx

multiversioned sub application asset paths in flex 4

Hopefully someone can help here, more or less looking for a) solution to relative paths or b) insight on another method of loading assets.
We have a standalone web application that is using SDK 4.1 and looks in its relative assets folder for all images and external swfs to be loaded.
on the server, this is the absolute path of the assets directory:
/ApplicationRoot/versionFldr/controls/assets/*
the application uses relative paths in all cases of loading an asset.. and this is continously being added to and updated as we advance versions of the app.
So, in essence, the app is looking for:
assets/*
now forward to the NEW application, lets call it "ParentApp" and the above application "ChildApp".
Parent App is in a different server directory than ChildApp
/ParentApp/version/controls/ParentApp.swf
/ChildApp/version/controls/ChildApp.swf
now, when ChildApp loads into ParentApp, it assumes that it is in the same directory that it's always been in. So, it looks for assets/* and cant find them because
/ParentApp/version/controls/assets/* != /ChildApp/version/controls/assets/*
I need to find a solution to have ChildApp look in an absolute path for ALL loaded assets when it is a child of ParentApp and have it look in paths relative to itself when it is standalone.
The caveats I have are that images are loaded into various controls, caches, and even mx:Text fields (html text with tags). I'm trying to avoid having to globally replace all path links across the application and having to create new coding procedures when new assets are created for the app. ChildApp is in production and has to stay on the 4.1 SDK.
ParentApp is new and has much more flexibility.
I've tried -source-path and -library-path compiler options in childApp, but this lead to compile errors and I have not been able to proceed.
Thank you in advance for any insight and help!
-AJ
I would solve this by having a "baseURL" variable in the child app. Give it a default value so that you can form the usual relative URL's that you are using: `var baseURL:String = "/assets/";
Unfortunately, you then have to modify every asset path in the child app so the path to the assets is something like: baseURL + assetFileName
When the child app is loaded into the parent app, you then give this baseURL variable a non-relative path. Ideally, you do that early in the process, before the child app tries to load any assets.

How might i setup my ASP.NET project to find my files?

edit I do not want to redirect pages, specific files etc. I would like to change the path where images, videos and other media are stored from the root source directory to the directory of my choosing. In this case c:/dev/prjfiles/prjname/public (c:/dev/prjfiles/prjname/ is my working directory) and i except when my html does img src="/pic.png" it will find the image in c:/dev/prjfiles/prjname/publi/pic.png. I need a working solution, i tried looking at how to set virtual directories and etc. I cant figure it out. Thus the bounty. I am generating the html, i am not writing asp:image runat="server" etc i am pulling data from a DB and outputing the html. The part that is still a WIP is the code that handles POST request. The html already exist but i cant have hundreds of files in site.com/here pollution my source directory (c:/dev/trunk/thisprj/thisprj/where my .aspx files are and i do not wish 500 .png/gif/jpg here)
I dont know how asp.net environments are usually set up. I am assuming i have a root path that is not available from the web, a bin/ where i may put my asp.net dll and a public where i stick in any files i want.
I would like to have my project files seperated from everything else. My JS, css and image files are in prjfiles/prjname/public with my sqlite db in prjfiles/prjname/ and extra binaries in prjfiles/prjname/bin.
The problem comes when i run my app and try to load an image. Such as /cssimg/error.png. My project does not find resource in my /public folder and i have no idea how to make it find them. How can i set my project up so it does?
NOTE: I set the working directory path so its at prjfiles/prjname/. In code i write ./bin/extrabin.exe and db.sqlite3 which access the files properly.
You might want to watch the getting started videos for ASP.NET
http://www.asp.net/get-started/
EDIT: More info added
As #Murph suggests, your assumptions are incorrect.
IIS takes care of blocking HTTP access to any important files and folders like your *.aspx.cs, and *.cs in the App_Code, any DLLs, anything under the App_Data directory and the web.config.
Content files, such as *.html, *.css, *.js, .gif, .jpg, .png are all served in the normal manner.
In this way, there is no need for a "public" folder.
I dont know how asp.net environments are usually set up. I am assuming i have a root path that is not available from the web, a bin/ where i may put my asp.net dll and a public where i stick in any files i want.
This is wrong assumption!
You have a root folder, which IS available in public. You set IIS or ASP.NEt Development Server to this folder.
(optional, but always needed) You have a web.config file in this root folder for configuration
You have a bin folder for your assemblies (each page or user control "include" compiles to a class)
(optional) You have App_Data as default folder for file-based DBs and/or other data files (say XML storage, ..)
(optional) You have an App_theme folder for styling and images. Read about ASP.NET themes.
(optional) You can add App_Code folder if you want to add classes to be compiled by the server.
You can create folders for scripts, etc...
Normally for complex logic, etc.. you create in a separate project outside the root and reference the result assembly in the bin folder.
Seriously, you cannot do ASP.NET work without an IDE or a manual. Visual Web Developer 2008 Express IDE is free and http://asp.net has tons of resources for getting started.
I don't know if I got the question right, but maybe you could try the <BASE> HTML tag.
HTML <base> Tag
"Specify a default URL and a default target for all links on a page"
There's a nice and simple example at W3Schools, check it out.
The negative side is that you need to put a <BASE> tag in each page you want.
It sounds like you should be able to create a virtual directory to do what you're asking -- but it's a very non-standard setup.
Keep in mind that IIS will prevent users from downloading DLLs and other project-level files, so you usually don't need to partition them off in a separate layer.
For example, just have a cssimg folder at the top level of your project, and skip the whole public folder thing.
I see where you're coming from. ASP.NET projects are set up a little differently from how you're treating them, but you can make them work like you want.
The root of an ASP.NET project IS publicly accessible. When you created your WebSite within Visual Studio, it created a default.aspx page right on the root. Are you hosting in IIS? If so, it's set up to serve up default.aspx by default. But I digress.
Here's how to make it work like you want (mostly):
Create a WebSite, then right-click the site and add a folder named "prjfiles". Right-click that folder and make another named "public". Create another subfolder of that one called "cssimg".
Now, if you want to use the image you mentioned, you'd reference it like this: "~/prjfiles/public/cssimg/error.png" (pathing starting with the root) or "./cssimg/error.png" if you're coming from a page in the public folder (relative pathing).
Really, though, you're doing too much work. Here's how to make it work with less effort:
Create your WebSite, right-click the project and add a folder called "cssimg".
Treat the root as you would the "public" folder- put your pages right there on the root or in subfolders, as needed. You can reference that same image file like this now: "./cssimg/error.png" (relative) or "~/cssimg/error.png" (start from root)
There's also another way to tell the engine where to look for resources, but it's for your css files. Inside the "head" tag, you can add a "style" element (with type="text/css") and inside that you can add something like this: #import '<%= ResolveUrl("~/prjfiles/public/cssimg/styles.css") %>';
Good luck!
If I correctly understood your problem, you're trying to find files which aren't physically stored on a filesystem folder, or stay on a different folder. You can deal with this problems by implementing a UrlRewrite mechanism.
I suggest you to read URL Rewriting in ASP.NET and, after, to take a look into this implementation: A Complete URL Rewriting Solution for ASP.NET 2.0.
If I understand all this correctly (please comment with any correction) right now all your files are together in the root directory and you use <img src="/img.png" /> and it works.
If this is the case, make another directory in the directory the images are in, say call that directory images and put the image files there. now use <img src="/images/img.png" />.
Done.

Resources