Trouble with Delete Plug-in Code

已答复 Trouble with Delete Plug-in Code

  • Friday, June 22, 2012 12:43 AM
     
      Has Code

    I have been trying to write a plug-in that prevents deletion of an opportunity that has its (custom) IsPrimary field set to True.  I got some advice on this forum that throwing an exception would both abort the delete tranaction and send an explanitory message to the user.  I'm growing quite frustrated getting my code to work as even the very simple SDK Sample Code portions of my program appear to fail. 

    Here is my code (stripped back with comments):

    using System;
    using System.Diagnostics;
    using System.Linq;
    using System.ServiceModel;
    using Microsoft.Xrm.Sdk;
    using System.Windows.Forms;
    using System.Collections.Generic;
    
    public class WomDelete : IPlugin
    {
        public void Execute(IServiceProvider serviceProvider)
        {
            IPluginExecutionContext context = 
                (IPluginExecutionContext) serviceProvider.GetService(typeof(IPluginExecutionContext));
    
            Entity entity;
    
            // Check if the input parameters property bag contains a target
            // of the create operation and that target is of type Entity.
            if (context.OutputParameters.Contains("Target") &&
            context.OutputParameters["Target"] is Entity)
            {
                // Obtain the target business entity from the input parameters.
                entity = (Entity)context.OutputParameters["Target"];
    
                // Verify that the entity represents a contact.
                if (entity.LogicalName != "opportunity") { return; }
            }
            else
            {
                throw new InvalidPluginExecutionException("No Target Found.");
                //return;
            }
    
    
            //// Business Logic Section
            //try
            //{
                //IOrganizationServiceFactory serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
                //IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId);
    
                //Opportunity opp = inputEntity.ToEntity<Opportunity>();   // Translate Late Bound to Early Bound entity
    
                //// If the record to be deleted is marked Primary then abort with message
                //if (opp.new_IsPrimary == true)
                //{
                    throw new InvalidPluginExecutionException("You cannot delete the Primary Workout Method for a loan. Set another Workout Method as Primary and then you can delete this Workout Method.");
                //}
            //}
            //catch (FaultException<OrganizationServiceFault> ex)
            //{
            //    throw new InvalidPluginExecutionException("An error occurred in the Workout Primary Control plug-in.", ex);
            //}
        } // end method
    } // end class
    

    I register have tried registering this plug-in class for "opportunity" entity "Delete" messages on the Pre-Validation, Pre-Operation and Post-Operation pipeline stages.  I have changed InputParameters to OutputParameters for Post-Operation stage.  All have been for Synchronus execution.

    As cuurently coded (above) I get the "No Target Found." exception thrown indicating that the following if test failed:

            if (context.OutputParameters.Contains("Target") &&
            context.OutputParameters["Target"] is Entity)
    

    Since this is right out of vertually all SDK sample plug-in code, I'm at a loss as to where to go next so I have come here (again I have use both "OutputParameters" and "InputParameters" in the above to no avail).

    I would love some guidence on what is wrong with my code and what the correct pipeline stage would be to register it for this type of Delete abort funtionality. 

    BTW, if I comment out all but the:

                    throw new InvalidPluginExecutionException("You cannot delete the Primary Workout Method for a loan. Set another Workout Method as Primary and then you can delete this Workout Method.");

    line of code, it does stop all deletes.  That is about all I have able to accomplish in the considerable amount of time I have been at this seemingly simple task.

    Any help would be very much appreciated.

All Replies

  • Friday, June 22, 2012 1:34 AM
     
     Answered Has Code

    The Delete message Target in context.InputParameters is an EntityReference, not an Entity as it is with the Create/Update messages; so the following should work:

    EntityReference entityReference;
    
            if (context.OutputParameters.Contains("Target") && context.OutputParameters["Target"] is EntityReference)
            {
                // Obtain the target business entity from the input parameters.
                entityReference = (EntityReference)context.OutputParameters["Target"];
    
                if (entityReference.LogicalName != "opportunity") { return; }
            }
    
    ...

    However, an EntityReference will not give you access to the Entity instance's properties, as it is, by definition, merely a reference.  To test for the IsPrimary attribute, you can either:

    • Register your plugin Pre-Delete and query Retrieve the entity including its IsPrimary attribute
    • Register a PreImage, including the IsPrimary attribute

    I would use the latter as it is far simpler and obviates the need for an additional query (quicker).


    --pogo (pat) @ pogo69.wordpress.com

    • Marked As Answer by Kahuna2000 Friday, June 22, 2012 2:44 AM
    •  
  • Friday, June 22, 2012 2:44 AM
     
     

    Thanks Pogo,

    To be clear, you are saying that Delete Messages use EntityReferece and Create/Update Messages use Entity?

    What stage would you recommend I use if I register for a PreImage? Pre-Operation?

  • Friday, June 22, 2012 2:52 AM
     
     

    To be clear, you are saying that Delete Messages use EntityReferece and Create/Update Messages use Entity?

    Correct - each message will provide you a Target in the InputParameters.  But the Target has a different type for Delete (EntityReference) than Create/Update (Entity).

    Which makes sense given that after the Delete operation the Entity no longer exists.

    What stage would you recommend I use if I register for a PreImage? Pre-Operation?

    You can register the PreImage and use it from either Pre or Post, but if your intention is to conditionally reject the operation entirely, Pre-Operation probably makes more sense - to get in early.


    --pogo (pat) @ pogo69.wordpress.com

  • Friday, June 22, 2012 2:54 AM
     
     
    Thanks again Pogo.  The SDK doc is of limited help on Delete Messages.