0
votes

When using the Exchange Web Services (EWS) Managed API to synchronize a folder hierarchy or synchronize items, where is the client-side cache located? Is it in-memory only? Is it on disk? Is there a way to find or control where the cache is located? I can't seem to find information on this anywhere.

1
What "client-side cache" are you referring to? The article you mention doesn't refer to any such cache, nor does the API documentation for SyncFolderHierarchy and SyncFolderItems. You'd use the documented approach and APIs to synchronize the contents of (some folders in) a mailbox from Exchange to whatever system you'd like to store them in. - Frank van Puffelen
That's sort of my question: what is the client-side cache? (which isn't mentioned anywhere in the documentation) What client-side data store is the server-side data being synchronized to? - Oran Dennison
The API simply allows you to access the data in Exchange. It's synchronized that whatever you synchronize it to. The article describes synchronization, because that is the common use-case for it (you get a state "cookie" back with every call that allows you to continue from that point). - Frank van Puffelen
You might also be served by this article: msdn.microsoft.com/en-us/library/office/…. It describes the whole approach to synchronization from a somewhat higher level and with (in my opinion) better examples. - Frank van Puffelen
Yes, I've read that and a million other articles. Are you saying that the client-side synchronization cache is nothing more than the ChangeCollection<ItemChange>? - Oran Dennison

1 Answers

2
votes

The SyncFolderHierarchy and SyncFolderItems together allow you to efficiently synchronize the contents of all (or a subset of the) folders in a mailbox in Exchange.

The flow indicated in the articles is indicative. The call to SyncFolderItems returns a ChangeCollection<T> with items of type ItemChange or FolderChange. If you process these items, you can pull down additional information on the folders or for example the actual contents of each item in the folder.

After you've processed the ChangeCollection, you're supposed to store the SyncState value somewhere. The next time you call SyncFolderItems you pass in that value and Exchange will return you the next batch of items.

Since it's likely that (especially the first time you synchronize) there are more items than SyncFolderItems can return in a single call, you should check MoreChangesAvailable to determine if there's more to do.

So all in all that turns into this loop:

// Track whether there are more items available for download on the server.
bool moreChangesAvailable = false;
do {
    // Get a list of all items in the Inbox by calling SyncFolderHierarchy repeatedly until no more changes are available.
    // The folderId parameter must be set to the root folder to synchronize,
    // and must be same folder ID as used in previous synchronization calls. 
    // 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 ignoredItemIds parameter is set to null, so that no items are ignored.
    // The maxChangesReturned parameter is set to return a maximum of 10 items (512 is the maximum).
    // The syncScope parameter is set to Normal items, so that associated items will not be returned.
    // 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 SyncFolderItems call in subsequent calls.
    ChangeCollection<ItemChange> icc = service.SyncFolderItems(new FolderId(WellKnownFolderName.Inbox), PropertySet.IdOnly, null, 10, SyncFolderItemsScope.NormalItems, cSyncState);

    // If the count of changes is zero, there are no changes to synchronize.
    if (icc.Count <> 0) {
        // Otherwise, write all the changes included in the response to the console. 
        foreach (ItemChange ic in icc) {
            Console.WriteLine("ChangeType: " + ic.ChangeType.ToString());
            Console.WriteLine("ItemId: " + ic.ItemId);
        }
    }

    // Save the sync state for use in future SyncFolderContent requests.
    // The sync state is used by the server to determine what changes to report
    // to the client.
    string sSyncState = icc.SyncState;

   // Determine whether more changes are available on the server.
   moreChangesAvailable = icc.MoreChangesAvailable;
}
while (moreChangesAvailable);

Code sample from MSDN, since I can't say it better than they do.

So there is no such thing as a client-side cache, unless you choose to store the items client-side yourself. If you choose not to store them, you can simply continue the loop until you reach the point where the stuff that you're interested in starts. The code above for example doesn't download anything, except the ItemChange records and the ID (indicated by PropertySet.IdOnly) of each item.

This MSDN article provides a great overview of the synchronization process.