Relative Path Problems in Javascript Ajax call
Okay, I have a JavaScript file with the following functions:
function AskReason() {
var answer = prompt("Please enter a reason for this action:", "");
if (answer != null)
DoReason(answer);
}
function createXMLHttpRequest() {
try {
return new XMLHttpRequest();
}
catch (e)
{ alert('XMLHttpRequest not working'); }
try {
return new ActiveXObject("Msxml2.XMLHTTP");
}
catch (e)
{ alert('Msxml2.XMLHTT not working'); }
try {
return new ActiveXObject("Microsoft.XMLHTTP");
}开发者_如何学编程
catch (e)
{ alert('Microsoft.XMLHTTP not working'); }
alert("XMLHttpRequest not supported");
return null;
}
function DoReason(reason) {
var xmlHttpReq = createXMLHttpRequest();
var url = "/Shared/AskReason.ashx?REASON=" + reason;
xmlHttpReq.open("GET", url, true);
xmlHttpReq.send(null);
}
This line:
var url = "/Shared/AskReason.ashx?REASON=" + reason;
Is what is causing the problem.
In VS 2010 debugging the app - this call works to my ashx handler.
When I move the project to a virtual directory - example http://localhost/myapp
this code will break and I have to change the javascript to this:
var url = "http://localhost/myapp/Shared/AskReason.ashx?REASON=" + reason;
Any ideas on how I can fix this to work in both environments or just accept the manual change when I deploy apps to servers?
Thanks, Mike
Pointy's way works, but you have to know in advance where you're going to deploy it.
Alternately, simply don't start the relative path with a /
:
var url = "Shared/AskReason.ashx?REASON=" + reason;
That will be resolved relative to the current document's location. So if the current document is:
http://localhost/myapp/index.aspx
...then that will resolve to
http://localhost/myapp/Shared/AskReason.ashx?REASON=foo
Paths that start with a "/" (and no protocol & host) are relative to the root of the host. If you deploy such that your application is at "http://whatever/myapp", then your root-relative paths have to start with "/myapp".
When you're working in a server-side environment that involves some sort of page template mechanism, a common trick is to have that part of the path be some kind of configuration variable so that you can write pages with paths like:
<a href='${root}/something/something'>click me</a>
Then that "root" variable is expanded based on configuration to "/myapp" or whatever.
I had a similar problem where an absolute URL was needed but the reference broke when going from localhost to the production server. I resolved it by checking if a "localhost" string exists in:
var environ = window.location.host;
Then you can simply do:
if (environ === "localhost") {
var baseurl = window.location.protocol + "//" + window.location.host + "/" + "shared/";
} else {
var baseurl = window.location.protocol + "//" + window.location.host + "/";
}
Then you can add baseurl
in front of whatever url you need to reference.
The url
var url = "/Shared/AskReason.ashx?REASON=" + reason;
Is looking for the file in the root directory [since it is an absolute path], effectively
http://localhost/Shared/AskReason.ashx
You should include the name of the virtual directory OR determine the appropriate structure:
Starting without the / will give you a relative path ... if you need to navigate directories use ../Shared/ style of notation, or finally use your servers Directory command to determine your current path.
I have the same issue with ASP.NET MVC with my AJAX call on a separate .js file. This is how it looks:
return $.ajax({
type: "POST",
url: '/Dashboard/Execute',
contentType: "application/json; charset=utf-8",
data: filter,
dataType: "json",
});
This works fine on my local, of course. But when deployed on a subdirectory in IIS, e.g.
wwwroot/appsite/subdomainfolder/
This will trigger 404 Not Found as it didn't attach the subdomainfolder on the URL.
If I remove the
"/"
at the beginning of the URL, it will generate it like this one:
http://localhost/subdomainfolder/Dashboard/Dashboard/ExecuteReader
Which again will trigger the 404 Not Found issue.
So here are the two options for my workaround:
Remove the backslash and remove the name of the controller (Dashboard on this case):
return $.ajax({
type: "POST",
url: '/Execute',
contentType: "application/json; charset=utf-8",
data: filter,
dataType: "json",
});
Or, stay as it is, just add double period at the beginning of the URL:
return $.ajax({
type: "POST",
url: '../Dashboard/Execute',
contentType: "application/json; charset=utf-8",
data: filter,
dataType: "json",
});
精彩评论