/// <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); } }
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); }
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 } }
/// <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; }
/// <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; }