Padrões de recorrência e EWS

Saiba mais sobre padrões de recorrência e séries recorrentes no Exchange.

Uma série recorrente é um compromisso ou reunião que se repete de acordo com um padrão definido. Uma série recorrente pode ter um número específico de ocorrências ou pode se repetir indefinidamente. Além disso, uma série recorrente pode ter exceções que não seguem o padrão do restante das ocorrências e podem ter ocorrências que foram excluídas do padrão. Você pode usar a API Gerenciada do EWS e o EWS para trabalhar com séries recorrentes e seus itens de calendário associados.

Itens de calendário recorrentes

Todos os itens de calendário se enquadram em uma das quatro categorias a seguir:

  • Itens de calendário não recorrentes

  • Mestres recorrentes

  • Ocorrências em uma série

  • Ocorrências modificadas em uma série, conhecidas como exceções

Neste artigo, examinaremos os três tipos de itens de calendário que fazem parte de uma série recorrente.

É útil entender como as séries recorrentes são implementadas no servidor exchange. Em vez de criar um item distinto separado para cada ocorrência em uma série recorrente, o servidor cria apenas um item real no calendário, conhecido como o mestre recorrente. O formato de um mestre recorrente é muito semelhante a um compromisso não recorrente, com a adição de informações de padrão de recorrência. Em seguida, o servidor gera ocorrências com base no padrão de recorrência em resposta a solicitações de cliente para informações de compromisso, usando um processo chamado expansão. Essas ocorrências geradas não são armazenadas permanentemente no servidor. Isso é importante de entender porque a maneira como você pesquisa itens de calendário determina quais informações você recebe e se ocorre expansão.

Padrões de recorrência

A peça-chave para uma série recorrente que torna a expansão possível é o padrão de recorrência. O padrão de recorrência é encontrado no mestre recorrente e descreve um conjunto de critérios para calcular ocorrências com base na data e hora do mestre recorrente.

Tabela 1. Padrões de recorrência disponíveis

Classe de API Gerenciada do EWS Elemento EWS Exemplos
Recurrence.DailyPattern
DailyRecurrence
Repita todos os dias.
Repita a cada dois dias.
Recurrence.MonthlyPattern
AbsoluteMonthlyRecurrence
Repita todos os meses no décimo dia do mês.
Repita a cada dois meses no vigésimo primeiro dia do mês.
Recurrence.RelativeMonthlyPattern
RelativeMonthlyRecurrence
Repita na segunda terça-feira de cada mês.
Repita na terceira quinta-feira do mês a cada três meses.
Recurrence.RelativeYearlyPattern
RelativeYearlyRecurrence
Repita na primeira segunda-feira de agosto todos os anos.
Recurrence.WeeklyPattern
WeeklyRecurrence
Repita todas as segundas-feiras.
Repita todas as terças e quintas-feiras a cada duas semanas.
Recurrence.YearlyPattern
AbsoluteYearlyRecurrence
Repita em 1º de setembro todos os anos.

A outra informação importante para um padrão de recorrência é quando a recorrência termina. Isso pode ser expresso como um número definido de ocorrências, como uma data de término ou como sem fim.

Tabela 2. Opções para o final de uma série recorrente

Método/propriedade da API Gerenciada do EWS Elemento EWS Descrição
Recorrência.NumberOfOccurrences
NumberedRecurrence
O valor dessa propriedade ou elemento especifica o número de ocorrências.
Recorrência.EndDate
EndDateRecurrence
A última ocorrência na série cai sobre ou antes da data especificada por essa propriedade ou elemento.
Recurrence.HasEnd
Recorrência.NeverEnds
NoEndRecurrence
A série não tem fim.

Exibições expandidas versus não expandidas

Usar o método FindAppointments na API Gerenciada do EWS (ou a operação FindItem com um elemento CalendarView no EWS) invoca o processo de expansão. Isso oculta compromissos mestre recorrentes do conjunto de resultados e, em vez disso, apresenta uma exibição expandida dessa série recorrente. Ocorrências de e exceções ao mestre recorrente que se enquadram nos parâmetros da exibição de calendário são incluídas no conjunto de resultados. Por outro lado, usar o método FindItems na API Gerenciada do EWS (ou a operação FindItem com um elemento IndexedPageItemView ou FractionalPageItemView no EWS), não invoca o processo de expansão e ocorrências e exceções não estão incluídas. Vamos examinar um exemplo comparando os dois métodos.

Tabela 3. Métodos e operações para encontrar compromissos

Método da API Gerenciada do EWS Operação do EWS Expande a série? Itens incluídos nos resultados
ExchangeService.FindAppointments
Operação FindItem com um elemento CalendarView
Sim
Compromissos não recorrentes, ocorrências individuais de séries recorrentes e exceções a séries recorrentes
ExchangeService.FindItems
Operação FindItem com um elemento IndexedPageItemView ou elemento FractionalPageItemView
Não
Compromissos não recorrentes e compromissos mestres recorrentes

Sadie acabou de inscrever o filho para a equipe de natação. A equipe treina todas as quartas-feiras pela manhã às 8h30, começando em 2 de julho, com o último treino sendo em 6 de agosto. Não querendo esquecer a prática, Sadie adiciona um compromisso recorrente ao seu calendário para lembrá-la.

Tabela 4. Compromisso recorrente de Sadie

Campo Compromisso Valor
Assunto
Prática da Equipe de Natação
Início
2 de julho de 2014 8:30 AM
End
2 de julho de 2014 10:00 AM
Recurs
Todas as quartas-feiras
Última ocorrência
6 de agosto de 2014 8:30 AM

Uma rápida olhada em um calendário mostra que a equipe terá um total de seis práticas. No entanto, não há seis itens de compromisso distintos no calendário. Em vez disso, há apenas um compromisso mestre recorrente representando a série.

Agora vamos ver como encontrar compromissos no calendário da Sadie que ocorrem no mês de julho. O exemplo de código a seguir usa o método FindItems na API Gerenciada do Exchange para produzir uma exibição não expandida do calendário da Sadie.

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);
}

Esse código resulta na solicitação de operação FindItem a seguir com um elemento IndexedPageItemView .

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages" 
    xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types" 
    xmlns:soap="https://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>

A resposta do servidor inclui apenas um único item, o mestre recorrente, indicado pelo valor do elemento CalendarItemType do RecurringMaster. O valor do elemento ItemId foi reduzido para legibilidade.

<?xml version="1.0" encoding="utf-8"?>
<s:Envelope xmlns:s="https://schemas.xmlsoap.org/soap/envelope/">
  <s:Header>
    <h:ServerVersionInfo MajorVersion="15" MinorVersion="0" MajorBuildNumber="939" MinorBuildNumber="16" Version="V2_11" 
        xmlns:h="https://schemas.microsoft.com/exchange/services/2006/types" 
        xmlns="https://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="https://schemas.microsoft.com/exchange/services/2006/messages" 
        xmlns:t="https://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>

Agora vamos comparar com uma exibição expandida. O exemplo de código a seguir usa o método FindAppointments na API Gerenciada do EWS para criar uma exibição expandida do calendário da Sadie.

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);
}

Esse código resulta na solicitação de operação FindItem a seguir com um elemento CalendarView .

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages" 
    xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types" 
    xmlns:soap="https://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>

Desta vez, a resposta do servidor inclui cinco ocorrências, uma para cada quarta-feira de julho. Os elementos CalendarItemType nesses itens têm um valor de Ocorrência. Observe que o mestre recorrente não está presente na resposta. Os valores dos elementos ItemId foram abreviados para legibilidade.

<?xml version="1.0" encoding="utf-8"?>
<s:Envelope xmlns:s="https://schemas.xmlsoap.org/soap/envelope/">
  <s:Header>
    <h:ServerVersionInfo MajorVersion="15" MinorVersion="0" MajorBuildNumber="939" MinorBuildNumber="16" Version="V2_11" 
        xmlns:h="https://schemas.microsoft.com/exchange/services/2006/types" 
        xmlns="https://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="https://schemas.microsoft.com/exchange/services/2006/messages" 
        xmlns:t="https://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>

Depois de ter um mestre recorrente, uma ocorrência ou uma exceção, você sempre poderá recuperar os outros itens relacionados. Dada uma ocorrência ou exceção, você pode recuperar o mestre recorrente e vice-versa.

Trabalhando com itens de calendário recorrentes

Você usa todos os mesmos métodos e operações para trabalhar com séries recorrentes que você usa para trabalhar com itens de calendário não recorrentes. A diferença é que, dependendo do item usado para invocar esses métodos ou operações, as ações que você tomar podem ser aplicadas a toda a série ou apenas a uma única ocorrência. As ações realizadas no mestre recorrente se aplicarão a todas as ocorrências da série, enquanto as ações tomadas para uma única ocorrência ou exceção só se aplicarão a essa ocorrência ou exceção.

Nesta seção

Confira também