Contact   •   Products   •   Search

Rick Strahl's Web Log

Wind, waves, code and everything in between...
ASP.NET • C# • HTML5 • JavaScript • AngularJs

Making Sense of ASP.NET Paths


ASP.Net includes quite a plethora of properties to retrieve path information about the current request, control and application. There's a ton of information available about paths on the Request object, some of it appearing to overlap and some of it buried several levels down, and it can be confusing to find just the right path that you are looking for.

To keep things straight I thought it a good idea to summarize the path options along with descriptions and example paths. I wrote a post about this a long time ago in 2004 and I find myself frequently going back to that page to quickly figure out which path I’m looking for in processing the current URL. Apparently a lot of people must be doing the same, because the original post is the second most visited even to this date on this blog to the tune of nearly 500 hits per day. So, I decided to update and expand a bit on the original post with a little more information and clarification based on the original comments.

Request Object Paths Available

Here's a list of the Path related properties on the Request object (and the Page object). Assume a path like http://www.west-wind.com/webstore/admin/paths.aspx for the paths below where webstore is the name of the virtual.

Request Property Description and Value
ApplicationPath Returns the web root-relative logical path to the virtual root of this app.
/webstore/
PhysicalApplicationPath Returns local file system path of the virtual root for this app.
c:\inetpub\wwwroot\webstore
PhysicalPath Returns the local file system path to the current script or path.
c:\inetpub\wwwroot\webstore\admin\paths.aspx
Path
FilePath
CurrentExecutionFilePath
All of these return the full root relative logical path to the script page including path and scriptname. CurrentExcecutionFilePath will return the ‘current’ request path after a Transfer/Execute call while FilePath will always return the original request’s path.
/webstore/admin/paths.aspx
AppRelativeCurrentExecutionFilePath Returns an ASP.NET root relative virtual path to the script or path for the current request. If in  a Transfer/Execute call the transferred Path is returned.
~/admin/paths.aspx
PathInfo Returns any extra path following the script name. If no extra path is provided returns the root-relative path (returns text in red below). string.Empty if no PathInfo is available.
/webstore/admin/paths.aspx/ExtraPathInfo
RawUrl Returns the full root relative URL including querystring and extra path as a string.
/webstore/admin/paths.aspx?sku=wwhelp40
Url Returns a fully qualified URL including querystring and extra path. Note this is a Uri instance rather than string.
http://www.west-wind.com/webstore/admin/paths.aspx?sku=wwhelp40
UrlReferrer The fully qualified URL of the page that sent the request. This is also a Uri instance and this value is null if the page was directly accessed by typing into the address bar or using an HttpClient based Referrer client Http header.
http://www.west-wind.com/webstore/default.aspx?Info
Control.TemplateSourceDirectory Returns the logical path to the folder of the page, master or user control on which it is called. This is useful if you need to know the path only to a Page or control from within the control. For non-file controls this returns the Page path.
/webstore/admin/

As you can see there’s a ton of information available there for each of the three common path formats:

  • Physical Path
    is an OS type path that points to a path or file on disk.
  • Logical Path
    is a Web path that is relative to the Web server’s root. It includes the virtual plus the application relative path.
  • ~/ (Root-relative) Path
    is an ASP.NET specific path that includes ~/ to indicate the virtual root Web path. ASP.NET can convert virtual paths into either logical paths using Control.ResolveUrl(), or physical paths using Server.MapPath(). Root relative paths are useful for specifying portable URLs that don’t rely on relative directory structures and very useful from within control or component code.

You should be able to get any necessary format from ASP.NET from just about any path or script using these mechanisms.

~/ Root Relative Paths and ResolveUrl() and ResolveClientUrl()

ASP.NET supports root-relative virtual path syntax in most of its URL properties in Web Forms. So you can easily specify a root relative path in a control rather than a location relative path:

<asp:Image runat="server" ID="imgHelp"  ImageUrl="~/images/help.gif" />

ASP.NET internally resolves this URL by using ResolveUrl("~/images/help.gif") to arrive at the root-relative URL of /webstore/images/help.gif which uses the Request.ApplicationPath as the basepath to replace the ~. By convention any custom Web controls also should use ResolveUrl() on URL properties to provide the same functionality.

In your own code you can use Page.ResolveUrl() or Control.ResolveUrl() to accomplish the same thing:

string imgPath = this.ResolveUrl("~/images/help.gif");
imgHelp.ImageUrl = imgPath;

Unfortunately ResolveUrl() is limited to WebForm pages, so if you’re in an HttpHandler or Module it’s not available.

ASP.NET Mvc also has it’s own more generic version of ResolveUrl in Url.Decode:

<script src="<%= Url.Content("~/scripts/new.js") %>" type="text/javascript"></script> 

which is part of the UrlHelper class. In ASP.NET MVC the above sort of syntax is actually even more crucial than in WebForms due to the fact that views are not referencing specific pages but rather are often path based which can lead to various variations on how a particular view is referenced.

In a Module or Handler code Control.ResolveUrl() unfortunately is not available which in retrospect seems like an odd design choice – URL resolution really should happen on a Request basis not as part of the Page framework. Luckily you can also rely on the static VirtualPathUtility class:

string path = VirtualPathUtility.ToAbsolute("~/admin/paths.aspx");

VirtualPathUtility also many other quite useful methods for dealing with paths and converting between the various kinds of paths supported. One thing to watch out for is that ToAbsolute() will throw an exception if a query string is provided and doesn’t work on fully qualified URLs. I wrote about this topic with a custom solution that works fully qualified URLs and query strings here (check comments for some interesting discussions too).

Similar to ResolveUrl() is ResolveClientUrl() which creates a fully qualified HTTP path that includes the protocol and domain name. It’s rare that this full resolution is needed but can be useful in some scenarios.

Mapping Virtual Paths to Physical Paths with Server.MapPath()

If you need to map root relative or current folder relative URLs to physical URLs or you can use HttpContext.Current.Server.MapPath(). Inside of a Page you can do the following:

string physicalPath = Server.MapPath("~/scripts/ww.jquery.js"));

MapPath is pretty flexible and it understands both ASP.NET style virtual paths as well as plain relative paths, so the following also works.

string physicalPath = Server.MapPath("scripts/silverlight.js");

as well as dot relative syntax:

string physicalPath = Server.MapPath("../scripts/jquery.js");

Once you have the physical path you can perform standard System.IO Path and File operations on the file. Remember with physical paths and IO or copy operations you need to make sure you have permissions to access files and folders based on the Web server user account that is active (NETWORK SERVICE, ASPNET typically).

Note the Server.MapPath will not map up beyond the virtual root of the application for security reasons.

Server and Host Information

Between these settings you can get all the information you may need to figure out where you are at and to build new Url if necessary. If you need to build a URL completely from scratch you can get access to information about the server you are accessing:

Server Variable Function and Example
SERVER_NAME The of the domain or IP Address
wwww.west-wind.com or 127.0.0.1
SERVER_PORT The port that the request runs under.
80
SERVER_PORT_SECURE Determines whether https: was used.
0 or 1
APPL_MD_PATH ADSI DirectoryServices path to the virtual root directory. Note that LM typically doesn’t work for ADSI access so you should replace that with LOCALHOST or the machine’s NetBios name.
/LM/W3SVC/1/ROOT/webstore

Request.Url and Uri Parsing

If you still need more control over the current request URL or  you need to create new URLs from an existing one, the current Request.Url Uri property offers a lot of control. Using the Uri class and UriBuilder makes it easy to retrieve parts of a URL and create new URLs based on existing URL. The UriBuilder class is the preferred way to create URLs – much preferable over creating URIs via string concatenation.

Uri Property Function
Scheme The URL scheme or protocol prefix.
http or https
Port The port if specifically specified.
DnsSafeHost The domain name or local host NetBios machine name
www.west-wind.com or rasnote
LocalPath The full path of the URL including script name and extra PathInfo.
/webstore/admin/paths.aspx
Query The query string if any
?id=1

The Uri class itself is great for retrieving Uri parts, but most of the properties are read only if you need to modify a URL in order to change it you can use the UriBuilder class to load up an existing URL and modify it to create a new one.

Here are a few common operations I’ve needed to do to get specific URLs:

Convert the Request URL to an SSL/HTTPS link

For example to take the current request URL and converted  it to a secure URL can be done like this:

UriBuilder build = new UriBuilder(Request.Url);
build.Scheme = "https";
build.Port = -1;  // don't inject port

Uri newUri = build.Uri;
string newUrl = build.ToString();

Retrieve the fully qualified URL without a QueryString
AFAIK, there’s no native routine to retrieve the current request URL without the query string. It’s easy to do with UriBuilder however:

UriBuilder builder = newUriBuilder(Request.Url);
builder.Query = "";
stringlogicalPathWithoutQuery = builder.ToString();

What else?

I took a look through the old post’s comments and addressed as many of the questions and comments that came up in there. With a few small and silly exceptions this update post handles most of these.

But I’m sure there are a more things that go in here. What else would be useful to put onto this post so it serves as a nice all in one place to go for path references? If you think of something leave a comment and I’ll try to update the post with it in the future.

Make Donation
Posted in ASP.NET  


Feedback for this Post

 
# re: Making Sense of ASP.NET Paths
by Sebastian Pereira December 21, 2009 @ 5:22am
I took the liberty to tweet this entry, hope you don't mind. Thank you!
# re: Making Sense of ASP.NET Paths
by Guy Harwood December 21, 2009 @ 9:44am
I often find myself going back to the original post from 2004.

Its the most comprehensive piece on this subject to be found!

thanks for the updated version :)
# re: Making Sense of ASP.NET Paths
by Steve from Pleasant Hill December 21, 2009 @ 12:17pm
That post was how I stumbled upon your site back in 2004. The rest, as they say, is history...
# re: Making Sense of ASP.NET Paths
by timash December 21, 2009 @ 12:38pm
Thanks! Great article, short and instructive!
Let me add 2 cents - http://tinyurl.com/y8czrwx - Request.Url and Request.RawUrl in SharePoint (which is built on the top of ASP.NET).
# re: Making Sense of ASP.NET Paths
by Ryan December 21, 2009 @ 11:58pm
Might be nice to also add a brief mention of ResolveClientUrl().
# re: Making Sense of ASP.NET Paths
by Ole December 22, 2009 @ 7:40am
Maybe you should mention that (ideally) physical file access should be done through the VirtualPathProvider class.

For instance, to read a file use:

Stream stream = VirtualPathProvider.OpenFile(virtualPath);

And thank you for your excellent blog!
# re: Making Sense of ASP.NET Paths
by rtpHarry December 22, 2009 @ 8:52am
Yeah its a post I have referred to many times. I was a bit confused to start off with until I realised this was an updated post.

Noticed you are missing a space in the last code sample:

stringlogicalPathWithoutQuery = builder.ToString();
# re: Making Sense of ASP.NET Paths
by Henrik Laursen December 24, 2009 @ 2:43am
Rick, I wish you and your family a merry christmas and a happy new year, with thanks for all the sublime articles and blogposts you've presented in the year gone by.
Looking forward to follow your work in the year to come.

Henrik
# re: Making Sense of ASP.NET Paths
by John Vogel December 24, 2009 @ 1:12pm
Thanks for the post! I found this one very useful because I often have to deal with different application paths between local development and the path on the web server.
# re: Making Sense of ASP.NET Paths
by Sheo Narayan January 07, 2010 @ 9:50pm
Another article in line with this article. Describes almost all useful properties of Request object

http://www.dotnetfunda.com/articles/article79.aspx

Hope this will be useful for the readers.

Best regards,
Sheo Narayan
# re: Making Sense of ASP.NET Paths
by Darshan Marathe January 08, 2010 @ 2:15am
Man Great stuff

Here

Have forwarded this link to all fellow developers :-)

Regards,
Darshan Marathe
www.jqguru.i.am
# re: Making Sense of ASP.NET Paths
by Voytek January 08, 2010 @ 7:36am
Another excellent article. The other ones I always have bookmarked: "Getting an ASP.NET Application Relative Path from a Logical Path" and "ResolveUrl without Page"
# Making Sense of ASP.NET Paths - Rick Strahl's Web Log
by DotNetShoutout January 09, 2010 @ 3:58am
Thank you for submitting this cool story - Trackback from DotNetShoutout
# re: Making Sense of ASP.NET Paths
by Andreii January 11, 2010 @ 2:39pm
Rick, the post is cool in terms of being a collection of concise descriptions of some important properties related to http requests. But I guess the post needs revising as it has some inaccuracies. For instance, FilePath gives us the virtual path to a resource while Path is a combination of FilePath and PathInfo props. Also, CurrentExecutionFilePath and FilePath return the same values unless you do Execute/Transfer from your page being requested initially. In the latter case FilePath will give you the original route it would have returned before Execute/Transfer is done but CurrentExecutionFilePath will return a new actual path to the resource being redirected to.
# re: Making Sense of ASP.NET Paths
by Andreii January 11, 2010 @ 2:45pm
And one more note. man ) I'd be using more accurate terms ) Virtual path in its standard notion in the context of ASP.Net isn't one that includes "~/...". More correct term for the latter form is relative path as it points to a resource relative to the root folder of an application. And when being resolved via ResolveUrl()/ResolveClientUrl() it will render into a virtual path that includes the application folder name. So we should distinguish physical paths, virtual paths and relative paths:) Here, logical path is a synonym to virtual path.
Love your site, man )
# re: Making Sense of ASP.NET Paths
by Rick Strahl January 11, 2010 @ 2:46pm
@Andreii - great feedback. Added a clarification to the path group. Thanks!
# re: Making Sense of ASP.NET Paths
by Hasan January 11, 2010 @ 11:50pm
Nice Tutorial
# re: Making Sense of ASP.NET Paths
by Matt February 01, 2010 @ 12:53pm
Probably one of the most useful blog posts ever...
# re: Making Sense of ASP.NET Paths
by Stefan February 09, 2010 @ 5:46am
Hello, I tried using Request.Url... does anyone know how to get the "exact content" of the url box. I've got a situation where home.aspx is set up in IIS as the default page of the IIS application (website).
So when someone types in [1] http://website.com/ or [2] http://website.com/home.aspx in their browser, they request the same page.
However, I need to distinguish between these 2 cases - i.e. know exactly what they typed in!
No matter whether they typed in [1] or [2], using Request.Url I'm always getting [2].
Can anyone help?
# re: Making Sense of ASP.NET Paths
by Rick Strahl February 09, 2010 @ 12:03pm
I don't think you can get at least not with server side code. The Web Server (IIS) resolves a directory path via the default document settings in the IIS configuration and as far as ASP.NET is concerned that's what you're getting.

If you really need the browser location string you can use some JavaScript on the client to capture window.location and post that back to the server in a hidden form variable for example.
# re: Making Sense of ASP.NET Paths
by Abel Braaksma February 13, 2010 @ 7:30am
Nice summary, Rick! I was wondering, if you have a "map virtual path to physical path" section, what about the opposite? Suppose I have been given a physical path, i.e.:
d:\iis\mysite\other\images

how do I retrieve the virtual path it's mapped to, i.e.:
~/other/images or 
/mysite/other/images or
http://example.com/other/images

I recently came about a use-case where an auto-images library, originally meant for WinForms, stores images on several temp locations and the class only supports retrieving the image's physical path. Now I can make up a little algorithm to map it to the server path, but doesn't something already exist in the ASP.NET base library?
# re: Making Sense of ASP.NET Paths
by Systembuilder February 22, 2010 @ 5:49pm
Hi:

How read thist the value "max_images_from_moon:45564" from the direction:

www.mydomain.com/max_images_from_moon:45564

is any request mode for this purpose?


Thanks guys
# re: Making Sense of ASP.NET Paths
by Rick Strahl February 22, 2010 @ 5:54pm
@SystemBuilder - If this is a legal URL (and I'm not sure if : is allowed in the path part of the URL) you'd retrieve it as the virtual path. Control.TemplateSourceDirectory should give it to you or you can use the LogicalPath and then strip any specific filenames from it (if any).
# I keep finding my way back to this - ASP.Net paths cheat sheet - http://www.west-wind.com/weblog/posts/132081.aspx
by Twitter Mirror February 24, 2010 @ 3:54pm
I keep finding my way back to this - ASP.Net paths cheat sheet - http://www.west-wind.com/weblog/posts
# ASP.NET Paths reference (Content Repost)
by .NET Battlebook March 01, 2010 @ 2:03pm
ASP.NET Paths reference (Content Repost)
# ASP.Net Path
by Gabriel Mongeon March 24, 2010 @ 3:28pm
ASP.Net Path
# re: Making Sense of ASP.NET Paths
by Brent Lockwood April 01, 2010 @ 3:17pm
Thanks for the good work.
# re: Making Sense of ASP.NET Paths
by Jerome Hill April 09, 2010 @ 7:45am
Rick, is there anything in ASP.Net (even new versions) that will convert all of the Relative paths to Absolute paths when the pages are rendered?

We've been told that having absolute paths in our marketing pages will give us better SEO ranking.

I'm looking for something that can either be a setting or an HttpModule. I don't want to have to go into each page and in the code behind wrap each href and src tag with a function to do this.

Any help would be appreciated.

Thanks
Jerome
# re: Making Sense of ASP.NET Paths
by hobit April 12, 2010 @ 10:50pm
Maybe you should mention that (ideally) physical file access should be done through the VirtualPathProvider class.

For instance, to read a file use:

Stream stream = VirtualPathProvider.OpenFile(virtualPath);


And thank you for your excellent blog!
# ASP.NET Get Current URL
by Florent Grandjean May 28, 2010 @ 6:32am
ASP.NET Get Current URL
# re: Making Sense of ASP.NET Paths
by Ralph June 14, 2010 @ 2:30pm
I love you Rick, you saved the day keep up the good work!
# re: Making Sense of ASP.NET Paths
by R June 21, 2010 @ 6:50am
# re: Making Sense of ASP.NET Paths
by Krish Van Colombo June 21, 2010 @ 7:40pm
Good stuff mate.
# re: Making Sense of ASP.NET Paths
by James July 09, 2010 @ 5:32am
Thanks for this post - really helped me out!
# re: Making Sense of ASP.NET Paths
by DYog July 29, 2010 @ 8:11pm
Hi,

Thanks for this good artical.

I have one issue in classic ASP.

I have to attach a pdf file to an emil.

This pdf is on other server and I have url of that file.

e.g. I have url http://webreport/PDF/Report.pdf
Now I want to attach this url file to my emil function.

How could I attach this to email I am creating?

Please Reply.

Thanks
# re: Making Sense of ASP.NET Paths
by Chris March 08, 2011 @ 6:30am
Hi Rick,

Thanks for the post! I have a question:

I have an asp.net web application developed in VS2008. The application is running as a SAS type of service, with many different companies using the app. I want to run the website in a SSL environment. I have a secured site configured and can have the application scripts installed in this website's default directory. When the client accesses their personal subdomain of our site (i.e. xyzcompany.ourcompany.com) we redirect to the secure site (secure.ourcompany.com) passing a parameter identifying which client was accessing the site. This parameter is then used to lookup, from an administration database, if the client is vaild, enabled, what the DSN information is, etc. If the client is valid, the application starts using the session variables defined from the admin database lookup. Everything works perfectly. Many clients can use the scripts and access their company specific databases, etc.

My issue: I want to have different versions of the scripts for the clients to run based on an entry in the admin database. Currently, the secure website is configured to physical path c:\secure\website\scripts\ (this is where my asp.net scripts are installed) I want to have subdirectories containing different versions. i.e. c:\secure\website\scripts\version1 ... c:\secure\website\scripts\version2... etc. In the VS2008 application, we use virtual root names for file locations... i.e ~\images\logo.png. This works fine if the application is installed in the "root" directory of the website. However, when I move the scripts to the new "version" sub-directory, the virtual path is no longer valid and the application dies due to files not found. (A server.transfer to ~\help.aspx fails because the path is actually ~\version1\help.aspx)

My question: how do I change the "virtual" root directory of the application based on the supplied session variable which identifies which "version subfolder" is now the application root folder?
# re: Making Sense of ASP.NET Paths
by Alex April 05, 2011 @ 6:08am
OK I just emailed this post to my team (working remotely) and asked to stick it to the wall.
Great stuff.
PS. And thanks for mentioning the MVC-version of "ResolveUrl"!
# re: Making Sense of ASP.NET Paths
by prgmrgirl April 08, 2011 @ 1:53pm
Somehow, whenever I have an issue and I google a resolution, your site always comes up and you almost always have the answer I need. Thank you for taking the time out to blog your findings.

Cheers!
# re: Making Sense of ASP.NET Paths
by Guru Prasad September 01, 2011 @ 11:32pm
You are aswome Dude.
When ever i google and come to your site (with your Photo in side). I know i will get what i am looking for.

You are the defenetion of Awsome ness :)
# re: Making Sense of ASP.NET Paths
by Saeed Neamati September 06, 2011 @ 1:00am
This is great. I think ASP.NET has done a great way to provide OO path access to the current request. The only problem is that, some names are different from JavaScript location object.
# re: Making Sense of ASP.NET Paths
by Serguei February 03, 2012 @ 5:26am
When I use synonyms for may base domain - how can I get correct URL?

For example...

base domain: site.de
synonym: site.com

I open "site.com" and I see in my browser "site.com".

But!

AbsolutePath @(HttpContext.Current.Request.Url.AbsolutePath)<br />
Authority @(HttpContext.Current.Request.Url.Authority)<br />
DnsSafeHost @(HttpContext.Current.Request.Url.DnsSafeHost)<br />
Host @(HttpContext.Current.Request.Url.Host)<br />
OriginalString @(HttpContext.Current.Request.Url.OriginalString)<br />

All are "site.de"
# re: Making Sense of ASP.NET Paths
by aximili May 15, 2014 @ 11:39pm
This is a great post. It has been very useful for me for 4 years!
 


West Wind  © Rick Strahl, West Wind Technologies, 2005 - 2014