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 this method is not correctly observing the execution results, the catch block below is wrong. 385801 action.ExecuteAsync(ActionContext.ControllerContext, paramMap); } 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> /// Returns the original unmodified entity for the provided <paramref name="clientEntity"/>. /// </summary> /// <remarks> /// Note that only members marked with <see cref="RoundtripOriginalAttribute"/> will be set /// in the returned instance. /// </remarks> /// <typeparam name="TEntity">The entity type.</typeparam> /// <param name="clientEntity">The client modified entity.</param> /// <returns>The original unmodified entity for the provided <paramref name="clientEntity"/>.</returns> /// <exception cref="ArgumentNullException">if <paramref name="clientEntity"/> is null.</exception> /// <exception cref="ArgumentException">if <paramref name="clientEntity"/> is not in the change set.</exception> public TEntity GetOriginal <TEntity>(TEntity clientEntity) where TEntity : class { if (clientEntity == null) { throw Error.ArgumentNull("clientEntity"); } ChangeSetEntry entry = _changeSetEntries.FirstOrDefault(p => Object.ReferenceEquals(p.Entity, clientEntity)); if (entry == null) { throw Error.Argument(Resource.ChangeSet_ChangeSetEntryNotFound); } if (entry.Operation == ChangeOperation.Insert) { throw Error.InvalidOperation(Resource.ChangeSet_OriginalNotValidForInsert); } return((TEntity)entry.OriginalEntity); }
public void Changeset_OriginalInvalidForInserts() { // can't specify an original for an insert operation Product curr = new Product { ProductID = 1 }; Product orig = new Product { ProductID = 1 }; ChangeSetEntry entry = new ChangeSetEntry { Id = 1, Entity = curr, OriginalEntity = orig, Operation = ChangeOperation.Insert }; ChangeSet cs = null; Assert.Throws<InvalidOperationException>(delegate { cs = new ChangeSet(new ChangeSetEntry[] { entry }); }, String.Format(Resource.InvalidChangeSet, Resource.InvalidChangeSet_InsertsCantHaveOriginal)); // get original should throw for insert operations entry = new ChangeSetEntry { Id = 1, Entity = curr, OriginalEntity = null, Operation = ChangeOperation.Insert }; cs = new ChangeSet(new ChangeSetEntry[] { entry }); Assert.Throws<InvalidOperationException>(delegate { cs.GetOriginal(curr); }, String.Format(Resource.ChangeSet_OriginalNotValidForInsert)); }
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; } } }
public override Task <object> ExecuteAsync(HttpControllerContext controllerContext, IDictionary <string, object> arguments) { return(TaskHelpers.RunSynchronously <object>(() => { // create the changeset object entity = arguments.Single().Value; // there is only a single parameter - the entity being submitted ChangeSetEntry[] changeSetEntries = new ChangeSetEntry[] { new ChangeSetEntry { Id = 1, ActionDescriptor = _updateAction, Entity = entity, Operation = _updateAction.ChangeOperation } }; ChangeSet changeSet = new ChangeSet(changeSetEntries); changeSet.SetEntityAssociations(); DataController controller = (DataController)controllerContext.Controller; if (!controller.Submit(changeSet) && controller.ActionContext.Response != null) { // If the submit failed due to an authorization failure, // return the authorization response directly return controller.ActionContext.Response; } // return the entity entity = changeSet.ChangeSetEntries[0].Entity; // REVIEW does JSON make sense here? return new HttpResponseMessage() { Content = new ObjectContent(_updateAction.EntityType, entity, new JsonMediaTypeFormatter()) }; })); }
public override Task<object> ExecuteAsync(HttpControllerContext controllerContext, IDictionary<string, object> arguments, CancellationToken cancellationToken) { return TaskHelpers.RunSynchronously<object>(() => { // create the changeset object entity = arguments.Single().Value; // there is only a single parameter - the entity being submitted ChangeSetEntry[] changeSetEntries = new ChangeSetEntry[] { new ChangeSetEntry { Id = 1, ActionDescriptor = _updateAction, Entity = entity, Operation = _updateAction.ChangeOperation } }; ChangeSet changeSet = new ChangeSet(changeSetEntries); changeSet.SetEntityAssociations(); DataController controller = (DataController)controllerContext.Controller; if (!controller.Submit(changeSet) && controller.ActionContext.Response != null) { // If the submit failed due to an authorization failure, // return the authorization response directly return controller.ActionContext.Response; } // return the entity entity = changeSet.ChangeSetEntries[0].Entity; // REVIEW does JSON make sense here? return new HttpResponseMessage() { Content = new ObjectContent(_updateAction.EntityType, entity, new JsonMediaTypeFormatter()) }; }, cancellationToken); }
/// <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); }
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 this method is not correctly observing the execution results, the catch block below is wrong. 385801 action.ExecuteAsync(ActionContext.ControllerContext, paramMap); } 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; } } }
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; } } }