private PluginContext CreatePluginContext(PluginContext pluginContext, Guid guid, string logicalName, Entity preImage, Entity postImage) { var thisPluginContext = pluginContext.Clone(); thisPluginContext.Mode = (int)this.mode; thisPluginContext.Stage = (int)this.stage; if (thisPluginContext.PrimaryEntityId == Guid.Empty) { thisPluginContext.PrimaryEntityId = guid; } thisPluginContext.PrimaryEntityName = logicalName; foreach (var image in this.images) { var type = (ImageType)image.Item3; var cols = image.Item4 != null ? new ColumnSet(image.Item4.Split(',')) : new ColumnSet(true); if (postImage != null && stage == ExecutionStage.PostOperation && (type == ImageType.PostImage || type == ImageType.Both)) { thisPluginContext.PostEntityImages.Add(image.Item1, postImage.CloneEntity(metadata.GetMetadata(postImage.LogicalName), cols)); } if (preImage != null && type == ImageType.PreImage || type == ImageType.Both) { thisPluginContext.PreEntityImages.Add(image.Item1, preImage.CloneEntity(metadata.GetMetadata(preImage.LogicalName), cols)); } } return(thisPluginContext); }
private PluginContext createPluginContext(PluginContext pluginContext, Entity workflow, workflow_stage?thisStage, Guid guid, string logicalName) { var thisPluginContext = pluginContext.Clone(); thisPluginContext.Mode = ((int)workflow.GetOptionSetValue <Workflow_Mode>("mode") + 1) % 2; thisPluginContext.Stage = thisStage.HasValue ? (int)thisStage : (int)workflow_stage.Postoperation; thisPluginContext.PrimaryEntityId = guid; thisPluginContext.PrimaryEntityName = logicalName; return(thisPluginContext); }
internal OrganizationResponse Execute(OrganizationRequest request, EntityReference userRef, PluginContext parentPluginContext) { // Setup HandleInternalPreOperations(request, userRef); var primaryRef = Mappings.GetPrimaryEntityReferenceFromRequest(request); // Create the plugin context var pluginContext = new PluginContext() { UserId = userRef.Id, InitiatingUserId = userRef.Id, MessageName = RequestNameToMessageName(request.RequestName), Depth = 1, OrganizationName = this.OrganizationName, OrganizationId = this.OrganizationId, PrimaryEntityName = primaryRef?.LogicalName, }; if (primaryRef != null) { var refEntity = db.GetEntityOrNull(primaryRef); pluginContext.PrimaryEntityId = refEntity == null ? Guid.Empty : refEntity.Id; } foreach (var prop in request.Parameters) { pluginContext.InputParameters[prop.Key] = prop.Value; } if (parentPluginContext != null) { pluginContext.ParentContext = parentPluginContext; pluginContext.Depth = parentPluginContext.Depth + 1; } var buRef = GetBusinessUnit(userRef); pluginContext.BusinessUnitId = buRef.Id; Mappings.RequestToEventOperation.TryGetValue(request.GetType(), out EventOperation? eventOp); var entityInfo = GetEntityInfo(request); var settings = MockupExecutionContext.GetSettings(request); // Validation if (!settings.SetUnsettableFields && (request is UpdateRequest || request is CreateRequest)) { var entity = request is UpdateRequest ? (request as UpdateRequest).Target : (request as CreateRequest).Target; Utility.RemoveUnsettableAttributes(request.RequestName, metadata.EntityMetadata.GetMetadata(entity.LogicalName), entity); } Entity preImage = null; Entity postImage = null; if (settings.TriggerProcesses && entityInfo != null) { preImage = TryRetrieve(primaryRef); if (preImage != null) { primaryRef.Id = preImage.Id; } } if (settings.TriggerProcesses && entityInfo != null && eventOp.HasValue) { // System Pre-validation pluginManager.TriggerSystem(eventOp.Value, ExecutionStage.PreValidation, entityInfo.Item1, preImage, postImage, pluginContext, this); // Pre-validation pluginManager.Trigger(eventOp.Value, ExecutionStage.PreValidation, entityInfo.Item1, preImage, postImage, pluginContext, this); // Shared variables should be moved to parent context when transitioning from 10 to 20. pluginContext.ParentContext = pluginContext.Clone(); pluginContext.SharedVariables.Clear(); // Pre-operation pluginManager.Trigger(eventOp.Value, ExecutionStage.PreOperation, entityInfo.Item1, preImage, postImage, pluginContext, this); workflowManager.Trigger(eventOp.Value, ExecutionStage.PreOperation, entityInfo.Item1, preImage, postImage, pluginContext, this); // System Pre-operation pluginManager.TriggerSystem(eventOp.Value, ExecutionStage.PreOperation, entityInfo.Item1, preImage, postImage, pluginContext, this); } // Core operation OrganizationResponse response = ExecuteRequest(request, userRef, parentPluginContext); // Post-operation if (settings.TriggerProcesses && entityInfo != null) { postImage = TryRetrieve(primaryRef); if (eventOp.HasValue) { pluginManager.TriggerSystem(eventOp.Value, ExecutionStage.PostOperation, entityInfo.Item1, preImage, postImage, pluginContext, this); pluginManager.Trigger(eventOp.Value, ExecutionStage.PostOperation, entityInfo.Item1, preImage, postImage, pluginContext, this); workflowManager.Trigger(eventOp.Value, ExecutionStage.PostOperation, entityInfo.Item1, preImage, postImage, pluginContext, this); } workflowManager.ExecuteWaitingWorkflows(pluginContext, this); } return(response); }
public void ExecuteIfMatch(object entityObject, Entity preImage, Entity postImage, PluginContext pluginContext, Core core) { // Check if it is supposed to execute. Returns preemptively, if it should not. var entity = entityObject as Entity; var entityRef = entityObject as EntityReference; var guid = (entity != null) ? entity.Id : entityRef.Id; var logicalName = (entity != null) ? entity.LogicalName : entityRef.LogicalName; if (entityName != "" && entityName != logicalName) { return; } if (entity != null && metadata.GetMetadata(logicalName)?.PrimaryIdAttribute != null) { entity[metadata.GetMetadata(logicalName).PrimaryIdAttribute] = guid; } if (pluginContext.Depth > 8) { throw new FaultException( "This workflow job was canceled because the workflow that started it included an infinite loop." + " Correct the workflow logic and try again."); } if (operation == EventOperation.Update && stage == ExecutionStage.PostOperation) { var shadowAddedAttributes = postImage.Attributes.Where(a => !preImage.Attributes.ContainsKey(a.Key) && !entity.Attributes.ContainsKey(a.Key)); entity = entity.CloneEntity(); entity.Attributes.AddRange(shadowAddedAttributes); } if (operation == EventOperation.Update && attributes.Count > 0) { var foundAttr = false; foreach (var attr in entity.Attributes) { if (attributes.Contains(attr.Key)) { foundAttr = true; break; } } if (!foundAttr) { return; } } if (entityName != "" && (operation == EventOperation.Associate || operation == EventOperation.Disassociate)) { throw new MockupException( $"An {operation} plugin step was registered for a specific entity, which can only be registered on AnyEntity"); } // Create the plugin context var thisPluginContext = pluginContext.Clone(); thisPluginContext.Mode = (int)this.mode; thisPluginContext.Stage = (int)this.stage; if (thisPluginContext.PrimaryEntityId == Guid.Empty) { thisPluginContext.PrimaryEntityId = guid; } thisPluginContext.PrimaryEntityName = logicalName; foreach (var image in this.images) { var type = (ImageType)image.Item3; var cols = image.Item4 != null ? new ColumnSet(image.Item4.Split(',')) : new ColumnSet(true); if (postImage != null && stage == ExecutionStage.PostOperation && (type == ImageType.PostImage || type == ImageType.Both)) { thisPluginContext.PostEntityImages.Add(image.Item1, postImage.CloneEntity(metadata.GetMetadata(postImage.LogicalName), cols)); } if (preImage != null && type == ImageType.PreImage || type == ImageType.Both) { thisPluginContext.PreEntityImages.Add(image.Item1, preImage.CloneEntity(metadata.GetMetadata(preImage.LogicalName), cols)); } } // Create service provider and execute the plugin MockupServiceProviderAndFactory provider = new MockupServiceProviderAndFactory(core, thisPluginContext, new TracingService()); try { pluginExecute(provider); } catch (TargetInvocationException e) { ExceptionDispatchInfo.Capture(e.InnerException).Throw(); } }
internal OrganizationResponse Execute(OrganizationRequest request, EntityReference userRef, PluginContext parentPluginContext) { // Setup HandleInternalPreOperations(request, userRef); var primaryRef = Mappings.GetPrimaryEntityReferenceFromRequest(request); // Create the plugin context var pluginContext = new PluginContext() { UserId = userRef.Id, InitiatingUserId = userRef.Id, MessageName = RequestNameToMessageName(request.RequestName), Depth = 1, OrganizationName = this.OrganizationName, OrganizationId = this.OrganizationId, PrimaryEntityName = primaryRef?.LogicalName, }; if (primaryRef != null) { var refEntity = db.GetEntityOrNull(primaryRef); pluginContext.PrimaryEntityId = refEntity == null ? Guid.Empty : refEntity.Id; } foreach (var prop in request.Parameters) { pluginContext.InputParameters[prop.Key] = prop.Value; } if (parentPluginContext != null) { pluginContext.ParentContext = parentPluginContext; pluginContext.Depth = parentPluginContext.Depth + 1; } var buRef = GetBusinessUnit(userRef); pluginContext.BusinessUnitId = buRef.Id; Mappings.RequestToEventOperation.TryGetValue(request.GetType(), out string eventOp); if (string.IsNullOrEmpty(eventOp)) { //then this may be a custom action request, so continue with the request name if (request.RequestName.Contains("_")) //if we have a prefix then assume it is a custom action { eventOp = request.RequestName.ToLower(); } } var entityInfo = GetEntityInfo(request); var settings = MockupExecutionContext.GetSettings(request); // Validation if (!settings.SetUnsettableFields && (request is UpdateRequest || request is CreateRequest)) { var entity = request is UpdateRequest ? (request as UpdateRequest).Target : (request as CreateRequest).Target; Utility.RemoveUnsettableAttributes(request.RequestName, metadata.EntityMetadata.GetMetadata(entity.LogicalName), entity); } Entity preImage = null; Entity postImage = null; if (settings.TriggerProcesses && entityInfo != null) { preImage = TryRetrieve(primaryRef); if (preImage != null) { primaryRef.Id = preImage.Id; } } if (settings.TriggerProcesses && entityInfo != null && !string.IsNullOrEmpty(eventOp)) { // System Pre-validation pluginManager.TriggerSystem(eventOp, ExecutionStage.PreValidation, entityInfo.Item1, preImage, postImage, pluginContext, this); // Pre-validation pluginManager.Trigger(eventOp, ExecutionStage.PreValidation, entityInfo.Item1, preImage, postImage, pluginContext, this); // Shared variables should be moved to parent context when transitioning from 10 to 20. pluginContext.ParentContext = pluginContext.Clone(); pluginContext.SharedVariables.Clear(); // Pre-operation pluginManager.Trigger(eventOp, ExecutionStage.PreOperation, entityInfo.Item1, preImage, postImage, pluginContext, this); workflowManager.TriggerSync(eventOp, ExecutionStage.PreOperation, entityInfo.Item1, preImage, postImage, pluginContext, this); // System Pre-operation pluginManager.TriggerSystem(eventOp, ExecutionStage.PreOperation, entityInfo.Item1, preImage, postImage, pluginContext, this); } // Core operation OrganizationResponse response = ExecuteRequest(request, userRef, parentPluginContext); // Post-operation if (settings.TriggerProcesses && entityInfo != null) { postImage = TryRetrieve(primaryRef); // In RetrieveMultipleRequests, the OutputParameters bag contains the entity collection if (request is RetrieveMultipleRequest) { pluginContext.OutputParameters["BusinessEntityCollection"] = (response as RetrieveMultipleResponse)?.EntityCollection; } if (!string.IsNullOrEmpty(eventOp)) { //copy the createon etc system attributes onto the target so they are available for postoperation processing CopySystemAttributes(postImage, entityInfo.Item1 as Entity); pluginManager.TriggerSystem(eventOp, ExecutionStage.PostOperation, entityInfo.Item1, preImage, postImage, pluginContext, this); pluginManager.TriggerSync(eventOp, ExecutionStage.PostOperation, entityInfo.Item1, preImage, postImage, pluginContext, this); pluginManager.StageAsync(eventOp, ExecutionStage.PostOperation, entityInfo.Item1, preImage, postImage, pluginContext, this); workflowManager.TriggerSync(eventOp, ExecutionStage.PostOperation, entityInfo.Item1, preImage, postImage, pluginContext, this); workflowManager.StageAsync(eventOp, ExecutionStage.PostOperation, entityInfo.Item1, preImage, postImage, pluginContext, this); } //When last Sync has been executed we trigger the Async jobs. if (parentPluginContext == null) { pluginManager.TriggerAsyncWaitingJobs(); workflowManager.TriggerAsync(this); } workflowManager.ExecuteWaitingWorkflows(pluginContext, this); } return(response); }
internal OrganizationResponse Execute(OrganizationRequest request, EntityReference userRef, PluginContext parentPluginContext) { // Setup HandleInternalPreOperations(request, userRef); var primaryRef = Mappings.GetPrimaryEntityReferenceFromRequest(request); // Create the plugin context var pluginContext = new PluginContext() { UserId = userRef.Id, InitiatingUserId = userRef.Id, MessageName = RequestNameToMessageName(request.RequestName), Depth = 1, ExtensionDepth = 1, OrganizationName = this.OrganizationName, OrganizationId = this.OrganizationId, PrimaryEntityName = primaryRef?.LogicalName, }; if (primaryRef != null) { var refEntity = db.GetEntityOrNull(primaryRef); pluginContext.PrimaryEntityId = refEntity == null ? Guid.Empty : refEntity.Id; } foreach (var prop in request.Parameters) { pluginContext.InputParameters[prop.Key] = prop.Value; } if (parentPluginContext != null) { pluginContext.ParentContext = parentPluginContext; pluginContext.Depth = parentPluginContext.Depth + 1; pluginContext.ExtensionDepth = parentPluginContext.ExtensionDepth + 1; parentPluginContext.ExtensionDepth = pluginContext.ExtensionDepth; } var buRef = GetBusinessUnit(userRef); pluginContext.BusinessUnitId = buRef.Id; Mappings.RequestToEventOperation.TryGetValue(request.GetType(), out string eventOp); var entityInfo = GetEntityInfo(request); var settings = MockupExecutionContext.GetSettings(request); // Validation if (!settings.SetUnsettableFields && (request is UpdateRequest || request is CreateRequest)) { var entity = request is UpdateRequest ? (request as UpdateRequest).Target : (request as CreateRequest).Target; Utility.RemoveUnsettableAttributes(request.RequestName, metadata.EntityMetadata.GetMetadata(entity.LogicalName), entity); } Entity preImage = null; Entity postImage = null; if (settings.TriggerProcesses && entityInfo != null) { preImage = TryRetrieve(primaryRef); if (preImage != null) { primaryRef.Id = preImage.Id; } } if (settings.TriggerProcesses && entityInfo != null) { // System Pre-validation pluginManager.TriggerSystem(eventOp, ExecutionStage.PreValidation, entityInfo.Item1, preImage, postImage, pluginContext, this); // Pre-validation pluginManager.Trigger(eventOp, ExecutionStage.PreValidation, entityInfo.Item1, preImage, postImage, pluginContext, this); } //perform security checks for the request CheckRequestSecurity(request, userRef); if (settings.TriggerProcesses && entityInfo != null) { // Shared variables should be moved to parent context when transitioning from 10 to 20. pluginContext.ParentContext = pluginContext.Clone(); pluginContext.SharedVariables.Clear(); // Pre-operation pluginManager.Trigger(eventOp, ExecutionStage.PreOperation, entityInfo.Item1, preImage, postImage, pluginContext, this); workflowManager.TriggerSync(eventOp, ExecutionStage.PreOperation, entityInfo.Item1, preImage, postImage, pluginContext, this); // System Pre-operation pluginManager.TriggerSystem(eventOp, ExecutionStage.PreOperation, entityInfo.Item1, preImage, postImage, pluginContext, this); } // Core operation OrganizationResponse response = ExecuteRequest(request, userRef, parentPluginContext); // Post-operation if (settings.TriggerProcesses && entityInfo != null) { postImage = TryRetrieve(primaryRef); // In RetrieveMultipleRequests, the OutputParameters bag contains the entity collection if (request is RetrieveMultipleRequest) { pluginContext.OutputParameters["BusinessEntityCollection"] = (response as RetrieveMultipleResponse)?.EntityCollection; } if (!string.IsNullOrEmpty(eventOp)) { //copy the createon etc system attributes onto the target so they are available for postoperation processing CopySystemAttributes(postImage, entityInfo.Item1 as Entity); pluginManager.TriggerSystem(eventOp, ExecutionStage.PostOperation, entityInfo.Item1, preImage, postImage, pluginContext, this); pluginManager.TriggerSync(eventOp, ExecutionStage.PostOperation, entityInfo.Item1, preImage, postImage, pluginContext, this); pluginManager.StageAsync(eventOp, ExecutionStage.PostOperation, entityInfo.Item1, preImage, postImage, pluginContext, this); workflowManager.TriggerSync(eventOp, ExecutionStage.PostOperation, entityInfo.Item1, preImage, postImage, pluginContext, this); workflowManager.StageAsync(eventOp, ExecutionStage.PostOperation, entityInfo.Item1, preImage, postImage, pluginContext, this); } //When last Sync has been executed we trigger the Async jobs. if (parentPluginContext == null) { pluginManager.TriggerAsyncWaitingJobs(); workflowManager.TriggerAsync(this); } workflowManager.ExecuteWaitingWorkflows(pluginContext, this); } #if XRM_MOCKUP_365 // Trigger Extension if (this.settings.MockUpExtensions.Any()) { /* * When moving business units, more than eight layers occur... */ if (pluginContext.ExtensionDepth > 8) { throw new FaultException( "This workflow job was canceled because the workflow that started it included an infinite loop." + " Correct the workflow logic and try again."); } } switch (request.RequestName) { case "Create": var createResponse = (CreateResponse)response; var entityLogicalName = ((Entity)request.Parameters["Target"]).LogicalName; var createdEntity = GetDbRow(new EntityReference(entityLogicalName, createResponse.id)) .ToEntity(); TriggerExtension( new XrmExtension(this, userRef, pluginContext), request, createdEntity, null, userRef); break; case "Update": var target = (Entity)request.Parameters["Target"]; var updatedEntity = GetDbRow(target.ToEntityReferenceWithKeyAttributes()).ToEntity(); TriggerExtension( new XrmExtension(this, userRef, pluginContext), request, updatedEntity, preImage, userRef); break; case "Delete": TriggerExtension( new XrmExtension(this, userRef, pluginContext), request, null, preImage, userRef); break; } #endif return(response); }
private void ExecuteIfMatch(Entity workflow, EventOperation operation, ExecutionStage stage, object entityObject, Entity preImage, Entity postImage, PluginContext pluginContext, Core core) { // Check if it is supposed to execute. Returns preemptively, if it should not. if (workflow.LogicalName != "workflow") { return; } var entity = entityObject as Entity; var entityRef = entityObject as EntityReference; var guid = (entity != null) ? entity.Id : entityRef.Id; var logicalName = (entity != null) ? entity.LogicalName : entityRef.LogicalName; if (workflow.GetAttributeValue <string>("primaryentity") != "" && workflow.GetAttributeValue <string>("primaryentity") != logicalName) { return; } if (pluginContext.Depth > 8) { throw new FaultException( "This workflow job was canceled because the workflow that started it included an infinite loop." + " Correct the workflow logic and try again."); } var isCreate = operation == EventOperation.Create; var isUpdate = operation == EventOperation.Update; var isDelete = operation == EventOperation.Delete; if (!isCreate && !isUpdate && !isDelete) { return; } if (isCreate && (!workflow.GetAttributeValue <bool?>("triggeroncreate").HasValue || !workflow.GetAttributeValue <bool?>("triggeroncreate").Value)) { return; } if (isDelete && (!workflow.GetAttributeValue <bool?>("triggerondelete").HasValue || !workflow.GetAttributeValue <bool?>("triggerondelete").Value)) { return; } var triggerFields = new HashSet <string>(); if (workflow.GetAttributeValue <string>("triggeronupdateattributelist") != null) { foreach (var field in workflow.GetAttributeValue <string>("triggeronupdateattributelist").Split(',')) { triggerFields.Add(field); } } if (isUpdate && ( workflow.GetAttributeValue <string>("triggeronupdateattributelist") == null || workflow.GetAttributeValue <string>("triggeronupdateattributelist") == "" || !entity.Attributes.Any(a => workflow.GetAttributeValue <string>("triggeronupdateattributelist").Split(',').Any(f => a.Key == f)))) { return; } var thisStage = isCreate ? workflow.GetOptionSetValue <workflow_stage>("createstage") : (isDelete ? workflow.GetOptionSetValue <workflow_stage>("deletestage") : workflow.GetOptionSetValue <workflow_stage>("updatestage")); if (thisStage == null) { thisStage = workflow_stage.Postoperation; } if ((int)thisStage != (int)stage) { return; } // Create the plugin context var thisPluginContext = pluginContext.Clone(); thisPluginContext.Mode = ((int)workflow.GetOptionSetValue <Workflow_Mode>("mode") + 1) % 2; thisPluginContext.Stage = thisStage.HasValue ? (int)thisStage : (int)workflow_stage.Postoperation; thisPluginContext.PrimaryEntityId = guid; thisPluginContext.PrimaryEntityName = logicalName; var parsedWorkflow = ParseWorkflow(workflow); if (parsedWorkflow == null) { return; } WorkflowTree postExecution = null; if (thisStage == workflow_stage.Preoperation) { postExecution = ExecuteWorkflow(parsedWorkflow, preImage, thisPluginContext, core); } else { postExecution = ExecuteWorkflow(parsedWorkflow, postImage, thisPluginContext, core); } if (postExecution.Variables["Wait"] != null) { waitingWorkflows.Add(postExecution.Variables["Wait"] as WaitInfo); } }