Managing Custom Properties

In this article we describe how to save properties received from your remote storage on a client side, attaching them to the item and how to access saved properties.

Saving Custom Properties

When you get custom properties data received from the remote storage you will pass it to the Engine as part of metadata, inside your IFolder.GetChildrenAsync(), IFolder.CreateFileAsync(), IServerNotifications.UpdateAsync() etc. methods:

public async Task GetChildrenAsync(...)
{
    var response = Serv.GetChildren(RemoteStoragePath);

    List<FileSystemItemMetadataExt> children = new List<FileSystemItemMetadataExt>();

    foreach (var item in response)
    {
        FileSystemItemMetadataExt userFileSystemItem = ...;
        ...

        userFileSystemItem.Lock = new ServerLockInfo()
        {
            LockToken = item.Lock.LockToken,
            Owner = item.Lock.Owner,
            LockExpirationDateUtc = item.Lock.Expires
        };

        children.Add(userFileSystemItem);
    }

    await resultContext.ReturnChildrenAsync(children.ToArray(), children.Count());
}

After creating item or updating item metadata, the Engine fires the Engine.ItemsChanged event, in which you can find a result status of the operation and save custom data. Inside this event you will save the custom data, such as locks, received from the remote storage:

Engine.ItemsChanged += Engine_ItemsChanged;

private void Engine_ItemsChanged(Engine sender, ItemsChangeEventArgs e)
{
    foreach (ChangeEventItem item in e.Items)
    {
        if (e.Direction == SyncDirection.Incoming && e.Result.IsSuccess)
        {
            switch (e.OperationType)
            {
                case OperationType.Create:
                case OperationType.Populate:
                case OperationType.UpdateMetadata:
                    var metadata = item.Metadata as FileSystemItemMetadataExt;
                    item.Properties.AddOrUpdate("LockInfo", metadata.Lock);
                    break;
            }
        }
    }
}

Note that the update is performed and this event is fired, only if the incoming IFileSystemItemMetadata.MetadataETag does NOT match the metadata eTag stored with the item. The Engine.ItemsChanged event is also always fired when incoming metadata eTag is null.

Reading Custom Properties

Saved custom data is available in all methods via the operation IOperationContext parameter provided in all methods: 

public async Task<IFileMetadata> WriteAsync(
    IFileSystemBasicInfo fileBasicInfo, 
    Stream content = null, 
    IOperationContext operationContext = null,
    ...
{
    var lockInfo = operationContext.Properties["LockInfo"].GetValue<ServerLockInfo>();
    Serv.Update(RemoteStoragePath, content, lockInfo.LockToken);
    ...
}

Note that because of the asynchronous nature of the file system, the file or folder can be deleted at any time, together with all data attached to it. To avoid exceptions in your code you will typically use Try-methods instead:

if (operationContext.Properties.TryGetValue("LockInfo", out IDataItem propLockInfo))
{
    if (propLockInfo.TryGetValue<ServerLockInfo>(out ServerLockInfo lockInfo))
    {
        ...
    }
}

Next Article:

Detecting Changes Using Content and Metadata eTags