Recurrence patterns and EWS

Learn about recurrence patterns and recurring series in Exchange.

Last modified: March 09, 2015

Applies to: EWS Managed API | Exchange Online | Exchange Server 2013 | Office 365

In this article
Recurring calendar items
Recurrence patterns
Expanded vs. non-expanded views
Working with recurring calendar items
In this section
Additional resources

A recurring series is an appointment or meeting that repeats according to a defined pattern. A recurring series can either have a specific number of occurrences or can repeat indefinitely. Additionally, a recurring series can have exceptions that don't follow the pattern of the rest of the occurrences, and can have occurrences that have been deleted from the pattern. You can use the EWS Managed API and EWS to work with recurring series and their associated calendar items.

All calendar items fall into one of the following four categories:

  • Non-recurring calendar items

  • Recurring masters

  • Occurrences in a series

  • Modified occurrences in a series, known as exceptions

In this article, we'll look at the three types of calendar items that are part of a recurring series.

It's helpful to understand how recurring series are implemented on the Exchange server. Instead of creating a separate distinct item for each occurrence in a recurring series, the server creates only one actual item in the calendar, known as the recurring master. The format of a recurring master is very similar to a non-recurring appointment, with the addition of recurrence pattern information. The server then generates occurrences based on the recurrence pattern in response to client requests for appointment information, using a process called expansion. These generated occurrences are not permanently stored on the server. This is important to understand because the way that you search for calendar items determines what information you receive and whether expansion occurs.

The key piece to a recurring series that makes expansion possible is the recurrence pattern. The recurrence pattern is found on the recurring master, and describes a set of criteria for calculating occurrences based on the date and time of the recurring master.

Table 1.  Available recurrence patterns

EWS Managed API class

EWS element

Examples

Recurrence.DailyPattern

DailyRecurrence

Repeat every day.

Repeat every other day.

Recurrence.MonthlyPattern

AbsoluteMonthlyRecurrence

Repeat every month on the tenth day of the month.

Repeat every other month on the twenty-first day of the month.

Recurrence.RelativeMonthlyPattern

RelativeMonthlyRecurrence

Repeat on the second Tuesday of every month.

Repeat on the third Thursday of the month every three months.

Recurrence.RelativeYearlyPattern

RelativeYearlyRecurrence

Repeat on the first Monday of August every year.

Recurrence.WeeklyPattern

WeeklyRecurrence

Repeat every Monday.

Repeat every Tuesday and Thursday every other week.

Recurrence.YearlyPattern

AbsoluteYearlyRecurrence

Repeat on September 1st every year.

The other important piece of information for a recurrence pattern is when the recurrence ends. This can be expressed as either a set number of occurrences, as an end date, or as having no end.

Table 2.  Options for the end of a recurring series

EWS Managed API method/property

EWS element

Description

Recurrence.NumberOfOccurrences

NumberedRecurrence

The value of this property or element specifies the number of occurrences.

Recurrence.EndDate

EndDateRecurrence

The last occurrence in the series falls on or before the date specified by this property or element.

Recurrence.HasEnd

Recurrence.NeverEnds

NoEndRecurrence

The series has no end.

Using the FindAppointments method in the EWS Managed API (or the FindItem operation with a CalendarView element in EWS) invokes the expansion process. This hides recurring master appointments from the result set, and instead presents an expanded view of that recurring series. Occurrences of and exceptions to the recurring master that fall within the parameters of the calendar view are included in the result set. Conversely, using the FindItems method in the EWS Managed API (or the FindItem operation with a IndexedPageItemView or FractionalPageItemView element in EWS), does not invoke the expansion process, and occurrences and exceptions are not included. Let's look at an example comparing the two methods.

Table 3.  Methods and operations for finding appointments

EWS Managed API method

EWS operation

Expands series?

Items included in results

ExchangeService.FindAppointments

FindItem operation with a CalendarView element

Yes

Non-recurring appointments, single occurrences of recurring series, and exceptions to recurring series

ExchangeService.FindItems

FindItem operation with an IndexedPageItemView element or FractionalPageItemView element

No

Non-recurring appointments and recurring master appointments

Sadie has just signed her son up for swim team. The team has practice every Wednesday morning at 8:30 AM, starting July 2, with the last practice being on August 6. Not wanting to forget about practice, Sadie adds a recurring appointment to her calendar to remind her.

Table 4.  Sadie's recurring appointment

Appointment field

Value

Subject

Swim Team Practice

Start

July 2, 2014 8:30 AM

End

July 2, 2014 10:00 AM

Recurs

Every Wednesday

Last occurrence

August 6, 2014 8:30 AM

A quick look at a calendar shows that the team will have a total of six practices. However, there aren't six distinct appointment items in the calendar. Instead, there is just one recurring master appointment representing the series.

Now let's look at finding appointments on Sadie's calendar that occur within the month of July. The following code example uses the FindItems method in the Exchange Managed API to produce a non-expanded view of Sadie's calendar.

PropertySet propSet = new PropertySet(AppointmentSchema.Subject,
                                      AppointmentSchema.Location,
                                      AppointmentSchema.Start, 
                                      AppointmentSchema.End,
                                      AppointmentSchema.AppointmentType);

#region FindItems + ItemView method
ItemView itemView = new ItemView(100);
itemView.PropertySet = propSet;

List<SearchFilter> filterList = new List<SearchFilter>();

// Find appointments that start after midnight on July 1, 2014.
SearchFilter.IsGreaterThan startFilter = new SearchFilter.IsGreaterThan(AppointmentSchema.Start,
    new DateTime(2014, 7, 1));
// Find appointments that end before midnight on July 31, 2014
SearchFilter.IsLessThan endFilter = new SearchFilter.IsLessThan(AppointmentSchema.End,
    new DateTime(2014, 7, 31));

filterList.Add(startFilter);
filterList.Add(endFilter);

SearchFilter.SearchFilterCollection calendarFilter = new SearchFilter.SearchFilterCollection(LogicalOperator.And, filterList);

// This results in a call to EWS.
FindItemsResults<Item> results = service.FindItems(WellKnownFolderName.Calendar, calendarFilter, itemView);

foreach(Item appt in results.Items)
{
    Console.WriteLine(appt.Subject);
}

That code results in the following FindItem operation request with an IndexedPageItemView element.

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages" 
    xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types" 
    xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Header>
    <t:RequestServerVersion Version="Exchange2007_SP1" />
    <t:TimeZoneContext>
      <t:TimeZoneDefinition Id="Pacific Standard Time" />
    </t:TimeZoneContext>
  </soap:Header>
  <soap:Body>
    <m:FindItem Traversal="Shallow">
      <m:ItemShape>
        <t:BaseShape>IdOnly</t:BaseShape>
        <t:AdditionalProperties>
          <t:FieldURI FieldURI="item:Subject" />
          <t:FieldURI FieldURI="calendar:Location" />
          <t:FieldURI FieldURI="calendar:Start" />
          <t:FieldURI FieldURI="calendar:End" />
          <t:FieldURI FieldURI="calendar:CalendarItemType" />
        </t:AdditionalProperties>
      </m:ItemShape>
      <m:IndexedPageItemView MaxEntriesReturned="100" Offset="0" BasePoint="Beginning" />
      <m:Restriction>
        <t:And>
          <t:IsGreaterThan>
            <t:FieldURI FieldURI="calendar:Start" />
            <t:FieldURIOrConstant>
              <t:Constant Value="2014-07-01T07:00:00.000Z" />
            </t:FieldURIOrConstant>
          </t:IsGreaterThan>
          <t:IsLessThan>
            <t:FieldURI FieldURI="calendar:End" />
            <t:FieldURIOrConstant>
              <t:Constant Value="2014-07-31T07:00:00.000Z" />
            </t:FieldURIOrConstant>
          </t:IsLessThan>
        </t:And>
      </m:Restriction>
      <m:ParentFolderIds>
        <t:DistinguishedFolderId Id="calendar" />
      </m:ParentFolderIds>
    </m:FindItem>
  </soap:Body>
</soap:Envelope>

The server's response includes only a single item, the recurring master, indicated by the CalendarItemType element value of RecurringMaster. The value of the ItemId element has been shortened for readability.

<?xml version="1.0" encoding="utf-8"?>
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
  <s:Header>
    <h:ServerVersionInfo MajorVersion="15" MinorVersion="0" MajorBuildNumber="939" MinorBuildNumber="16" Version="V2_11" 
        xmlns:h="http://schemas.microsoft.com/exchange/services/2006/types" 
        xmlns="http://schemas.microsoft.com/exchange/services/2006/types" 
        xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" />
  </s:Header>
  <s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <m:FindItemResponse xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages" 
        xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types">
      <m:ResponseMessages>
        <m:FindItemResponseMessage ResponseClass="Success">
          <m:ResponseCode>NoError</m:ResponseCode>
          <m:RootFolder IndexedPagingOffset="1" TotalItemsInView="1" IncludesLastItemInRange="true">
            <t:Items>
              <t:CalendarItem>
                <t:ItemId Id="AAMkADA5..." ChangeKey="DwAAABYA..." />
                <t:Subject>Swim Team Practice</t:Subject>
                <t:Start>2014-07-02T15:30:00Z</t:Start>
                <t:End>2014-07-02T17:00:00Z</t:End>
                <t:Location>Neighborhood Swimming Pool</t:Location>
                <t:CalendarItemType>RecurringMaster</t:CalendarItemType>
              </t:CalendarItem>
            </t:Items>
          </m:RootFolder>
        </m:FindItemResponseMessage>
      </m:ResponseMessages>
    </m:FindItemResponse>
  </s:Body>
</s:Envelope>

Now let's compare with an expanded view. The following code example uses the FindAppointments method in the EWS Managed API to create an expanded view of Sadie's calendar.

PropertySet propSet = new PropertySet(AppointmentSchema.Subject,
                                      AppointmentSchema.Location,
                                      AppointmentSchema.Start, 
                                      AppointmentSchema.End,
                                      AppointmentSchema.AppointmentType);

CalendarView calView = new CalendarView(new DateTime(2014, 7, 1),
    new DateTime(2014, 7, 31));
calView.PropertySet = propSet;

FindItemsResults<Appointment> results = service.FindAppointments(WellKnownFolderName.Calendar, calView);

foreach(Appointment appt in results.Items)
{
    Console.WriteLine(appt.Subject);
}

This code results in the following FindItem operation request with a CalendarView element.

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages" 
    xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types" 
    xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Header>
    <t:RequestServerVersion Version="Exchange2007_SP1" />
    <t:TimeZoneContext>
      <t:TimeZoneDefinition Id="Pacific Standard Time" />
    </t:TimeZoneContext>
  </soap:Header>
  <soap:Body>
    <m:FindItem Traversal="Shallow">
      <m:ItemShape>
        <t:BaseShape>IdOnly</t:BaseShape>
        <t:AdditionalProperties>
          <t:FieldURI FieldURI="item:Subject" />
          <t:FieldURI FieldURI="calendar:Location" />
          <t:FieldURI FieldURI="calendar:Start" />
          <t:FieldURI FieldURI="calendar:End" />
          <t:FieldURI FieldURI="calendar:CalendarItemType" />
        </t:AdditionalProperties>
      </m:ItemShape>
      <m:CalendarView StartDate="2014-07-01T07:00:00.000Z" EndDate="2014-07-31T07:00:00.000Z" />
      <m:ParentFolderIds>
        <t:DistinguishedFolderId Id="calendar" />
      </m:ParentFolderIds>
    </m:FindItem>
  </soap:Body>
</soap:Envelope>

This time, the server response includes five occurrences, one for each Wednesday in July. The CalendarItemType elements on these items all have a value of Occurrence. Note that the recurring master is not present in the response. The values of the ItemId elements have been shortened for readability.

<?xml version="1.0" encoding="utf-8"?>
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
  <s:Header>
    <h:ServerVersionInfo MajorVersion="15" MinorVersion="0" MajorBuildNumber="939" MinorBuildNumber="16" Version="V2_11" 
        xmlns:h="http://schemas.microsoft.com/exchange/services/2006/types" 
        xmlns="http://schemas.microsoft.com/exchange/services/2006/types" 
        xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" />
  </s:Header>
  <s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <m:FindItemResponse xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages" 
        xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types">
      <m:ResponseMessages>
        <m:FindItemResponseMessage ResponseClass="Success">
          <m:ResponseCode>NoError</m:ResponseCode>
          <m:RootFolder TotalItemsInView="5" IncludesLastItemInRange="true">
            <t:Items>
              <t:CalendarItem>
                <t:ItemId Id="AAMkADA6..." ChangeKey="DwAAABYA..." />
                <t:Subject>Swim Team Practice</t:Subject>
                <t:Start>2014-07-02T15:30:00Z</t:Start>
                <t:End>2014-07-02T17:00:00Z</t:End>
                <t:Location>Neighborhood Swimming Pool</t:Location>
                <t:CalendarItemType>Occurrence</t:CalendarItemType>
              </t:CalendarItem>
              <t:CalendarItem>
                <t:ItemId Id="AAMkADA7..." ChangeKey="DwAAABYA..." />
                <t:Subject>Swim Team Practice</t:Subject>
                <t:Start>2014-07-09T15:30:00Z</t:Start>
                <t:End>2014-07-09T17:00:00Z</t:End>
                <t:Location>Neighborhood Swimming Pool</t:Location>
                <t:CalendarItemType>Occurrence</t:CalendarItemType>
              </t:CalendarItem>
              <t:CalendarItem>
                <t:ItemId Id="AAMkADA8..." ChangeKey="DwAAABYA..." />
                <t:Subject>Swim Team Practice</t:Subject>
                <t:Start>2014-07-16T15:30:00Z</t:Start>
                <t:End>2014-07-16T17:00:00Z</t:End>
                <t:Location>Neighborhood Swimming Pool</t:Location>
                <t:CalendarItemType>Occurrence</t:CalendarItemType>
              </t:CalendarItem>
              <t:CalendarItem>
                <t:ItemId Id="AAMkADA9..." ChangeKey="DwAAABYA..." />
                <t:Subject>Swim Team Practice</t:Subject>
                <t:Start>2014-07-23T15:30:00Z</t:Start>
                <t:End>2014-07-23T17:00:00Z</t:End>
                <t:Location>Neighborhood Swimming Pool</t:Location>
                <t:CalendarItemType>Occurrence</t:CalendarItemType>
              </t:CalendarItem>
              <t:CalendarItem>
                <t:ItemId Id="AAMkADAA..." ChangeKey="DwAAABYA..." />
                <t:Subject>Swim Team Practice</t:Subject>
                <t:Start>2014-07-30T15:30:00Z</t:Start>
                <t:End>2014-07-30T17:00:00Z</t:End>
                <t:Location>Neighborhood Swimming Pool</t:Location>
                <t:CalendarItemType>Occurrence</t:CalendarItemType>
              </t:CalendarItem>
            </t:Items>
          </m:RootFolder>
        </m:FindItemResponseMessage>
      </m:ResponseMessages>
    </m:FindItemResponse>
  </s:Body>
</s:Envelope>

After you have a recurring master, an occurrence, or an exception, you can always retrieve the other related items. Given an occurrence or exception, you can retrieve the recurring master, and vice versa.

You use all the same methods and operations to work with recurring series as you use to work with non-recurring calendar items. The difference is that, depending on the item you use to invoke those methods or operations, the actions you take can apply to the entire series, or just a single occurrence. Actions taken on the recurring master will apply to all occurrences in the series, while actions taken to a single occurrence or exception will only apply to that occurrence or exception.

Show: