Where Do All These Paths Lead?!?
by John Peterson
Now, before I get a ton of e-mail saying that I'm
straying off the topic of ASP, let me just inform you that
I know I am and I'm doing it anyway!
I'm writing this article because the issue of paths seems
to come up time after time in my discussions with people who are just starting
to learn about ASP. While it's not directly a part of ASP, a solid
understanding of directory structure and paths comes in extremely handy when
your trying to learn and / or use ASP. You ASP gurus and DOS junkies out there
can just stop reading right here. On the other hand, if you ever find
yourself wondering
"Should that be a slash or a back-slash?" or "Why can't the
stupid script find that file? It's right there!!!" you may want
to read on...
Sample Site
To help make this article a little easier to understand, the first thing I'm
going to do is make up a simple web site layout which I'll refer back to when
giving examples. Lets call the site http://www.somedomain.com. Since I'm
assuming most of you are probably running Microsoft based sites, I'll use a
layout you should be somewhat familiar with. I'm using Microsoft's default
location of C:\Inetpub\wwwroot as the root of our fictional web site. This
means that if someone typed http://www.somedomain.com into their browser, your
web server would serve them pages from the C:\Inetpub\wwwroot directory.
Inside that directory are the images and samples subdirectories. Continuing
down the tree, samples has a subdirectory of it's own, also named images.
That completes the layout of our sample site.
What the heck are those dots doing there?
Assuming you've actually been looking at some of our samples and source code,
you've almost certainly seen places in it
where we use either a . or a .. before a filename. The . and .. notation
date back to the days of good old DOS. (It actually predates that, but for
our discussion we'll leave it at that.) Anytime you issue the dir command
in a DOS session, . and .. are the first two entries in the resulting file
list. The single dot is shorthand for the current directory. The
double dot represents the parent of the current directory (the one immediately
above it in the directory tree). Assume we are at a DOS prompt in the
C:\Inetpub\wwwroot directory from our sample above. If you were to issue
the command dir, you would receive back the list of the files and subdirectories
in that directory. You would get back the same result if you entered dir .
or the command dir C:\Inetpub\wwwroot. If you instead entered dir .., you
would receive a list of the contents of the C:\Intepub directory since it's the
directory immediately above C:\Inetpub\wwwroot.
This type of notation comes in extremely
handy when you want to access a file which isn't in the same directory as your
HTML or ASP document. Assume you're working on a document in the samples
directory, when you realize you need to include the sample.gif image from the
C:\Inetpub\wwwroot\images directory. You can't just use <IMG
SRC="images/image.gif"> because the computer would look in
C:\Inetpub\wwwroot\samples\images since you are already in the samples
directory. If you instead use <IMG
SRC="../images/image.gif">, you'll get the image from the corrent
place. The .. tells the computer to go up one directory from where you
currently are before looking for the image.gif file in the images
directory.
Relative vs. Absolute
Our discussion of . and .. naturally leads into the difference between
relative and absolute paths. Let me ease into this topic by saying "Unless
I have a damn good reason, I always use relative paths!" Before
I get too far up onto my soap box on this issue, let
me first explain the difference. Relative paths are paths which like the name
implies, locate a file in relation to where you are. In our context, this
is wherever your ASP script or HTML file is located. Absolute
paths locate a file by specifying its actual fully qualified physical location.
| Absolute Path |
Relative Path (from C:\Inetpub\wwwroot) |
| C:\textfile.txt |
..\..\textfile.txt |
| C:\Inetpub\textfile.txt |
..\textfile.txt |
| C:\Inetpub\wwwroot\index.htm |
.\index.htm |
| C:\Inetpub\wwwroot\images\image.gif |
.\images\image.gif |
| C:\Inetpub\wwwroot\samples\sample.htm |
.\samples\sample.htm |
| C:\Inetpub\wwwroot\samples\images\image.jpg |
.\samples\images\image.jpg |
Now back to the discussion of which type you should use. I prefer relative for
the simple reason that I often don't work directly on the computer that's
serving our actual pages to the internet. Using relative paths allows me
to structure my own machine however I want. If I were to use absolute
paths, I'd either need to have my directory structure exactly mirror our server
or change all the links whenever I copied the files to the server. Neither
one is overly appealing to me. The other benefit of using relative paths
is that, if for some reason you need to move or rename a directory, for the most
part, your pages will continue to work without modification after the
move. For example, if we decided that the samples directory should really
be called examples, all we'd need to do would be to rename the directory and all
our pages would continue to work. If we
had used the full path, we'd now need to go through every script and change
samples to examples. Probably not an easy task depending on the size of
your file library!
Physical vs. Virtual (\ vs /)
Up until now, we've mainly been talking about physical
paths. These are paths as they exist on your hard drive or other storage
device. On PC's they are characterized by backslashes. The other
type of path is called a virtual path. These may or may not correspond
directly to physical paths on your drive and use forward slashes instead.
Perhaps the most common example of a virtual path is /scripts. This is
usually not in the same place as your documents (mainly for control over who can
modify it). In order to still allow you to access the /scripts directory
in order to run the scripts, the web server maps any incoming request for
something contained in /scripts to whatever the physical location of the files
may be. This is often C:\Inetpub\scripts, since that's Microsoft's default
setup, but it by no means needs to be. It can be located somewhere else on
the drive, on a different drive, or even on a different computer entirely!
If there is no special mapping for a specific virtual path then the server maps
it to the corresponding relative physical path in your directory tree.
You can think of virtual paths as list of exceptions to
actual physical locations. When a request comes in, the server checks the
list. If it finds a match, it goes to get the file and gives it to you (as
a result you never really know where it was). If it doesn't find a match,
it simply looks on the the physical drive in the corresponding location.
If neither one of these results in a match, you'll get a 404 Error saying that
the server can't find what you asked it for.
For the most part you should write your
HTML using /'s and not \'s. This issue has gotten a little confused by the
fact that the server and browser software is usually smart enough to find what
you're looking for even if you use the wrong type, but it's not always, so watch
yourself!
The whole Absolute vs. Relative path argument still
applies here, i just looks different. Here's a recap of the table
comparing them only this time using virtual paths instead of physical ones:
| Absolute Path |
Relative Path (from http://www.somedomain.com/samples) |
| http://www.somedomain.com/index.htm or /index.htm |
../index.htm |
| http://www.somedomain.com/images/image.gif or /images/image.gif |
../images/image.gif |
| http://www.somedomain.com/samples/sample.htm or /samples/sample.htm |
./sample.htm |
| http://www.somedomain.com/samples/images/image.jpg or /samples/images/image.jpg |
./images/image.jpg |
Server.MapPath (Finally some ASP!)
Ok, so now that you understand the difference and
hopefully I've convinced you you should be using relative virtual paths.
Everything is right in the world of paths isn't it? Well not quite.
There's one little problem. This whole virtual thing works great for HTML
files and to locate scripts, but not so great in the scripts themselves.
Many of the file related ASP commands don't particularly like being handed a
virtual path as input. The script's thinking "You want me to open
./samples/sample_list.txt? Where the heck do I find that?" You
see where ASP lives is in the files, and once you're at the files the web
server's no longer telling you that /scripts really means C:\Inetpub\scripts and
not C:\Inetpub\wwwroot\samples\scripts (which doesn't exist)! So
unfortunately, we need to use fully qualified physical path locations
again. That sort of puts a damper on being able to move our scripts around
or share them with others.... or does it?
Enter Server.MapPath. According to Microsoft, the
"MapPath method maps the specified relative or virtual path to the
corresponding physical directory on the server." Yeah, now we can
specify a relative, virtual path and let the server do the work of figuring out
the physical location for us! We get the best of both worlds! Not so
fast, there's a couple things you should know. Once again according to
Microsoft, "The MapPath method does not support relative path syntax (.) or
(..). For example, the following relative path, ../MyDir/MyFile.txt, returns an
error." and "The MapPath method does not check whether the path it
returns is valid or exists on the server."
The second statement is true, it doesn't care if the
path you're asking for exists or not and personally I think that's a good
thing. If you're using it to try and make a directory, it wouldn't exist
yet, but you'd still want to know the answer, so for this type script it's
important that this be the case. The first statement, as far as I can
tell, is incorrect! I tried their example that's supposed to fail on our
server and it ran fine. I'm assuming this statement is left over from an
older version, but I'd be very interested to hear if anyone finds they do have
trouble using relative paths.
That's It!
That's all I've got to say on the subject of paths. If you
found this article useful, think of any additional information it should have
included, or just want to say Hi!, please feel free to drop me an email at
john@asp101.com. Suggestions for
future article topics are also welcome. I hope this has helped clear some
things up for you and finally if you feel that reading this was a waste of time,
then you should probably have stopped when I gave you the chance!