예제 #1
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);
        }
예제 #2
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;
        }
            public Task <JObject> ExecuteTableOperationAsync(IMobileServiceTableOperation operation)
            {
                var itemId = (string)operation.Item[MobileServiceSystemColumns.Id];

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

                return(operation.ExecuteAsync());
            }
예제 #4
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());
            }
        /// <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 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;
        }
예제 #7
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;
        }
예제 #8
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;
		}
예제 #9
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);
        }
예제 #10
0
        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 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;
        }
예제 #12
0
        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);
        }