protected override void Initialize(IServiceProvider provider) { SequentialWorkflow containingSequentialWorkflow = null; SequentialWorkflow.TryGetContainingWorkflow(this, out containingSequentialWorkflow); //using (ServiceSecurityContext.Current.WindowsIdentity.Impersonate()) //{ // using (DefaultClient client = new DefaultClient()) // { // client.RefreshSchema(); // Guid targetUser; // if (containingSequentialWorkflow.ActorId == CellOTPGate.AnonymousID) // { targetUser = containingSequentialWorkflow.TargetId; } // else // { targetUser = containingSequentialWorkflow.ActorId; } // RmPerson person = client.Get(new Microsoft.ResourceManagement.ObjectModel.RmReference(targetUser.ToString())) as RmPerson; // userCellPhone = person.MobilePhone; // } //} base.Initialize(provider); }
/// <summary> /// Copy the FIM WorkflowData items to a Dictionary /// </summary> /// <param name="variablesInputString">the String containing the WorkflowData item name(s)</param> /// <returns>a Dictionary containing WorkflowData.Name WorkflowData.Value</returns> private Dictionary <String, Object> PowerShellSessionVariables(String variablesInputString) { Dictionary <String, Object> powerShellSessionVariables = new Dictionary <String, Object>(); // In order to read the Workflow Dictionary we need to get the containing (parent) workflow SequentialWorkflow containingWorkflow = null; if (!SequentialWorkflow.TryGetContainingWorkflow(this, out containingWorkflow)) { throw new InvalidOperationException("Unable to get Containing Workflow"); } String logOutput = "Containing Workflow Dictionary (WorkflowData):"; foreach (String workflowDataName in variablesInputString.Split(new Char[] { ' ', ',', '.', ':', ';' })) { try { String workflowDataValue = containingWorkflow.WorkflowDictionary[workflowDataName].ToString(); powerShellSessionVariables.Add(workflowDataName, workflowDataValue); logOutput += String.Format("\n\t{0}: {1}", workflowDataName, workflowDataValue); } catch (KeyNotFoundException keyNotFoundException) { trace.TraceFatal("Required item missing from FIM Workflow Data.\n", keyNotFoundException.StackTrace); throw new KeyNotFoundException("Required item missing from FIM Workflow Data.", keyNotFoundException.InnerException); } } trace.TraceVerbose(logOutput); return(powerShellSessionVariables); }
protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext) { SequentialWorkflow containingSequentialWorkflow = null; SequentialWorkflow.TryGetContainingWorkflow(this, out containingSequentialWorkflow); this.readResourceActivity1.ActorId = new Guid("e05d1f1b-3d5e-4014-baa6-94dee7d68c89"); this.readResourceActivity1.ResourceId = containingSequentialWorkflow.TargetId; return(base.Execute(executionContext)); }
/// <summary> /// Handles the ExecuteCode event of the PrepareDelete CodeActivity. /// </summary> /// <param name="sender">The source of the event.</param> /// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param> private void PrepareDelete_ExecuteCode(object sender, EventArgs e) { Logger.Instance.WriteMethodEntry(EventIdentifier.DeleteResourcesPrepareDeleteExecuteCode, "TargetType: '{0}'.", this.TargetType); try { // Determine the resources to be deleted based on the target type switch (this.TargetType) { case DeleteResourcesTargetType.WorkflowTarget: // If the activity is configured to delete the workflow target, // load the target from the parent workflow SequentialWorkflow parentWorkflow; if (SequentialWorkflow.TryGetContainingWorkflow(this, out parentWorkflow)) { this.Targets.Add(parentWorkflow.TargetId); } break; case DeleteResourcesTargetType.SearchForTarget: // If the activity is configured to search for the target(s), // the targets should be the bound results of the find resources activity break; case DeleteResourcesTargetType.ResolveTarget: // If the activity is configured to resolve target(s), // verify that the supplied lookup resolved to a Guid or List<Guid> and assign the resolved // values as targets if (this.Resolve.Lookups.ContainsKey(this.TargetExpression) && this.Resolve.Lookups[this.TargetExpression] != null) { if (this.Resolve.Lookups[this.TargetExpression] is Guid) { this.Targets.Add((Guid)this.Resolve.Lookups[this.TargetExpression]); } else if (this.Resolve.Lookups[this.TargetExpression].GetType() == typeof(List <Guid>)) { this.Targets = (List <Guid>) this.Resolve.Lookups[this.TargetExpression]; } } break; } } finally { Logger.Instance.WriteMethodExit(EventIdentifier.DeleteResourcesPrepareDeleteExecuteCode, "TargetType: '{0}'. Target Count: {1}.", this.TargetType, this.Targets.Count); } }
/// <summary> /// Executes the activity. /// </summary> /// <param name="executionContext">The execution context.</param> /// <returns>The <see cref="ActivityExecutionStatus"/> object.</returns> protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext) { Logger.Instance.WriteMethodEntry(EventIdentifier.AsyncUpdateResourceExecute); try { // Ideally we would set CallContext in OnActivityExecutionContextLoad instead here in Execute // as OnActivityExecutionContextLoad gets called on each hydration and rehydration of the workflow instance // but looks like it's invoked on a different thread context than the rest of the workflow instance execution. // To minimize the loss of the CallContext on rehydration, we'll set it in the Execute of every WAL child activities. // It will still get lost (momentarily) when the workflow is persisted in the middle of the execution of a replicator activity, for example. Logger.SetContextItem(this, this.WorkflowInstanceId); SequentialWorkflow parentWorkflow; if (!SequentialWorkflow.TryGetContainingWorkflow(this, out parentWorkflow)) { throw Logger.Instance.ReportError(new InvalidOperationException(Messages.UnableToGetParentWorkflowError)); } // Create the workflow program queue so we can facilitate asynchronous // submission of requests WorkflowQueue queue = CreateWorkflowProgramQueue(this.queuingService, this); object[] args = new object[] { this.ActorId, this.ResourceId, this.UpdateParameters, parentWorkflow.RequestId, this.ApplyAuthorizationPolicy, 0, queue.QueueName }; Logger.Instance.WriteVerbose(EventIdentifier.AsyncUpdateResourceExecute, "Invoking DataAccessService.Update() for ActorId: '{0}', ResourceId: '{1}', ParentRequestId: '{3}' ApplyAuthorizationPolicy: '{4}' and QueueName: '{6}'.", args); // Submit the request via reflection and cleanup the queue // Added the AuthorizationTimeOut value of 0, which is "Fire and Forget" this.dataAccessServiceType.InvokeMember( "Update", BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Instance, null, this.dataAccessService, args, CultureInfo.InvariantCulture); DeleteWorkflowProgramQueue(this.queuingService, queue); return(base.Execute(executionContext)); } catch (Exception ex) { throw Logger.Instance.ReportError(EventIdentifier.AsyncUpdateResourceExecuteError, ex); } finally { Logger.Instance.WriteMethodExit(EventIdentifier.AsyncUpdateResourceExecute); } }
public static void SetContextItem(Activity activity, Guid workflowInstanceId) { Logger.SetContextItem("WorkflowInstanceId", workflowInstanceId); SequentialWorkflow parentWorkflow; if (!SequentialWorkflow.TryGetContainingWorkflow(activity, out parentWorkflow)) { return; } Logger.SetContextItem("RequestId", parentWorkflow.RequestId); Logger.SetContextItem("ActorId", parentWorkflow.ActorId); Logger.SetContextItem("TargetId", parentWorkflow.TargetId); Logger.SetContextItem("WorkflowDefinitionId", parentWorkflow.WorkflowDefinitionId); }
private void InitializeUpdate_ExecuteCode(object sender, EventArgs e) { if (readResourceActivity1.Resource["labSource"].ToString() == "INTERNAL") { if (countUpn <= 1) { displayName = firstName + " " + lastName; } else { displayName = firstName + " " + lastName + countUpn.ToString(); } } else { if (countUpn <= 1) { displayName = firstName + " " + lastName + ",EX"; } else { displayName = firstName + " " + lastName + countUpn.ToString() + ",EX"; } } //Get containing Workflow SequentialWorkflow containingWorkflow = null; if (!SequentialWorkflow.TryGetContainingWorkflow(this, out containingWorkflow)) { throw new InvalidOperationException("Could not get parent workflow!"); } string displayNameSuffix = ReadWorkFlowParameters(UpnSuffix, containingWorkflow); displayName += displayNameSuffix; updateResourceActivity1_ActorId1 = requestorGUID; updateResourceActivity1_ResourceId1 = targetGUID; updateResourceActivity1.UpdateParameters = new UpdateRequestParameter[] { new UpdateRequestParameter("AccountName", UpdateMode.Modify, samAccountName), new UpdateRequestParameter("DisplayName", UpdateMode.Modify, displayName), new UpdateRequestParameter("labUpn", UpdateMode.Modify, upn) }; }
private void InitiliazeReadSubject_ExecuteCode(object sender, EventArgs e) { RequestType currentRequest = this.ReadCurrentRequestActivity.CurrentRequest; ReadOnlyCollection <CreateRequestParameter> requestParameters = currentRequest.ParseParameters <CreateRequestParameter>(); SequentialWorkflow containingWorkflow = null; if (!SequentialWorkflow.TryGetContainingWorkflow(this, out containingWorkflow)) { throw new InvalidOperationException("Unable to get Containing Workflow"); } this.readResourceActivity1_ActorId1 = FIMADMGUID; this.readResourceActivity1_ResourceId1 = containingWorkflow.TargetId; requestorGUID = containingWorkflow.ActorId; targetGUID = containingWorkflow.TargetId; }
private void initializeReadCostCenter_ExecuteCode(object sender, EventArgs e) { RequestType currentRequest = this.ReadCurrentRequest.CurrentRequest; ReadOnlyCollection <CreateRequestParameter> requestParameters = currentRequest.ParseParameters <CreateRequestParameter>(); // Retrieve current workflow SequentialWorkflow workflow = null; if (!SequentialWorkflow.TryGetContainingWorkflow(this, out workflow)) { throw new InvalidOperationException(); } // Save information _requestor = workflow.ActorId; _target = workflow.TargetId; // Init ReadUser activity this.ReadCostCenter_ActorId1 = FIMADMGUID; this.ReadCostCenter_ResourceId1 = _target; }
/// <summary> /// Handles the ExecuteCode event of the Prepare CodeActivity. /// </summary> /// <param name="sender">The source of the event.</param> /// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param> private void Prepare_ExecuteCode(object sender, EventArgs e) { Logger.Instance.WriteMethodEntry(EventIdentifier.FindResourcesPrepareExecuteCode); try { // Prepare the output lists this.FoundResources = new List <ResourceType>(); this.FoundIds = new List <Guid>(); // Retrieve the target resource for the workflow SequentialWorkflow parentWorkflow; if (SequentialWorkflow.TryGetContainingWorkflow(this, out parentWorkflow)) { this.workflowTarget = parentWorkflow.TargetId; } // Throw an exception if the XPath filter was not supplied for the activity if (string.IsNullOrEmpty(this.XPathFilter)) { throw Logger.Instance.ReportError(EventIdentifier.FindResourcesPrepareExecuteCodeMissingXPathError, new InvalidOperationException(Messages.FindResources_MissingXPathError)); } // Configure the selection attributes for the Enumerate Resources activity // If attributes were not supplied for the activity, default to just the ObjectID to reduce the overhead // associated with retrieving all attributes for enumerated resources if (this.Attributes != null && this.Attributes.Length > 0) { this.Find.Selection = this.Attributes; } else { this.Find.Selection = new string[] { "ObjectID" }; } } finally { Logger.Instance.WriteMethodExit(EventIdentifier.FindResourcesPrepareExecuteCode, "XPathFilter to Resolve: '{0}'. Attributes to Read: '{1}'.", this.XPathFilter, string.Join(",", this.Find.Selection)); } }
protected override void InitializeAuthenticationGate(IServiceProvider provider) { sentSMS = false; // When the activity is first loaded, we're going to try to retrieve the user info from the registration data if (this.AuthenticationGateActivity.RegistrationData == null || string.IsNullOrEmpty(this.userCellPhone = UnicodeEncoding.Unicode.GetString(this.AuthenticationGateActivity.RegistrationData))) { //Looks like our cell phone data was not stored in registration data //Default to FIM store using (ServiceSecurityContext.Current.WindowsIdentity.Impersonate()) { using (DefaultClient client = new DefaultClient()) { client.RefreshSchema(); SequentialWorkflow containingSequentialWorkflow = null; SequentialWorkflow.TryGetContainingWorkflow(this.AuthenticationGateActivity, out containingSequentialWorkflow); Guid targetUser; if (containingSequentialWorkflow.ActorId == CellOTPGate.AnonymousID) { targetUser = containingSequentialWorkflow.TargetId; } else { targetUser = containingSequentialWorkflow.ActorId; } RmPerson person = client.Get(new Microsoft.ResourceManagement.ObjectModel.RmReference(targetUser.ToString())) as RmPerson; this.userCellPhone = person.MobilePhone; } } } base.InitializeAuthenticationGate(provider); }
private void Decide_ExecuteCode(object sender, EventArgs e) { Logger.Instance.WriteMethodEntry(EventIdentifier.DetermineActorDecideExecuteCode, "ActorType: '{0}'.", this.ActorType); try { switch (this.ActorType) { case ActorType.Service: this.Actor = WellKnownGuids.FIMServiceAccount; break; case ActorType.Requestor: SequentialWorkflow parentWorkflow; SequentialWorkflow.TryGetContainingWorkflow(this, out parentWorkflow); this.Actor = parentWorkflow.ActorId; break; case ActorType.Resolve: object resolved = this.ActivityExpressionEvaluator.ResolveExpression(this.ActorString); if (resolved is Guid) { this.Actor = (Guid)resolved; } else if (resolved == null) { throw Logger.Instance.ReportError(new WorkflowActivityLibraryException(Messages.DetermineActor_NullResolvedActorError)); } else if (resolved.GetType().IsGenericType&& resolved.GetType().GetGenericTypeDefinition() == typeof(List <>)) { throw Logger.Instance.ReportError(new WorkflowActivityLibraryException(Messages.DetermineActor_MultipleResolvedActorsError)); } else if (resolved is string && !string.IsNullOrEmpty(resolved as string)) { try { this.Actor = new Guid(resolved as string); } catch (Exception ex) { throw Logger.Instance.ReportError(new WorkflowActivityLibraryException(Messages.DetermineActor_InvalidActorGuidFormatError, ex)); } } else { throw Logger.Instance.ReportError(new WorkflowActivityLibraryException(Messages.DetermineActor_UnresolvedActorError)); } break; case ActorType.Account: switch (this.Query.FoundIds.Count) { case 1: this.Actor = this.Query.FoundIds[0]; break; case 0: throw Logger.Instance.ReportError(EventIdentifier.DetermineActorDecideExecuteCodeNotFoundActorAccountError, new WorkflowActivityLibraryException(Messages.DetermineActor_NotFoundActorAccountError)); default: throw Logger.Instance.ReportError(EventIdentifier.DetermineActorDecideExecuteCodeMultipleActorAccountsError, new WorkflowActivityLibraryException(Messages.DetermineActor_MultipleActorAccountsError)); } break; } } finally { Logger.Instance.WriteMethodExit(EventIdentifier.DetermineActorDecideExecuteCode, "ActorType: '{0}'. Actor: '{1}'. ", this.ActorType, this.Actor); } }
/// <summary> /// Runs the PowerShell Script using: /// - FIM WorkflowData items as PowerShell variables /// - the specified PowerShell module (if specified in the WF) /// - stores the script output in a new FIM WorkflowData item (if specified in the WF) /// </summary> private void RunScript() { trace.TraceStart("START PowerShellActivity RunScript"); /// /// Translate the WorkflowData items to PowerShell variables /// InitialSessionState initialSessionState = InitialSessionState.CreateDefault(); String logDetailForPowerShellVariables = string.Empty; if (!String.IsNullOrEmpty(this.PowerShellVariables)) { logDetailForPowerShellVariables = "### PowerShell Variables from FIM WorkflowData"; foreach (KeyValuePair <String, Object> sessionVariable in this.PowerShellSessionVariables(PowerShellVariables)) { trace.TraceVerbose("Adding PowerShell Session Variable:\n{0} : {1}", sessionVariable.Key, sessionVariable.Value); initialSessionState.Variables.Add(new SessionStateVariableEntry(sessionVariable.Key, sessionVariable.Value, null)); logDetailForPowerShellVariables += String.Format("\n${0} = '{1}'", sessionVariable.Key, sessionVariable.Value); } } /// /// Load the PowerShell Module if specified by the WF /// if (!String.IsNullOrEmpty(this.PowerShellModule)) { trace.TraceInformation("Loading PowerShell Module: {0}", this.PowerShellModule); initialSessionState.ImportPSModule(new String[] { PowerShellModule }); } // Call the RunspaceFactory.CreateRunspace(InitialSessionState) // method to create the runspace where the pipeline is run. Runspace runspace = RunspaceFactory.CreateRunspace(initialSessionState); runspace.Open(); using (PowerShell powershell = PowerShell.Create()) { powershell.Runspace = runspace; powershell.AddScript(Script); powershell.AddParameter("Verbose"); // Invoke the PowerShell Pipeline synchronously trace.TraceInformation("### Invoking Pipeline\n{0}\n\n###PowerShell Script from WF\n{1}", logDetailForPowerShellVariables, Script); try { Collection <PSObject> results = powershell.Invoke(); // Display the results. trace.TraceVerbose("{0} results returned.", results.Count); foreach (PSObject result in results) { String psObjectDetail = result.ToString(); //foreach (PSMemberInfo member in result.Members) //{ // psObjectDetail += String.Format("\n\t{0}:{1}", member.Name, member.Value); //} foreach (PSMemberInfo member in result.Properties) { psObjectDetail += String.Format("\n\t{0}:{1}", member.Name, member.Value); } trace.TraceVerbose(psObjectDetail); } // Throw on any non-terminating errors. foreach (ErrorRecord error in powershell.Streams.Error) { trace.TraceWarning("PowerShell Error: {0}", error); String errorText = String.Format("PowerShell activity failed with the following error: \n{0}", error.ToString()); throw new Microsoft.ResourceManagement.Workflow.WorkflowExtensionException("PowerShell Activity", errorText); } /// /// Copy the PowerShell output to the FIM WorkflowData dictionary /// if (results.Count == 1 & !String.IsNullOrEmpty(this.WorkflowDataNameForOutput)) { trace.TraceVerbose("Storing the PowerShell output in FIM WorkflowData item named: {0}", this.WorkflowDataNameForOutput); // In order to add our PowerShell result to the FIM Workflow Dictionary we need to get the containing (parent) workflow SequentialWorkflow containingWorkflow = null; if (!SequentialWorkflow.TryGetContainingWorkflow(this, out containingWorkflow)) { trace.TraceError("Unable to get Containing Workflow."); throw new InvalidOperationException("Unable to get Containing Workflow"); } containingWorkflow.WorkflowDictionary[this.WorkflowDataNameForOutput] = results[0].ToString(); } } catch (RuntimeException ex) { trace.TraceError("PowerShell Error: {0}", ex.Message); throw; } finally { // Throw on any non-terminating errors. String verboseOutput = "PowerShell Verbose Output:\n"; foreach (VerboseRecord verboseRecord in powershell.Streams.Verbose) { verboseOutput += verboseRecord.ToString(); } trace.TraceVerbose(verboseOutput); } } trace.TraceStop("STOP PowerShellActivity RunScript"); }
/// <summary> /// Handles the ExecuteCode event of the BuildRequests CodeActivity. /// </summary> /// <param name="sender">The source of the event.</param> /// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param> private void BuildRequests_ExecuteCode(object sender, EventArgs e) { Logger.Instance.WriteMethodEntry(EventIdentifier.UpdateLookupsBuildRequestsExecuteCode); try { foreach (UpdateLookupDefinition update in this.UpdateLookupDefinitions) { LookupEvaluator lookup = new LookupEvaluator(update.TargetLookup); if (lookup.TargetIsWorkflowDictionary) { // Get the parent workflow to facilitate access to the workflow dictionary SequentialWorkflow parentWorkflow; SequentialWorkflow.TryGetContainingWorkflow(this, out parentWorkflow); // For simplicity, start by adding the key to the parent workflow dictionary so we can assume that its there if (!parentWorkflow.WorkflowDictionary.ContainsKey(lookup.TargetAttribute)) { parentWorkflow.WorkflowDictionary.Add(lookup.TargetAttribute, null); } if (update.Mode == UpdateMode.Modify) { parentWorkflow.WorkflowDictionary[lookup.TargetAttribute] = update.Value; } else if (update.Value != null) { // Use reflection to determine the expected List<> type based on the value // Also get the Add and Remove methods for the list Type listType = typeof(List <>).MakeGenericType(new Type[] { update.Value.GetType() }); MethodInfo add = listType.GetMethod("Add"); MethodInfo remove = listType.GetMethod("Remove"); switch (update.Mode) { case UpdateMode.Insert: if (parentWorkflow.WorkflowDictionary[lookup.TargetAttribute] == null) { parentWorkflow.WorkflowDictionary[lookup.TargetAttribute] = update.Value; } else if (parentWorkflow.WorkflowDictionary[lookup.TargetAttribute].GetType() == update.Value.GetType()) { // Single value, create a new instance of the appropriate List<> type // and add both values: existing and new object existingValue = parentWorkflow.WorkflowDictionary[lookup.TargetAttribute]; parentWorkflow.WorkflowDictionary[lookup.TargetAttribute] = Activator.CreateInstance(listType); add.Invoke(parentWorkflow.WorkflowDictionary[lookup.TargetAttribute], new object[] { existingValue }); add.Invoke(parentWorkflow.WorkflowDictionary[lookup.TargetAttribute], new object[] { update.Value }); } else if (parentWorkflow.WorkflowDictionary[lookup.TargetAttribute].GetType() == listType) { // The dictionary key is a list of the expected type, add the value add.Invoke(parentWorkflow.WorkflowDictionary[lookup.TargetAttribute], new object[] { update.Value }); } else { // We have a problem and need to report an error throw Logger.Instance.ReportError(new WorkflowActivityLibraryException(Messages.UpdateLookup_InsertVariableError, update.Value.GetType(), lookup.TargetAttribute, parentWorkflow.WorkflowDictionary[lookup.TargetAttribute].GetType())); } break; case UpdateMode.Remove: if (parentWorkflow.WorkflowDictionary[lookup.TargetAttribute] == null) { // Do nothing } else if (parentWorkflow.WorkflowDictionary[lookup.TargetAttribute].Equals(update.Value)) { // A single matching value exists, clear the variable parentWorkflow.WorkflowDictionary[lookup.TargetAttribute] = null; } else if (parentWorkflow.WorkflowDictionary[lookup.TargetAttribute].GetType() == listType) { // The variable is a list of the expected type, attempt to remove the value remove.Invoke(parentWorkflow.WorkflowDictionary[lookup.TargetAttribute], new object[] { update.Value }); // Check the count on the list to determine if we are down to a single value or have no value // If so, adjust the value of the variable accordingly to eliminate the list object listValue = null; int i = 0; foreach (object o in (IEnumerable)parentWorkflow.WorkflowDictionary[lookup.TargetAttribute]) { i += 1; listValue = o; } if (i <= 1) { parentWorkflow.WorkflowDictionary[lookup.TargetAttribute] = listValue; } } break; } } // If we ended up with a null value in the workflow dictionary key, // remove the key to cleanup after ourselves if (parentWorkflow.WorkflowDictionary[lookup.TargetAttribute] == null) { parentWorkflow.WorkflowDictionary.Remove(lookup.TargetAttribute); } } else if (!string.IsNullOrEmpty(lookup.TargetResourceLookup) && this.TargetLookups.ContainsKey(lookup.TargetResourceLookup) && this.TargetLookups[lookup.TargetResourceLookup] != null) { // Based on the type of the resolved target lookup (should be Guid or List<Guid>) // build the list of target resources for the update List <Guid> targets = new List <Guid>(); if (this.TargetLookups[lookup.TargetResourceLookup] is Guid) { targets.Add((Guid)this.TargetLookups[lookup.TargetResourceLookup]); } else if (this.TargetLookups[lookup.TargetResourceLookup].GetType() == typeof(List <Guid>)) { targets.AddRange((List <Guid>) this.TargetLookups[lookup.TargetResourceLookup]); } foreach (Guid target in targets) { // Add the target to the update requests dictionary, if it doesn't already exist, // and add the new update request parameter if (!this.PendingRequests.ContainsKey(target)) { this.PendingRequests.Add(target, new List <UpdateRequestParameter>()); } this.PendingRequests[target].Add(new UpdateRequestParameter(lookup.TargetAttribute, update.Mode, update.Value)); } } } // If there are requests that need to be submitted to fulfill the updates, // assign the list of targets to the for each loop which will evaluate each change // to determine if they will result in changes if (this.PendingRequests.Count > 0) { this.ForEachPending.InitialChildData = this.PendingRequests.Keys.ToList(); } Logger.Instance.WriteVerbose(EventIdentifier.UpdateLookupsBuildRequestsExecuteCode, "The number of requests that need to be submitted to fulfill the updates: '{0}'.", this.PendingRequests.Count); } finally { Logger.Instance.WriteMethodExit(EventIdentifier.UpdateLookupsBuildRequestsExecuteCode); } }