ASP.NET - path to use to reference .CSS and .JS - javascript

I have a Master Page in the root of my project. I have Content Pages throughout my project and in subfolders referencing this Master Page. What is the correct way to reference my .CSS and .JS files if I always want them to be relative to the root?
Here is how I'm doing it now:
link href="/common/css/global.css"
script src="/common/javascript/global.js"
But that breaks the link. I tried without the leading "/" but that didn't work on my pages in the subfolders.

I would use something like
Server.ResolveClientUrl("~/common/css/global.css")
This will get a proper url for you at all times.
Example:
Per the comment this would be full usage.
<link type="text/css" rel="stylesheet"
href='<%= Server.ResolveClientUrl("~/common/css/global.css") %>' />
According to comments, other validated usage, no "error CS1061: 'System.Web.HttpServerUtility' does not contain a definition" error:
<script type="text/javascript"
src="<%= Page.ResolveUrl("~/Scripts/YourScript.js") %>" ></script>
Also is important to always put the closing tag .

You can make the <link> tag to run at server so Asp.Net will resolve the URL for you like this:
<link href="~/common/css/global.css" runat="server" />
(Notice the '~')
I don't know if it can be applied to the <script> tag though, you should try...
EDIT: I discovered recently on a project that you can (and should) use a ScriptManager to hold your scripts (you can only have 1 per page). You can put one in your MasterPage and reference all your scripts. Inside your content page, you then add a ScriptManagerProxy that will 'reference' the scripts on the master page and you can even add other scripts for that content page only.

I do it as simple as this: link href="<%=ResolveUrl("~/common/css/global.css")%>"

The solutions I saw so far didn't work in my project (especially not for .css links). The issues were the following:
inside <link> it didn't resolve the <%=...%> expression
it did not find the Page.ResolveURL in all cases
there was some trouble with ' and " quotes if you embedd <%=...%>
So I'd like to offer this solution: In code behind (your master page's C# class), add the the following 3 methods:
public partial class SiteBasic : System.Web.UI.MasterPage
{
public string ResolveURL(string url)
{
var resolvedURL=this.Page.ResolveClientUrl(url);
return resolvedURL;
}
public string cssLink(string cssURL)
{
return string.Format("<link href='{0}' rel='stylesheet' type='text/css'/>",
ResolveURL(cssURL));
}
public string jsLink(string jsURL)
{
return string.Format("<script src='{0}' type='text/javascript'></script>",
ResolveURL(jsURL));
}
}
For stylsheet references, you can then say:
<%=cssLink("~/css/custom-theme/jquery-ui-1.8.20.custom.css")%>
For JavaScript references, it looks like so:
<%=jsLink("~/Scripts/jquery-1.7.2.js")%>
And for other references, you can use:
<a href='<%=ResolveURL("~/Default.htm")%>'>link</a>
<img title='image' src='<%=ResolveURL("~/Images/logo.png")%>'/>
Note: I found it is better to use single quotes outside and double quotes inside the href or src attribute as shown in the example above. Doing it vice versa caused trouble in some cases as I found.
This solution is simple and it worked well in my case, even if the pages referencing the master page reside in different subdirectories. What it basically does is translating the ~ path (which needs to be absolute from the root of your web site) into a relative path (using as many ../ in the path as needed) based on the page you're currently displaying.
Advanced hint:
If you're using AJAX calls to invoke web service methods, then you'll have the same issue referencing them if you have ASPX pages on different directory levels. I recommend you define something like (assuming that your web services reside in the directory ~/AJAX):
<script type="text/javascript">
function getWebServicePath() { return '<%=ResolveURL("~/AJAX/")%>'; }
</script>
inside the <head> ... </head> section of your master page. This will make the entry path of the web service available in your JavaScript. You can use it like
$.ajax({
type: "POST",
url: getWebServicePath()+"myWebService.asmx/myMethod",
data: $.toJSON({ param: "" }),
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (msg) {
// ... code on success ...
},
error: function (ex) {
// ... code on error ...
}
});

Related

Browser attempts to load JS file from invalid address, when accessing razor page through URL

I have set a razor page as the landing page for my application:
options.Conventions.AddAreaPageRoute("Home","/Home/Index", "");
My pages are all contained in areas, so in order to access them by url more easily I wanted to avoid writing the additional area name, so from Home/Home/page to Home/Index:
options.Conventions.AddAreaPageRouteModelConvention("Home", "/Home/Index", model =>
{
foreach (var selector in model.Selectors)
{
selector.AttributeRouteModel = new AttributeRouteModel
{
Template = new string(selector.AttributeRouteModel.Template.SkipWhile(c => c != '/').Skip(1).ToArray()),
};
}
});
I also modified my app settings:
app.UseMvc(routes =>
{
routes.MapRoute(
name: "Default",
template: "{area=Home}/{page=Index}");
});
I removed all the other mapRoutes, including controller routing, etc.
After I added this snippet I tried accessing the pages by /Home/Index, and it worked, however my js scripts are not loading and thus not functioning. Then I removed the aforementioned option and attempted to access the page by Home/Home/Index and my scripts were still not loading. They do load property if I use the anchors I have set up:
<a class="nav-bar-brand" asp-area="Home" asp-page="/Home/Index">...</a>
The script file is included in the Layout:
<script src="js/site.js" type="text/javascript"></script>
The problem appears to be that the browser is looking for the file in the wrong place, this is the Request URL that the General header contains "https://localhost/Home/Home/js/site.js", while in reality the proper address is "https://localhost/js/site.js", why is this happening and how do I fix it?
<script src="**~/**js/site.js" type="text/javascript"></script>
You must update your code thats. (
/
or
~/
get starting on domain root folder)

How to check if JSF resource exists before loading view

In a project using JSF, we have JavaScript files located here:
MyProject/view/javascript/*.js
In the xhtml file, I include these resources as
<script type="text/javascript" src="javascript/#{myBean.jsFileName}.js" />
This works fine, but it's possible that #{myBean.jsFileName}.js doesn't exist, in which case I want to load "Default.js".
In myBean (or in the xhtml file itself), how can I first check for the existence of a js file before setting the #{myBean.jsFileName} value? I've tried variations of this:
File f = new File("javascript/myFile.js");
if (!f.exists){ jsFileName="Default"};
But I don't think that's right. Am I on the right track?
You can use ExternalContext#getResource() to obtain a web resource as URL. It will return null if resource doesn't exist. It takes a path relative to the web root and should preferably always start with /.
So. this should do in bean:
String fullPath = "/view/javascript/myFile.js";
URL resource = FacesContext.getCurrentInstance().getExternalContext().getResource(fullPath);
if (resource == null) {
fullPath = "/view/javascript/default.js";
}
Or, equivalently, this in the view, which is IMO somewhat hacky:
<c:set var="available" value="#{not empty facesContext.externalContext.getResource(bean.fullPath)}" />
<script src="#{available ? bean.fullPath : bean.fullDefaultPath}" />
See also:
getResourceAsStream() vs FileInputStream
Unrelated to the concrete problem, if you were using JSF 2.x (at least Facelets, as implied by being able to use unified EL in template text in your code snippet), you should be using resource libraries with <h:outputScript>. See also How to reference CSS / JS / image resource in Facelets template?

Rewriting Root Directory Path "/" for Javascript

We can modify the document root directory path for PHP using
$_SERVER['DOCUMENT_ROOT'] = "to/some/new/directory";
//Now the "/" which represent the ^(above) path
in .htaccess we have
RewriteBase "/to/some/new/directory"
Now, I need to modify the root directory path to use in javascript. How to do it?
Currently, I am declaring a variable containing static path to the my personalized root directory and using it as
var root = "../to/new/path";
document.location = root+"/somepage.php";
Scenario
I think i should tell a little bit about the scenario, for you guys to catch my idea
Default Web Root Directory
http_docs/
inside it contain a main folder
http_docs/application <-- contains the actual application
http_docs/js <-- contains the script
http_docs/index.html
Now, the application also contains ajax feature for updating, editing, loading new content, or other resources, which if accessed at "/" will represent at /some/path/i/called not /application/some/path/i/called,
To come around this problem
I can define a static variable like
var root = "application/";
and use it somewhere like
$.post(....., function(data) { $(body).append("<img src='"+root+"resources/img1.jpg"); });
But for a single use, defining the path as static, might not be a big deal, but, when the application grows, and certain modification would cause me to change all the paths i give in the js part. I thought, it would be sensible, just like, I do it in PHP, using <img src="/resources/img1.jpg" />
I tried my best to explain this question, if still is not understandable, please community, lets help them understand. I welcome you to edit my question.
EDITED: Trying to answer the updated question
Assuming the JavaScript is called included from the index.html file, if you insert a img tag and use relative urls, they will be relative to the path of the index file. So <img src='application/resources/img1.jpg'> would work just fine. If the script should work for several sublevels (e.g. if the page "application/etc/etc2/somePage.html" needs images from "application/resources/")it may be easier to use absolute urls, and you could include a javascript block on every page generated by php that holds the absolute url to the "root" of the application, like:
<!-- included by php in all html pages, e.g. in defautlHeadter.php -->
<script type="text/javascript">
var rootUrl = "<?= getTheRootUrl() ?>";
</script>
Where getTheRootUrl() is a method or server variable that gives the root url you need. If the url is translated/remapped (by apache etc. outside of what is visible to php) you may need to hardcode the root url in the php method but at least it will be only one file to change if you ever change the root directory.
Then you can use the root url to specify absolute paths anywhere in the application/website using rootUrl + "/some/relative/path" in anywhere in the application.
I once made something like this, to set
window.app_absolute = '<?php echo GetRelativePath(dirname(__FILE__)); ?>'
I also use something like this
static function GetRelativePath($path)
{
$dr = $_SERVER['DOCUMENT_ROOT']; //Probably Apache situated
if (empty($dr)) //Probably IIS situated
{
//Get the document root from the translated path.
$pt = str_replace('\\\\', '/', Server::GetVar('PATH_TRANSLATED',
Server::GetVar('ORIG_PATH_TRANSLATED')));
$dr = substr($pt, 0, -strlen(Server::GetVar('SCRIPT_NAME')));
}
$dr = str_replace('\\\\', '/', $dr);
return substr(str_replace('\\', '/', str_replace('\\\\', '/', $path)), strlen($dr));
}
... Something along those lines, hacked up for demonstration purposes.

Get path to image

I wrote a javascript method to display an image dynamically depending on whether or not a plugin is installed or not. Depending on the page, the url might be deep into sub paths and i wanted to see if i can get a path back to the image without all the marky-mark.
Example
myImage src location = {root}/Content/Images/myImage.png
Now call the js to display the image on the following pages. I show the path of the example page and the image element with the src path. Notice how its different depending on how deep we are. If i use an absolute path, then i would have to change it for my test environment and production. I thought I could use ~ but i guess not. Ideas ?
http://mysite.com/sub1/sub2/ -- <img src="../../Content/Images/myImage.png" />
http://localhost:2500/sub1/ -- <img src="../Content/Images/myImage.png" />
The tilde is only relevant for .NET server side code.
An easy way to accomplish what you're looking for is to write the root path out to a javascript variable or function.
For example on the server side on your page:
public string RootPath
{
get
{
return ResolveUrl("~/");
}
}
And then use the following javascript:
<script type="text/javascript">
<!--
function getRoot()
{
return '<%= RootPath %>';
}
// -->
</script>
You can then use the javascript getRoot function to get to the root of the website and use it for your urls.

~/ equivalent in javascript

Any smart way of doing a "root" based path referencing in JavaScript, just the way we have ~/ in ASP.NET?
Have your page generate a tag with something like:
<link rel="home" id="ApplicationRoot" href="http://www.example.com/appRoot/" />
Then, have a function in JavaScript that extracts the value such as:
function getHome(){
return document.getElementById("ApplicationRoot").href;
}
Use base tag:
<head>
<base href="http://www.example.com/myapp/" />
</head>
...
from now any link use on this page, no matter in javascript or html, will be relative to the base tag, which is "http://www.example.com/myapp/".
You could also use the asp.net feature VirtualPathUtility:
<script>
var basePath = '<%=VirtualPathUtility.ToAbsolutePath("~/")%>';
</script>
Notice: I don't encode the path to a JSON-string (escape quotes, control characters etc). I don't think this is a big deal (quotes for example aren't allowed unescaped in an URL), but one never knows...
I usually create a variable at the top of the js file and assign it the root path. Then I use that variable when referencing a file.
var rootPath = "/";
image.src = rootPath + "images/something.png";
~/ is the application root and not a literal root, it interpets ~/ to mean <YourAppVirtualDir>/
To do a literal root in JavaScript it's just /, i.e "/root.html". There's no way of getting an application level path like that in JavaScript.
You could hack it in the ASPX file and output it in a tag but I would consider the security implications of that.
Kamarey's answer can be improved to support a dynamic base path:
<head>
<base href="http://<%= Request.Url.Authority + Request.ApplicationPath%>/" />
</head>
This will ensure a correct root path regardless of deployment configuration.
To be fair, this doesn't answer the original question, but it elimiates most needs for getting the root path from javascript. Simply use relative URL's everywhere, without prefixing with slash.
Should you still need to access it from javascript, add an id attribute and use document.getElementFromId() as MiffTheFox suggested - but on the base-tag.
Another option that's a bit simpler and more universal would be to take the following:
<script src="/assets/js/bootstrap.min.js"><script>
and use Page.ResolveClientUrl like so:
<script src='<%=ResolveClientUrl("~/assets/js/bootstrap.min.js")%>'></script>
then regardless of what subdirectory the urls will always be rendered correctly.
The following function will calculate the root of the currently running application. I use it to locate the absolute location of resources, when called from somewhere deep within the application tree.
function AppRoot() {
//
// Returns the root of the currently running ASP application.
// in the form: "http://localhost/TRMS40/"
//
// origin: "http://localhost"
// pathname: "/TRMS40/Test/Test%20EMA.aspx"
//
// usage:
// window.open( AppRoot() + "CertPlan_Editor.aspx?ID=" + ID);
//
var z = window.location.pathname.split('/');
return window.location.origin + "/" + z[1] + "/";
}
In the PreRender of your .NET base page, add this:
protected override void
OnPreRender(EventArgs e) {
base.OnPreRender(e);
if (Page.Header != null)
{
//USED TO RESOLVE URL IN JAVASCRIPT
string baseUrl = String.Format("var baseUrl='{0}';\n",
HttpContext.Current.Request.ApplicationPath);
Page.Header.Controls.Add(new LiteralControl(String.Format(Consts.JS_TAG,
baseUrl)));
}
}
Then in your global JavaScript function, add the following:
function resolveUrl(url) {
if (url.indexOf("~/") == 0) {
url = baseUrl + url.substring(2);
}
return url; }
Now you can use it like this:
document.getElementById('someimage').src = resolveUrl('~/images/protest.jpg');
May be a little much for some projects, but works great for full fledged applications.
Solution for ASP.NET MVC applications
This works when using IIS and also IIS Express in VS.
Put this snippet before all scripts load, in order to have the root url variable "approot".
at your service in the scripts:
<script>
var approot = "#Url.Content("~")";
</script>
--> other scripts go here or somewhere later in the page.
Then use it in your script or page script.
Example:
var sound_root_path = approot + "sound/";
var img_root_path = approot + "img/";
the approot variable will be something either:
"/YourWebsiteName/" <-- IIS
or just:
"/" <-- IIS Express
For ASP.net MVC Razor pages, Create a base tag like below in the <Head> tag
<base href="http://#Request.Url.Authority#Request.ApplicationPath" />
and in all your relative javascript URLs, make sure to start without a slash(/) otherwise it will refer from the root.
For ex. create all your urls like
"riskInfo": { url: "Content/images/RiskInfo.png", id: "RI" },
or
$http.POST("Account/GetModelList", this, request, this.bindModelList);
If you want to use it in HTML Still you can use ~, see this
href = #Url.Content("~/controllername/actionName")
See the check box click event in my MVC Application
#Html.CheckBoxFor(m=>Model.IsChecked,
new {#onclick=#Url.Content("~/controller/action("+ #Model.Id + ", 1)"),
#title="Select To Renew" })

Categories