Skip to main content

AssociateEntitiesPostOperationUpdate

Utilities

Code

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

namespace PracticeGateway.Plugin
{
/// <summary>
/// Plugin that executes after an Associate operation to automatically assign web roles to contacts
/// when they are associated with assignments. The web role assignments are determined by a
/// configuration stored in the tt_configuration entity.
///
/// Registered on: Associate message, Post-operation
/// Target Entity: Contact and tt_assignment relationship (tt_Contact_tt_Assignment)
/// </summary>
public class AssociateEntitiesPostOperationUpdate : PluginBase
{
public AssociateEntitiesPostOperationUpdate(string unsecure, string secure)
: base(typeof(AssociateEntitiesPostOperationUpdate))
{
}

/// <summary>
/// Main plugin execution method
/// </summary>
/// <param name="localContext">The local plugin execution context</param>
protected override void ExecuteCdsPlugin(ILocalPluginContext localContext)
{
if (localContext == null)
throw new InvalidPluginExecutionException(nameof(localContext));

// Initialize core services
ITracingService tracingService = localContext.TracingService;
IPluginExecutionContext context = localContext.PluginExecutionContext;
IOrganizationService currentUserService = localContext.CurrentUserService;

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

// Ensure plugin is triggered by the correct message
if (context.MessageName != "Associate")
throw new InvalidPluginExecutionException($"Unexpected message: {context.MessageName}");

// Instantiate utility class with shared services
Utils.Utils utils = new Utils.Utils(currentUserService, tracingService);

// Validate the relationship and extract contact and assignment references
if (!utils.ValidateContactAssignmentRelationship(context, tracingService, out EntityReference contact, out EntityReference assignment))
{
return; // Exit if validation fails (utility handles tracing)
}

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

// Retrieve the assignment record to get its name
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 assignment-to-web-role configuration from tt_configuration
var assignmentConfig = utils.GetAssignmentConfiguration(currentUserService, tracingService);
if (assignmentConfig == null)
{
return; // Exit if configuration is missing or invalid
}

// Retrieve the list of web roles associated with 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}'.");

// Loop through each web role and associate it with the contact if not already linked
foreach (var webRoleName in webRoles)
{
// Retrieve the web role entity by name
Entity webRole = utils.GetWebRoleByName(currentUserService, webRoleName);

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

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

// Associate the contact with 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 and rethrow any unexpected errors
tracingService.Trace($"Error in AssociateEntitiesPostOperationUpdate: {ex}");
throw new InvalidPluginExecutionException("Plugin execution failed.", ex);
}
}
}
}