WebDAV Server Engine Request Processing Pipeline Customization

IT Hit WebDAV Server Engine is a highly customizable library that provides the means for extending its functionality by the means of creating custom method handlers, options handlers,  property handlers and report handlers.

Creating a Custom Method Handler for GET Request

In most cases, WebDAV server is accessed using desktop WebDAV client such as Microsoft mini redirector/Web Folders or Mac OS X Finder. The desktop WebDAV client never submits GET request to a WebDAV folder, so if you are using desktop clients only, you do not need to care about the scenario described here.

However, a user may also try to access your WebDAV server typing a URL of the WebDAV server in a web browser. In this case, you would want to display some custom web page that contains information about how to connect to your server. In other cases, you can just list files in this specific WebDAV folder so user can browse the files structure right in a web browser.

When user types WebDAV server root or to some folder (http://myserver/somefolder/) in a web browser address bar and hits 'Go', the web browser submits GET request to a WebDAV folder. The GET requests submitted to WebDAV folders are not regulated by WebDAV protocol and are not processed by the IT Hit WebDAV Server. To display some custom web page, you must implement custom method handler and register it with the Engine.

To register a handler, call DavEngineAsync.RegisterMethodHandler method passing HTTP method name and object instance implementing IMethodHandlerAsync interface. The original handler, if any, is returned from RegisterMethodHandler method. An example below processes and displays an ASP.NET web page in response to GET request to a folder:

DavEngine engine = new DavEngine();

...

var handler = new MyCustomGetHandler();

handler.OriginalHandler = engine.RegisterMethodHandler("GET", handler);
engine.Run(myContext);


class MyCustomGetHandler : IMethodHandler
{
    public IMethodHandler OriginalHandler { get; set; }
 
    public bool EnableOutputBuffering
    {
        get { return false; }
    }
 
    public bool EnableOutputDebugLogging
    {
        get { return false; }
    }
 
    public bool EnableInputDebugLogging
    {
        get { return false; }
    }
 
    ///<summary>
    /// Handles GET request.
    ///</summary>
    ///<param name="context">Instace of <see cref="DavContextBase"/>.</param>
    ///<param name="item">Instance of <see cref="IHierarchyItem"/> which was returned by
    ///<see cref="DavContextBase.GetHierarchyItem"/> for this request.</param>
    public void ProcessRequest(DavContextBase context, IHierarchyItem item)
    {
        if (item is IFolder)
        {
            // Remember to call EnsureBeforeResponseWasCalled here if your context implementation
            // makes some useful things in BeforeResponse.
            context.EnsureBeforeResponseWasCalled();
            Page page = (Page)System.Web.Compilation.BuildManager.CreateInstanceFromVirtualPath(
                "~/MyCustomHandlerPage.aspx", typeof(Page));
            page.ProcessRequest(HttpContext.Current);
        }
        else
        {
            OriginalHandler.ProcessRequest(context, item);
        }
    }
        
    public bool AppliesTo(IHierarchyItem item)
    {
        return item is IFolder || OriginalHandler.AppliesTo(item);
    }
}

The following example lists folder content:

public void ProcessRequest(DavContextBase context, IHierarchyItem item)
{
    if (item is IFolder)
    {
        context.EnsureBeforeResponseWasCalled();
 
        // in case of HttpListener you must also set content lenght: context.Response.ContentLength = 12345;
        context.Response.ContentType = "text/html";
        using (var writer = new StreamWriter(context.Response.OutputStream))
        {
            writer.Write("<html><head></head><body>");
 
            IEnumerable<IHierarchyItem> items = ((IFolder)item).GetChildren(null);
            foreach (IHierarchyItem hierarchyItem in items)
            {
                writer.Write("<a href='" + context.Request.ApplicationPath.TrimEnd('/') + hierarchyItem.Path + "'>");
                writer.Write(hierarchyItem.Name);
                writer.Write("</a><br/>");
            }
 
            writer.Write("</body></html>");
        }
    }
    else
    {
        OriginalHandler.ProcessRequest(context, item);
    }
}