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