Skip to main content

AssociateEntitiesPostOperationUpdate

This plugin runs after a Contact is associated with an Assignment. It automatically assigns the Contact to the appropriate Web Roles based on the Assignment.

Libraries

using System;
using System.Collections.Generic;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Query;
using Newtonsoft.Json;

Plugin

namespace PracticeGateway.Plugin
{
public class AssociateEntitiesPostOperationUpdate : PluginBase
{
public AssociateEntitiesPostOperationUpdate(string unsecure, string secure)
: base(typeof(AssociateEntitiesPostOperationUpdate))
{
}

protected override void ExecuteCdsPlugin(ILocalPluginContext localContext)
{
if (localContext == null)
throw new InvalidPluginExecutionException(nameof(localContext));

// Get the services we need to work with data and log messages
ITracingService tracingService = localContext.TracingService;
IPluginExecutionContext context = localContext.PluginExecutionContext;
IOrganizationService currentUserService = localContext.CurrentUserService;

try
{
tracingService.Trace("Starting AssociateEntitiesPostOperationUpdate");

// Make sure this plugin was triggered by an "Associate" action
if (context.MessageName != "Associate")
throw new InvalidPluginExecutionException($"Unexpected message: {context.MessageName}");

// Helper class for common operations
Utils.Utils utils = new Utils.Utils(currentUserService, tracingService);

// Get the Contact and Assignment that were just linked together
if (!utils.ValidateContactAssignmentRelationship(context, tracingService, out EntityReference contact, out EntityReference assignment))
{
return; // Stop if the relationship isn't what we expect
}

tracingService.Trace($"Contact {contact.Id} associated with Assignment {assignment.Id}");

// Get the Assignment's name (we need this to find the right web roles)
Entity assignmentEntity = currentUserService.Retrieve("tt_assignment", assignment.Id, new ColumnSet("tt_name"));
string assignmentName = assignmentEntity.GetAttributeValue<string>("tt_name");

tracingService.Trace($"Assignment Name: {assignmentName}");

// Load the configuration that maps Assignments to Web Roles
var assignmentConfig = utils.GetAssignmentConfiguration(currentUserService, tracingService);
if (assignmentConfig == null)
{
return; // Stop if configuration is missing
}

// Find which Web Roles should be assigned for this Assignment
List<string> webRoles = utils.GetWebRolesForAssignment(assignmentConfig, assignmentName, tracingService);

if (webRoles.Count == 0)
{
tracingService.Trace($"No web roles configured for assignment '{assignmentName}'.");
return;
}

tracingService.Trace($"Found {webRoles.Count} web roles to process for assignment '{assignmentName}'.");

// Add the Contact to each Web Role (if not already added)
foreach (var webRoleName in webRoles)
{
// Look up the Web Role record by name
Entity webRole = utils.GetWebRoleByName(currentUserService, webRoleName);

if (webRole == null)
{
tracingService.Trace($"Web Role '{webRoleName}' not found.");
continue;
}

// Check if Contact is already linked to this Web Role
if (utils.IsContactAssociatedWithWebRole(currentUserService, contact.Id, webRole.Id))
{
tracingService.Trace($"Contact already associated with Web Role '{webRoleName}', skipping.");
continue;
}

// Link the Contact to the Web Role
currentUserService.Associate(
"contact",
contact.Id,
new Relationship("adx_webrole_contact"),
new EntityReferenceCollection { new EntityReference("adx_webrole", webRole.Id) }
);

tracingService.Trace($"Successfully associated contact with Web Role '{webRoleName}'.");
}

tracingService.Trace("Finished AssociateEntitiesPostOperationUpdate");
}
catch (Exception ex)
{
// Log the error and stop the plugin
tracingService.Trace($"Error in AssociateEntitiesPostOperationUpdate: {ex}");
throw new InvalidPluginExecutionException("Plugin execution failed.", ex);
}
}
}
}