So, I've decided to write this post in english, so that more people working with ASP.NET might have benefit from it. I'm sorry my english is not that perfect yet.
I ran into problems with my new webhotel, and I'm having them right now as i write. I am still unsure, what exactly causes the problem, but my speculations are that possibly asp.net executes under another user, when run from the Global.asax Application_Dispose or Application_End. (Is this correct?)
I am programming my own website in Visual Basic, which is hosted on a shared hosting solution. The ASP.NET version used is 2.0, and the aspnet user on the server has read/write to any folder inside my domain, at least most of the time. Thing is, I've used the same code for at least a half year now, and it has been working just fine, until I had to switch to another host, as the old one went bankrupt, duh.
So now my site has been deployed on a new server, which has a lot in common with the old one, but has one major flaw, that won't effect most web solutions, but unfortunately renders some of my (previously fine working) code obsolete.
My website is running independent of databases. It can be configured to use them for less important tasks such as custom event logging and tracking some of the websites users habits in order to fight dupe-accounts on the website.
Whenever an application instance is created, that is, when the first user enters the site, a subroutine is called from Global.asax.vb to load all data from files located in the App_Data folder of the website. This is working fine, now to the point:
Whenever the application is destroyed again, a subroutine is called from Application_Dispose, which has to save all the new generated data to files in the App_Data folder.
The data saving subroutines are very long and uses several threads, and so, they could invite a lot of unforseen bugs, but this is not the problem, as these subroutines have been tested on two other shared servers, aswell as my own computer. They even work on this server, if i call them from another place than the Global.asax, but as soon as I try to make the application automatically save everything through Application_Dispose (or Application_End), i get a System.UnauthorizedAccessException on every file i try to write to.
This problem has had me pondering for a while, and I've even made a more simple test, to make sure that this really isn't something with my subroutines or threading bugs.
First thing I did was to create test.aspx in my domain root, and put following code into its Page_Load:
Dim Fil As New System.IO.StreamWriter([App_Data path on the server] & "test.txt", False)
Fil.WriteLine("Hallow thar! :)")
Fil.Flush()
Fil.Close()
I even tried changing the path to outside of App_Data, and also tried both places with the extension ".stxt" instead of ".txt". Everytime, it executed the script without problem, and my file was there to read and see exactly "Hallow thar! :)", written in it.
Then I went to the Global.asax.vb and put this code into Application_Disposed, then later Application_End:
Try
Dim Fil As New System.IO.StreamWriter([App_Data path] & "test2.txt", False)
UserListLoad()
Fil.WriteLine("HALLOW!! -.- ")
Fil.Flush()
Fil.Close()
Catch ex As Exception
logerror(ex)
End Try
And so, the logerror subroutine started spitting out an exeption everytime i reset my application. I restarted it by replacing an empty .vb file in the App_Code folder some times, and later tried having it end by itself (takes patience, but that's life i guess).
Still. No way could I find a test2.txt file in my App_Data folder, and so, all I have is error messages in my SQL-database looking like this (part of the path is omitted to protect my website and host from hackers):
System.UnauthorizedAccessException: Access to the path '[root]\App_Data\Data\test2.txt' is denied.
at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
at System.IO.FileStream.Init(String path, FileMode mode, FileAccess
access, Int32 rights, Boolean useRights, FileShare share, Int32
bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String
msgPath, Boolean bFromProxy)
at System.IO.FileStream..ctor(String
path, FileMode mode, FileAccess access, FileShare share, Int32
bufferSize, FileOptions options)
at System.IO.StreamWriter.CreateFile(String path, Boolean append)
at System.IO.StreamWriter..ctor(String path, Boolean append, Encoding encoding, Int32 bufferSize)
at System.IO.StreamWriter..ctor(String path, Boolean append)
at zunavi.Global.Application_End(Object sender, EventArgs e) in [root]\App_Code\Global.asax.vb:line 151
So, maybe just an idiot for not reading the documentation thoroughly, and I might just be stupid for using Application_Dispose or Application_End for something else than cleaning up resources, or maybe this is a major problem, that appareantly only exist at some hosts.
Again: I suspect the application for somehow impersonating when executing code from Application_Dispose or Application_End.
Please send me an e-mail if you know anything about this or have experienced the same. More is to follow, should (when) I find out more about this.
Sander Tams.