As I discussed in a previous post "ASP.NET Web Application without ASPX Extension", I've been working on a custom WebDAV server for a client. The initial proof-of-concept was just to see if we could get some .NET code that would respond to all paths for a given web application. From there I had to make WebDAV work.
What is WebDAVTo recap: WebDAV is an IETF Standard Protocol. It is an extension to the ubiquitous HTTP standard, adding on request methods to get property information about files and folders, make folders (called collections in WebDAV parlance), change properties, lock files, etc. Basically anything that you would want on a distributed file system. WebDAV is natively supported by Windows 2000 and XP, Mac OS X, and Linux (using davfs). When using this native support, you're able to interact with WebDAV just like you are using a local filesystem or a network share. There are also many standalone client implementations that act more like FTP clients.
Why Would You Write Your Own DAV Server?Sharing files over a network is nothing new of course. Using Windows File Sharing, many people are used to using network shares to store files on a server and to share with their coworkers. The limitation of most of these file sharing systems is that they share exactly what is on the filesystem. What if you want to integrate file sharing with an application that stores file meta-data in a database? What if you want to programmatically control the files and folders that you show to your users? By building your own WebDAV server you can query a database to get all of the meta-data (and even file contents) to serve to your users.
How To Build a WebDAV ServerI did quite a bit of searching and found WebDAV server implementation in Python, Ruby, and Java, but could not find anything done in a .NET language which my client uses for all of their application infrastructure. So, I built one!
As I mentioned in my previous post, we can take over the complete HTTP request for all requested paths. I use a Command Pattern to handle the different types of WebDAV requests. The Commands are responsible for getting information from the HTTP Request that they need to fulfill the request and for writing the proper HTTP Response. Each of the Commands delegates the actual File manipulation to a set of provider classes. Those classes are accessed through an Abstract Factory which allows for me to easily change the backend implementation. This allows for a good separation of concerns. The WebDAV Service layer knows how to read and write WebDAV and the File Provider layer knows how to get and store information about files and folders. (The abstraction between the Commands and the File Providers is a bit leaky still, but I'm confident I'll be able to refactor it into a cleaner separation.)
The first backend provider that I created for testing was a FileSystem provider. I've mapped the WebDAV server to a specific directory and use standard
System.IO commands to manipulate files. This is a lot easier because it allowed me to focus on implementing the protocol without worrying about interacting with a less familiar data access layer.
Test Your ImplementationThe WebDAV folks have built a great test suite called Litmus that you can use to validate your server implementation. It performs all of the basic operations on files and collections to validate that the server performs to the specification. Start with Litmus and you've got your entire functional test harness written for you. That is some TDD in action! Litmus goes a long way to get you to protocol compliance, but it took a bit of cleaning and tweaking before Windows Explorer would happily mount the Web Folder.
In addition to Litmus I found a couple of other tools really handy for debugging:
- Ethereal - a very nice protocol analyzer that will let you inspect a series of requests and responses.
- DAVExplorer - a Java WebDAV client that will write detailed logs of requests and responses.
Don't be afraid to write your own WebDAV server, it's really fun!
WebDAV Reference Book: WebDAV: Next-Generation Collaborative Web Authoring by Lisa Dusseault