How to get relative path in Javascript?

In my ASP.net web project, I’ve written the following Javascript code in a .js file:

function getDeviceTypes() {
    var deviceTypes;
    $.ajax({
        async: false,
        type: "POST",
        url: "Controls/ModelSelectorWebMethods.aspx/getDeviceTypes",
        data: '{ }',
        contentType: "application/json;",
        dataType: "json",
        success: function(response) {
            deviceTypes = response.d;
        },
        error: function(xhr, status) {
            debugger;
            alert('Error getting device types.');
        }
    });    // end - $.ajax
    return deviceTypes;
}

It was working great until I tried to load this .js file into a page in a subdirectory.

Let’s suppose that the name of my project is widget.

When I use this code in the main virtual directory, Javascript interprets Controls/ModelSelectorWebMethods.aspx/getDeviceTypes to mean https://mysite.com/widget/Controls/ModelSelectorWebMethods.aspx/getDeviceTypes and all is well. However, from the page in a subdirectory, Javascript interprets it to mean https://mysite.com/widget/subdirectory/Controls/ModelSelectorWebMethods.aspx/getDeviceTypes and it doesn’t work.

How can I write my Javascript code so that the AJAX web method can be called from pages in any directory in my application?

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

You’ve got two options:

  1. Build a configuration/ preferences object in JavaScript which contains all your environment specific settings:
     var config = {
         base: <% /* however the hell you output stuff in ASPX */ %>,
         someOtherPref: 4
     };

    and then prefix the AJAX url with config.base (and change the value for config.base whether you’re on a dev/ testing/ deployment server.)
  2. Use the <base /> HTML tag to set the URL prefix for all relative URL’s. This affects all relative URL’s: image’s, links etc.

Personally, I’d go for option 1. You’ll most likely find that config object coming in handy elsewhere.

Obviously the config object will have to be included in a part of your site where server-side-code is evaluated; a .js file won’t cut it without configuring your server. I always include the config object in the HTML <head>; its a small config object, whose contents can change on each page, so it’s perfectly warrented to stick it in there.

Method 2

As long as you don’t care about asp.net virtual directories (which makes it actually impossible to figure out from script, you’ll have to pass something from the server) you can look at the URL and parse it:

function baseUrl() {
   var href = window.location.href.split('/');
   return href[0]+'//'+href[2]+'/';
}

then:
...
   url: baseUrl()+"Controls/ModelSelectorWebMethods.aspx/getDeviceTypes",
...

… and now I see from your comments above that virtual directories are a problem. I usually do this.

1) In your masterpage, put code to inject a script somewhere, preferably before anything else (I add it directly to HEAD by adding controls instead of using ScriptManager) to make sure it’s run before any other script. c#:

string basePath = Request.ApplicationPath;
// Annoyingly, Request.ApplicationPath is inconsistent about trailing slash
// (if not root path, then there is no trailing slash) so add one to ensure 
// consistency if needed
string myLocation = "basePath='" + basePath + basePath=="/"?"":"/" + "';";
// now emit myLocation as script however you want, ideally in head

2) Change baseUrl to include that:
function baseUrl() {
   var href = window.location.href.split('/');
   return href[0]+'//'+href[2]+basePath;
}

Method 3

Create an app root variable…

var root = location.protocol + "//" + location.host;

And use an absolute URI (instead of relative) when you are making AJAX requests…
url: root + "/Controls/ModelSelectorWebMethods.aspx/getDeviceTypes"

Method 4

I think this function will work… it is to get a relative path as “../../../”
so if you invoke this function in each page, this will return a relative path format.

function getPath() {
    var path = "";
    nodes = window.location. pathname. split('/');
    for (var index = 0; index < nodes.length - 3; index++) {
        path += "../";
    }
    return path;
}

Method 5

You can import the namespace at the beginning: System.Web.Hosting.HostingEnvironment

  <%@ Master Language="VB" AutoEventWireup="false" CodeFile="Site.master.vb" Inherits="Site" %>
   <%@ Import namespace="System.Web.Hosting.HostingEnvironment" %>

and on js:

  <script type="text/javascript">
        var virtualpathh = "<%=ApplicationVirtualPath  %>";
   </script>

Method 6

Could you use window.location.pathname?

var pathname = window.location.pathname;
$.ajax({
    //...
    url: pathname + 'Controls/...', // might need a leading '/'
    //...
});


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x