Javascript in Virtual Directory unaware of Virtual Directory - javascript

Say I have the site
http://localhost/virtual
where virtual is the virtual directory
I have an Ajax request that is defined in a javascript file using JQuery
$.getJSON("/Controller/Action")
When this is called, the client tries to find the url at the root level i.e.
http://localhost/Controller/Action
If I add the tilde (~) symbol in, it turns into
http://localhost/virtual/~/Controller/Action
It should (if it was to do what I wanted) resolve to
http://localhost/virtual/Controller/Action
Any ideas on how to fix this?

Aku's hint above looked right but it didn't want to work for me. Finally I figured out to use it like this
<script type="text/javascript">
var config = {
contextPath: '<%= #Url.Content("~") %>'
};
</script>
and then in my JavaScript I use it like this
config.contextPath + 'myAppPath".
So in case of no virtual directory this resolves to
"/" + "myAppPath"
and in case of a virtual directory this resolves to
"/VirtualPath/" + + "myAppPath"
and this finally worked for me.

I used this solution successfully
Place the following element in your masterpage
<%= Html.Hidden("HiddenCurrentUrl", Url.Action("Dummy"))%>
Declare a global variable in your main javascript file
var baseUrl = "";
Set baseUrl to the value of "HiddenCurrentUrl" when your javascript is loaded
baseUrl = $("#HiddenCurrentUrl").val();
baseUrl = baseUrl.substring(0, baseUrl.indexOf("Dummy"));
Use baseUrl
$.getJSON(baseUrl + "Action")
EDIT Improved solution
In your controller
ViewBag.BaseUrl = Request.Url.GetLeftPart(UriPartial.Authority) + Request.ApplicationPath + "/";
In your master page
<script type="text/javascript">
var YourNameSpace = YourNameSpace || {};
YourNameSpace.config = {
baseUrl: "#ViewBag.BaseUrl"
}
</script>
Use your baseUrl
$.getJSON(YourNameSpace.config.baseUrl + "Action")

Another way to get a base url is
<script type="text/javascript">
window.g_baseUrl = '#Url.Content("~")';
</script>
For example, if you run your app from SomeName virtual directory then
window.g_baseUrl variable will be equal to /SomeName/
Benefit of this method is an ability to call actions in the other controllers like so
$.getJSON(window.g_baseUrl + "AnotherController/Action")

Maybe,$.getJSON("Controller/Action") will do?

The tilde shortcut for your application root path is a special feature of ASP.NET, not part of URLs themselves. Consequently trying to use a URL with a tilde in from JavaScript won't resolve the site root, it'll just give you a literal ~ as you can see.
You'd need to pass the value of the application root path to JavaScript so it can construct URLs itself. I'm not that familiar with ASP.NET but I believe you could do something like:
<script type="text/javscript">
var approot= <%= JavaScriptSerializer.Serialize(Request.ApplicationPath) %>;
... $.getJSON(approot+'/Controller/Action') ...;
</script>
A simpler way to do it if you know there's a link on the page to the approot would be to read the href of that link:
var approot= $('#homepagelink').attr('href');

Relative Path to the JS file was the only solution I found
$.getJSON("../Controller/Action")

I know this question is very old but I was lately struggling with this issue and was able to resolve it using
url:'<%=VirtualPathUtility.ToAbsolute("~/Include/cntrols/Data.aspx") %>',
this works great in my ajax call...

It is too late to answer this question. But may be useful to someone as I had same problem. Instead of doing all this steps mentioned in above answers, better way is to use
Url.Action('action','controller').
It'll generate url /VIRDIR/controller/action if it is running from virtual directory or generate /controller/action in other case.

Related

My relative URL path to my View breaks on Deployment

I have a very standard ASP MVC app that I use a little javascript to show a Partial View. In order to make that Javascript work I needed to hard code a path to the Partial which is different between Dev and Production.
Mainly, in Dev there is no App specification where as in Production there is. See here:
Production=var URL = '/WetWashRequest/wetWashRequests/GetDetails?WONumber=' + wo;
Dev = var URL = '/wetWashRequests/GetDetails?WONumber=' + wo;
What this means is that as I work on it locally I delete the first part and when I want to deploy I have to remember to re add it.
This seems so ridiculously flawed that I can only assume I am being ignorant and doing something wrong...
You can take advantage of UrlHelper to get the URLs, as long as you do it in view:
var URL = '#Url.Action("GetDetails")';
Obviously, it doesn't make sense to put all your JavaScript in view, so what I will normal do is set just this in my view, in a namespace var, and then reference it in my external JavaScript:
View
<script>
var MyApplication = MyApplication || {};
MyApplication.GetDetailsUrl = '#Url.Action("GetDetails")';
</script>
External JS
$.get(MyApplication.GetDetailsUrl, { WONumber: wo }, function (result) {
...
});

Javascript Get Hostname of File Host

Although this question is similar, it is not what I am looking for.
Let's say on HostA.com I include a script from HostB.com:
<script type="text/javascript" src="http://www.hostb.com/script.js">
When script.js runs, I need to get the name of HostB (let's assume it can change). If I use:
var hostName = window.location.hostname;
It will return HostA.com rather than HostB.com obviously because that is where the the window object is scoped.
How can I get the name of HostB from within the script? Do I have to locate the <script> element in the DOM and parse the src attribute or is there a better way?
EDIT
Yes, it is on my server, but may be on other servers as well. I am developing a javascript plugin and am trying to make absolute paths so it doesn't try to reference files on the server including the plugin.
Here is how: first off, include this as the first line of your script. I know it is a comment. Do it anyways
//BLAHBLAHBLAHBLAHAAABBBCCCDDDEEEFFFGGGILIKEPI
next, use this function inside of that script to determine the host
function findHost(){
var scripts=document.getElementsByTagName('script');
var thisScript=null;
for(var i=0;i<scripts.length;i++){
if(scripts[i].innerHTML.indexOf('//BLAHBLAHBLAHBLAHAAABBBCCCDDDEEEFFFGGGILIKEPI')!==-1)
var thisScript=scripts[i];
}
var urlParser=document.createElement('a');
urlParser.href=thisScript.getAttribute('src');
return urlParser.hostname;
}
I am loading the script with RequireJS which looks something like this:
<script data-main="http://hostb.com/js/app/main.js" src="http://hostb.com/js/vendor/require.js" type="text/javascript"></script>
I figured out, with help from #adeneo that I can do something like this:
$('script[data-main*="/js/app/main.js"]').attr('data-main')
Which returns:
http://hostb.com/js/app/main.js
And I can parse it for the hostname.
var url = $('script[data-main*="/main.js"]').attr('data-main');
parser = document.createElement('a');
parser.href = url;
host = parser.hostname;
Thanks for the suggestions and nudge in the right direction!
BREAKING NEWS
Turns out their is an easier way for anyone using RequireJS (who finds this question in search) and needs to be able to load absolute URL's with the script host:
var myCssPath = require.toUrl('css/mystyles.css');
That builds an absolute path using the hostname of the server running!
To omit using the hostname twice (as you described in your 'accepted answer') I implemented the solution this as follows:
HTML on HostA.com:
<script data-main="my_embed_id" src="http://hostb.com/js/vendor/require.js" type="text/javascript"></script>
require.js on HostB.com:
// get host where this javascript runs
var url = $('script[data-main="my_embed_id"]').attr('src');
var hostb = url.replace(/(\/\/.*?\/).*/g, '$1');
Which returns:
http://hostb.com
Inspired by: How to make an external javascript file knows its own host?

Configuration files for javascript so base url can be changed

We are using AJAX to call WCF services from various sub folders.
So the urls of the DOM OBJECT window.location.HREF
would be :
http://localhost:80/myVirtualDirectory/Reporting/reporting.aspx
OR
http://localhost:80/myVirtualDirectory/Sales/sales.aspx
My service actually resides at:
http://localhost:80/myVirtualDirectory/
When I am calling from a "sub folder" the service cannot be found or I have to put *.svc files in parent and all sub folders.
So need all my AJAX "url" to start with
http://localhost:80/myVirtualDirectory/
Only I don't know what myVirtualDirectory is going to be as we deploy this application to our customers' web sites.
I wrote a scriptblock to push this out as:
var urlBase = "http://localhost:80/myVirtualDirectory/"
The code in C# was like this (abridged)
"var urlBase = '//'+window.location.host+" + Request.ApplicationName + " '/' ";
Is there a better way?
Please keep in mind that we are moving away from ASPX in favour of plain old html pages(POHP) with knockout.js
You could try using the <base> tag on your HTML:
<head>
<base href="http://localhost:80/myVirtualDirectory/">
</head>
You might be able to use servletContext.getContextPath():
http://docs.oracle.com/cd/E17802_01/products/products/servlet/2.5/docs/servlet-2_5-mr2/javax/servlet/ServletContext.html#getContextPath()

How should I create relative paths in javascript using MVC3?

I am having some difficulty aligning my paths without a hardcode in javascript. I am running an asp.net MVC3 web application.
If my path is of the form
var url = 'http://serverNameHardcode/websiteNameHardcode/service/service?param1=' + param;
Then things work fine when I do
$.get(url,
{},
function (data) {alert('callback success');},'json');
I would like to create a relative path. I tried
var url = 'service/service?param1=' + param;
And this works when I run locally and also in Firefox, but not in IE7. When I publish to the server without the hardcode the callback never fires. I know MVC-3 adds some complexity to routing, but I do not know if it applies to this situation; so, I marked this question as such.
How should I setup my path so I don't need hardcodes?
Just write out the app path as a global js variable from your master view, then compose links as
APPPATH + "path/whatever"
Just had to solve this for one of my jQuery plugins, where it is preferable not to modify anything global (i.e. outside the scope of the plugin use) so I had to disregard the marked answer.
I also found that because I host DEV locally in IIS I could not use a root-relative path (as localhost is not the root).
The solution I came up with extended what I had already started with: a data-controller attribute specifying which controller to use in the element I am applying my plugin to. I find it preferable to data-drive the controller names so the components can be more easily reused.
Previous:
<div data-controller="Section">
Solution:
<div data-controller="#Url.Content("~/Section")">
This injects the server root (e.g. /Test.WindowsAzure.Apr2014/ before the controller name so I wind up with /Test.WindowsAzure.Apr2014/Section which is perfect for then appending actions and other parameters as you have. It also avoids having an absolute path in the output (which takes up extra bytes for no good reason).
In your case use something like:
// Assuming $element points to the element your plugin/code is attached to...
var baseUrl = $element.data('controller');
var url = baseUrl + '/service?param1=' + param;
Update:
Another approach we now use, when we do not mind injecting a global value, is Razor-inject a single global JavaScript variable onto window in the layout file with:
<script>
window.SiteRoot = "#Url.Content("~/")";
</script>
and use it with
var url = window.SiteRoot + '/service?param1=' + param;
One option:
var editLink = '#Url.Action("_EditActivity", "Home")';
$('#activities').load(editLink + "?activityID=" + id);
another example:
var actionURL = '#Url.Action("_DeleteActivity", "Home")';
$('#activities').load(actionURL + "?goalID=" + gID + "&activityID=" + aID);
If you don't need to add to the string:
$('#activities').load('#Url.Action("_Activities", "Home", new { goalID = Model.goalID},null)');
I really need the path to get this to work, maybe its IE7. Who knows. But this worked for me.
Grab the URL and store it somewhere. I chose to implement the data attribute from HTML5.
<div id="websitePath" data-websitePath='#Request.Url.GetLeftPart(System.UriPartial.Authority)#Request.ApplicationPath'></div>
Then when you need to perform some AJAX or otherwise use a URL in javascript you simply refer to the stored value. Also, there are differences in the versions of IIS (not cool if your devbox is IIS5 and your server is IIS7). #Request.ApplicationPath may or may not come back with a '/' appended to the end. So, as a workaround I also trim the last character if it is /. Then include / as part of the url.
var urlprefix = $('#websitePath').data('websitepath');
urlprefix = urlprefix.replace(/\/$/, "");
var url = urlprefix + '/service/service?param1=' + param;
While the accepted answer is correct I would like to add a suggestion (i.e. how I do it).
I am using MVC, and any ajax request goes to a controller. My controllers have services so if a service call is required the controller will take of that.
So what's my point? So if ajax always communicates with a controller, then i would like to let the MVC routing resolve the path for me. So what I write in Javascript for url is something like this:
url: 'controller/action'
This way there is no need for the root path etc...
Also, you can put this in a separate Javascript file and it will also work whereas #Url.Content will need to be called on the view.

How to get the currently loading script name and the url variable of the script?

I am loading a script using the script embed tag and I want to get the url variables and the loading script name inside the script. Is it possible? For Example,
<script src="test.js?id=12"></script>
Inside test.js is there any way to get the url variable id?
Any help would be appreciated.
Thanks,
Karthik
Aside from the answers in the linked post, FWIW with Firefox 4 only you can (with caveats); document.currentScript.src which will return the full url, including arguments.
Thanks for all your efforts I have made that working by assigning an id attribute in the script tag and accessed via jQuery,
<script src="test.js?id=12" id="myScript"></script>
var currentScript = $("#myScript").attr('src'); //This will give me my script src
Thanks,
Karthik
If you want to get a variable from the current URL you can use this:
function queryParser(url){
this.get=function(p){return this.q[p];}
this.q={};
this.map=function(url){
url=url || window.location.search.substring(1);
var url=url.split('&');
var part;
for(var i=0;i<url.length;i++){
part=url[i].split('=');
this.q[part[0]]=part[1];
}
}
this.map(url);
}
var query=new queryParser();
// assuming you have ?test=something
alert(query.get('test'));
I recommend you map the result, so you don't re-parse whenever you want to find a specific element.
I don't really know why you'd pass a query string in a script tag like that, unless you specifically want off-site includes with a simple robust system for various effects. Or are actually using PHP to handle that request.
If you want to "send" a variable to one of your scripts, you can always do:
<script type="text/javascript">
var myVar="I'm in global scope, all scripts can access me";
</script>
<script src="test.js?id=12"></script>
If you really need to get the URL of the currently included script, you can use the code supplied by my peers in the other answers, you can then use:
var query=new queryParser(scriptURL);
alert(query.get('id'));// would alert 12 in your case
Navigating through the link on your comments you can get the proper answer.
Anyway, to make things easier:
var allScripts=document.getElementsByTagName('script');
var indexLastScript= allScripts.length -1;
alert (allScripts[indexLastScript].src);
This will show up "test.js?id=12" as a regular String so its up to you to split it in order to get de param.
Hope it helps, I've tried it on the run over the Chrome Javascript Console. :D.

Categories

Resources