If you have used System.IO.File.Exists in ASP.Net, you probably have found out that unless the account under which ASP.Net is running (e.g. ASPNET for Windows XP and IIS_WPG for Windows 2003 Server, etc) has access to a networked location (either a unc or a mapped drive, File.Exists will always return a false no matter whether the file actually exists in the location queried or not. This behavior has caused a lot of headaches for Web developers.
The solution is to grant the ASP.Net account the access rights to whichever networked folders it needs access to. More details can be found in this Microsoft knowledge base article.
I was puzzled though as to why File.Exists should return a false which indicates “file not found” error instead of throw an exception that indicate the real underlying problem—permission denied for the account under which ASP.Net is running.
By running .Net Reflector I was able to pinpoint the problem. The following list is the code for System.IO.File.Exists (in mscorlib) as you can see, what is interesting in Microsoft’s code is that it does check the permission first (where the FileIOPermission line is). But unfortunately, if the caller does not have the permission to perform the operation, a security exception is thrown. Even though all the exceptions are caught by the subsequent catch blocks, nothing is propagated back to the caller. The exceptions are simply lost and the caller would only see a false being returned without knowing exactly what happened.
public static bool Exists(string path) {
try {
if (path == null) { return false; }
if (path.Length == 0) { return false; }
path = Path.GetFullPathInternal(path);
new FileIOPermission(FileIOPermissionAccess.Read, new string[] { path }, false, false).Demand();
return InternalExists(path); }
catch (ArgumentException) { }
catch (NotSupportedException) { }
catch (SecurityException) { }
catch (IOException) { }
catch (UnauthorizedAccessException) { }
return false; } } }
Why this production-strength code was done that way? This certainly puzzled me as whoever wrote the code at Microsoft went so far to ensure that all possible exceptions were caught separately instead of using a generic catch statement, yet did absolutely nothing about the exceptions.