private void InvokeAction(HttpActionDescriptor action, object[] parameters, ChangeSetEntry changeSetEntry) { try { Collection <HttpParameterDescriptor> pds = action.GetParameters(); Dictionary <string, object> paramMap = new Dictionary <string, object>(pds.Count); for (int i = 0; i < pds.Count; i++) { paramMap.Add(pds[i].ParameterName, parameters[i]); } // TODO - Issue #103 // This method is not correctly observing the execution results, the catch block below is wrong. // Submit should be Task<bool>, not bool, and should model bind for the CancellationToken which would then // be propagated through to all the helper methods (one or more of which might also need to be made async, // once we start respecting the fact that the read/write actions should be allowed to be async). action.ExecuteAsync(ActionContext.ControllerContext, paramMap, CancellationToken.None); } catch (TargetInvocationException tie) { ValidationException vex = tie.GetBaseException() as ValidationException; if (vex != null) { ValidationResultInfo error = new ValidationResultInfo(vex.Message, 0, String.Empty, vex.ValidationResult.MemberNames); if (changeSetEntry.ValidationErrors != null) { changeSetEntry.ValidationErrors = changeSetEntry.ValidationErrors.Concat(new ValidationResultInfo[] { error }).ToArray(); } else { changeSetEntry.ValidationErrors = new ValidationResultInfo[] { error }; } } else { throw; } } }
/// <summary> /// This method invokes the user overridable <see cref="PersistChangeSet"/> method wrapping the call /// with the appropriate exception handling logic. All framework calls to <see cref="PersistChangeSet"/> /// must go through this method. Some data sources have their own validation hook points, /// so if a <see cref="ValidationException"/> is thrown at that level, we want to capture it. /// </summary> /// <returns>True if the <see cref="ChangeSet"/> was persisted successfully, false otherwise.</returns> private bool PersistChangeSetInternal() { try { PersistChangeSet(); } catch (ValidationException e) { // if a validation exception is thrown for one of the entities in the changeset // set the error on the corresponding ChangeSetEntry if (e.Value != null && e.ValidationResult != null) { IEnumerable <ChangeSetEntry> updateOperations = ChangeSet.ChangeSetEntries.Where( p => p.Operation == ChangeOperation.Insert || p.Operation == ChangeOperation.Update || p.Operation == ChangeOperation.Delete); ChangeSetEntry operation = updateOperations.SingleOrDefault(p => Object.ReferenceEquals(p.Entity, e.Value)); if (operation != null) { ValidationResultInfo error = new ValidationResultInfo(e.ValidationResult.ErrorMessage, e.ValidationResult.MemberNames); error.StackTrace = e.StackTrace; operation.ValidationErrors = new List <ValidationResultInfo>() { error }; } } else { throw; } } return(!ChangeSet.HasError); }