Esempio n. 1
0
        public async Task <JObject> ExecuteTableOperationAsync(IMobileServiceTableOperation operation)
        {
            MobileServicePreconditionFailedException preconditionFailedException = null;
            JObject result = null;

            do
            {
                preconditionFailedException = null;
                try
                {
                    result = await operation.ExecuteAsync();
                }
                catch (MobileServicePreconditionFailedException ex)
                {
                    preconditionFailedException = ex;
                }

                if (preconditionFailedException != null)
                {
                    var serverItem = preconditionFailedException.Value.ToObject <T>();

                    operation.Item[MobileServiceSystemColumns.Version] = serverItem.Version;
                }
            }while (preconditionFailedException != null);

            return(result);
        }
Esempio n. 2
0
 public Task <JObject> ExecuteTableOperationAsync(IMobileServiceTableOperation operation)
 {
     if (_excludedTables.Contains(operation.Table.TableName))
     {
         return(Task.FromResult((JObject)null));
     }
     return(operation.ExecuteAsync());
 }
Esempio n. 3
0
        /// handle conflicts one at a time, and retry the operations as the conflict handling choice is made
        public virtual async Task <JObject> ExecuteTableOperationAsync(IMobileServiceTableOperation operation)
        {
            Func <Task <JObject> > tryOperation = operation.ExecuteAsync;

            do
            {
                try
                {
                    JObject result = await tryOperation();

                    return(result);
                }
                catch (Exception ex) when(ex is MobileServiceConflictException || ex is MobileServicePreconditionFailedException)
                {
                    var error       = (MobileServiceInvalidOperationException)ex;
                    var localItem   = operation.Item.ToObject <DiaryEntry>();
                    var serverValue = error.Value;

                    if (serverValue == null)
                    { // 409 doesn't return the server item
                        serverValue = await operation.Table.LookupAsync(localItem.Id) as JObject;
                    }

                    var serverItem = serverValue.ToObject <DiaryEntry>();

                    if (serverItem.Title == localItem.Title && serverItem.Description == localItem.Description)
                    {
                        // items are same so we can ignore the conflict
                        return(serverValue);
                    }

                    var userAction = await App.Current.MainPage.DisplayAlert(
                        "Conflict", $"Local version: {localItem}\nServer version: {serverItem}", "Use server", "Use client");

                    if (userAction)
                    {
                        return(serverValue);
                    }
                    else
                    {
                        // Overwrite the server version and try the operation again by continuing the loop
                        operation.Item[MobileServiceSystemColumns.Version] = serverValue[MobileServiceSystemColumns.Version];

                        if (error is MobileServiceConflictException)
                        {
                            // change operation from Insert to Update
                            tryOperation = async() => await operation.Table.UpdateAsync(operation.Item) as JObject;
                        }
                    }
                }
                catch (Exception e)
                {
                    Debug.WriteLine(e);
                    throw e;
                }
            } while (true);
        }
Esempio n. 4
0
        void OverwriteServerDataUsingLocalData(IMobileServiceTableOperation operation, JObject serverItem)
        {
            if (operation == null || serverItem == null)
            {
                return;
            }

            operation.Item[MobileServiceSystemColumns.Version] = serverItem[MobileServiceSystemColumns.Version];
        }
        public virtual async Task <JObject> ExecuteTableOperationAsync(IMobileServiceTableOperation op)
        {
            MobileServicePreconditionFailedException error;

            do
            {
                error = null;

                try
                {
                    return(await op.ExecuteAsync());
                }
                catch (MobileServicePreconditionFailedException ex)
                {
                    error = ex;
                }

                if (error != null)
                {
                    // conflict on the server
                    var localValue  = op.Item.ToObject <SensorDataItem>();
                    var serverValue = error.Value;
                    switch (_conflictResolutionPolicy)
                    {
                    case ConflictResolutionPolicy.KeepLocal:
                        // forcing local (client) data
                        if (serverValue == null)
                        {
                            // try retrieving serverValue (null)
                            var table = _client.GetTable(op.Table.TableName);
                            table.SystemProperties = MobileServiceSystemProperties.Version;
                            serverValue            = (JObject)(await table.LookupAsync((string)op.Item[MobileServiceSystemColumns.Id]));
                        }
                        if (serverValue != null)
                        {
                            // update local with server value
                            op.Item[MobileServiceSystemColumns.Version] = serverValue[MobileServiceSystemColumns.Version];
                        }
                        else
                        {
                            op.AbortPush();
                        }
                        break;

                    case ConflictResolutionPolicy.KeepRemote:
                        return((JObject)serverValue);

                    default:
                        op.AbortPush();
                        break;
                    }
                }
            } while (error != null);

            return(null);
        }
Esempio n. 6
0
 public override Task <JObject> ExecuteTableOperationAsync(IMobileServiceTableOperation operation)
 {
     if (TableOperationAction != null)
     {
         return(this.TableOperationAction(operation));
     }
     else
     {
         return(base.ExecuteTableOperationAsync(operation));
     }
 }
 public override Task<JObject> ExecuteTableOperationAsync(IMobileServiceTableOperation operation)
 {
     if (TableOperationAction != null)
     {
         return this.TableOperationAction(operation);
     }
     else
     {
         return base.ExecuteTableOperationAsync(operation);
     }
 }
            public Task <JObject> ExecuteTableOperationAsync(IMobileServiceTableOperation operation)
            {
                var itemId = (string)operation.Item[MobileServiceSystemColumns.Id];

                if (this.AbortCondition(itemId))
                {
                    operation.AbortPush();
                }

                return(operation.ExecuteAsync());
            }
Esempio n. 9
0
        public override async Task<JObject> ExecuteTableOperationAsync(IMobileServiceTableOperation operation)
        {
            MobileServicePreconditionFailedException ex = null;
            JObject result = null;

            do
            {
                ex = null;
                try
                {
                    result = await base.ExecuteTableOperationAsync(operation);
                }
                catch (MobileServicePreconditionFailedException e)
                {
                    ExceptionHandlingHelper.HandleNonFatalError(e, "Synchronization failed. Looks like there is a conflict.");

                    ex = e;
                }
                catch (MobileServiceConflictException e)
                {
                    ExceptionHandlingHelper.HandleNonFatalError(e, "Synchronization failed. Looks like there is a conflict.");

                    throw;
                }
                catch (MobileServiceInvalidOperationException e)
                {
                    ExceptionHandlingHelper.HandleNonFatalError(e, "Synchronization failed. An unexpected exception occured.");

                    throw;
                }

                if (ex != null)
                {
                    // There was a conflict in the server

                    var serverItem = ex.Value;
                    // The server item will be returned in the `Value` property of the exception
                    // object, but there are some scenarios in the .NET runtime where this is
                    // not the case, so if the object wasn't returned, we retrieve it.
                    if (serverItem == null)
                    {
                        serverItem = (JObject)(await operation.Table.LookupAsync((string)operation.Item["id"]));
                    }

                    // Update the version of the pending item so that it won't have another
                    // conflict when the operation is retried.
                    operation.Item[MobileServiceSystemColumns.Version] = serverItem[MobileServiceSystemColumns.Version];
                }
            } while (ex != null);

            return result;
        }
Esempio n. 10
0
        public virtual async Task<JObject> ExecuteTableOperationAsync(IMobileServiceTableOperation op)
        {
            MobileServicePreconditionFailedException error;
            do
            {
                error = null;

                try
                {
                    return await op.ExecuteAsync();
                }
                catch (MobileServicePreconditionFailedException ex)
                {
                    error = ex;
                }

                if (error != null)
                {
                    // conflict on the server
                    var localValue = op.Item.ToObject<SensorDataItem>();
                    var serverValue = error.Value;
                    switch (_conflictResolutionPolicy)
                    {
                        case ConflictResolutionPolicy.KeepLocal:
                            // forcing local (client) data
                            if (serverValue == null)
                            {
                                // try retrieving serverValue (null)
                                var table = _client.GetTable(op.Table.TableName);
                                table.SystemProperties = MobileServiceSystemProperties.Version;
                                serverValue = (JObject)(await table.LookupAsync((string)op.Item[MobileServiceSystemColumns.Id]));
                            }
                            if (serverValue != null)
                                // update local with server value
                                op.Item[MobileServiceSystemColumns.Version] = serverValue[MobileServiceSystemColumns.Version];
                            else
                                op.AbortPush();
                            break;
                        case ConflictResolutionPolicy.KeepRemote:
                            return (JObject)serverValue;
                        default:
                            op.AbortPush();
                            break;
                    }

                }
            } while (error != null);

            return null;
        }
Esempio n. 11
0
            public Task <JObject> ExecuteTableOperationAsync(IMobileServiceTableOperation operation)
            {
                var itemId = (string)operation.Item[MobileServiceSystemColumns.Id];

                if (this.AbortCondition(itemId))
                {
                    this.test.Log("Found id to abort ({0}), aborting the push operation");
                    operation.AbortPush();
                }
                else
                {
                    this.test.Log("Pushing operation {0} for item {1}", operation.Kind, itemId);
                }

                return(operation.ExecuteAsync());
            }
Esempio n. 12
0
        public async Task<JObject> ExecuteTableOperationAsync(IMobileServiceTableOperation operation)
        {
            MobileServicePreconditionFailedException error;

            do
            {
                error = null;
                try
                {
                    return await operation.ExecuteAsync();
                }
                catch (MobileServicePreconditionFailedException ex)
                {
                    error = ex;
                }

                if (error != null)
                {
                    bool resolveWithLocal = true;
                    bool resolveWithServer = true;

                    var localItem = operation.Item.ToObject<Models.Fluid>();
                    var serverValue = error.Value;
                    if (resolveWithLocal)
                    {
                        //Result with local Version
                        operation.Item[MobileServiceSystemColumns.Version] = serverValue[MobileServiceSystemColumns.Version];
                        continue;
                    }
                    else if (resolveWithServer)
                    {
                        //resolve with server version
                        return (JObject)serverValue;
                    }
                    else
                    {
                        operation.AbortPush();
                        error = null;
                    }
                }

            }
            while (error != null);

            return null;
        }
Esempio n. 13
0
        public async Task <JObject> ExecuteTableOperationAsync(IMobileServiceTableOperation operation)
        {
            MobileServicePreconditionFailedException ex;
            JObject result = null;

            do
            {
                ex = null;
                try
                {
                    result = await operation.ExecuteAsync();
                }
                catch (MobileServicePreconditionFailedException e)
                {
                    ex = e;
                }

                // There was a conflict in the server
                if (ex != null)
                {
                    // Grabs the server item from the exception. If not available, fetch it.
                    var serverItem = ex.Value;
                    if (serverItem == null)
                    {
                        serverItem = (JObject)(await operation.Table.LookupAsync((string)operation.Item["id"]));
                    }

                    // Prompt user action
                    var userAction = await App.Current.MainPage.DisplayAlert("Conflict Occurred", "Select which version to keep.", "Server", "Client");

                    if (userAction)
                    {
                        return(serverItem);
                    }
                    else
                    {
                        // Overwrite the server version and try the operation again by continuing the loop.
                        operation.Item[MobileServiceSystemColumns.Version] = serverItem[MobileServiceSystemColumns.Version];
                    }
                }
            } while (ex != null);

            return(result);
        }
        /// <summary>
        /// Sync conflict resolution logic
        /// </summary>
        /// <param name="operation"></param>
        /// <returns></returns>
        /// <remarks>
        /// Gets called by SDK when it detects a synchronization conflict during sync operations.
        /// If there are multiple conflicts during a sync operation then this method will be called
        /// once for each conflict.
        /// </remarks>
        public virtual async Task <JObject> ExecuteTableOperationAsync(IMobileServiceTableOperation operation)
        {
            MobileServicePreconditionFailedException error;

            do
            {
                error = null;

                try
                {
                    return(await operation.ExecuteAsync());
                }
                catch (MobileServicePreconditionFailedException ex)
                {
                    error = ex;
                }

                if (error != null)
                {
                    var serverValue = error.Value;

                    ResolverResponse resolution = await ConflictResolver(serverValue, operation.Item);

                    if (resolution == ResolverResponse.LocalVersion)
                    {
                        // Overwrite the server version and try the operation again by continuing the loop
                        operation.Item[MobileServiceSystemColumns.Version] = serverValue[MobileServiceSystemColumns.Version];
                        continue;
                    }
                    else if (resolution == ResolverResponse.ServerVersion)
                    {
                        return((JObject)serverValue);
                    }
                    else
                    {
                        operation.AbortPush();
                    }
                }
            } while (error != null);

            return(null);
        }
        public async Task <JObject> ExecuteTableOperationAsync(IMobileServiceTableOperation operation)
        {
            try
            {
                Debug.Write(string.Format("Execute operation: {0}    {1}", operation.Kind, operation.Item));
                _log = string.Format("Execute operation: {0}    {1}", operation.Kind.ToString(), operation.Item.ToString());
                if (InsertionLog.insertLog != null)
                {
                    InsertionLog.insertLog(_log);
                }
                return(await operation.ExecuteAsync());
            }
            catch (MobileServiceConflictException ex)
            {
                await operation.Table.UpdateAsync(operation.Item);

                ExceptionErrorLogger.writeFileOnInternalStorage(ex.ToString());
                return(new JObject());
            }
        }
Esempio n. 16
0
        public async Task <JObject> ExecuteTableOperationAsync(IMobileServiceTableOperation operation)
        {
            MobileServicePreconditionFailedException preconditionFailedException = null;
            JObject result = null;

            do
            {
                preconditionFailedException = null;
                try
                {
                    result = await operation.ExecuteAsync();
                }
                catch (MobileServicePreconditionFailedException ex)
                {
                    preconditionFailedException = ex;
                }

                // there is a conflict between the local version and the server version of the item
                if (preconditionFailedException != null)
                {
                    // get the server's version of the item
                    var serverItem = preconditionFailedException.Value.ToObject <T>();

                    // Replace the local pending item's version value with the server item's version value.
                    // This will force the local change to override the server version.
                    // This is somewhat destructive (clobbering), and not favorable for all scenarios.
                    // See the below commented out code for an alternative strategy that is more conservative.
                    operation.Item[MobileServiceSystemColumns.Version] = serverItem.Version;


                    /* The following commented out lines do not force the local copy to the server. Instead, an error message is presented to the user. */
                    /* This could be improved even futher by presenting both versions of the data to the user and letting him/het decide with to keep. */
                    //var localItem = operation.Item.ToObject<Acquaintance>();
                    //RaiseDataSyncErrorEvent(new DataSyncErrorEventArgs<Acquaintance>(localItem, serverItem));
                    //operation.AbortPush();
                    //return result;
                }
            }while (preconditionFailedException != null);

            return(result);
        }
Esempio n. 17
0
        public async Task <JObject> ExecuteTableOperationAsync(IMobileServiceTableOperation operation)
        {
            MobileServicePreconditionFailedException ex;
            JObject result = null;

            do
            {
                ex = null;
                try
                {
                    result = await operation?.ExecuteAsync();
                }
                catch (MobileServicePreconditionFailedException e)
                {
                    ex = e;
                }

                // There was a conflict in the server
                if (ex != null)
                {
                    // Grabs the server item from the exception. If not available, fetch it.
                    var serverItem = ex.Value;
                    if (serverItem == null)
                    {
                        var operationItemId = operation?.Item["id"].ToString();
                        serverItem = await operation?.Table?.LookupAsync(operationItemId) as JObject;
                    }

                    var didUserSelectServe = await GetUserResponseToKeepServerDataOrLocalData();

                    if (didUserSelectServe)
                    {
                        return(serverItem);
                    }

                    OverwriteServerDataUsingLocalData(operation, serverItem);
                }
            } while (ex != null);

            return(result);
        }
Esempio n. 18
0
            public async Task <JObject> ExecuteTableOperationAsync(IMobileServiceTableOperation operation)
            {
                MobileServicePreconditionFailedException ex = null;
                JObject result = null;

                do
                {
                    ex = null;
                    try
                    {
                        this.test.Log("Attempting to execute the operation");
                        result = await operation.ExecuteAsync();
                    }
                    catch (MobileServicePreconditionFailedException e)
                    {
                        ex = e;
                    }

                    if (ex != null)
                    {
                        this.test.Log("A MobileServicePreconditionFailedException was thrown, ex.Value = {0}", ex.Value);
                        var serverItem = ex.Value;
                        if (serverItem == null)
                        {
                            this.test.Log("Item not returned in the exception, trying to retrieve it from the server");
                            serverItem = (JObject)(await client.GetTable(operation.Table.TableName).LookupAsync((string)operation.Item["id"]));
                        }

                        var typedClientItem = operation.Item.ToObject <T>();
                        var typedServerItem = serverItem.ToObject <T>();
                        var typedMergedItem = conflictResolution(typedClientItem, typedServerItem);
                        var mergedItem      = JObject.FromObject(typedMergedItem);
                        mergedItem[MobileServiceSystemColumns.Version] = serverItem[MobileServiceSystemColumns.Version];
                        this.test.Log("Merged the items, will try to resubmit the operation");
                        operation.Item = mergedItem;
                    }
                } while (ex != null);

                return(result);
            }
Esempio n. 19
0
    public async Task <JObject> ExecuteTableOperationAsync(IMobileServiceTableOperation operation)
    {
        JObject result = null;
        MobileServicePreconditionFailedException conflictError = null;

        do
        {
            try
            {
                result = await operation.ExecuteAsync();
            }
            catch (MobileServicePreconditionFailedException e)
            {
                conflictError = e;
            }

            if (conflictError != null)
            {
                // There was a conflict on the server. Let's "fix" it by
                // forcing the client entity
                JObject serverItem = conflictError.Value;

                // In most cases, the server will return the server item in the request body
                // when a Precondition Failed is returned, but it's not guaranteed for all
                // backend types.
                if (serverItem == null)
                {
                    serverItem = (JObject)(await operation.Table.LookupAsync((string)operation.Item[MobileServiceSystemColumns.Id]));
                }

                // Now update the local item with the server version
                operation.Item[MobileServiceSystemColumns.Version] = serverItem[MobileServiceSystemColumns.Version];
            }
        } while (conflictError != null);

        return(result);
    }
Esempio n. 20
0
        public async Task <JObject> ExecuteTableOperationAsync(IMobileServiceTableOperation operation)
        {
            JObject result = null;
            MobileServicePreconditionFailedException conflictError = null;

            Debug.WriteLine("Beginning Sync");
            do
            {
                try
                {
                    result = await operation.ExecuteAsync();
                }
                catch (MobileServicePreconditionFailedException e)
                {
                    conflictError = e;
                }
                catch (Exception ex)
                {
                    Debug.WriteLine(ex.ToString());
                }

                if (conflictError != null)
                {
                    JObject serverItem = conflictError.Value;

                    if (serverItem == null)
                    {
                        serverItem = (JObject)(await operation.Table.LookupAsync((string)operation.Item[MobileServiceSystemColumns.Id]));
                    }


                    serverItem[MobileServiceSystemColumns.Version] = operation.Item[MobileServiceSystemColumns.Version];
                }
            } while (conflictError != null);

            return(result);
        }
            public async Task <JObject> ExecuteTableOperationAsync(IMobileServiceTableOperation operation)
            {
                MobileServicePreconditionFailedException ex = null;
                JObject result = null;

                do
                {
                    ex = null;
                    try
                    {
                        result = await operation.ExecuteAsync();
                    }
                    catch (MobileServicePreconditionFailedException e)
                    {
                        ex = e;
                    }

                    if (ex != null)
                    {
                        var serverItem = ex.Value;
                        if (serverItem == null)
                        {
                            serverItem = (JObject)(await client.GetTable(operation.Table.TableName).LookupAsync((string)operation.Item["id"]));
                        }

                        var typedClientItem = operation.Item.ToObject <T>();
                        var typedServerItem = serverItem.ToObject <T>();
                        var typedMergedItem = conflictResolution(typedClientItem, typedServerItem);
                        var mergedItem      = JObject.FromObject(typedMergedItem);
                        mergedItem[MobileServiceSystemColumns.Version] = serverItem[MobileServiceSystemColumns.Version];
                        operation.Item = mergedItem;
                    }
                } while (ex != null);

                return(result);
            }
Esempio n. 22
0
 public Task <JObject> ExecuteTableOperationAsync(IMobileServiceTableOperation operation)
 {
     return(Task.FromResult(operation.Item));
 }
Esempio n. 23
0
 /// <summary>
 /// A method that is called to execute a single table operation against remote table.
 /// </summary>
 /// <param name="operation">Instance of <see cref="IMobileServiceTableOperation"/> that represents a remote table operation.</param>
 /// <returns>Task that completes when operation has been executed and errors have been handled.</returns>
 public virtual Task <JObject> ExecuteTableOperationAsync(IMobileServiceTableOperation operation)
 {
     return(operation.ExecuteAsync());
 }
 /// <summary>
 /// A method that is called to execute a single table operation against remote table.
 /// </summary>
 /// <param name="operation">Instance of <see cref="IMobileServiceTableOperation"/> that represents a remote table operation.</param>
 /// <returns>Task that completes when operation has been executed and errors have been handled.</returns>
 public virtual Task<JObject> ExecuteTableOperationAsync(IMobileServiceTableOperation operation)
 {
     return operation.ExecuteAsync();
 }
 public Task<JObject> ExecuteTableOperationAsync(IMobileServiceTableOperation operation)
 {
     Debug.WriteLine("Executing operation '{0}' for table '{1}'", operation.Kind, operation.Table.TableName);
     return operation.ExecuteAsync();
 }
        public override async Task <JObject> ExecuteTableOperationAsync(IMobileServiceTableOperation operation)
        {
            MobileServicePreconditionFailedException error;

            do
            {
                error = null;

                try
                {
                    return(await operation.ExecuteAsync());
                }
                catch (MobileServicePreconditionFailedException ex)
                {
                    error = ex;
                }

                if (error != null)
                {
                    var localItem   = operation.Item.ToObject <ToDoItem>();
                    var serverValue = error.Value;

                    var builder = new AlertDialog.Builder(this.activity);
                    builder.SetTitle("Conflict between local and server versions");
                    builder.SetMessage("How do you want to resolve this conflict?\n\n" + "Local item: \n" + localItem +
                                       "\n\nServer item:\n" + serverValue.ToObject <ToDoItem>());

                    var clickTask = new TaskCompletionSource <int>();

                    builder.SetPositiveButton(LOCAL_VERSION, (which, e) =>
                    {
                        clickTask.SetResult(1);
                    });
                    builder.SetNegativeButton(SERVER_VERSION, (which, e) =>
                    {
                        clickTask.SetResult(2);
                    });
                    builder.SetOnCancelListener(new CancelListener(clickTask));

                    builder.Create().Show();

                    int command = await clickTask.Task;
                    if (command == 1)
                    {
                        // Overwrite the server version and try the operation again by continuing the loop
                        operation.Item[MobileServiceSystemColumns.Version] = serverValue[MobileServiceSystemColumns.Version];
                        continue;
                    }
                    else if (command == 2)
                    {
                        return((JObject)serverValue);
                    }
                    else
                    {
                        operation.AbortPush();
                    }
                }
            } while (error != null);

            return(null);
        }
Esempio n. 27
0
        public virtual async Task <JObject> ExecuteTableOperationAsync(IMobileServiceTableOperation operation)
        {
            MobileServiceInvalidOperationException error;

            error = null;
            do
            {
                try
                {
                    JObject result = await operation.ExecuteAsync();

                    return(result);
                }
                catch (MobileServicePreconditionFailedException ex)
                {
                    CapptainAgent.Instance.SendError("MobileServicePreconditionFailedException.Error", new Dictionary <object, object>()
                    {
                        { "errorMessage", ex.Message }
                    });
                    error = ex;
                }
                catch (Exception ex)
                {
                    CapptainAgent.Instance.SendError("Exception in SyncHandler", new Dictionary <object, object>()
                    {
                        { "errorMessage", ex.Message }
                    });
                    throw;
                }

                if (error != null)
                {
                    var localItem   = operation.Item.ToObject <Job>();
                    var serverValue = await operation.Table.LookupAsync(localItem.Id) as JObject;

                    var serverItem = serverValue.ToObject <Job>();

                    if (localItem.Equals(serverItem))
                    {
                        // items are same so we can ignore the conflict
                        return(serverValue);
                    }

                    IUICommand command = await ShowConflictDialog(localItem, serverValue);

                    if (command.Label == LOCAL_VERSION)
                    {
                        CapptainAgent.Instance.SendEvent("Conflict resolved. Overwriting server Job: " + localItem.Id +
                                                         " with Job from localstore");
                        // Overwrite the server version and try the operation again by continuing the loop
                        operation.Item[MobileServiceSystemColumns.Version] = serverValue[MobileServiceSystemColumns.Version];
                    }
                    else if (command.Label == SERVER_VERSION)
                    {
                        CapptainAgent.Instance.SendEvent("Conflict resolved. Overwriting local Job: " + localItem.Id +
                                                         " with latest Job from Server");
                        return((JObject)serverValue);
                    }
                    else
                    {
                        operation.AbortPush();
                    }
                }
            } while (error != null);
            return(null);
        }
Esempio n. 28
0
        /// <inheritdoc />
        public override Task <JObject> ExecuteTableOperationAsync(IMobileServiceTableOperation operation)
        {
            Debug.WriteLine("About to execute table {0} operation of {1}", operation.Table.TableName, operation.Kind);

            return(base.ExecuteTableOperationAsync(operation));
        }
        public virtual async Task<JObject> ExecuteTableOperationAsync(IMobileServiceTableOperation operation)
        {
            MobileServiceInvalidOperationException error;
            Func<Task<JObject>> tryOperation = operation.ExecuteAsync;

            do
            {
                error = null;

                try
                {
                    JObject result = await operation.ExecuteAsync();
                    return result;
                }
                catch (MobileServiceConflictException ex)
                {
                    error = ex;
                }
                catch (MobileServicePreconditionFailedException ex)
                {
                    error = ex;
                }
                catch (Exception e)
                {
                    Debug.WriteLine(e.ToString());
                    throw e;
                }

                if (error != null)
                {
                    var localItem = operation.Item.ToObject<TodoItem>();
                    var serverValue = error.Value;
                    if (serverValue == null) // 409 doesn't return the server item
                    {
                        serverValue = await operation.Table.LookupAsync(localItem.Id) as JObject;
                    }
                    var serverItem = serverValue.ToObject<TodoItem>();


                    if (serverItem.Complete == localItem.Complete && serverItem.Text == localItem.Text)
                    {
                        // items are same so we can ignore the conflict
                        return serverValue;
                    }

                    IUICommand command = await ShowConflictDialog(localItem, serverValue);
                    if (command.Label == LOCAL_VERSION)
                    {
                        // Overwrite the server version and try the operation again by continuing the loop
                        operation.Item[MobileServiceSystemColumns.Version] = serverValue[MobileServiceSystemColumns.Version];
                        if (error is MobileServiceConflictException) // change operation from Insert to Update
                        {
                            tryOperation = async () => await operation.Table.UpdateAsync(operation.Item) as JObject;
                        }
                        continue;
                    }
                    else if (command.Label == SERVER_VERSION)
                    {
                        return (JObject)serverValue;
                    }
                    else
                    {
                        operation.AbortPush();
                    }
                }
            } while (error != null);

            return null;
        }
        public override async Task<JObject> ExecuteTableOperationAsync(IMobileServiceTableOperation operation)
        {
            MobileServicePreconditionFailedException error;

            do
            {
                error = null;

                try
                {
                    return await operation.ExecuteAsync();
                }
                catch (MobileServicePreconditionFailedException ex)
                {
                    error = ex;
                }

                if (error != null)
                {
                    var localItem = operation.Item.ToObject<ToDoItem>();
                    var serverValue = error.Value;

                    var builder = new AlertDialog.Builder(this.activity);
                    builder.SetTitle("Conflict between local and server versions");
                    builder.SetMessage("How do you want to resolve this conflict?\n\n" + "Local item: \n" + localItem +
                        "\n\nServer item:\n" + serverValue.ToObject<ToDoItem>());

                    var clickTask = new TaskCompletionSource<int>();

                    builder.SetPositiveButton(LOCAL_VERSION, (which, e) =>
                    {
                        clickTask.SetResult(1);
                    });
                    builder.SetNegativeButton(SERVER_VERSION, (which, e) =>
                    {
                        clickTask.SetResult(2);
                    });
                    builder.SetOnCancelListener(new CancelListener(clickTask));

                    builder.Create().Show();

                    int command = await clickTask.Task;
                    if (command == 1)
                    {
                        // Overwrite the server version and try the operation again by continuing the loop
                        operation.Item[MobileServiceSystemColumns.Version] = serverValue[MobileServiceSystemColumns.Version];
                        continue;
                    }
                    else if (command == 2)
                    {
                        return (JObject)serverValue;
                    }
                    else
                    {
                        operation.AbortPush();
                    }
                }
            } while (error != null);

            return null;
        }
        public virtual async Task <JObject> ExecuteTableOperationAsync(IMobileServiceTableOperation operation)
        {
            MobileServiceInvalidOperationException error;
            Func <Task <JObject> > tryOperation = operation.ExecuteAsync;

            do
            {
                error = null;

                try
                {
                    JObject result = await operation.ExecuteAsync();

                    return(result);
                }
                catch (MobileServiceConflictException ex)
                {
                    error = ex;
                }
                catch (MobileServicePreconditionFailedException ex)
                {
                    error = ex;
                }

                if (error != null)
                {
                    var localItem   = operation.Item.ToObject <ToDoItem>();
                    var serverValue = error.Value;
                    if (serverValue == null) // 409 doesn't return the server item
                    {
                        serverValue = await operation.Table.LookupAsync(localItem.Id) as JObject;
                    }

                    var serverItem = serverValue.ToObject <ToDoItem>();

                    if (serverItem.Complete == localItem.Complete &&
                        serverItem.Text == localItem.Text)
                    {
                        // items are same so we can ignore the conflict
                        return(serverValue);
                    }

                    int command = await ShowConflictDialog(localItem, serverValue);

                    if (command == 1)
                    {
                        // Overwrite the server version and try the operation again by continuing the loop
                        operation.Item[MobileServiceSystemColumns.Version] = serverValue[MobileServiceSystemColumns.Version];
                        if (error is MobileServiceConflictException) // change operation from Insert to Update
                        {
                            tryOperation = async() => await operation.Table.UpdateAsync(operation.Item) as JObject;
                        }
                        continue;
                    }
                    else if (command == 2)
                    {
                        return((JObject)serverValue);
                    }
                    else
                    {
                        operation.AbortPush();
                    }
                }
            } while (error != null);

            return(null);
        }
Esempio n. 32
0
 public Task <JObject> ExecuteTableOperationAsync(IMobileServiceTableOperation operation)
 {
     Debug.WriteLine("Executing operation '{0}' for table '{1}'", operation.Kind, operation.Table.TableName);
     return(operation.ExecuteAsync());
 }
Esempio n. 33
0
		/// <summary>
		/// A method that is called to execute a single table operation against remote table.
		/// </summary>
		/// <returns>The table operation async.</returns>
		/// <param name="operation">Operation.</param>
		public virtual async Task<JObject> ExecuteTableOperationAsync (IMobileServiceTableOperation operation)
		{
			// We can grab the local item from the operation.
			var localItem = operation.Item.ToObject<TodoItem> ();
			TodoItem serverItem = null;

			// Output some debug info.
			Debug.WriteLine ("Executing operation:");
			Debug.WriteLine ($"   Kind: {operation.Kind}");
			Debug.WriteLine ($"   Table: {operation.Table}");
			Debug.WriteLine ($"   State: {operation.State}");

			MobileServicePreconditionFailedException error = null;

			JObject result = null;
			do
			{
				error = null;

				try
				{
					// Try to execute the requested operation and catch the error to see if we can resolve it.
					result = await operation.ExecuteAsync ();
				}
				catch (MobileServicePreconditionFailedException ex)
				{
					//Debug.WriteLine ($"Error handling sync: {ex}");
					// This exception happens if the "Version" property (marked with the [Version] attribute) in the TodoItem does not match (local != server). 
					// Every time an item gets updated, Azure changes the version to know if something has been modified.
					error = ex;
				}
				// Should only see MobileServicePreconditionFailedException in here. If something fails, comment this out and check what's wrong.
				// Everything not caught in here will bubble up and eventually be caught in the TodoItemManager.SyncAsync().
				/*
				catch(Exception unhandledEx)
				{
					Debug.WriteLine($"Unhandled exception while syncing. Throwing on: {unhandledEx}");
					throw;
				}
				*/

				if (error != null)
				{
					serverItem = error.Value.ToObject<TodoItem> ();

					// Ask the user what to do.
					int choice = await ShowConflictDialog (localItem, serverItem);
					if (choice == 0)
					{
						// Resolve in favor of the client item.
						// Update the local item to the server version so the conflict won't happen again. We simply pretend our local version is the newest (example: server is 3, local is 2; by setting local to 3, 
						// the versions are identical, so local content will overwrite server content).
						localItem.Version = serverItem.Version;

						// We are inside a loop. By continuing, the operation will be retried; since we have resolved it, it should now succeed.
						continue;
					}
					else if(choice == 1)
					{
						// Return the object we got from the server. We must return the "JObject" here, not the actual Item (http://www.newtonsoft.com/json/help/html/t_newtonsoft_json_linq_jobject.htm).
						return error.Value;
					}
					else
					{
						// Can cancel the entire operation but retain the queued operations. Possible if you want to offer a "Cancel" button in the conflict resolution dialog.
						operation.AbortPush();
					}

					// Optional:
					// You might want to merge server and client item. In this case, bump the version of the local item to the server version and change the local item with updates from the server item.
					// Then resync and the changes will be pushed.
				}
			}
			while(error != null);

			return result;
		}