Синхронизация папок с помощью EWS в Exchange

Узнайте, как использовать управляемый API EWS или EWS для получения списка папок или списка измененных папок для синхронизации клиента.

EWS в Exchange использует синхронизацию элементов и синхронизацию папок для синхронизации содержимого почтового ящика между клиентом и сервером. Синхронизация папок получает начальный список папок из корневой папки, а затем со временем получает изменения, внесенные в эти папки, а также новые папки.

Если вы выполняете синхронизацию папок с помощью управляемого API EWS, сначала получите начальный список папок в корневой папке с помощью метода ExchangeService.SyncFolderHierarchy . Затем вы обновляете значение параметра cSyncState во время последующих вызовов, чтобы получить список новых и измененных папок.

Чтобы выполнить синхронизацию папок с помощью EWS, необходимо запросить начальный список папок в корневой папке с помощью операции SyncFolderHierarchy , проанализировать ответ, а затем в будущем получить изменения в папках в корневой папке и проанализировать ответ. После получения клиентом списка исходных или измененных папок он выполняет обновления локально. Способ и время получения изменений в будущем зависит от шаблона структуры синхронизации , используемого приложением.

Получение списка всех папок или измененных папок с помощью управляемого API EWS

В следующем примере кода показано, как получить начальный список папок в корневой папке, а затем получить список изменений в папках в корневой папке, произошедших с момента предыдущей синхронизации. Во время первоначального вызова метода ExchangeService.SyncFolderHierarchy задайте для параметра cSyncState значение NULL. После завершения метода сохраните значение cSyncState локально, чтобы использовать его в следующем вызове метода SyncFolderHierarchy . Как при первоначальном вызове, так и в последующих вызовах папки извлекаются пакетами из десяти, используя последовательные вызовы метода SyncFolderHierarchy , пока не останется никаких изменений. В этом примере параметру propertySet присваивается значение IdOnly, чтобы уменьшить количество вызовов к базе данных Exchange, что является оптимальным вариантом синхронизации. В этом примере предполагается, что служба является допустимой привязкой объекта ExchangeService , а cSyncState представляет состояние синхронизации, возвращенное предыдущим вызовом SyncFolderHierarchy.

// Get a list of all folders in the mailbox by calling SyncFolderHierarchy.
// The folderId parameter must be set to the root folder to synchronize. 
// The propertySet parameter is set to IdOnly to reduce calls to the Exchange database
// because any additional properties result in additional calls to the Exchange database. 
// The syncState parameter is set to cSyncState, which should be null in the initial call, 
// and should be set to the sync state returned by the previous SyncFolderHierarchy call 
// in subsequent calls.
ChangeCollection<FolderChange> fcc = service.SyncFolderHierarchy(new FolderId(WellKnownFolderName.Root), PropertySet.IdOnly, cSyncState);
// If the count of changes is zero, there are no changes to synchronize.
if (fcc.Count == 0)
{
    Console.WriteLine("There are no folders to synchronize.");
}
// Otherwise, write all the changes included in the response 
// to the console. 
// For the initial synchronization, all the changes will be of type
// ChangeType.Create.
else
{
    foreach (FolderChange fc in fcc)
    {
        Console.WriteLine("ChangeType: " + fc.ChangeType.ToString());
        Console.WriteLine("FolderId: " + fc.FolderId);
        Console.WriteLine("===========");
    }
}
// Save the sync state for use in future SyncFolderItems requests.
// The sync state is used by the server to determine what changes to report
// to the client.
string fSyncState = fcc.SyncState;

После получения списка новых или измененных папок на сервере создайте или обновите папки на клиенте.

Получение начального списка папок с помощью EWS

В следующем примере показан XML-запрос для получения начальной иерархии папок с помощью операции SyncFolderHierarchy . Это также XML-запрос, который управляемый API EWS отправляет при получении списка исходных папок с помощью метода SyncFolderHierarchy. Элемент SyncState операции SyncFolderHierarchy не включен, так как это начальная синхронизация. В этом примере элементу BaseShape присваивается значение IdOnly , чтобы уменьшить количество вызовов к базе данных Exchange, что является оптимальным вариантом синхронизации.

<?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="Exchange2013" />
  </soap:Header>
  <soap:Body>
    <m:SyncFolderHierarchy>
      <m:FolderShape>
        <t:BaseShape>IdOnly</t:BaseShape>
      </m:FolderShape>
      <m:SyncFolderId>
        <t:DistinguishedFolderId Id="root" />
      </m:SyncFolderId>
    </m:SyncFolderHierarchy>
  </soap:Body>
</soap:Envelope>

В следующем примере показан XML-ответ, возвращаемый сервером после обработки запроса на операцию SyncFolderHierarchy . Первоначальный ответ включает элементы Create для всех папок, так как все папки считаются новыми во время начальной синхронизации. Значения некоторых атрибутов и элементов сокращены для удобства чтения, а некоторые блоки элементов Create были удалены для краткости.

<?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="785"
                         MinorBuildNumber="6"
                         Version="V2_6"
                         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:SyncFolderHierarchyResponse xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"
                                   xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types">
      <m:ResponseMessages>
        <m:SyncFolderHierarchyResponseMessage ResponseClass="Success">
          <m:ResponseCode>NoError</m:ResponseCode>
          <m:SyncState>H4sIAA==</m:SyncState>
          <m:IncludesLastFolderInRange>true</m:IncludesLastFolderInRange>
          <m:Changes>
            <t:Create>
              <t:Folder>
                <t:FolderId Id="AAMkADM="
                            ChangeKey="AQAAABYA"/>
              </t:Folder>
            </t:Create>
            <t:Create>
              <t:Folder>
                <t:FolderId Id="AAMkADMzM="
                            ChangeKey="AQAAABY"/>
              </t:Folder>
            </t:Create>
            <t:Create>
              <t:Folder>
                <t:FolderId Id="AAMkAD/AAA="
                            ChangeKey="AQAAABYA"/>
              </t:Folder>
            </t:Create>
            <t:Create>
              <t:Folder>
                <t:FolderId Id="AAMkADBh="
                            ChangeKey="AQAAABYA"/>
              </t:Folder>
            </t:Create>
            ...
          </m:Changes>
        </m:SyncFolderHierarchyResponseMessage>
      </m:ResponseMessages>
    </m:SyncFolderHierarchyResponse>
  </s:Body>
</s:Envelope>

После получения списка новых папок на сервере создайте папки на клиенте.

Получение изменений с момента последней синхронизации с помощью EWS

В следующем примере показан XML-запрос для получения списка изменений папок в корневой папке с помощью операции SyncFolderHierarchy . Это также XML-запрос, который управляемый API EWS отправляет при получении списка изменений в корневой папке. В этом примере задается значение элемента SyncState , возвращаемое в предыдущем ответе. В целях демонстрации в этом примере для элемента BaseShape задается значение AllProperties , а не IdOnly , чтобы отобразить возвращенные дополнительные свойства. Рекомендуется установить для элемента BaseShape значение IdOnly. Значение SyncState сокращено для удобства чтения.

<?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="Exchange2013" />
  </soap:Header>
  <soap:Body>
    <m:SyncFolderHierarchy>
      <m:FolderShape>
        <t:BaseShape>AllProperties</t:BaseShape>
      </m:FolderShape>
      <m:SyncFolderId>
        <t:DistinguishedFolderId Id="root" />
      </m:SyncFolderId>
      <m:SyncState>H4sIAA==</m:SyncState>
    </m:SyncFolderHierarchy>
  </soap:Body>
</soap:Envelope>

В следующем примере показан XML-ответ, возвращаемый сервером после обработки запроса на операцию SyncFolderHierarchy от клиента. Этот ответ указывает, что одна папка была обновлена, одна папка создана, а одна папка была удалена с момента предыдущей синхронизации. Значение элемента SyncState , атрибутов Id и ChangeKey сокращено для удобства чтения.

Помните, что запрос включал AllPropertiesBaseShape. Это только для демонстрационных целей. Рекомендуется задать для элемента BaseShape значение IdOnly в рабочей среде.

<?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="745" MinorBuildNumber="21" Version="V2_3" 
           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:SyncFolderHierarchyResponse xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages" 
            xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types">
      <m:ResponseMessages>
        <m:SyncFolderHierarchyResponseMessage ResponseClass="Success">
          <m:ResponseCode>NoError</m:ResponseCode>
          <m:SyncState>H4sIAAA</m:SyncState>
          <m:IncludesLastFolderInRange>true</m:IncludesLastFolderInRange>
          <m:Changes>
            <t:Update>
              <t:Folder>
                <t:FolderId Id="AAMkADM=" ChangeKey="AQAAABY" />
                <t:ParentFolderId Id="AQMkADMzADI1==" ChangeKey="AQAAAA==" />
                <t:FolderClass>IPF.Note</t:FolderClass>
                <t:DisplayName>Meeting Notes</t:DisplayName>
                <t:TotalCount>3</t:TotalCount>
                <t:ChildFolderCount>0</t:ChildFolderCount>
                <t:EffectiveRights>
                  <t:CreateAssociated>true</t:CreateAssociated>
                  <t:CreateContents>true</t:CreateContents>
                  <t:CreateHierarchy>true</t:CreateHierarchy>
                  <t:Delete>true</t:Delete>
                  <t:Modify>true</t:Modify>
                  <t:Read>true</t:Read>
                  <t:ViewPrivateItems>true</t:ViewPrivateItems>
                </t:EffectiveRights>
                <t:UnreadCount>0</t:UnreadCount>
              </t:Folder>
            </t:Update>
            <t:Create>
              <t:Folder>
                <t:FolderId Id="AAMkADMzM=" ChangeKey="AQAAABYAA" />
                <t:ParentFolderId Id="AQMkO67A==" ChangeKey="AQAAAA==" />
                <t:FolderClass>IPF.Note</t:FolderClass>
                <t:DisplayName>Schedules</t:DisplayName>
                <t:TotalCount>0</t:TotalCount>
                <t:ChildFolderCount>0</t:ChildFolderCount>
                <t:EffectiveRights>
                  <t:CreateAssociated>true</t:CreateAssociated>
                  <t:CreateContents>true</t:CreateContents>
                  <t:CreateHierarchy>true</t:CreateHierarchy>
                  <t:Delete>true</t:Delete>
                  <t:Modify>true</t:Modify>
                  <t:Read>true</t:Read>
                  <t:ViewPrivateItems>true</t:ViewPrivateItems>
                </t:EffectiveRights>
                <t:UnreadCount>0</t:UnreadCount>
              </t:Folder>
            </t:Create>
            <t:Delete>
              <t:FolderId Id="AAMkAD/AAA=" ChangeKey="AQAAAA==" />
            </t:Delete>
          </m:Changes>
        </m:SyncFolderHierarchyResponseMessage>
      </m:ResponseMessages>
    </m:SyncFolderHierarchyResponse>
  </s:Body>
</s:Envelope>

Обновление клиента

Если вы используете управляемый API EWS, после получения списка новых или измененных папок используйте метод Folder.Load , чтобы получить свойства новых или измененных элементов, сравнить свойства с локальными значениями и обновить или создать папки на клиенте.

Если вы используете EWS, используйте операцию GetFolder , чтобы получить свойства новых или измененных папок, а также обновить или создать папки на клиенте.

См. также