21

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?

Dan
  • 12,808
  • 7
  • 45
  • 54

8 Answers8

26

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.

Jesse B.
  • 284
  • 3
  • 2
15

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")
Andreas
  • 659
  • 6
  • 17
  • I am marking this as the answer as it is funky, and I like funky mixes of jQuery and MVC. Although I might use something diff to using Url.Action as the substring thing isn't so clean – Dan Jun 30 '10 at 11:41
  • Great that you found this helpful! I'm not satisfied with the Url.Action solution so please tell me how you end up solving it. I hate URL stuff. Always problems between dev/test/prod environments. – Andreas Jun 30 '10 at 12:40
  • I voted up as well. It is funky, but I am unable to think of a more elegant solution right now and this works... clever. – Ryan Anderson Feb 01 '11 at 18:31
  • This is a poor approach to solutions that wrap up their logic in multiple JS files and are creating closures around the logic to ensure things are done appropriately. – offthat Feb 21 '16 at 23:52
  • @offthat Edited the solution to use namespacing. Is that a better approach? – Andreas May 11 '16 at 13:11
4

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") 
aku
  • 122,288
  • 32
  • 173
  • 203
2

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

Anton Gogolev
  • 113,561
  • 39
  • 200
  • 288
2

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');
bobince
  • 528,062
  • 107
  • 651
  • 834
0

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...

Scorpio
  • 1,151
  • 1
  • 19
  • 37
0

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

Dan
  • 12,808
  • 7
  • 45
  • 54
0

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.

gmail user
  • 2,753
  • 4
  • 33
  • 42