Creating CalDAV Server
CalDAV is a standard that enables exchange if information about calendars, events, to-dos, journals and free-busy time. With a CalDAV server you can create and manage scheduling information in iCalendar format and synchronize calendars with client applications.
In this article we will describe the minimum set of interfaces required to implement on your CalDAV server. Note that this will enable only a limited amount of CalDAV clients to connect to the server. To support more clients, including iOS and OS X calendars you will have to implement Discovery support and basic ACL implementation.
Folders Structure on Your CalDAV Server
Below you can see a typical folders hierarchy on your CalDAV server.
Lets see what functionality calendar folders and files handle and what interfaces they should implement.
Represents a calendar. Calendar folder contains calendar files.
Calendar folder must implement ICalendarFolderAsync interface. This interface is derived from ICalendarItem, IFolderAsync and ICalendarReportAsync interfaces.
- ICalendarItem – enables calendaring support discovery.
- IFolderAsync - represents a folder and enables folder content management.
- ICalendarReportAsync – enables calendar queries and synchronization with CalDAV client.
Below you can see the interfaces hierarchy for ICalendarFolderAsync interface.
You should not create calendar folders inside other calendar folders. Nesting of calendars is not allowed. However potentially calendar folder can contain regular WebDAV folders.
Typically calendar file contains a single event or to-do in the iCalendar format. When you create, delete or update an event or to-do in your calendar a single calendar file is updated. An event stored in a calendar file consists of one or more components, that you can parse and serialize using IT Hit iCalendar & vCard library provided as part of the CalDAV/CardDAV Server License. Here we will only review how to read, write, create and delete calendar file as a raw stream of data.
Calendar file must implement ICalendarFileAsync interface. This interface is derived from IFileAsync and ICalendarItem.
- IFileAsync - provides the means for saving and reading file content.
- ICalendarItem - enables calendaring support discovery.
Below you can see the interfaces hierarchy for ICalendarFileAsync interface.
Events and To-dos Management
How Events and To-Dos are Created
Each event or to-do is stored in a separate calendar file. When a new event or to-do is being created in the client application the request is sent to server and the Engine calls IFolderAsync.CreateFileAsync() method. Than the Engine calls IContentAsync.WriteAsync() on a calendar file returned from CreateFileAsync() method to write event content. Below you can see a sequence of calls during event or to-do creation:
- The Engine calls DavContextBaseAsync.GetHierarchyItemAsync passing the path of the file being created (cals/cal1/file1.ics). If the file does not exists in your storage you will return null from this method.
- The Engine calls DavContextBaseAsync.GetHierarchyItemAsync passing the path of the folder in which the file should be created (cals/cal1). You will return a calendar, implementing ICalendarFolderAsync to the Engine.
- IFolderAsync.CreateFileAsync is called on the item returned in previous step. You will create a new calendar file and return an item implementing ICalendarFileAsync to the Engine.
- Engine calls IContentAsync.WriteAsync on the item returned in previous step. You will save content in your back-end storage in your WriteAsync implementation.
How Events and To-Dos are Deleted
When an event or to-do is being deleted the Engine calls IHierarchyItemAsync.DeleteAsync method. Below you can see a sequence diagram:
How Events and To-dos are Updated
When event or to-do is being updated the Engine calls IContentAsync.WriteAsync method passing a stream with an event/to-do in iCalendar format. Typically you will parse the stream content using IT Hit Collab library and save it in your back-end storage.
How Events and To-dos are being Read
To read events and to-dos the client application typically initiates a synchronization process. Regardless of what synchronization process is used, to read a single event or to-do content the Engine calls IContentAsync.ReadAsync method. In this method implementation you will construct the event or to-do and write it to provided stream.
File Content Length
Unlike regular WebDAV server, where knowing correct content length is critical, with CalDAV/CardDAV server your IContentAsync.ContentLength property implementation can return -1, indicating that the size of the file content is unknown. If your implementation returns -1 the server will generate chunked response. Most CalDAV/CardDAV clients support chunked responses, so knowing content length is not required. As soon as iCalendar content could be large, especially in case you have inline file attachments inside your event/to-do, you will typically return -1, to simplify your code and minimize time the raw iCalendar content is kept in memory.
If you need to store large calendar files and your server is hosted in IIS, read Uploading Large Files to IIS / ASP.NET article.