On my current project, I was tasked with adding a WebDAV folder to an ASP.NET application. I found a WebDAV component on sourceforge, and thought I’d give it a try, prior to investigating the less-free options. It took an hour or so to get the sample web application working. It looked like it had the hooks necessary in order to tie into the existing authentication and authorization in the application, so I started integrating it into the application.
My first pass at integrating it was to do everything at once: tie in WebDAV.net, add authentication and authorization, and change the WebDAV/file mapping from root = root to root/a/b/c = root. Needless to say, this was too big of a chunk to bite off.
So step 1 turned into getting it so that I could open the application with a WebDAV client. This involved tweaking another HttpModule that was throwing a NullReferenceException because app.User wasn’t defined. Things seemed to work, so I checked it in.
Step 2 was to tie in auth. I got the WebDAV component to set the response status to 401, but it and the Forms authentication disagreed about what that meant: WebDAV wanted to send a HTTP Basic Auth request, and ASP.NET wanted the user to be redirected to the login page. After fighting with this for a day or so, it became clear that the WebDAV part of the site would need to be a separate ASP.NET application. Also, another dev pointed out that the WebDAV module was messing up other parts of the site.
So I created a new project and plopped the WebDAV module in it. It took some time to get it back to the point where it was running (the HttpModule wasn’t being loaded at one point, and it wasn’t giving me either warnings or errors). Next was to create a connection to the database…
I tried copying over configuration from the main application to the new application in order to get all of the dependency injection stuff to work on the WebDAV application. This way I could do
ServiceLocator<ILoginDataProvider>.Get(), just like the main application did when the user logged in. I was creeping towards this, when I realized that most of the high-level auth code in the main application assumed that it was running in a forms-based authentication environment (e.g. the data provider pulled information from the session, if it was constructed with the CompositeWeb services container), and I needed to do a protocol-based authentication.
I had an epiphany at this point — why complicate things by using CompositeWeb when all I needed was to make two calls to the LoginDataProvider? Two concrete constructor calls later, I had auth implemented for the WebDAV web application.
Along the way, I discovered that the best way to test was to set up a virtual directory in IIS. Visual Studio was helpful enough to create the virtual directory of my choosing. In order to get WebDAV to work correctly, I needed to add the ASP.NET ISAPI dll as a wildcard handler, and I needed to tell IIS that there would never be any authentication (i.e. disable digest, basic, and integrated authentication). Disabling integrated authentication makes VS tell you that you can’t debug the application, but this is a lie… Build the application, then Debug, Attach to Process, and pick aspnet_wp.exe. You just can’t use the F5 shortcut that normally does all of that for you.
So, here’s what I’d say about integrating WebDAV into an existing ASP.NET application:
- WebDAV.net works fine (though the framework has a couple of very obvious bugs when you don’t set up debug logging).
- Make it a separate application. If you want it to look like it’s a subfolder of your application, deploy it to a subdirectory of the application.
- Don’t try to use CompositeWeb and WebDAV.net at the same time.