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?
6 Answers
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.

- 14,151
- 6
- 34
- 55

- 74,180
- 73
- 171
- 204
-
2@[GateKiller](http://stackoverflow.com/questions/3164?sort=oldest#3218): 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. – Costo Aug 13 '08 at 01:09
Wouldn't it be nice to have Server.RelativePath(path)?
well, you just need to extend it ;-)
public static class ExtensionMethods
{
public static string RelativePath(this HttpServerUtility srv, string path, HttpRequest context)
{
return path.Replace(context.ServerVariables["APPL_PHYSICAL_PATH"], "~/").Replace(@"\", "/");
}
}
With this you can simply call
Server.RelativePath(path, Request);

- 1,981
- 1
- 13
- 13
-
3a better replacement for the physical path would be ~/. path.Replace(context.ServerVariables("APPL_PHYSICAL_PATH"), "~/") – Josh Russo Jul 12 '13 at 19:33
I know this is old but I needed to account for virtual directories (per @Costo's comment). This seems to help:
static string RelativeFromAbsolutePath(string path)
{
if(HttpContext.Current != null)
{
var request = HttpContext.Current.Request;
var applicationPath = request.PhysicalApplicationPath;
var virtualDir = request.ApplicationPath;
virtualDir = virtualDir == "/" ? virtualDir : (virtualDir + "/");
return path.Replace(applicationPath, virtualDir).Replace(@"\", "/");
}
throw new InvalidOperationException("We can only map an absolute back to a relative path if an HttpContext is available.");
}

- 6,324
- 5
- 28
- 44

- 18,008
- 5
- 42
- 51
I like the idea from Canoas. Unfortunately I had not "HttpContext.Current.Request" available (BundleConfig.cs).
I changed the methode like this:
public static string RelativePath(this HttpServerUtility srv, string path)
{
return path.Replace(HttpContext.Current.Server.MapPath("~/"), "~/").Replace(@"\", "/");
}

- 1,253
- 16
- 12
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.

- 40,752
- 27
- 129
- 174
-
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. – tags2k Aug 06 '08 at 09:00
-
[@tagsk](http://stackoverflow.com/questions/3164#3195) - 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](http://msdn.microsoft.com/en-us/library/ms178116.aspx): > ASP.NET includes the Web application > root operator (~), which you can use > when specifying a path in server > c – Yaakov Ellis Aug 06 '08 at 09:30
-
2Yaakov - Not so. For instance, a function I use takes a root path and returns an `IEnumerable
` collection recursively. In my web application I can provide this path resolving my relative path to a physical one, but when I get back this recursive list and want to map them back to relative paths in my application I do not have that info. – one.beat.consumer Jun 14 '12 at 18:00
For asp.net core i wrote helper class to get pathes in both directions.
public class FilePathHelper
{
private readonly IHostingEnvironment _env;
public FilePathHelper(IHostingEnvironment env)
{
_env = env;
}
public string GetVirtualPath(string physicalPath)
{
if (physicalPath == null) throw new ArgumentException("physicalPath is null");
if (!File.Exists(physicalPath)) throw new FileNotFoundException(physicalPath + " doesn't exists");
var lastWord = _env.WebRootPath.Split("\\").Last();
int relativePathIndex = physicalPath.IndexOf(lastWord) + lastWord.Length;
var relativePath = physicalPath.Substring(relativePathIndex);
return $"/{ relativePath.TrimStart('\\').Replace('\\', '/')}";
}
public string GetPhysicalPath(string relativepath)
{
if (relativepath == null) throw new ArgumentException("relativepath is null");
var fileInfo = _env.WebRootFileProvider.GetFileInfo(relativepath);
if (fileInfo.Exists) return fileInfo.PhysicalPath;
else throw new FileNotFoundException("file doesn't exists");
}
from Controller or service inject FilePathHelper and use:
var physicalPath = _fp.GetPhysicalPath("/img/banners/abro.png");
and versa
var virtualPath = _fp.GetVirtualPath(physicalPath);

- 3,066
- 5
- 26
- 37