12

When my ASP.NET site uses documents (e.g. XML), I normally load the document as follows:

Server.MapPath("~\Documents\MyDocument.xml")

However, I would like to move the Documents folder out of the website folder so that it is now a sibling of the website folder. This will make maintaining the documents considerably easier.

However, rewriting the document load code as follows:

Server.MapPath("../../Documents/MyDocument.xml")

results in a complaint from ASP.NET that it cannot 'exit above the top directory'.

So can anyone suggest how I can relatively specify the location of a folder outside the website folder? I really don't want to specify absolute paths for the obvious deployment reasons.

Thanks

David

David
  • 14,678
  • 20
  • 80
  • 145

4 Answers4

28

If you know where it is relative to your web root, you can use Server.MapPath to get the physical location of your web root, and then Path class's method to get your document path.

In rough unchecked code something like:

webRootPath = Server.MapPath("~")
docPath = Path.GetFullPath(Path.Combine(rootPath, "../Documents/MyDocument.xml"))

Sorry if I got the Syntax wrong, but the Path class should be what you are after to play with real FS paths rather than the web type paths.

The reason your method failed is that Server.MapPath takes a location on your web server and the one you gave is not valid, since it is "above" the top of the root of the server hierarchy.

MSDN.WhiteKnight
  • 503
  • 5
  • 25
Chris
  • 26,164
  • 4
  • 67
  • 85
  • 1
    Possibly even better is to add the Documents folder as a virtual directory to the website in IIS. – David Aug 06 '10 at 10:27
  • You could do that. It really depends if users need access to these documents (or whether you want them to). If there is no need for them ever to be downloaded then there is no real need to have them as a virtual directory. You can of course secure them other ways (deny permissions on the directory, etc.) but not having an associated url is always the best way to secure. I dont' really know what your usage is though so without more idea of what this Documents directory is for I wouldn't like to say what is the best course of action (and its probabyl a separate question anyway). :) – Chris Aug 06 '10 at 10:31
  • I see you point about not having a URL. I don't really need to worry too much about that, it's a small intranet and the files are just mail merge templates. I just needed to give one user access to the directory to make copy changes to the documents, without giving her access to the actual website folder. – David Aug 06 '10 at 11:04
  • 1
    You need to use Path.GetFullPath not Path.Combine. See http://stackoverflow.com/questions/670566/path-combine-absolute-with-relative-path-strings –  Dec 19 '11 at 12:54
  • @RobinBrown: You are totally right. I've updated my answer to use both. Mainly because GetFullPath only takes one parameter and you don't want to just concatenate strings since that might not create the path you want (eg "C:\temp" and "foo" should combine to "c:\temp\foo"). – Chris Dec 19 '11 at 13:16
  • What is that?? \Documents/ – usefulBee Jun 29 '16 at 20:36
  • 1
    @usefulBee: assuming your query was about the opening `\` then you are right, it should have been a `/`. If your question was what or where the `Documents` bit came from then that was the folder the original poster had. If your question is something else then do feel free to ask. Happy to give any clarifications I can. – Chris Jun 30 '16 at 09:25
  • @Chris, thank you for your gracious response! And yes, my query was about the opening, and you fixed that. – usefulBee Jun 30 '16 at 17:10
  • And I've just noticed that I screwed up my markup in my original comment. It was meant to talk about the opening `\ ` but it thought I was trying to escape the closing `. Interestingly escaping the backslash didn't work either (hence why I now have a space in there too). :) – Chris Jul 01 '16 at 12:35
6
docPath = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"..\Documents\MyDocument.xml");

AppDomain.BaseDirectory returns current web application assembly directory path.

Tadas Šukys
  • 3,886
  • 4
  • 24
  • 30
1

If you need to resolve the path in either case absolute or relative (even outside the web app root folder) use this:

public static class WebExtesions
{
    public static string ResolveServerPath(this HttpContextBase context, string path) {
        bool isAbsolute = System.IO.Path.IsPathRooted(path);
        string root = context.Server.MapPath("~");
        string absolutePath = isAbsolute ? 
                                    path : 
                                    Path.GetFullPath(Path.Combine(root, path));
        return absolutePath;
    }
}
cleftheris
  • 4,256
  • 33
  • 51
  • @cleftherus Why do you need the `this` in the `this HttpContextBase context`? – Chopo87 Jun 24 '13 at 12:11
  • 1
    @Chopo87 In my case I was working with HttpContextWrapper class (Asp.Net MVC) which is a subclass of HttpContextBase. You can change the extention method to take HttpContext instead. – cleftheris Jun 24 '13 at 13:06
  • @cleftherus Thanks, I will go for the `HttpContext` in my case – Chopo87 Jun 24 '13 at 13:17
0

If you want to specify the Location somewhere in harddrive , then its is not easily available on web environment. If files are smaller in size and quantity then you can keep it inside directory and point then using ~/path till directory.

But in some cases we used to do Request object. For more visit this link

http://msdn.microsoft.com/en-us/library/5d5940ad.aspx