Accessing calendar items in a recurring series by using the EWS Managed API 2.0

Last modified: October 13, 2012

Applies to: EWS Managed API | Exchange Server 2007 Service Pack 1 (SP1) | Exchange Server 2010

Note: This content applies to the EWS Managed API 2.0 and earlier versions. For the latest information about the EWS Managed API, see Web services in Exchange.

A recurring series is a sequence of calendar items that follow a recurrence pattern and have a recurrence range. A recurring series consists of a recurring master item, occurrence items, and sometimes exception items. The following table defines these item types. For more information about the items in a recurring series, see Overview of a recurring series in the EWS Managed API 2.0. This topic explains how you can use the Microsoft Exchange Web Services (EWS) Managed API to access the items in a recurring series.

Item type

Description

Recurring master item

The item that anchors the recurring series and holds all recurrence pattern and recurrence range information. Each recurring series has one recurring master item.

Occurrence items

The sequence of calendar items in a recurring series that adhere to the recurrence pattern of the series.

Exception items

Items in the series that started as occurrence items, but were modified so that they no longer have the same property values as occurrence items. Modifying any property on an occurrence item makes it an exception item.

To determine the item type of a calendar item

  1. Bind to the calendar item by using its unique identifier. The following code shows how to bind to a calendar item and provide it with connection configuration information by using an ExchangeService object named service. The ItemId has been shortened to preserve readability.

    Appointment appointment = Appointment.Bind(service, new ItemId("AAMkA="));
    
  2. Check the value of the AppointmentType property on the calendar item. The following code shows how to determine the type of the calendar item by using the AppointmentType property.

    if (appointment.AppointmentType == AppointmentType.RecurringMaster)
    {
       // Calendar item is a recurring master item for a recurring series.
    }
    else if (appointment.AppointmentType == AppointmentType.Occurrence)
    {
       // Calendar item is an occurrence in a recurring series.
    }
    else if (appointment.AppointmentType == AppointmentType.Exception)
    {
       // Calendar item is an exception in a recurring series.
    }
    else
    {
       // Calendar item is not part of a recurring series.
       // The value of appointment.AppointmentType is AppointmentType.Single.
    }
    

To search for a recurring master item

  1. Create a search filter. The following code shows how to create a search filter to find items that have a start date on or after January 1, 2009. For more information about how to build search filters, see Working with search filters by using the EWS Managed API 2.0.

    SearchFilter.SearchFilterCollection searchFilter = new SearchFilter.SearchFilterCollection();
    searchFilter.Add(new SearchFilter.IsGreaterThanOrEqualTo(AppointmentSchema.Start, new DateTime(2009, 1, 1)));
    
  2. Create an ItemView and specify which properties to return in the result set. The following code shows how to configure a search that will return a maximum of twenty items, each containing the following properties: Id, Subject, Start, and AppointmentType. For more information about how to configure ItemView, see Searching for items in a mailbox by using the EWS Managed API 2.0.

    ItemView view = new ItemView(20);
    view.PropertySet = new PropertySet(BasePropertySet.IdOnly, AppointmentSchema.Subject, AppointmentSchema.Start, AppointmentSchema.AppointmentType);
    
  3. Send the request to search the mailbox that is associated with the service binding. The following code shows how to search the Calendar folder by using the search filter and view defined in the previous steps. This example assumes that service is a valid ExchangeService binding.

    FindItemsResults<Item> findResults = service.FindItems(WellKnownFolderName.Calendar, searchFilter, view);
    
  4. Iterate through the search results, checking the value of the AppointmentType property for each item. FindItems returns items having AppointmentType equal to AppointmentType.RecurringMaster and items having AppointmentType equal to AppointmentType.Single; therefore, you must check the value of the AppointmentType property to identify recurring master items.

    foreach (Item item in findResults.Items)
    {
        Appointment appt = item as Appointment;
        if (appt.AppointmentType == AppointmentType.RecurringMaster)
        {
           // Calendar item is a recurring master item for a recurring series.
        }
    }
    

To search for occurrence items and exception items

  1. Create a CalendarView, specify the date range for the search, and specify which properties to return in the result set. The following code shows how to configure a search that will return calendar items that occur between January 1, 2009 and January 31, 2009 (inclusive), with each item containing the following properties: Id, Subject, Start, IsReccuring, and AppointmentType.

    DateTime startDate = new DateTime(2009, 1, 1);
    DateTime endDate = new DateTime(2009, 1, 31);
    CalendarView calView = new CalendarView(startDate, endDate);
    calView.PropertySet = new PropertySet(BasePropertySet.IdOnly, AppointmentSchema.Subject, AppointmentSchema.Start, AppointmentSchema.IsRecurring, AppointmentSchema.AppointmentType);
    
  2. Send the request to search the mailbox that is associated with the service binding. The following code shows how to search the Calendar folder by using the CalendarView that was defined in the previous steps. This example assumes that service is a valid ExchangeService binding.

    FindItemsResults<Appointment> findResults = service.FindAppointments(WellKnownFolderName.Calendar, calView);
    
  3. Iterate through the search results, checking the value of the AppointmentType property for each item. FindAppointments returns items having AppointmentType equal to AppointmentType.Occurrence, items having AppointmentType equal to AppointmentType.Exception, and items having AppointmentType equal to AppointmentType.Single; therefore, you must check the value of the AppointmentType property to identify occurrence items and exception items.

    foreach (Appointment appt in findResults.Items)
    {
        if (appt.AppointmentType == AppointmentType.Occurrence)
        {
           // Calendar item is an occurrence in a recurring series.
        }
        else if (appt.AppointmentType == AppointmentType.Exception)
        {
           // Calendar item is an exception in a recurring series.
        }
    }
    

To get the recurring master item of a series by using an occurrence item or an exception item

  • Bind to the recurring master item for the series by using the unique identifier of an occurrence item in the series or by using the unique identifier of an exception item in the series. The following code shows how to bind to a recurring master item and provide it with connection configuration information by using an ExchangeService object named service. The string sOccurrenceIdOrExceptionId represents the ItemId of an occurrence item or an exception item in the series.

    Appointment recurringMasterItem = Appointment.BindToRecurringMaster(service, new ItemId(sOccurrenceIdOrExceptionId));
    

To get an occurrence item or exception item by using the index

  • Bind to an occurrence item or exception item by using the unique identifier of the recurring master item for the series and by specifying the index of the item that you want. For information about how items in a recurring series are indexed, see Overview of a recurring series in the EWS Managed API 2.0. The following code shows how to bind to the third item in a recurring series and provide it with connection configuration information by using an ExchangeService object named service. The string sRecurringMasterId represents the ItemId of the recurring master item for the series.

    Appointment occurrenceOrException = Appointment.BindToOccurrence(service, new ItemId(sRecurringMasterId), 3);
    

To get the previous item or next item in a series

  1. Save the start date/time of the occurrence item or exception item that you are interested in. In the following code, occurrenceItemOrExceptionItem is the appointment for which to get the previous appointment and next appointment.

    DateTime occurStart = occurrenceItemOrExceptionItem.Start;
    
  2. Iterate through the appointments in the recurring series, using the value of the Start property to locate the appointment that you are interested in, and finding the previous appointment to and next appointment after that appointment. The following code shows how to iterate through the appointments in a series, identify the appointment that has a Start property value that matches the value that you saved in the previous step, and use the BindToOccurrence method to get the previous appointment and the next appointment in the series. When you reach the end of the series, or try to access an item by using an index that does not exist in the series, you will get an exception with the message "Occurrence Index is out of recurrence range." The following code catches these exceptions and displays the appropriate message. The string sRecurringMasterId represents the ItemId of the recurring master item for the series.

    int iCurrentIndex = 1;
    try
    {
        while (true)
        {
            // Get the appointment that is located at the current index in the series.
            Appointment seriesAppt = Appointment.BindToOccurrence(service, new ItemId(sRecurringMasterId), iCurrentIndex);
    
            // If the current appointment's Start value matches the item that you are looking for, get the previous item and next item in the series.
            if (seriesAppt.Start == occurStart)
            {
                // Get the previous appointment in the series, if there is one.
                if (iCurrentIndex > 1)
                {
                    Appointment priorAppt = Appointment.BindToOccurrence(service, new ItemId(sRecurringMasterId), iCurrentIndex - 1);
                }
                else
                {
                    Console.WriteLine("There is no previous appointment in the series.");
                }
    
                // Get next appointment in the series.
                try
                {
                    Appointment nextAppt = Appointment.BindToOccurrence(service, new ItemId(sRecurringMasterId), iCurrentIndex + 1);
                }
                catch (Exception e)
                {
                    if (e.Message == "Occurrence index is out of recurrence range.")
                    {
                        Console.WriteLine("There is no 'next' occurrence in the series.");
                    }
                    else
                    {
                        throw e;
                    }
                }
            }
            iCurrentIndex++;
        }
    }
    catch (Exception e)
    {
        if (e.Message == "Occurrence index is out of recurrence range.")
        {
            Console.WriteLine("The end of the series has been reached.");
        }
        else
        {
            throw e;
        }
    }
    

To get the first or last item in a series

  • Bind to the first or last item in a series by using the recurring master item for the series. The following code shows how to get the first item and last item in a series and provide connection configuration information by using an ExchangeService object named service. The recurringMasterItem object represents the recurring master item for the series.

    // Get the first item in the series.
    Appointment firstItem = Appointment.Bind(service, recurringMasterItem.FirstOccurrence.ItemId);
    
    // Get the last item in the series.
    Appointment lastItem = Appointment.Bind(service, recurringMasterItem.LastOccurrence.ItemId);
    

To identify when a series starts and ends

  • Use properties on the recurring master item to identify when a series starts and ends. The following code shows how to identify when a series starts and ends by using properties on the recurring master item for the series. The recurringMasterItem object represents the recurring master item for the series.

    // Get the start date of the first item in the series.
    DateTime seriesStartDate = recurringMasterItem.FirstOccurrence.Start.Value;
    
    // Get the start date for the last item in the series. 
    DateTime seriesEndDate = recurringMasterItem.LastOccurrence.Start.Value;
    

To identify the exception items in a series

  • Use the ModifiedOccurrences property on the recurring master item for the series to identify the exception items in a series. Each OccurrenceInfo object in the ModifiedOccurrences collection contains four properties: End, ItemId, OriginalStart, and Start. To access additional properties on the exception item, you must bind to the item by using the OccurrenceInfo.ItemId. The following code shows how to iterate through the exception items in a recurring series and bind to each exception item to access the Subject property. The recurringMasterItem object represents the recurring master item for the series.

    foreach (OccurrenceInfo item in recurringMasterItem.ModifiedOccurrences)
    {
       Appointment modifiedItem = Appointment.Bind(service, item.ItemId);
       Console.WriteLine("Subject: " + modifiedItem.Subject);
    }
    

    Note

    The properties that are populated on each OccurrenceInfo object in the ModifiedOccurrences collection are not necessarily the properties that caused the occurrence to become an exception. Changing any property on an occurrence item, even one that is not in the set of properties that are available on an OccurrenceInfo object, causes an occurrence to become an exception.

To identify the deleted items in a series

  • Use the DeletedOccurrences property on the recurring master item for the series to identify the items that have been deleted from a series. Each OccurrenceInfo object in the ModifiedOccurrences collection contains only one populated property: Start. Because the ItemId property is not populated, you cannot bind to a deleted item. The following code shows how to iterate through the deleted items in a recurring series and access the Start property. The recurringMasterItem object represents the recurring master item for the series.

    foreach (OccurrenceInfo item in recurringMasterItem.DeletedOccurrences)
    {
       Console.WriteLine("Start: " + item.Start.Value.ToString());
    }
    

Compiling the code

For information about compiling this code, see Getting started with the EWS Managed API 2.0.

Robust programming

  • Write appropriate error handling code for common search errors.

  • Review the client request XML that is sent to the Exchange server.

  • Review the server response XML that is sent from the Exchange server.

  • Set the service binding as shown in Setting the Exchange service URL by using the EWS Managed API 2.0. Do not hard code URLs because if mailboxes move, they might be serviced by a different Client Access server. If the client cannot connect to the service, retry setting the binding by using the AutodiscoverUrl(String) method.

  • Set the target Exchange Web Services schema version by setting the requestedServerVersion parameter of the ExchangeService constructor. For more information, see Versioning EWS requests by using the EWS Managed API 2.0.

Security

  • Use HTTP with SSL for all communication between client and server.

  • Always validate the server certificate that is used for establishing the SSL connections. For more information, see Validating X509 certificates by using the EWS Managed API 2.0.

  • Do not include user names and passwords in trace files.

  • Verify that Autodiscover lookups that use HTTP GET to find an endpoint always prompt for user confirmation; otherwise, they should be blocked.