/// <summary>
        /// Called when a card must be read from back-end storage.
        /// </summary>
        /// <param name="output">Stream to write vCard content.</param>
        /// <param name="startIndex">Index to start reading data from back-end storage. Used for segmented reads, not used by CardDAV clients.</param>
        /// <param name="count">Number of bytes to read. Used for segmented reads, not used by CardDAV clients.</param>
        public override async Task ReadAsync(Stream output, long startIndex, long count)
        {
            string vCard = null;

            using (StreamReader reader = File.OpenText(this.fileSystemInfo.FullName))
            {
                vCard = await reader.ReadToEndAsync();
            }

            // Typically the stream contains a single vCard.
            IEnumerable <IComponent> cards = new vFormatter().Deserialize(vCard);
            ICard2 card = cards.First() as ICard2;

            // We store a business card in the original vCard form sent by the CardDAV client app.
            // This form may not be understood by some CardDAV client apps.
            // Here we convert card to the form understood by the client CardDAV application.

            if (AppleCardInteroperability.Convert(context.Request.UserAgent, card))
            {
                // Write modified vCard to output.
                new vFormatter().Serialize(output, card);
            }
            else
            {
                // No conversion is needed.
                await base.ReadAsync(output, startIndex, count);
            }
        }
        /// <summary>
        /// Called when client application deletes this file.
        /// </summary>
        /// <param name="multistatus">Error description if case delate failed. Ignored by most clients.</param>
        public override async Task DeleteAsync(MultistatusException multistatus)
        {
            // Notify attendees that event is canceled if deletion is successful.
            string calendarObjectContent = File.ReadAllText(fileSystemInfo.FullName);

            await base.DeleteAsync(multistatus);

            IEnumerable <IComponent> calendars = new vFormatter().Deserialize(calendarObjectContent);
            ICalendar2 calendar = calendars.First() as ICalendar2;

            calendar.Method = calendar.CreateMethodProp(MethodType.Cancel);
            await iMipEventSchedulingTransport.NotifyAttendeesAsync(context, calendar);
        }
        /// <summary>
        /// Called when event or to-do is being saved to back-end storage.
        /// </summary>
        /// <param name="stream">Stream containing VCALENDAR, typically with a single VEVENT ot VTODO component.</param>
        /// <param name="contentType">Content type.</param>
        /// <param name="startIndex">Starting byte in target file
        /// for which data comes in <paramref name="content"/> stream.</param>
        /// <param name="totalFileSize">Size of file as it will be after all parts are uploaded. -1 if unknown (in case of chunked upload).</param>
        /// <returns>Whether the whole stream has been written.</returns>
        public override async Task <bool> WriteAsync(Stream content, string contentType, long startIndex, long totalFileSize)
        {
            bool result = await base.WriteAsync(content, contentType, startIndex, totalFileSize);

            // Notify attendees that event is created or modified.
            string calendarObjectContent       = File.ReadAllText(fileSystemInfo.FullName);
            IEnumerable <IComponent> calendars = new vFormatter().Deserialize(calendarObjectContent);
            ICalendar2 calendar = calendars.First() as ICalendar2;

            calendar.Method = calendar.CreateMethodProp(MethodType.Request);
            await iMipEventSchedulingTransport.NotifyAttendeesAsync(context, calendar);

            return(result);
        }