locked
CRM 2011: Plugin to close the re-opened opportunity based on revised quote RRS feed

  • Question

  • Hi all,

    Currently I'm developing a plugin to close  the re-opened opportunity based on revising an active quote, this should be executed on the Set State Message of the Opportunity on Pre-Operation to restore the current previous status, actual value and actual close date if the status was Won, I have tried the below code to achieve my requirements:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    using Microsoft.Xrm.Sdk;
    using System.ServiceModel;
    
    namespace CloseReopenedOpportunity
    {
        public class CloseOpportunity : IPlugin
        {
            public void Execute( IServiceProvider serviceProvider )
            {
                try
                {
                    // Obtain the execution context from the service provider.
                    IPluginExecutionContext context = (IPluginExecutionContext)
                        serviceProvider.GetService(typeof(IPluginExecutionContext));
    
                    // Obtain the organization service reference.
                    IOrganizationServiceFactory serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
                    IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId);
    
                    // The InputParameters collection contains all the data passed in the message request.
                    if ( context.InputParameters.Contains("Target") &&
                        context.InputParameters [ "Target" ] is Entity )
                    {
                        // Obtain the target entity from the input parmameters.
                        //Entity entity = (Entity)context.InputParameters [ "Target" ];
    
                        Entity preOpen = (Entity)context.PreEntityImages [ "OpportunityImage" ];
    
                        String oppStatus = (String)preOpen [ "statecode" ];
    
                        throw new InvalidPluginExecutionException("opportunity states was " + oppStatus);
                    }
                }
                catch ( Exception e )
                {
                    throw new InvalidPluginExecutionException(e.Message, e);
                }
            }
        }
    }
    

    It's not the full plugin code for sure, however it doesn't work correctly as ot doesn't display the opportunity status

     

    Please advise..

    Sunday, November 20, 2011 9:21 AM

Answers

  • Hi Mostafa,

    Actually i got bit confused by the lines in your post "Currently I'm developing a plugin to close  the re-opened opportunity based on revising an active quote", my understanding as per your next post that you are trying to execute a code when a opportunity will be re-opened, in this case you may have to register your plugin into the SetStateDynamicEntity and can check the status value using the following code:


    if (context.InputParameters.Contains("EntityMoniker") && context.InputParameters["EntityMoniker"] is EntityReference &&
         ((EntityReference)context.InputParameters["EntityMoniker"]).LogicalName == "opportunity") {
         switch (context.MessageName)
         {
     
        // Check if entity status is changed
         case "SetStateDynamicEntity":

         if (context.InputParameters.Contains("State"))
         {

     EntityReference OpprtunityEntityRef = (EntityReference)context.InputParameters["EntityMoniker"]);
     
          if (((OptionSetValue)context.InputParameters["State"]).Value == 1)
             {
                  // your code will come here
           // You can retrieve entity object by the Retrieve method using the OpprtunityEntityRef.Id or by registering pre image
         
             }
          }
     }

    I hope this helps.


    Jehanzeb Javeed

    http://worldofdynamics.blogspot.com
    Linked-In Profile |CodePlex Profile

    If you find this post helpful then please "Vote as Helpful" and "Mark As Answer".
    Monday, November 21, 2011 11:07 AM

All replies

  • any suggestions ??
    Sunday, November 20, 2011 12:11 PM
  • Kindly I need help debugging the plugin I have copied the dll and pdb fiels to the "C:\Program Files\Microsoft Dynamics CRM\Server\bin\assembly" directory

    I have inmstalled the VS 2010 remote debugger on server i have attached the process w3wp.exe on my machine, also I have setted the breakpoint at line:

     

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

    I tried to test the plugin by revising a quote and the opportunity is re-opened but nothing happens, i.e: it didn't displays the message or an error

    Please advise...

     

    Sunday, November 20, 2011 12:38 PM
  • hi mostafa

     Most of the stuff you have done correctly

     please make sure of the following.

    when you are attaching to w3wp.exe make sure it the current context.

    that is the browser should be referesh or do iisrese and restart the Async service

    so that we are sure that we have the same code as we are debbugging .y

    Also try  registering the plugin in the database.

    Make sure that  you are registering the correct message SetState & SetStateDynamic

    hope this works

    dkay

    hi mostafa

    You have to attach in both SetState and SetStateDynamic,

    Some internal CRM actions on system entities use SetState, whereas most state changes use SetStateDynamic.

     As there's no exhaustive documentation on which actions use SetState and which use SetStateDynamic,

    general good practice is to register plugin steps on both messages

    hope this helps

    dkay


     --------------------------------------------------------------------------------
     If you find this post helpful then please "Vote as Helpful" and "Mark As Answer".

    • Proposed as answer by D kay Tuesday, November 22, 2011 6:40 AM
    Sunday, November 20, 2011 4:36 PM
  • Hi,

    You should register your plugin for Win message on Opportunity entity and access the entity in plugin like the code below:

     

    Entity jj_OpptyClose = (Entity)context.InputParameters["OpportunityClose"];
    
    EntityReference jj_OpptyRef = jj_opptyClose["opportunityid"] as EntityReference;
    

     

     


    Jehanzeb Javeed

    http://worldofdynamics.blogspot.com
    Linked-In Profile |CodePlex Profile

    If you find this post helpful then please "Vote as Helpful" and "Mark As Answer".
    Sunday, November 20, 2011 10:17 PM
  • Jehanzeb, If you have read the problem carefully I need to execute the plugin op re-opening the opportunity so why shoud I register it against the Win message ?!

    However this is waht I get till now, I have developped this sample to monitor the status change and I have registered it on postoperation and I have registered two pre and post images:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    using Microsoft.Xrm.Sdk;
    using System.ServiceModel;
    using Microsoft.Crm.Sdk.Messages;
    
    namespace CloseReopenedOpportunity
    {
        public class CloseOpportunity : IPlugin
        {
            public void Execute( IServiceProvider serviceProvider )
            {
                try
                {
                    // Obtain the execution context from the service provider.
                    IPluginExecutionContext context = (IPluginExecutionContext)
                        serviceProvider.GetService(typeof(IPluginExecutionContext));
    
                    // Obtain the organization service reference.
                    IOrganizationServiceFactory serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
                    IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId);
    
                    // The InputParameters collection contains all the data passed in the message request.
                    if ( context.InputParameters.Contains("Target") &&
                        context.InputParameters [ "Target" ] is Entity )
                    {
                        Entity preOpen = (Entity)context.PreEntityImages [ "OpportunityImage" ];
                        Entity postOpen = (Entity)context.PostEntityImages [ "OpportunityImage" ];
    
                        OptionSetValue statusbeforeoptionset = (OptionSetValue)preOpen [ "statecode" ];
                        int statusbefore = statusbeforeoptionset.Value;
    
                        OptionSetValue statusafteroptionset = (OptionSetValue)postOpen["statecode"];
                        int statusafter = statusafteroptionset.Value;
    
                        throw new InvalidPluginExecutionException("opportunity status was " + statusbefore + " and now it's " + statusafter);
                    }
                }
                catch ( Exception e )
                {
                    throw new InvalidPluginExecutionException(e.Message, e);
                }
            }
        }
    }
    

    But it always displays the status on post operation, I don't know what is missing ??

    Monday, November 21, 2011 10:45 AM

  • Hi

    Did this help?

    Please make sure to mark as answer to the response that helped you get through. This will help others with similar problem identify the answer and also close this thread as resolved.

    Thanks

    Dk

    Monday, November 21, 2011 10:55 AM
  • Please read the above posts, and try to help
    Monday, November 21, 2011 11:02 AM
  • Hi Mostafa,

    Actually i got bit confused by the lines in your post "Currently I'm developing a plugin to close  the re-opened opportunity based on revising an active quote", my understanding as per your next post that you are trying to execute a code when a opportunity will be re-opened, in this case you may have to register your plugin into the SetStateDynamicEntity and can check the status value using the following code:


    if (context.InputParameters.Contains("EntityMoniker") && context.InputParameters["EntityMoniker"] is EntityReference &&
         ((EntityReference)context.InputParameters["EntityMoniker"]).LogicalName == "opportunity") {
         switch (context.MessageName)
         {
     
        // Check if entity status is changed
         case "SetStateDynamicEntity":

         if (context.InputParameters.Contains("State"))
         {

     EntityReference OpprtunityEntityRef = (EntityReference)context.InputParameters["EntityMoniker"]);
     
          if (((OptionSetValue)context.InputParameters["State"]).Value == 1)
             {
                  // your code will come here
           // You can retrieve entity object by the Retrieve method using the OpprtunityEntityRef.Id or by registering pre image
         
             }
          }
     }

    I hope this helps.


    Jehanzeb Javeed

    http://worldofdynamics.blogspot.com
    Linked-In Profile |CodePlex Profile

    If you find this post helpful then please "Vote as Helpful" and "Mark As Answer".
    Monday, November 21, 2011 11:07 AM
  • Thanks alot for your help :) But I think my plugin is more simple, I will register the plugin on update message and will get the pre and post status values using images and will compare them to be sure that the opportunity has been re-opened. i.e: if the pre status value = 1 and post status value = 0 then the opportunity has been re-opened.

    But my problem with the above code is that the pre value is always displayed

    Please advise...
    Monday, November 21, 2011 11:16 AM

  • Hi Mostafa,

    All the entity status updates handle via SetStateRequest SDK requests and it fires SetState and SetStateDynamicEntity plugin messages, in plugin code you can register your plugin for the SetStateDynamicEntity message and register the pre image so in pre-image you will get the entity status 1 and can check the new status using the below code line:

    if (((OptionSetValue)context.InputParameters["State"]).Value == 0)
    {
    }


    Jehanzeb Javeed

    http://worldofdynamics.blogspot.com
    Linked-In Profile |CodePlex Profile

    If you find this post helpful then please "Vote as Helpful" and "Mark As Answer".
    Monday, November 21, 2011 11:23 AM
  • Here is what I have done:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    using Microsoft.Xrm.Sdk;
    using System.ServiceModel;
    using Microsoft.Crm.Sdk.Messages;
    
    namespace CloseReopenedOpportunity
    {
        public class CloseOpportunity : IPlugin
        {
            public void Execute( IServiceProvider serviceProvider )
            {
                try
                {
                    // Obtain the execution context from the service provider.
                    IPluginExecutionContext context = (IPluginExecutionContext)
                        serviceProvider.GetService(typeof(IPluginExecutionContext));
    
                    // Obtain the organization service reference.
                    IOrganizationServiceFactory serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
                    IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId);
    
                    // The InputParameters collection contains all the data passed in the message request.
                    if ( context.InputParameters.Contains("Target") &&
                        context.InputParameters [ "Target" ] is Entity )
                    {
                        Entity preOpen = (Entity)context.PreEntityImages [ "OpportunityImage" ];
                        Entity postOpen = (Entity)context.PostEntityImages [ "OpportunityImage" ];
    
                        OptionSetValue statusbeforeoptionset = (OptionSetValue)preOpen [ "statecode" ];
                        int statusbefore = statusbeforeoptionset.Value;
                        int statusafter = 0;
                        if ( context.OutputParameters.Contains ( "statecode" ) )
                        {
                            statusafter = ( (OptionSetValue)context.OutputParameters [ "statecode" ] ).Value;
                        }
                        
                        throw new InvalidPluginExecutionException("opportunity status was " + statusbefore + " and now it's " + statusafter);
                    }
                }
                catch ( Exception e )
                {
                    throw new InvalidPluginExecutionException(e.Message, e);
                }
            }
        }
    }
    

    but now it gives me error: The given key was not present in the dictionary

    Monday, November 21, 2011 11:39 AM
  • Any suggestions  ??
    Monday, November 21, 2011 12:16 PM
  • Dear Jehanzeb, thanks alot for your help, it works but only for Opp re-opened directly not through revising quotes.

    Could you please help me updating the code or step registration data so that the plugin would trigger on re-opening opportunity through revising the related quote ??

    Saturday, November 26, 2011 12:50 AM