Links in area Layout to Content\Css folder located in the root of ASP NET MVC application - css

Good morning/day/evening/night, everyone,
Asking for your ideas in dealing with Area in ASP NET MVC.
My application has several areas, and each one has its own _Layout. How can I make links inside it to Css subfolder (the same with Scripts) located in Content folder in the root? Layouts from areas use identical css and image files, so I doubt I should create new Content folder inside each Area and duplicate identical files. Please explain how I should solve the problem. And many thanks in advance.

You can use the virtual root path operator ~
The templated _Layout created for you gives you an example.
<link href="~/Content/bootstrap.min.css" rel="stylesheet" type="text/css" />
...
<script src="~/Scripts/bootstrap.min.js"></script>
Even inside an Area it will resolve to the root Content and Scripts so that resources, Bootstrap in this example, do not need to be copied for each Area.
Keep in mind this is resolved server-side.
So if you need to access it in script on a view page:
<script>
var scriptRoot = "#Url.Content("~/Scripts")";
</script>
And in controller code:
public ActionResult Index()
{
ViewBag.BoostrapPath = Url.Content("~/Content/boostrap.css");
return View();
}

Related

Getting static web context resources to work on both bookmarkable and non-bookmarkable Wicket pages

In a Wicket 1.4 app, I have some static CSS & JS resources under [project root]/WebContent/css and [project root]/WebContent/js respectively.
My Wicket HTML files are in src/resources/fi/company/product/pages with corresponding Java classes in src/main/fi/company/product/pages. (In the resulting WAR file, the HTML & property files are of course in the same places as Java classes.)
The HTML files contain references to the resources such as:
<head>
<link rel="stylesheet" type="text/css" href="css/main.css"/>
<script type="text/javascript" src="js/calendar.js"></script>
</head>
This works fine everywhere (or so we thought until recently). NB: my Java code does not reference these resources at all.
Looking at the source of a rendered page (whose URL is e.g. http://localhost:8080/report/42.4 or http://localhost:8080/?wicket:interface=:6:::: ), the resource reference appears as:
<link rel="stylesheet" type="text/css" href="../css/main.css"/>
However, we just noticed that when the app is deployed somewhere else than (Tomcat) root, the resources break on non-bookmarkable pages.
In other words, when the URL is e.g.
http://localhost:8080/foobar/?wicket:interface=:2::::
and a page refers to
<link rel="stylesheet" type="text/css" href="../css/main.css"/>
...the browser tries to fetch the resource at the invalid URL
http://localhost:8080/css/main.css
Now, what is the simplest (yet non-hacky) way to get these static resources working, regarless of the deployment path?
I could switch to using bookmarkable pages exclusively (which would require changing the constructors of the pages), but I suppose that shouldn't be necessary...
Edit: Looks like I got CSS resources working (on most places) simply by using <wicket:link>, as advised in this answer:
<head>
<wicket:link>
<link rel="stylesheet" type="text/css" href="css/main.css"/>
</wicket:link>
</head>
However, now the CSS references are broken on a page with an URL like http://localhost:8080/foobar/report/42.9
Wicket is trying to do something strange with the "css/main.css" path:
ERROR org.apache.wicket.RequestCycle - Can't instantiate page using constructor public fi.company.product.pages.ReportPage(org.apache.wicket.PageParameters) and argument 0 = "css" 1 = "main"
org.apache.wicket.WicketRuntimeException: Can't instantiate page using constructor public fi.company.product.pages.ReportPage(org.apache.wicket.PageParameters) and argument 0 = "css" 1 = "main"
at org.apache.wicket.session.DefaultPageFactory.createPage(DefaultPageFactory.java:212)
at org.apache.wicket.session.DefaultPageFactory.newPage(DefaultPageFactory.java:89)
at org.apache.wicket.request.target.component.BookmarkablePageRequestTarget.newPage(BookmarkablePageRequestTarget.java:305)
Edit 2: Actually I'm not sure if <wicket:link> is the right solution here, since these resource files are not "class path resources". I guess my question is, can you make this work while still using web context resources (i.e., without making these class path resources)?
Right, I solved it, and the solution turned out to be very surprising.
Earlier I wrote:
A curious thing is that without any changes, it seems I can no longer
reproduce the problem...
That wasn't quite true, as I had made one small change (that I thought was inconsequential): I had deleted a file WebContent/index.jsp which in our project was a remnant that served no purpose.
Once it dawned on me that this could have fixed it, I did some more testing, and indeed:
For static resources to work as expected, you must not have an index.html or index.jsp file in the root web content directory (i.e., the parent of the CSS and JS resource dirs), as that in some cases breaks ../ references.
This probably isn't even Wicket-specific, but perhaps it is Tomcat-specific—if anyone knows more, feel free to chime in. I'm dubious whether this question ever helps anyone else, but still, glad I got it working!

ASP MVC import CSS

I am new to ASP.NET MVC and I am trying to include a CSS file into my view.
The view is strongly typed and has a List Scaffold Template, it is linked to a master page which itself is linked to a css file and works fine for the master slide but when trying to link the view to a seperate css file I cant as I cannot include tags.
Anybody know how I can resolve this?
<link href="#Url.Content("~/Content/YOURSTYLESHEET.css")" rel="stylesheet" type="text/css" />
You should add a new content place holder in your site.master page in the head tags, i always have one called "HeadContent" which i use for inclusion of scripts and css that i only want on individual pages.

Problem with referencing CSS and JavaScript files relatively

I have an IIS web site. This web site contains other web sites so the structure is like this.
\
MainWebSite\
Scripts\
CSS\
App1\
Scripts\
CSS\
App2\
Scripts\
CSS\
All sites are ASP.NET MVC web applications.
In the MasterPage of App1, I reference the script files like this:
<script type="text/javascript" src="../../Scripts/jquery-ui-1.8.custom.min.js">
</script>
The problem is that it now tries to find the file at http:\server\MainWebSite\Scripts....
How can I work around that? Should I put all my scripts and CSS files into the root directory, is that a preferred solution?
In ASP.NET there is a great function that is part of the Page Object:
ResolveUrl(String)
This is used by passing in a relative string, but the best part is you can use the ~ to symbolize the root of your website:
<script type="text/javascript" src='<%=ResolveURL("~/PATH_FROM_ROOT/Scripts/jquery-ui-1.8.custom.min.js")%>'></script>
[Note the single quotes.]
Try this
<script type="text/javascript" src="~/../Scripts/jquery-ui-1.8.custom.min.js" runat="server"></script>
In the above markup, I'm assuming that your script files are in MainWebSite\Scripts\
"~" brings your reletive reference from your application root directory. The benefit is that if you shift your master page file from MainWebSite\App1\ to MainWebSite\App1\MasterPages\ you will not have to change all the relatively referenced urls in your master page.
The best solution is to use absolute URLs for CSS and JavaScript. Using an appending global variable you can also use it on your development system, too.

How to Properly Reference a JavaScript File in an ASP.NET Project?

I have some pages that reference javascript files.
The application exists locally in a Virtual Directory, i.e. http://localhost/MyVirtualDirectory/MyPage.aspx
so locally I reference the files as follows:
<script src="/MyVirtualDirectory/Scripts/MyScript.js" type="text/javascript"></script>
The production setup is different though. The application exists as its own web site in production, so I don't need to include the reference to the virtual directory. The problem with this is that I need to modify every file that contains a javascript reference so it looks like the following:
<script src="../Scripts/MyScript.js" type="text/javascript"></script>
I've tried referencing the files this way in my local setup but it doesn't work.
Am I going about this completely wrong? Can somebody tell me what I need to do?
Thanks
Use ResolveUrl("~/")
<script src="<%=ResolveUrl("~/scripts/myscript.js") %>" type="text/javascript"></script>
~/ will get to you the root of your application, virtual or otherwise
Previous answers seem to assume that the Scripts directory always exists as a subdirectory of your application root. If that assumption is correct, and if the page is also at the root, then both of your earlier tags can be simply:
<script src="Scripts/MyScript.js" type="text/javascript"></script>
But my read of your second example is that Scripts isn't always a subdirectory of your application root (because the ../ at the beginning moves up a level, so Scripts would be a peer of your application root). That said, you did say the second example didn't work. :-) But if that's really the case, I'd strongly recommend adjusting one environment or the other so that the relative paths agree, and then always using relative paths as above.
The only reason for using ResolveUrl as far as I know would be if the pages in the application are in a folder structure and the tag may appear in a page at the root or in a page in a "subdirectory". If so, you can use ResolveUrl in both cases so you have an anchor point. I never author things that way, I always ensure I know where the page will be in the hierarchy (if there needs to be a hierarchy) and use an appropriate relative path for the current document.
You can use the HttpRuntime.AppDomainAppVirtualPath property to get the virtual path (if any) for your app and use that to fix up the javascript paths (using <%= ... %> in the <script> tags etc.)
You can further add a global javascript variable in your master page that exposes that value as well, so that any scripts that need to know the actual app root can access it that way.
Another way in MVC5:
1) in the layout html View file, place RenderSection in the place you need the script to be:
<html><body>
#RenderSection("scripts1", required: false)
</body></html>
note that you can change the "Scripts1" to be whatever name you like.
2) in your view html file, just call the "scripts1", doesn't matter where, with your path and js file name:
#Scripts1.Render("~/Scripts/MyScript.js")
3) make sure the MyScript js file is in the Scripts Folder of your project.
That's it.

Base URL in ASP.net Master Pages with virtual Directories

I have an ASP.net master page. In this master, I have all my css and javascript files defined. I also have a few images and a few buttons and hyperlinks.
All the urls are all declared as relative ie "/scripts/ian.js"
Everything works fine if this site is the root website, but I need it to work in a virtual directory.
My problem is when I place this website in a virtual directory under a root site, all my links are pointing to the root site. so my links point to www.root.com/scripts/ian.js but it should be pointing to www.root.com/virtualDir/scripts/ian.js
I thought the Base Href tag in the header would help, but so far it does not seem to be helping in anyway. All the links are still pointing to the root website when i hover over them.
What I would like is a single setting either in IIS or the config file that I can set a root url and any image, script or link either on the master page or content page, would point to the right place.
Any suggestions or ideas are welcome.
Thanks
All the urls are all declared as
relative ie "/scripts/ian.js"
Those seem to be absolute URL's that you're using, rather than relative URL's, which is probably why the <base /> tag isn't having the desired effect:
This attribute specifies an absolute
URI that acts as the base URI for
resolving relative URIs.
-- from http://www.w3.org/TR/html401/struct/links.html#h-12.4
You could try removing the leading '/' from your URL's to see if that works?
Failing that, I tend to use ResolveClientUrl to get around issues like this, which you'd use in the same way as others have suggested using ResolveUrl:
<script type="text/javascript" src="<%= ResolveClientUrl("~/path/to/js") %>"></script>
...
<img src="<%= ResolveClientUrl("~/path/to/img") %>" alt="..." />
Hope this helps.
Most tags, including regular HTML tags like <link>, <img>, etc can use the ~/ as the application root path if the *'runat="server"' attribute is set.
eg.
<img src="~/images/test.png" runat="server" />
This makes tag a server tag and the tilde is replaced with the application root before the output is returned to the browser.
This doesn't work as expected for the <script> though. When 'runat="server' is set for the script tag, then the script is considered to be server-side javascript and execution is attempted.
To work around this you can either inject the javascript using one of the register client script methods. your you can use the <%= ResolveUrl('~')%> tag in your script tag.
This static method returns you full http path to root folder of your application (web site or virtual directory)
public static string GetAppRootUrl(bool endSlash)
{
string host = HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Authority);
string appRootUrl = HttpContext.Current.Request.ApplicationPath;
if (!appRootUrl.EndsWith("/")) //a virtual
{
appRootUrl += "/";
}
if (!endSlash)
{
appRootUrl = appRootUrl.Substring(0, appRootUrl.Length - 1);
}
return host + appRootUrl;
}
So, you can write in master page:
<script src="<%= Server.HtmlEncode(GetAppRootUrl(false)) %>/scripts/ian.js" language="javascript" type="text/javascript"></script>
Use tilde(~) in yout reference (i.e ~/scrips/ian.js)...see if it works
For links try Page.ResolveUrl in the .aspx page.
So I found this IIS weirdness last night:
<script src="/js/file.js"></script>
Will not work properly in a virtual application that's in a subdirectory of the main IIS site.
Instead, you MUST do it like this:
<script src="/js/file.js" type="text/javascript"></script>
Which is the standard way to do it, but if you're not looking for it, it can surprise you that that additional tag makes the relative path issues go away.

Resources