
Hello Everyone,
I have a requirement to restrict an Account from having multiple Service Offerings associated with it if those Service Offerings link to the same underlying Service Master record.
The custom C# plugin code is complete, compiles successfully, and is correctly deployed to the Dataverse environment. However, we are currently blocked at the final deployment step: registering the plugin step in the Plugin Registration Tool (PRT).
When attempting to register the step for the Associate message at the PreValidation stage, the official Microsoft PRT consistently rejects the configuration with the error: "Invalid Primary Entity or Secondary Entity specified. Please re-enter the data."
I have tried exchanging the primary and secondary entities but the tool doesn't take both of them as primary entity. The logical names are for sure correct.
Service Offering has a lookup column (Service Name) to Service Master table. Account and Service Offering has got Many-Many relationship

When registered without primary and secondary entity, I am able to achieve the primary task of restricting an account having multiple service offerings of same underlying Service Master record. But the association to fresh and New Account error out.
What exactly have to be checked here? I have ran out of options 😭

You cannot register an Associate or Disassociate step against a specific Primary or Secondary entity (like Account or Service Offering).
The Rule: The Associate message is global.
The PRT requires Primary Entity = none and Secondary Entity = none.
The Fix: Revert to the configuration where you left them as "none". That was actually the correct setup.
The Safety Mechanism: Since the plugin is global, you must ensure the very first line of your plugin filters by the relationship name to prevent it from firing on every association in the system.
// Inside your Execute method
var relationship = (Relationship)context.InputParameters["Relationship"];
if (relationship.SchemaName != "new_account_serviceoffering_relationship_name")
{
return; // Exit immediately if it's not your specific relationship
}
The error you are facing when associating to a new Account (one that has no existing Service Offerings) is likely due to the Target vs. RelatedEntities swap or a Null Reference when the existing list is empty.
In an Associate plugin, the Target is not always the "Account." It depends on which side of the relationship the user started the action from.
Scenario A: User opens Account $\rightarrow$ Adds Service Offering. (Target = Account).
Scenario B: User opens Service Offering $\rightarrow$ Adds Account. (Target = Service Offering).
The Debug Checklist:
If your code assumes context.InputParameters["Target"] is always the Account, it will crash when the direction is reversed (Scenario B), casting the wrong entity to the wrong type.
Recommended Code Logic:
Here is the logic structure that handles both the empty list (fresh account) and the direction swap:
Identify Entities Safeley: Check Target.LogicalName. If it is "account", then RelatedEntities are the Service Offerings. If Target is "service_offering", then RelatedEntities contains the Account.
Retrieve Incoming Master ID: The RelatedEntities collection only contains GUIDs (EntityReferences). It does not contain the "Service Master" lookup value. You must perform a service.Retrieve on the incoming ID to get its Service Master ID
Handle Empty Lists: When you query the Account to see its existing Service Offerings:
Ensure your QueryExpression/FetchXML handles the case where 0 records are returned.
If the Account is new, the list of existing Service Masters will be empty. Ensure your loop doesn't try to compare against a null list.
Summary:
Stick to Primary Entity = "none". The PRT error is a red herring; your registration was fine. The issue is almost certainly inside the code's handling of the Target direction or a missing Retrieve for the lookup value on the incoming record.
Please Upvote if this helps!