Creating a Custom WebDAV Method Handler
With IT Hit WebDAV Server Engine for .NET you can create a custom method handler to process any custom HTTP verbs as part of the Engine processing pipeline. The most typical verb that you would want to process in your WebDAV server that is not handled by the Engine is a GET request. In this article, we will describe how to create it.
Creating a Custom Method Handler for GET Request
When a WebDAV server is accessed using a desktop WebDAV clients 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 access your WebDAV server by 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, list folder contents, or display other information.
When a user types WebDAV server root URL or URL of some folder (such as https://myserver/somefolder/) in a web browser address bar and hits 'Go', the web browser submits a 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 a custom method handler and register it with the Engine.
To register a handler, call DavEngineAsync.RegisterMethodHandler method passing the HTTP method name and object instance implementing IMethodHandler 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 a 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); | |
} | |
} |
Private engine As DavEngine = New DavEngine() | |
'... | |
Private handler As MyCustomGetHandler = New MyCustomGetHandler(); | |
handler.OriginalHandler = engine.RegisterMethodHandler("GET", handler); | |
engine.Run(myContext); | |
Class MyCustomGetHandler | |
Inherits IMethodHandler | |
Public Property OriginalHandler As IMethodHandler | |
Public ReadOnly Property EnableOutputBuffering As Boolean | |
Get | |
Return False | |
End Get | |
End Property | |
Public ReadOnly Property EnableOutputDebugLogging As Boolean | |
Get | |
Return False | |
End Get | |
End Property | |
Public ReadOnly Property EnableInputDebugLogging As Boolean | |
Get | |
Return False | |
End Get | |
End Property | |
'<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 Sub ProcessRequest(ByVal context As DavContextBase, ByVal item As IHierarchyItem) | |
If TypeOf item Is IFolder Then | |
' Remember to call EnsureBeforeResponseWasCalled here if your context implementation | |
' makes some useful things in BeforeResponse. | |
context.EnsureBeforeResponseWasCalled() | |
Dim page As Page = CType(System.Web.Compilation.BuildManager.CreateInstanceFromVirtualPath("~/MyCustomHandlerPage.aspx", GetType(Page)), Page) | |
page.ProcessRequest(HttpContext.Current) | |
Else | |
OriginalHandler.ProcessRequest(context, item) | |
End If | |
End Sub | |
Public Function AppliesTo(ByVal item As IHierarchyItem) As Boolean | |
Return TypeOf item Is IFolder OrElse OriginalHandler.AppliesTo(item) | |
End Function | |
End Class |
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); | |
} | |
} |
Public Sub ProcessRequest(ByVal context As DavContextBase, ByVal item As IHierarchyItem) | |
If TypeOf item Is IFolder Then | |
context.EnsureBeforeResponseWasCalled() | |
' in case of HttpListener you must also set content lenght: context.Response.ContentLength = 12345; | |
context.Response.ContentType = "text/html" | |
Using writer = New StreamWriter(context.Response.OutputStream) | |
writer.Write("<html><head></head><body>") | |
Dim items As IEnumerable(Of IHierarchyItem) = (CType(item, IFolder)).GetChildren(Nothing) | |
For Each hierarchyItem As IHierarchyItem In items | |
writer.Write("<a href='" & context.Request.ApplicationPath.TrimEnd("/"c) + hierarchyItem.Path & "'>") | |
writer.Write(hierarchyItem.Name) | |
writer.Write("</a><br/>") | |
Next | |
writer.Write("</body></html>") | |
End Using | |
Else | |
OriginalHandler.ProcessRequest(context, item) | |
End If | |
End Sub |