CRUD Incoming Synchronization

In case your remote storage provides updates via create, update, delete and move events via web sockets you will use the IServerNotifications interface to reflect changes in the user file system.

Synchronization Settings

In this mode you will disable incoming synchronization by setting the IncomingSyncMode to IncomingSyncMode.Disabled:

engine.SyncService.IncomingSyncMode = IncomingSyncMode.Disabled;

Update Operation

To update a file or folder you will call the IServerNotifications.UpdateAsync() method:

var file = Serv.GetFile("/file.ext");
IFileMetadata metadata = new FileMetadataExt();
metadata.Length = file.ContentLength;
metadata.ContentETag = file.ContentEtag;
metadata.MetadataETag = file.MetadataETag;
metadata.RemoteStorageItemId = file.ID;
metadata.RemoteStorageParentItemId = file.ParentID;
metadata.Name = file.DisplayName;
metadata.Attributes = FileAttributes.Normal;
metadata.CreationTime = file.CreationDate;
metadata.LastWriteTime = file.LastModified;
metadata.LastAccessTime = file.LastModified;
metadata.ChangeTime = file.LastModified;

IServerNotifications sn = engine.ServerNotifications(@"C:\Users\User1\VFS\file.ext");
var res = await sn.UpdateAsync(item);

Note the ContentETag and MetadataETag properties being set. The Engine will use them to detect changes and update content and metadata separately. See the Detecting Content and Metadata Changes article for more details.

In case the content eTags do not match (or the incoming eTag is null) and the file is hydrated, the Engine will dehydrate the file, update the metadata (including file content length) and then will hydrate the file content. 

Create Operation

To create files and folders in the user file system you will call the IServerNotifications.CreateAsync() method passing the list of items metadata to be created:

IFileSystemItemMetadata item = Mapping.GetUserFileSysteItemMetadata("/Folder/file.ext");
IServerNotifications sn = engine.ServerNotifications(@"C:\Users\User1\VFS\Folder\");
await sn.CreateAsync(new[] { item });

Delete Operation

To delete a file or folder call the IServerNotifications.DeleteAsync() method:

IServerNotifications sn = engine.ServerNotifications(@"C:\Users\User1\VFS\file.ext");
await sn.DeleteAsync();

Move Operation

To move or rename a file or folder call IServerNotifications.MoveToAsync() method:

string remoteStorageNewPath = "/Folder/file.ext";
string userFileSystemNewPath = engine.Mapping.ReverseMapPath(remoteStorageNewPath);
IServerNotifications sn = engine.ServerNotifications(@"C:\Users\User1\VFS\file.ext");
var res = await sn.MoveToAsync(userFileSystemNewPath);
switch (res.Status)
{
    case OperationStatus.NotFound:
        // Source item is not loaded. Creating the item in the target folder.
        var item = Serv.GetItem(remoteStorageNewPath);
        IFileSystemItemMetadata metadata = Mapping.GetUserFileSystemItemMetadata(item);
        string userFileSystemParentPath = Path.GetDirectoryName(userFileSystemNewPath);
        var snParent = await engine.ServerNotifications(userFileSystemParentPath);
        snParent.CreateAsync(new[] { metadata });
        break;

    case OperationStatus.TargetNotFound:
        // Target parent folder does not exists or is offline, delete the source item.
        await sn.DeleteAsync();
        break;
}

Operation Result

Each of the IServerNotifications methods returns the OperationResult object that contains result of the operation and a number of items being updated. For example if parent folder does not exists in user file system, because of the on-demand population, a method does not change any items and returns OperationStatus.NotFound.

To keep all your post-processing code, such al logging, custom properties updates and Microsoft Office documents merging, in one place use the ItemsChanged event, which provides access to OperationResult operation type and item information. You can find more about this event in the ItemsChange Event article.

Synching Lost Changes

To sync all changes that happened when the Engine was not running or web sockets were disconnected you can call the IncomingPoolingSync.ProcessAsync() method:

await engine.SyncService.IncomingPooling.ProcessAsync();

This will trigger one-time synchronization of all changes using pooling, by traversing all folders and files loaded on the client. 

Next Article:

Sync ID Incoming Synchronization