Sincronizar carpetas mediante EWS en Exchange

Obtenga información sobre cómo usar la API administrada de EWS o EWS para obtener una lista de carpetas, o una lista de carpetas que han cambiado, con el fin de sincronizar el cliente.

EWS en Exchange usa la sincronización de elementos y la sincronización de carpetas para sincronizar el contenido del buzón entre el cliente y el servidor. La sincronización de carpetas obtiene la lista inicial de carpetas de una carpeta raíz y, a continuación, con el tiempo, obtiene los cambios realizados en esas carpetas y obtiene también carpetas nuevas.

Si va a realizar la sincronización de carpetas mediante la API administrada de EWS, primero obtendrá la lista inicial de carpetas en la carpeta raíz mediante el método ExchangeService.SyncFolderHierarchy . Después, actualice el valor del parámetro cSyncState durante las llamadas posteriores para obtener la lista de carpetas nuevas y modificadas.

Para realizar la sincronización de carpetas mediante EWS, solicite la lista inicial de carpetas de la carpeta raíz mediante la operación SyncFolderHierarchy , analice la respuesta y, en algún momento en el futuro, obtenga los cambios en las carpetas de la raíz y analice la respuesta. Una vez que el cliente recibe la lista de carpetas iniciales o modificadas, realiza actualizaciones localmente. Cómo y cuándo se recuperan los cambios en el futuro depende del patrón de diseño de sincronización que use la aplicación.

Obtener la lista de todas las carpetas o carpetas modificadas mediante la API administrada de EWS

En el ejemplo de código siguiente se muestra cómo obtener una lista inicial de carpetas en una carpeta raíz y, a continuación, obtener una lista de los cambios realizados en las carpetas de la carpeta raíz que se han producido desde la sincronización anterior. Durante la llamada inicial al método ExchangeService.SyncFolderHierarchy , establezca el valor de cSyncState en null. Cuando se complete el método, guarde el valor de cSyncState localmente para usarlo en la siguiente llamada al método SyncFolderHierarchy . Tanto en la llamada inicial como en las llamadas posteriores, las carpetas se recuperan en lotes de diez, mediante llamadas sucesivas al método SyncFolderHierarchy , hasta que no quedan más cambios. En este ejemplo se establece el parámetro propertySet en IdOnly para reducir las llamadas a la base de datos de Exchange, que es un procedimiento recomendado de sincronización. En este ejemplo, se supone que el servicio es un enlace de objetos ExchangeService válido y que cSyncState representa el estado de sincronización devuelto por una llamada anterior a 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;

Después de recuperar la lista de carpetas nuevas o modificadas en el servidor, cree o actualice las carpetas en el cliente.

Obtener la lista inicial de carpetas mediante EWS

En el ejemplo siguiente se muestra una solicitud XML para obtener la jerarquía de carpetas inicial mediante la operación SyncFolderHierarchy . Esta es también la solicitud XML que la API administrada de EWS envía al recuperar la lista de carpetas iniciales mediante el método SyncFolderHierarchy. El elemento SyncState de la operación SyncFolderHierarchy no se incluye porque se trata de la sincronización inicial. En este ejemplo se establece el elemento BaseShape en IdOnly para reducir las llamadas a la base de datos de Exchange, que es un procedimiento recomendado de sincronización.

<?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>

En el ejemplo siguiente se muestra la respuesta XML devuelta por el servidor después de procesar la solicitud de operación SyncFolderHierarchy . La respuesta inicial incluye crear elementos para todas las carpetas porque todas las carpetas se consideran nuevas durante una sincronización inicial. Los valores de algunos atributos y elementos se han acortado para mejorar la legibilidad y algunos bloques de elementos Create se han quitado por brevedad.

<?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>

Después de recuperar la lista de carpetas nuevas en el servidor, cree las carpetas en el cliente.

Obtener los cambios desde la última sincronización mediante EWS

En el ejemplo siguiente se muestra la solicitud XML para obtener la lista de cambios en las carpetas de la carpeta raíz mediante la operación SyncFolderHierarchy . Esta es también la solicitud XML que la API administrada de EWS envía al recuperar la lista de cambios en la carpeta raíz. En este ejemplo se establece el valor del elemento SyncState en el valor devuelto en la respuesta anterior. Y con fines de demostración, en este ejemplo se establece el elemento BaseShape en AllProperties en lugar de IdOnly para mostrar las propiedades adicionales devueltas. Establecer el elemento BaseShape en IdOnly es un procedimiento recomendado de sincronización. El valor de SyncState se ha acortado para mejorar la legibilidad.

<?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>

En el ejemplo siguiente se muestra la respuesta XML devuelta por el servidor después de procesar la solicitud de operación SyncFolderHierarchy del cliente. Esta respuesta indica que se actualizó una carpeta, se creó una carpeta y se eliminó una carpeta desde la sincronización anterior. El valor del elemento SyncState , los atributos Id y los atributos ChangeKey se han acortado para mejorar la legibilidad.

Recuerde que la solicitud incluía la clase BaseShapeAllProperties. Esto es sólo para fines de demostración. Se recomienda establecer el elemento BaseShape en IdOnly en producción.

<?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>

Actualización del cliente

Si usa la API administrada de EWS, después de obtener la lista de carpetas nuevas o modificadas, use el método Folder.Load para obtener propiedades en los elementos nuevos o modificados, comparar las propiedades con los valores locales y actualizar o crear las carpetas en el cliente.

Si usa EWS, use la operación GetFolder para obtener propiedades en las carpetas nuevas o modificadas y actualizarlas o crearlas en el cliente.

Vea también