Example #1
0
		/// <summary>
		/// A method that is called when push operation has completed.
		/// </summary>
		/// <param name="result">Result.</param>
		public virtual Task OnPushCompleteAsync (MobileServicePushCompletionResult result)
		{
			// We get here after we recevice the reply from Azure - in here it is too late to handle the conflicts!
			// In theory, we should never see any error here if we handle them in ExecuteTableOperationAsync().
			Debug.WriteLine ("Push complete result:" + result.Status);
			Debug.WriteLine ("Push complete errors:" + result.Errors);
			return Task.FromResult (0);
		}
 public override Task OnPushCompleteAsync(MobileServicePushCompletionResult result)
 {
     this.PushCompletionResult = result;
     if (this.PushCompleteAction != null)
     {
         return PushCompleteAction(result);
     }
     else
     {
         return base.OnPushCompleteAsync(result);
     }
 }
Example #3
0
        public override async Task OnPushCompleteAsync(MobileServicePushCompletionResult result)
        {
            foreach (var error in result.Errors)
            {
                if (error.Status == HttpStatusCode.Conflict)
                {
                    await error.CancelAndUpdateItemAsync(error.Result);
                    error.Handled = true;
                }
            }

            await base.OnPushCompleteAsync(result);
        }
Example #4
0
        public Task OnPushCompleteAsync(MobileServicePushCompletionResult result)
        {
            Debug.WriteLine("Push result: {0}", result.Status);
            foreach (var error in result.Errors)
            {
                Debug.WriteLine("  Push error: {0}", error.Status);
                if (error.Status == HttpStatusCode.Conflict)
                {
                    // Simplistic conflict handling - server wins
                    error.Handled = true;
                    error.CancelAndUpdateItemAsync(error.Item);
                }
            }


            return Task.FromResult(0);
        }
        private async Task FinalizePush(OperationBatch batch, MobileServicePushStatus batchStatus, IEnumerable <MobileServiceTableOperationError> syncErrors)
        {
            var result = new MobileServicePushCompletionResult(syncErrors, batchStatus);

            try
            {
                await batch.SyncHandler.OnPushCompleteAsync(result);

                // now that we've successfully given the errors to user, we can delete them from store
                await batch.DeleteErrorsAsync();
            }
            catch (Exception ex)
            {
                batch.OtherErrors.Add(ex);
            }

            if (batchStatus != MobileServicePushStatus.Complete || batch.HasErrors(syncErrors))
            {
                List <MobileServiceTableOperationError> unhandledSyncErrors = syncErrors.Where(e => !e.Handled).ToList();

                Exception inner;
                if (batch.OtherErrors.Count == 1)
                {
                    inner = batch.OtherErrors[0];
                }
                else
                {
                    inner = batch.OtherErrors.Any() ? new AggregateException(batch.OtherErrors) : null;
                }

                // create a new result with only unhandled errors
                result = new MobileServicePushCompletionResult(unhandledSyncErrors, batchStatus);
                this.TaskSource.TrySetException(new MobileServicePushFailedException(result, inner));
            }
            else
            {
                this.TaskSource.SetResult(0);
            }
        }
 public virtual Task OnPushCompleteAsync(MobileServicePushCompletionResult result)
 {
     return Task.FromResult(0);
 }
        private async Task FinalizePush(OperationBatch batch, MobileServicePushStatus batchStatus, IEnumerable<MobileServiceTableOperationError> syncErrors)
        {
            var result = new MobileServicePushCompletionResult(syncErrors, batchStatus);

            try
            {
                await batch.SyncHandler.OnPushCompleteAsync(result);

                // now that we've successfully given the errors to user, we can delete them from store
                await batch.DeleteErrorsAsync();
            }
            catch (Exception ex)
            {
                batch.OtherErrors.Add(ex);
            }

            if (batchStatus != MobileServicePushStatus.Complete || batch.HasErrors(syncErrors))
            {
                List<MobileServiceTableOperationError> unhandledSyncErrors = syncErrors.Where(e => !e.Handled).ToList();

                Exception inner;
                if (batch.OtherErrors.Count == 1)
                {
                    inner = batch.OtherErrors[0];
                }
                else
                {
                    inner = batch.OtherErrors.Any() ? new AggregateException(batch.OtherErrors) : null;
                }

                // create a new result with only unhandled errors
                result = new MobileServicePushCompletionResult(unhandledSyncErrors, batchStatus);
                this.TaskSource.TrySetException(new MobileServicePushFailedException(result, inner));
            }
            else
            {
                this.TaskSource.SetResult(0);
            }
        }
        public override async Task OnPushCompleteAsync(MobileServicePushCompletionResult result)
        {

            foreach (MobileServiceTableOperationError error in result.Errors)
            {
                #region Server wins
#if Server


                #region insert
                // 403
                // Client 1 soft deleted or client 2 network failure // Client 2 inserts
                // resolution Update the local item with server value
                if (error.OperationKind == MobileServiceTableOperationKind.Insert && error.Status == HttpStatusCode.Conflict)
                {

                    // If same preserve server changes 
                    // if different preserver client changes
                    // cannot compare no server item get server item in a seperate call
                    TodoItem clientItem = error.Item.ToObject<TodoItem>();
                    var todoTab = App.MobileService.GetTable<TodoItem>();
                    //TodoItem serverItem;

                    var serverValue = await todoTab.LookupAsync(clientItem.Id);


                    // failed network call so remove update client with server version
                    if (clientItem.Text == serverValue.Text)
                    {
                       await error.CancelAndUpdateItemAsync(error.Result);
                    }
                    // Id collision
                    else
                    {
                        clientItem.Id = null;
                        await todoTable.InsertAsync(clientItem);
                        await error.CancelAndDiscardItemAsync();

                    }
                }
                #endregion

                #region update
                // 412 
                // Client 1 updates // Client 2 tries to update outdated item
                // resolution Update the local item with server value
                if (error.OperationKind == MobileServiceTableOperationKind.Update && error.Status == HttpStatusCode.PreconditionFailed)
                {
                    await error.CancelAndUpdateItemAsync(error.Result);
                }

                //404
                // Client 1 deletes // Client 2 tries to update deleted item
                // Remove the item from local store
                if (error.OperationKind == MobileServiceTableOperationKind.Update && error.Status == HttpStatusCode.NotFound)
                {
                    await error.CancelAndDiscardItemAsync();
                }
                #endregion

                #region delete

                //412
                // Client 1 updates // Client 2 tries to deletes item
                // Resolution cancel the delete and update the local store with server value
                if (error.OperationKind == MobileServiceTableOperationKind.Delete && error.Status == HttpStatusCode.PreconditionFailed)
                {
                    await error.CancelAndUpdateItemAsync(error.Result);
                }
                #endregion

#endif
                #endregion

                #region ClientWins
#if Client
                TodoItem clientItem = error.Item.ToObject<TodoItem>();
                await error.CancelAndDiscardItemAsync();

                #region insert
                // 403
                // Client 1 soft deleted or client 2 network failure // Client 2 inserts
                // resolution Update the local item with server value
                if (error.OperationKind == MobileServiceTableOperationKind.Insert && error.Status == HttpStatusCode.Conflict)
                {
                    var todoTab = App.MobileService.GetTable<TodoItem>();
                    //TodoItem serverItem;

                    var serverValue = await todoTab.LookupAsync(clientItem.Id);

                    // failed network call so remove update client with server version
                    if (clientItem.Text == serverValue.Text)
                    {
                        await error.CancelAndUpdateItemAsync(error.Result);
                    }
                    // Id collision
                    else
                    {
                        clientItem.Id = null;
                        await todoTable.InsertAsync(clientItem);
                        await error.CancelAndDiscardItemAsync();

                    }
                }
                #endregion

                #region update
                // 412 
                // Client 1 updates // Client 2 tries to update outdated item
                // resolution Update the server item
                if (error.OperationKind == MobileServiceTableOperationKind.Update && error.Status == HttpStatusCode.PreconditionFailed)
                {
                    error.Item[MobileServiceSystemColumns.Version] = error.Result[MobileServiceSystemColumns.Version];
                    await todoTable.UpdateAsync(clientItem);
                }

                //404
                // Client 1 deletes // Client 2 tries to update deleted item
                // insert the item to the server with a different id or undelete the item if soft delete is enabled
                if (error.OperationKind == MobileServiceTableOperationKind.Update && error.Status == HttpStatusCode.NotFound)
                {
                    // if soft delete enabled the call undelete and then update
                    await todoTable.InsertAsync(clientItem);
                }
                #endregion

                #region delete

                //412
                // Client 1 updates // Client 2 tries to deletes item
                // Resolution cancel the delete and update the local store with server value
                if (error.OperationKind == MobileServiceTableOperationKind.Delete && error.Status == HttpStatusCode.PreconditionFailed)
                {
                    error.Item[MobileServiceSystemColumns.Version] = error.Result[MobileServiceSystemColumns.Version];
                    await todoTable.DeleteAsync(clientItem);

                }
                #endregion
#endif
                #endregion
            }
        }
Example #9
0
 /// <summary>
 /// A method that is called when push operation has completed.
 /// </summary>
 /// <param name="result">An instance of <see cref="MobileServicePushCompletionResult"/></param>
 /// <returns>Task that completes when result has been handled.</returns>
 public virtual Task OnPushCompleteAsync(MobileServicePushCompletionResult result)
 {
     return(Task.FromResult(0));
 }
 /// <summary>
 /// Initializes a new instance of <see cref="MobileServicePushFailedException"/>
 /// </summary>
 /// <param name="pushResult">Result of push operation.</param>
 /// <param name="innerException">Inner exception that caused the push to fail.</param>
 public MobileServicePushFailedException(MobileServicePushCompletionResult pushResult, Exception innerException)
     : base("Push operation has failed. See the PushResult for details.", innerException)
 {
     this.PushResult = pushResult;
 }
Example #11
0
 /// <summary>
 /// Initializes a new instance of <see cref="MobileServicePushFailedException"/>
 /// </summary>
 /// <param name="pushResult">Result of push operation.</param>
 /// <param name="innerException">Inner exception that caused the push to fail.</param>
 public MobileServicePushFailedException(MobileServicePushCompletionResult pushResult, Exception innerException)
     : base("Push operation has failed. See the PushResult for details.", innerException)
 {
     this.PushResult = pushResult;
 }
 /// <summary>
 /// Initializes a new instance of <see cref="MobileServicePushFailedException"/>
 /// </summary>
 /// <param name="pushResult">Result of push operation.</param>
 /// <param name="innerException">Inner exception that caused the push to fail.</param>
 public MobileServicePushFailedException(MobileServicePushCompletionResult pushResult, Exception innerException)
     : base(Resources.Push_Failure, innerException)
 {
     this.PushResult = pushResult;
 }