Click or drag to resize

DavEngineAsyncRegisterMethodHandler Method

IT Hit WebDAV Classes Reference
Registers custom method handler.

Namespace:  ITHit.WebDAV.Server
Assembly:  ITHit.WebDAV.Server (in ITHit.WebDAV.Server.dll) Version: 13.3.13068
Syntax
public override IMethodHandler<IHierarchyItem> RegisterMethodHandler(
	string method,
	IMethodHandler<IHierarchyItem> handler
)

Parameters

method
Type: SystemString
HTTP verb.
handler
Type: ITHit.Server.ExtensibilityIMethodHandlerIHierarchyItem
Custom handled implementing IMethodHandlerTHierarchyItem interface.

Return Value

Type: IMethodHandlerIHierarchyItem
Original handler if any.
Remarks
Using this method you can register custom method handler to be called by the engine. If the handler for the specified method was already defined it is returned from this method. The original handler can be saved and called later from your custom handler.
Examples
DavEngineAsync engine = new DavEngineAsync();
MyCustomGetHandler handler = new MyCustomGetHandler();
handler.OriginalHandler = engine.RegisterMethodHandler("GET", handler);

MyDavContext context = new MyDavContext(...);
engine.RunAsync(context);
Examples

The code below is part of 'WebDAVServer.FileSystemStorage.AspNet' C# & VB samples provided with the SDK.

internal class MyCustomGetHandler : IMethodHandler<IHierarchyItem>
{
    public IMethodHandler<IHierarchyItem> OriginalHandler { get; set; }

    public bool EnableOutputBuffering
    {
        get { return false; }
    }

    public bool EnableOutputDebugLogging
    {
        get { return false; }
    }

    public bool EnableInputDebugLogging
    {
        get { return false; }
    }

    private readonly string htmlPath;

    public MyCustomGetHandler(string contentRootPathFolder)
    {
        this.htmlPath = contentRootPathFolder;
    }

    public async Task ProcessRequestAsync(ContextAsync<IHierarchyItem> context, IHierarchyItem item)
    {
        string urlPath = context.Request.RawUrl.Substring(context.Request.ApplicationPath.TrimEnd('/').Length);

        if (item is IItemCollection)
        {
            // In case of GET requests to WebDAV folders we serve a web page to display 
            // any information about this server and how to use it.

            // Remember to call EnsureBeforeResponseWasCalledAsync here if your context implementation
            // makes some useful things in BeforeResponseAsync.
            await context.EnsureBeforeResponseWasCalledAsync();
            IHttpAsyncHandler page = (IHttpAsyncHandler)System.Web.Compilation.BuildManager.CreateInstanceFromVirtualPath(
                "~/MyCustomHandlerPage.aspx", typeof(MyCustomHandlerPage));

            if(Type.GetType("Mono.Runtime") != null)
            {
                page.ProcessRequest(HttpContext.Current);
            }
            else
            {
                // Here we call BeginProcessRequest instead of ProcessRequest to start an async page execution and be able to call RegisterAsyncTask if required. 
                // To call APM method (Begin/End) from TAP method (Task/async/await) the Task.FromAsync must be used.
                await Task.Factory.FromAsync(page.BeginProcessRequest, page.EndProcessRequest, HttpContext.Current, null);
            }
        }
        else
        {
            await OriginalHandler.ProcessRequestAsync(context, item);
        }
    }

    public bool AppliesTo(IHierarchyItem item)
    {
        return item is IFolder || OriginalHandler.AppliesTo(item);
    }
}
Examples

The code below is part of 'CalDAVServer.SqlStorage.AspNet' C# & VB samples provided with the SDK.

internal class MyCustomGetHandler : IMethodHandler<IHierarchyItem>
{
    public IMethodHandler<IHierarchyItem> OriginalHandler { get; set; }

    public bool EnableOutputBuffering
    {
        get { return false; }
    }

    public bool EnableOutputDebugLogging
    {
        get { return false; }
    }

    public bool EnableInputDebugLogging
    {
        get { return false; }
    }

    private readonly string htmlPath;

    public MyCustomGetHandler(string contentRootPathFolder)
    {
        this.htmlPath = contentRootPathFolder;
    }

    public async Task ProcessRequestAsync(ContextAsync<IHierarchyItem> context, IHierarchyItem item)
    {
        string urlPath = context.Request.RawUrl.Substring(context.Request.ApplicationPath.TrimEnd('/').Length);

        if (item is IItemCollection)
        {
            // In case of GET requests to WebDAV folders we serve a web page to display 
            // any information about this server and how to use it.

            // Remember to call EnsureBeforeResponseWasCalledAsync here if your context implementation
            // makes some useful things in BeforeResponseAsync.
            await context.EnsureBeforeResponseWasCalledAsync();

            // Request to iOS/OS X CalDAV/CardDAV profile.
            if (context.Request.RawUrl.EndsWith("?connect"))
            {
                await WriteProfileAsync(context, item, htmlPath);
                return;
            }
            IHttpAsyncHandler page = (IHttpAsyncHandler)System.Web.Compilation.BuildManager.CreateInstanceFromVirtualPath(
                "~/MyCustomHandlerPage.aspx", typeof(MyCustomHandlerPage));

            if(Type.GetType("Mono.Runtime") != null)
            {
                page.ProcessRequest(HttpContext.Current);
            }
            else
            {
                // Here we call BeginProcessRequest instead of ProcessRequest to start an async page execution and be able to call RegisterAsyncTask if required. 
                // To call APM method (Begin/End) from TAP method (Task/async/await) the Task.FromAsync must be used.
                await Task.Factory.FromAsync(page.BeginProcessRequest, page.EndProcessRequest, HttpContext.Current, null);
            }
        }
        else
        {
            await OriginalHandler.ProcessRequestAsync(context, item);
        }
    }

    public bool AppliesTo(IHierarchyItem item)
    {
        return item is IFolder || OriginalHandler.AppliesTo(item);
    }

    private async Task WriteProfileAsync(ContextAsync<IHierarchyItem> context, IHierarchyItemBase item, string htmlPath)
    {
        string mobileconfigFileName = null;
        string decription = null;
        if (item is ICalendarFolder)
        {
            mobileconfigFileName = "CalDAV.AppleProfileTemplete.mobileconfig";
            decription = (item as ICalendarFolder).CalendarDescription;
        }

        decription = !string.IsNullOrEmpty(decription) ? decription : item.Name;

        string templateContent = null;
        using (TextReader reader = new StreamReader(Path.Combine(htmlPath, mobileconfigFileName)))
        {
            templateContent = await reader.ReadToEndAsync();
        }

        Uri url = new Uri(context.Request.UrlPrefix);

        string payloadUUID = item.Path.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries).Last(); // PayloadUUID

        string profile = string.Format(templateContent
            , url.Host // host name
            , item.Path // CalDAV / CardDAV Principal URL. Here we can return (await (item as ICurrentUserPrincipal).GetCurrentUserPrincipalAsync()).Path if needed.
            , (context as DavContext).Identity.Name // user name
            , url.Port // port                
            , (url.Scheme == "https").ToString().ToLower() // SSL
            , decription // CardDAV / CardDAV Account Description
            , Assembly.GetAssembly(this.GetType()).GetName().Version.ToString()
            , Assembly.GetAssembly(typeof(DavEngineAsync)).GetName().Version.ToString()
            , payloadUUID
            );

        byte[] profileBytes = SignProfile(context, profile);

        context.Response.ContentType = "application/x-apple-aspen-config";
        context.Response.AddHeader("Content-Disposition", "attachment; filename=profile.mobileconfig");
        context.Response.ContentLength = profileBytes.Length;
        await context.Response.OutputStream.WriteAsync(profileBytes, 0, profileBytes.Length);
    }

    private byte[] SignProfile(ContextAsync<IHierarchyItem> context, string profile)
    {
        // Here you will sign your profile with SSL certificate to avoid "Unsigned" warning on iOS and OS X.
        // For demo purposes we just return the profile content unmodified.
        return context.Engine.ContentEncoding.GetBytes(profile);
    }
}
Examples

The code below is part of 'CardDAVServer.SqlStorage.AspNet' C# & VB samples provided with the SDK.

internal class MyCustomGetHandler : IMethodHandler<IHierarchyItem>
{
    public IMethodHandler<IHierarchyItem> OriginalHandler { get; set; }

    public bool EnableOutputBuffering
    {
        get { return false; }
    }

    public bool EnableOutputDebugLogging
    {
        get { return false; }
    }

    public bool EnableInputDebugLogging
    {
        get { return false; }
    }

    private readonly string htmlPath;

    public MyCustomGetHandler(string contentRootPathFolder)
    {
        this.htmlPath = contentRootPathFolder;
    }

    public async Task ProcessRequestAsync(ContextAsync<IHierarchyItem> context, IHierarchyItem item)
    {
        string urlPath = context.Request.RawUrl.Substring(context.Request.ApplicationPath.TrimEnd('/').Length);

        if (item is IItemCollection)
        {
            // In case of GET requests to WebDAV folders we serve a web page to display 
            // any information about this server and how to use it.

            // Remember to call EnsureBeforeResponseWasCalledAsync here if your context implementation
            // makes some useful things in BeforeResponseAsync.
            await context.EnsureBeforeResponseWasCalledAsync();

            // Request to iOS/OS X CalDAV/CardDAV profile.
            if (context.Request.RawUrl.EndsWith("?connect"))
            {
                await WriteProfileAsync(context, item, htmlPath);
                return;
            }
            IHttpAsyncHandler page = (IHttpAsyncHandler)System.Web.Compilation.BuildManager.CreateInstanceFromVirtualPath(
                "~/MyCustomHandlerPage.aspx", typeof(MyCustomHandlerPage));

            if(Type.GetType("Mono.Runtime") != null)
            {
                page.ProcessRequest(HttpContext.Current);
            }
            else
            {
                // Here we call BeginProcessRequest instead of ProcessRequest to start an async page execution and be able to call RegisterAsyncTask if required. 
                // To call APM method (Begin/End) from TAP method (Task/async/await) the Task.FromAsync must be used.
                await Task.Factory.FromAsync(page.BeginProcessRequest, page.EndProcessRequest, HttpContext.Current, null);
            }
        }
        else
        {
            await OriginalHandler.ProcessRequestAsync(context, item);
        }
    }

    public bool AppliesTo(IHierarchyItem item)
    {
        return item is IFolder || OriginalHandler.AppliesTo(item);
    }

    private async Task WriteProfileAsync(ContextAsync<IHierarchyItem> context, IHierarchyItemBase item, string htmlPath)
    {
        string mobileconfigFileName = null;
        string decription = null;
        if (item is IAddressbookFolder)
        {
            mobileconfigFileName = "CardDAV.AppleProfileTemplete.mobileconfig";
            decription = (item as IAddressbookFolder).AddressbookDescription;
        }

        decription = !string.IsNullOrEmpty(decription) ? decription : item.Name;

        string templateContent = null;
        using (TextReader reader = new StreamReader(Path.Combine(htmlPath, mobileconfigFileName)))
        {
            templateContent = await reader.ReadToEndAsync();
        }

        Uri url = new Uri(context.Request.UrlPrefix);

        string payloadUUID = item.Path.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries).Last(); // PayloadUUID

        string profile = string.Format(templateContent
            , url.Host // host name
            , item.Path // CalDAV / CardDAV Principal URL. Here we can return (await (item as ICurrentUserPrincipal).GetCurrentUserPrincipalAsync()).Path if needed.
            , (context as DavContext).Identity.Name // user name
            , url.Port // port                
            , (url.Scheme == "https").ToString().ToLower() // SSL
            , decription // CardDAV / CardDAV Account Description
            , Assembly.GetAssembly(this.GetType()).GetName().Version.ToString()
            , Assembly.GetAssembly(typeof(DavEngineAsync)).GetName().Version.ToString()
            , payloadUUID
            );

        byte[] profileBytes = SignProfile(context, profile);

        context.Response.ContentType = "application/x-apple-aspen-config";
        context.Response.AddHeader("Content-Disposition", "attachment; filename=profile.mobileconfig");
        context.Response.ContentLength = profileBytes.Length;
        await context.Response.OutputStream.WriteAsync(profileBytes, 0, profileBytes.Length);
    }

    private byte[] SignProfile(ContextAsync<IHierarchyItem> context, string profile)
    {
        // Here you will sign your profile with SSL certificate to avoid "Unsigned" warning on iOS and OS X.
        // For demo purposes we just return the profile content unmodified.
        return context.Engine.ContentEncoding.GetBytes(profile);
    }
}
Examples

The code below is part of 'WebDAVServer.FileSystemSynchronization.AspNetCore' C# & VB samples provided with the SDK.

C#
internal class MyCustomGetHandler : IMethodHandler<IHierarchyItem>
{
    public IMethodHandler<IHierarchyItem> OriginalHandler { get; set; }

    public bool EnableOutputBuffering
    {
        get { return false; }
    }

    public bool EnableOutputDebugLogging
    {
        get { return false; }
    }

    public bool EnableInputDebugLogging
    {
        get { return false; }
    }

    private readonly string htmlPath;

    public MyCustomGetHandler(string contentRootPathFolder)
    {
        this.htmlPath = contentRootPathFolder;
    }

    public async Task ProcessRequestAsync(ContextAsync<IHierarchyItem> context, IHierarchyItem item)
    {
        string urlPath = context.Request.RawUrl.Substring(context.Request.ApplicationPath.TrimEnd('/').Length);

        if (item is IItemCollection)
        {
            // In case of GET requests to WebDAV folders we serve a web page to display 
            // any information about this server and how to use it.

            // Remember to call EnsureBeforeResponseWasCalledAsync here if your context implementation
            // makes some useful things in BeforeResponseAsync.
            await context.EnsureBeforeResponseWasCalledAsync();

            string htmlName = "MyCustomHandlerPage.html";
            using (TextReader reader = File.OpenText(Path.Combine(htmlPath, htmlName)))
            {
                string html = await reader.ReadToEndAsync();
                html = html.Replace("_webDavServerRoot_", context.Request.ApplicationPath.TrimEnd('/'));
                html = html.Replace("_webDavServerVersion_",
                    typeof(DavEngineAsync).GetTypeInfo().Assembly.GetName().Version.ToString());

                await WriteFileContentAsync(context, html, htmlName);
            }
        }
        else
        {
            await OriginalHandler.ProcessRequestAsync(context, item);
        }
    }

    private async Task WriteFileContentAsync(ContextAsync<IHierarchyItem> context, string content, string filePath)
    {
        Encoding encoding = context.Engine.ContentEncoding; // UTF-8 by default
        context.Response.ContentLength = encoding.GetByteCount(content);     
        context.Response.ContentType = string.Format("{0}; charset={1}", MimeType.GetMimeType(Path.GetExtension(filePath)) ?? "application/octet-stream", encoding.WebName);

        // Return file content in case of GET request, in case of HEAD just return headers.
        if (context.Request.HttpMethod == "GET")
        {               
            await using (var writer = new StreamWriter(context.Response.OutputStream, encoding))
            {
                await writer.WriteAsync(content);
            }
        }
    }

    public bool AppliesTo(IHierarchyItem item)
    {
        return item is IFolder || OriginalHandler.AppliesTo(item);
    }
}
See Also