Namespace: ITHit.WebDAV.Server
public override IMethodHandler<IHierarchyItem> RegisterMethodHandler( string method, IMethodHandler<IHierarchyItem> handler )
DavEngineAsync engine = new DavEngineAsync(); MyCustomGetHandler handler = new MyCustomGetHandler(); handler.OriginalHandler = engine.RegisterMethodHandler("GET", handler); MyDavContext context = new MyDavContext(...); engine.RunAsync(context);
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); } }
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); } }
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); } }
The code below is part of 'WebDAVServer.FileSystemSynchronization.AspNetCore' 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(); 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); } }