Show / Hide Table of Contents

Synchronization

They synchronization endpoints allows you to sync all of your content to store it locally. You can choose to sync everything, or just assets, certain content types or deletions.

The initial sync

To start syncing content you need to call the SyncInitial method. If you call it without any parameters you sync every content type and all assets, but you could also specify that you wish to sync only a specific content type or only assets or deletions.

var result = await client.SyncInitial();
//Sync everything

var result = await client.SyncInitial(SyncType.Asset);
//Sync only assets

var result = await client.SyncInitial(SyncType.Entry)
//Sync only entries

var result = await client.SyncInitial(SyncType.Entry, "123")
//Sync only entries of the "123" content type

var result = await client.SyncInitial(SyncType.Deletions)
//Sync only deletions of assets and entries

var result = await client.SyncInitial(SyncType.DeletedAsset)
//Sync only deleted assets

var result = await client.SyncInitial(SyncType.DeletedEntry)
//Sync only deleted entries

Handling the result of a synchronization

All sync operations return a SyncResult. This class contains all assets, entries and deletions that the synchronization call resulted in and also contains two URL properties. NextSyncUrl and NextPageUrl. NextPageUrl is only present if there is more content to be recieved for the current sync operation, NextSyncUrl will be null in this case. If there is no more content for the current sync only NextSyncUrl will be present.

var res = await client.SyncInitial();
//Sync everything

var syncedEntries = res.Entries;
//An IEnumerable of Entry<dynamic>

var syncedAssets = res.Assets;
//An IEnumerable of SyncedAsset

var deletedEntries = res.DeletedEntries;
//An IEnumerable of SystemProperty

var deletedEntries = res.DeletedAssets;
//An IEnumerable of SystemProperty

Note that the synced entries are of the type Entry<dynamic>. This is because the JSON returned by a sync must contain every locale of a space. The JSON structure of an entry would look something like this.

"fields": {
        "productName": {
          "en-US": "SoSo Wall Clock",
          "sv": "SåSå Väggklocka"
        },
        "slug": {
          "en-US": "soso-wall-clock"
        },
        "productDescription": {
          "en-US": "The newly released SoSo Clock from Lemnos..."
        },
        "sizetypecolor": {
          "en-US": "10\" x 2.2\""
        }
}

This poses a problem when deserializing as we cannot have C# members that include hyphens (-) in their name. Furthermore we would probably not want to create classes that have a structure like this anyway, a product class with a property ProductName which is an object with two more properties, one for each language. To work around this for sync operations the Entry<dynamic> is used. This means that you can access any property in any language by using an indexer.

var res = await client.SyncInitial();

Console.WriteLine(res.Entries.First().Fields.productName["en-US"].ToString()); // => SoSo Wall Clock
Console.WriteLine(res.Entries.First().Fields.productName.sv.ToString()); // => SåSå Väggklocka

This is also the reason for not using the Asset class directly for synced assets, but rather the SyncedAsset class.

var res = await client.SyncInitial();

Console.WriteLine(res.Assets.First().Fields.title["en-US"].ToString()); // => SoSo Wall Clock
Console.WriteLine(res.Assets.First().Fields.title.sv.ToString()); // => SåSå Väggklocka

Syncing the next page or result

After a sync completes and you receive your SyncResult you would normally store the NextSyncUrl somewhere to be able to call it when it is time to fetch changes. To do that you simply pass either the full URL or the synctoken directly to the SyncNextResult method.

var res = await client.SyncInitial();

if(!string.IsNullOrEmpty(res.NextSyncUrl)){
    //store the sync url somewhere
    db.Store(res.NextSyncUrl);
}

//Sometime later it's time to fetch the syncUrl from storage and fetch the next SyncResult
var syncUrl = db.RetrieveSyncUrl();

var res = await client.SyncNextResult(syncUrl);

//Process the result and again store the NextSyncUrl and sync again at the next interval

if(!string.IsNullOrEmpty(res.NextSyncUrl)){
    //store the sync url somewhere
    db.Store(res.NextSyncUrl);
} 

It is important to note that Contentful makes no assumption on the interval of your sync operations. That is up to the individual application to decide. You could sync every 10 minutes or every other week. The syncresult will contain all changes in your space since the last sync operation.

Keep your synctoken or url safe!
If you lose it there's no retrieveing it and you would have to redo an initial sync.

Recursively syncing all pages

If you wish to make sure the initial sync retrieves all pages during the intial sync you can use the SyncInitialRecursive method.

var res = await client.SyncInitialRecursive();
//Sync everything and recursively process any NextPageUrls

var syncedEntries = res.Entries;
//An IEnumerable of Entry<dynamic> containing all entries for all pages aggregated into a single collection.

var syncedAssets = res.Assets;
//An IEnumerable of SyncedAsset containing all assets for all pages aggregated into a single collection.

var deletedEntries = res.DeletedEntries;
//An IEnumerable of SystemProperty containing all deleted entries for all pages aggregated into a single collection.

var deletedEntries = res.DeletedAssets;
//An IEnumerable of SystemProperty containing all deleted assets for all pages aggregated into a single collection.

It is very important to understand that this potentially results in multiple calls to the sync endpoint at Contentful. It is also very possible if you have a large number of pages that the collection of entries and assets become very large. In those situations it might be better to manually process each page in turn using the SyncInitial and SyncNextResult methods.

Back to top Copyright © 2015-2016 Contentful
Generated by DocFX