Reputation: 13
I'm developing my first dataverse plugin. My issue is I get an error preventing the delete action from completing. Thus, I can't debug. Assuming there was an issue with the code, I added a "Switch" to turn the execution on or off for testing.
bool on = !true;
if (on == true)
{...
This should have effectively caused the plugin to do nothing. However, I still get an error on the client side. This behavior is aligned with the expected behavior of the InvalidPluginExecutionException Class. The docs (https://learn.microsoft.com/en-us/dotnet/api/microsoft.xrm.sdk.invalidpluginexecutionexception?view=dataverse-sdk-latest) state: "When thrown by a plug-in, the Microsoft Dataverse platform displays to the user the exception message in a dialog of the Web application.". Which is exactly what's happening.
So, I remove All the code from the plugin as such and
using System;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Query;
namespace Deleted_Metadata_Actions
{
public class PluginBasePreOp
{
}
}
Same behavior. Error when deleting and unable to delete the item. See error below.
So, what's going on?
I feel like I'm missing something simple. I need the delete action to complete so I can have a profile to debug. How can I have the plugin registered on pre validation and get the delete action to complete?
Additional details.
Entity: dataverse table 'phx_trainingtitles'
Registered step: PreValidation - Synchronous
Message: Delete
.NET Framework - 4.6.2
Full code:
using System;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Query;
namespace Deleted_Metadata_Actions
{
public class PluginBasePreOp : IPlugin
{
public void Execute(IServiceProvider serviceProvider)
{
// Get the execution context and service provider
IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
IOrganizationServiceFactory serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId);
// Create a "Switch" to turn Plugin on or off
// Add or remove negation operator to change plugin state
bool on = !true;
if (on == true)
{
try
{
if (context.MessageName.ToLower() == "delete")
{
if (context.Stage == 10) // PreValidation (Synchronous)
{
if (context.PreEntityImages.Contains("PreEntityImage"))
{
Entity preImage = context.PreEntityImages["PreEntityImage"];
if (preImage.Contains("phx_jobtitle"))
{
string deletedJobTitle = preImage["phx_jobtitle"].ToString();
context.SharedVariables["DeletedJobTitle"] = deletedJobTitle; // Store in shared variable
// Log the deletion event in PreValidation
LogChangePreVal(service, context, deletedJobTitle);
}
else
{
throw new InvalidPluginExecutionException("Missing 'phx_jobtitle' in PreEntityImage.");
}
}
else
{
throw new InvalidPluginExecutionException("PreEntityImage is missing.");
}
}
else if (context.Stage == 40) // PostValidation (Asynchronous)
{
if (context.SharedVariables.Contains("DeletedJobTitle"))
{
string deletedJobTitle = context.SharedVariables["DeletedJobTitle"].ToString();
// Query to find related training users with the deleted job title
QueryExpression query = new QueryExpression("phx_trainingusers")
{
ColumnSet = new ColumnSet("phx_traininguserid", "phx_jobtitles") // Retrieve details for logging
};
query.Criteria.AddCondition("phx_jobtitles", ConditionOperator.Equal, deletedJobTitle);
// Execute the query
EntityCollection relatedUsers = service.RetrieveMultiple(query);
// Log deletion event before actual deletion
LogChangePostVal(service, context, deletedJobTitle);
// Delete each related record
foreach (var user in relatedUsers.Entities)
{
service.Delete("phx_trainingusers", user.Id);
}
}
else
{
throw new InvalidPluginExecutionException("Shared variable 'DeletedJobTitle' is missing.");
}
}
}
}
catch (Exception ex)
{
throw new InvalidPluginExecutionException($"An error occurred: {ex.Message}", ex);
}
}
else
{
// On is false: Do nothing
}
}
private void LogChangePreVal(IOrganizationService service, IPluginExecutionContext context, string deletedJobTitle)
{
Entity logEntry = new Entity("phx_changemanagement");
logEntry["phx_changetype"] = context.MessageName; // Message type (e.g., "Delete")
logEntry["phx_initiatedby"] = new EntityReference("systemuser", context.UserId); // User who initiated deletion
logEntry["phx_itemname"] = deletedJobTitle; // The job title being deleted
service.Create(logEntry); // Save log entry
}
private void LogChangePostVal(IOrganizationService service, IPluginExecutionContext context, string deletedJobTitle)
{
Entity logEntry = new Entity("phx_changemanagement");
logEntry["phx_changetype"] = "Plugin_" + context.MessageName; // Plugin-specific logging
logEntry["phx_initiatedby"] = nameof(PluginBasePreOp); // Plugin class name
logEntry["phx_itemname"] = deletedJobTitle; // The deleted job title
service.Create(logEntry); // Save log entry
}
}
}
Upvotes: 0
Views: 17