My technical musings

Building a plugin for CRM 2015 Won or Lost Opportunities

Recently I had to develop a plugin for a CRM 2015 system that triggered each time the opportunity was modified. This worked fine for the normal day to day edits of the opportunity but it failed to catch when the opportunity was closed as Won or Lost.

Normally I would hook the plugin to the Update message on opportunity with the Plugin Registration Tool but when I tested it I wasn't getting the results I wanted. After some digging around I discovered 2 more messages for opportunities, and these are Win and Lose.

On the face of it this seemed quite simple, just hook the plugin to these messages and its job done. Unfortunately its not quite as simple as that as the messages themselves don't actually pass the opportunity entity when they fire, they actually pass the opportunityclose entity which I have to be honest I am not incredibly familiar with. The good news is I didn't really have to worry about it as one of the attributes of the entity is the opportunityid, so all I had to do was get the passed opportunityclose entity and read the opportunityid attribute then search for the opportunity record with a matching id and then use those values. In fact it sounds more difficult than it actually is. 

Here is some sample code to catch the Win message

public void Execute(IServiceProviderserviceProvider)
    Microsoft.Xrm.Sdk.IPluginExecutionContext context = (Microsoft.Xrm.Sdk.IPluginExecutionContext)serviceProvider.GetService(typeof(Microsoft.Xrm.Sdk.IPluginExecutionContext));
    IOrganizationServiceFactoryserviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
    IOrganizationService _service = serviceFactory.CreateOrganizationService(context.UserId);
    if (context.InputParameters.Contains("OpportunityClose"))
        Entity oppCloseEnt = (Entity)context.InputParameters["OpportunityClose"];
        if (oppCloseEnt.Contains("opportunityid"))
            EntityReference er = (EntityReference)oppCloseEnt["opportunityid"];
            // do stuff here


The good news is that the code is the same for the Lose message.