81

i'm working on an asp.net app, the following link works in IE but not in FF.

<a href="~/BusinessOrderInfo/page.aspx" >

Isn't the tilde something that can only be used in asp.net server controls. Where it will be replaced by an actual path?

Is it possible to use the tilde in an anchor tag? If so what does it mean?

When I'm at the root, the link works

www.myserver.com/default.aspx, click the link, ok!

www.myserver.com/otherpart/default.aspx, click the link, not ok!

The link generated by ASP.NET is:

www.myserver.com/otherpart/~BusinessOrderInfo/page.aspx

Is this by design?

Michel
  • 23,085
  • 46
  • 152
  • 242
  • 11
    The `~` is called the [Application Root Operator](https://learn.microsoft.com/en-us/previous-versions/aspnet/ms178116(v=vs.100)) btw in case you're googling for it – KyleMit Feb 19 '20 at 17:16
  • Since ASP.Net core 1.0, it's called the `tilde Tag Helper`: https://learn.microsoft.com/en-us/aspnet/core/mvc/views/tag-helpers/built-in – user276648 Jul 19 '22 at 01:19

6 Answers6

100

You are correct, it only works in server controls. You've got these basic options:

Change to HyperLink to run as a Web Control:

<asp:HyperLink NavigateUrl="~/BusinessOrderInfo/page.aspx" Text="Whatever" runat="server" />

Or, run the anchor on the server side as an HTML Control:

<a href="~/BusinessOrderInfo/page.aspx" runat="server" >

Or, use Page.ResolveUrl:

<a href="<%= Page.ResolveUrl("~/BusinessOrderInfo/page.aspx") %>">...</a>
John K
  • 28,441
  • 31
  • 139
  • 229
Dean Harding
  • 71,468
  • 13
  • 145
  • 180
22

HTML controls can be turned into server controls by adding the runat="server" attribute.

<a href="~/BusinessOrderInfo/page.aspx" runat="server">
Damien Dennehy
  • 3,937
  • 2
  • 19
  • 21
  • Keep in mind - the downside to this is performance is hurt because the image tags are converted to server controls when the page needs to be generated, while there isn't really a need for this. – atconway Sep 01 '11 at 20:23
  • This also seems to work if the container tag has runat="server" in it, at least it does with when wanting my favicon to live in the root path and be accessible from any path that uses my master page – Matthew Lock Oct 04 '18 at 08:08
12

The tilde refers to the application root directory, and will be translated correctly in control properties such as NavigateUrl.

My understanding is that if you use it in plain-HTML tags, it will not be translated by ASP.Net.

devio
  • 36,858
  • 7
  • 80
  • 143
  • 8
    This is mostly true. If you use a plain HTML tag like and give it a runat="server" you can successfully use a virtual path to refer to your content. – Nathan Taylor Jun 19 '10 at 23:09
1

This function can also be used to resolve paths for non server elements

VirtualPathUtility.ToAbsolute($"~/App_Themes/Default/Icons/myimage.gif")
Dbl
  • 5,634
  • 3
  • 41
  • 66
0

If you remove tilde and use forward slash only you will achieve the same result, i.e. pointing to the root folder on the current domain:

<a href="/BusinessOrderInfo/page.aspx" >
boateng
  • 910
  • 11
  • 21
0

Using Web Paths and Tilde "~" in ASP.NET

  1. ~/ is not part of HTML, CSS, or JavaScript path systems.
  2. ~/ is an artificial path resolution character only ASP.NET or 3rd party products use.
  3. ~/ is a Web Server only path that gets translated to a new path by the code running on the server.
  4. ~/ is a character that tells ASP.NET on the IIs Windows Server to find the "application root" of your website.
  5. ~/ resolves as a "Virtual Path" as it tells the server to find virtual or application root of a ASP.NET Web Application controlled by a given AppDomain on the server and resolve it from that new virtual root.
  6. ~/ in most cases resolves to the web root of any website right right after the domain, no matter what page or subfolder you are in when the path is called. In almost all cases this resolves to /. So the two are the same in MOST cases unless you set up a Virtual Application on the server.
  7. ~/ is really only useful when your website uses one or more Virtual Applications in a web server like IIs. These are artificial sub-applications under your web domain that add a new folder or path under a web root that do not truly exist but represent separate applications and processes managed by the server. This often creates one or more virtual application folders under your domain in IIs which ASP.NET and IIs manage when running separate instances of your ASP.NET website under one domain. See below...
  8. Microsoft .NET is now using ~/ in Routing Attribute paths. When used they start the path back at the web root as an absolute path, but also override all controller or other attribute paths.

VIRTUAL WEB APPLICATIONS

In the old days, we used to create Virtual Applications in IIs Web Server to create two more web paths in order to isolate one or more web 'experiences' using the same domain. Each Virtual Path might be a "ghost" path that points back to the web root but creates an additional ghost folder under the web root. In many cases, that new virtual path pointed to a physical folder separate from the normal web path or even to computer hard drive path or mapping. ASP.NET with the right permission then ran web site code from there. The new virtual path shown to visitors of your web domain would then appear as part of the main site but run a second instance of your web application using a separate process run by ASP.NET (a separate AppPool or worker process).

~/ was then very useful in those cases. It was used in path resolution and easily mapped to the root of these new virtual application roots or paths created by the server, allowing you run multiple application under one website with no change to your paths in your ASP.NET code. The server-side code would then resolve the paths for you inside each virtual application with no changes to the code base.

~/ in those situations was extremely valuable as you no longer needed to manage multiple paths in your web app for each application if it ran in multiple virtual web applications under one website with different web roots. It could always find the new root in each application using ~/ rather than the true web root which was always http://example.com/

EXAMPLES

Most paths in ASP.NET using ~/ resolve to / in a normal website without virtual applications, and point all paths to the web root of the URL below. In most cases that is why ASP.NET ~/ is redundant. Just use /. Both point to the web root:

https://example.com/

However, if you added virtual directories to your domain, as this example below shows, ~/ inside each separate web application would resolve to two different web roots:

https://example.com/virtualapplication1/
https://example.com/virtualapplication2/

In the early days of ASP.NET, I always grabbed the application path using this code below stored in a global variable. This allowed me to fully control all paths from a relative application web root off the domain root or a virtual root no matter where my web application was moved to. But this path is what the ~/ replaced long ago. However, it still might be better as you can build paths from it dynamically on the server:

var myWebRoot = HttpContext.Current.Request.ApplicationPath;

My opinion is virtual applications like this are rarely used today as domains are cheap and subdomains are often used instead, like so:

https://app1.example.com/
https://app2.example.com/

All web paths should use absolute paths in every case possible /. The exception is CSS paths which are relative to the page source page or code calling them internally. Many say that means those absolute web paths break if you move them. But I argue, why would you need to reference the root for your website then suddenly change that? If you do, that should be managed on the server side and injected into your HTML and JavaScript, not the other way around.

Second of all, many Open Source, UNIX-based vendors are creating JavaScript API libraries that stumble around with dot paths which HTML and CSS do not support, like ./ or .

These are UNIX conventions that just mean to point to the local folder or the same folder the calling code is in. It's the same as NO PATH, so why use it? There are cases for their use, but the end result has zero affect on Web Paths. So I would avoid their use. The ONLY place they work in JavaScript reliably is in the new JavaScript Module in ECMAScript. But in proprietary API's like Google Angular, they are required.

For example these two image paths using UNIX local path conventions using ./ or . both fail in HTML and create missing image errors:

// These return broken image icons in browsers when using
// these unconventional UNIX local dot path conventions on the Web:
<img id="image1" src="./images/image1.png" />
<img id="image2" src="/images/.image2.png" />

So avoid all these deviant path system and stick with / absolute HTML paths and your code will always work for decades to come!

Stokely
  • 12,444
  • 2
  • 35
  • 23
  • Your concluding statement means not coding to support deployment as a virtual application, correct? – Ian W Mar 31 '23 at 15:32
  • Based on my (.NET 7, Razor Pages, IIS) testing `~/` in an `href` works in a virtual application, but it does not work in the `asp-page` tag helper. However, a simple `/` in 'asp-page` **does** work in a virtual application. (Where "work" means the link retains the virtual directory in the path) – Ian W Mar 31 '23 at 15:42