If I have managed to locate and verify the existence of a file using Server.MapPath and I now want to send the user directly to that file, what is the fastest way to convert that absolute path back into a relative web path?

+5  A: 

If you used Server.MapPath, then you should already have the relative web path. According to the MSDN documentation, this method takes one variable, path, which is the virtual path of the Web server. So if you were able to call the method, you should already have the relative web path immediately accessible.

Yaakov Ellis

@Yaakov: This is not necessarily true - the MapPath call could have been performed by another method and passed into / called from my file checker method, or (in my case) built from a number of different elements, one of which is my resources directory (defined as "~/__Resources"). Obviously directing the user to this path is going to result in unexpected results.

This would also be useful to know because sometimes the absolute file path might have been pulled out of the database with no other contextual information.

+4  A: 

Perhaps this might work:

String RelativePath = AbsolutePath.Replace(Request.ServerVariables["APPL_PHYSICAL_PATH"], String.Empty);

(i'm using c# but could be adapted to vb)

(@Tags2k: I have editted the above answer)

This only works within the context of a request.

@tagsk - I don't know about that. By the way that the method is defined, if the string that you input into Server.MapPath is valid and returns a physical server path, then this had to have been a valid virtual path as well, regardless of how you generated it.

Regarding use of the tilde (~) at the beginning of a virtual address, see this MSDN article on ASP.NET Web Site Paths:

ASP.NET includes the Web application root operator (~), which you can use when specifying a path in server controls. ASP.NET resolves the ~ operator to the root of the current application. You can use the ~ operator in conjunction with folders to specify a path that is based on the current root.

So even if you have a virtual path beginning with ~/, there should be no problem using it for redirecting the user.

Yaakov Ellis

@GateKiller: This works for me if I remove the initial Server.MapPath and just do the replace on AbsolutePath, so if you can edit your post to reflect this I'll mark yours as the answer.

@Yaakov: Point taken about redirecting to a URL with a tilde (although this is concerning as tilde is a valid URL character), but I'm afraid I still don't agree about having the virtual path. Take the example I mentioned about simply being provided the absolute path from the database, you may know this is somewhere in the web path but you wouldn't have the relative path without doing the parsing.



Take the example I mentioned about simply being provided the absolute path from the database, you may know this is somewhere in the web path but you wouldn't have the relative path without doing the parsing.

Again, the definition of Server.MapPath is that you provide a virtual path to whatever file you want, and it gives you the physical path. If the path that you provide is not virtual, then Server.MapPath wont return any valid physical path. Even if you have the path submitted to Server.MapPath stored in your DB, if it is not a virtual path, then it wont work.

If you think that I am mistaken on this, could you please give an example of a path submitted to Server.MapPath where this path is not a valid virtual path, yet it still yields a valid physical path as a return value?

Yaakov Ellis
An example I experienced was to use Directory.GetFiles() to match an image against a customer e.g. Directory.GetFiles(Server.MapPath(ImagesPath),CustomerNumber + ".*",SearchOption.TopDirectoryOnly) - used as the extension may not be determined. The image was rarely used so was not perceived as an overhead). This gives you a full path back, and needs you to translate it back to a relative path for an Image.ImageUrl control.
Dominic Zukiewicz

@Yaakov: I agree that if you were calling MapPath you would mostly have the relative path, but my description was only meant as an example, even if it was a poorly chosen one. The actual question is the title of the post, whose need would occur more than in just the scenario I gave.

You might have had the absolute path passed into your method by another method, regardless of how that other method got the path. A prime example would be if you are writing a utility method:

public static Uri AbsolutePathToWebRelativePath(this Uri uri)
    // TODO: What now?

In such a scenario, you would of course use the code provided by GateKiller.


@GateKiller: Note that if you use IIS Virtual Directories in your website, your solution can fail because the Application physical path can be different from the file's physical path.