locked
Canceling child case activities on merge RRS feed

  • Question

  • Hi,

    I am developing a plugin to cancel child case's activities when cases are merged using 'Merge Cases' button.

    I've registered the plugin on merge message. But when I deploy it I don't think its working.

    This is my code; Can someone please let me know what am I doing wrong?

     protected void ExecutePostTaskUpdate(LocalPluginContext localContext)
            {
                if (localContext == null)
                {
                    throw new ArgumentNullException("localContext");
                }
    
                // TODO: Implement your custom Plug-in business logic.
                // Obtain the execution context from the service provider.
                IPluginExecutionContext context = localContext.PluginExecutionContext;
                IOrganizationService service = localContext.OrganizationService;
    
                if (context.InputParameters.Contains("Target") &&
                context.InputParameters["Target"] is Entity)
                {
                    // Obtain the target entity from the input parmameters.
                    Entity entity = (Entity)context.InputParameters["Target"];
    
                    //verify that the target entity represents an entity type you are expecting.
                    if (entity.LogicalName != "task")
                        return;
    
                    string entityActivityStatus = "Canceled";
                    try
                    {
                        if (entity.Attributes.Contains(
                            "statecode"))
                        {
                            if (entity.Attributes["new_issuephase"] != "Work Complete")
                            {
                                entity.Attributes.Add("statecode", entityActivityStatus);
                            }
                            else
                                return;
                        }
                    }
                    catch (FaultException ex)
                    {
                        
                        throw new InvalidPluginExecutionException("An error occurred in the plug-in",ex);
                    }
                }
            }

    Thanks

    Thursday, October 30, 2014 8:15 PM

Answers

  • Hello Roxanna,

    I built and tested the code:

            public void Execute(IServiceProvider serviceProvider)
            {
                //Extract the tracing service for use in debugging sandboxed plug-ins.
                ITracingService tracingService =
                    (ITracingService)serviceProvider.GetService(typeof(ITracingService));
    
                // Obtain the execution context from the service provider.
                IPluginExecutionContext context = (IPluginExecutionContext)
                    serviceProvider.GetService(typeof(IPluginExecutionContext));
    
                var factory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
    
                var service = factory.CreateOrganizationService(context.UserId);
    
                //The InputParameters collection contains all the data passed in the message request.
                if (context.InputParameters.Contains("SubordinateId") &&
                    context.InputParameters["SubordinateId"] is Guid)
                {
    
                    try
                    {
    
                        Guid subordinateId = (Guid)context.InputParameters["SubordinateId"];
    
                        var fetch = @"<fetch version='1.0' output-format='xml-platform' mapping='logical' distinct='false'>
                                      <entity name='task'>
                                        <attribute name='activityid' />
                                        <filter type='and'>
                                          <filter type='and'>
                                            <condition attribute='regardingobjectid' operator='eq' uitype='account' value='" + subordinateId + @"' />
                                            <condition attribute='statecode' operator='eq' value='0' />
                                          </filter>
                                        </filter>
                                      </entity>
                                    </fetch>";
    
                        EntityCollection ec = service.RetrieveMultiple(new FetchExpression(fetch));
    
                        if (ec.Entities.Count > 0)
                        {
                            // Create an ExecuteMultipleRequest object.
                            ExecuteMultipleRequest requestWithResults = new ExecuteMultipleRequest()
                            {
                                // Assign settings that define execution behavior: continue on error, return responses. 
                                Settings = new ExecuteMultipleSettings()
                                {
                                    ContinueOnError = false,
                                    ReturnResponses = true
                                },
                                // Create an empty organization request collection.
                                Requests = new OrganizationRequestCollection()
                            };
    
                            foreach (var item in ec.Entities)
                            {
    
                                SetStateRequest setStateRequest = new SetStateRequest();
                                setStateRequest.EntityMoniker = new EntityReference("task", item.Id);
                                setStateRequest.State = new OptionSetValue(2);
                                setStateRequest.Status = new OptionSetValue(6);
    
                                requestWithResults.Requests.Add(setStateRequest);
                            }
    
                            ExecuteMultipleResponse responseWithResults =
                                (ExecuteMultipleResponse)service.Execute(requestWithResults);
    
                        }
    
                    }
                    catch (Exception Ex)
                    {
    
                        throw new InvalidPluginExecutionException(Ex.ToString());
                    }
                }
            }

    I registered the plugin as follows:

    

    I used the Account entity, but you can adjust it with Case entity.

    Hope it helps.

    Monday, November 3, 2014 12:15 PM

All replies

  • hello,

    please see the sample on the following link.

    http://msdn.microsoft.com/en-us/library/hh547408.aspx

    merge operations got two ids. The subordinate record gets deactivated. You can get the guid if the record from subordinateid.

    what you have to do in your plugin is to get all the activities corresponds to this case I'd and iterte thru the records and set status one by one.

    hth, let me know if you need further assistance.

    regards

    Jithesh

    Thursday, October 30, 2014 9:18 PM
  • Also there is a problem with your plugin code

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

    In merge you won't get Target as Entity, but it will return MonikerSelection.

    You need to change your plugin like below

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

       


    Microsoft Dynamics CRM Training|Our Blog | Follow US | Our Facebook Page | Microsoft Dynamics CRM 2011 Application Design
    Make sure to "Vote as Helpful" and "Mark As Answer",if you get answer of your question.

    Friday, October 31, 2014 1:23 AM
    Moderator
  • Hello Roxanna,

    I built and tested the code:

            public void Execute(IServiceProvider serviceProvider)
            {
                //Extract the tracing service for use in debugging sandboxed plug-ins.
                ITracingService tracingService =
                    (ITracingService)serviceProvider.GetService(typeof(ITracingService));
    
                // Obtain the execution context from the service provider.
                IPluginExecutionContext context = (IPluginExecutionContext)
                    serviceProvider.GetService(typeof(IPluginExecutionContext));
    
                var factory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
    
                var service = factory.CreateOrganizationService(context.UserId);
    
                //The InputParameters collection contains all the data passed in the message request.
                if (context.InputParameters.Contains("SubordinateId") &&
                    context.InputParameters["SubordinateId"] is Guid)
                {
    
                    try
                    {
    
                        Guid subordinateId = (Guid)context.InputParameters["SubordinateId"];
    
                        var fetch = @"<fetch version='1.0' output-format='xml-platform' mapping='logical' distinct='false'>
                                      <entity name='task'>
                                        <attribute name='activityid' />
                                        <filter type='and'>
                                          <filter type='and'>
                                            <condition attribute='regardingobjectid' operator='eq' uitype='account' value='" + subordinateId + @"' />
                                            <condition attribute='statecode' operator='eq' value='0' />
                                          </filter>
                                        </filter>
                                      </entity>
                                    </fetch>";
    
                        EntityCollection ec = service.RetrieveMultiple(new FetchExpression(fetch));
    
                        if (ec.Entities.Count > 0)
                        {
                            // Create an ExecuteMultipleRequest object.
                            ExecuteMultipleRequest requestWithResults = new ExecuteMultipleRequest()
                            {
                                // Assign settings that define execution behavior: continue on error, return responses. 
                                Settings = new ExecuteMultipleSettings()
                                {
                                    ContinueOnError = false,
                                    ReturnResponses = true
                                },
                                // Create an empty organization request collection.
                                Requests = new OrganizationRequestCollection()
                            };
    
                            foreach (var item in ec.Entities)
                            {
    
                                SetStateRequest setStateRequest = new SetStateRequest();
                                setStateRequest.EntityMoniker = new EntityReference("task", item.Id);
                                setStateRequest.State = new OptionSetValue(2);
                                setStateRequest.Status = new OptionSetValue(6);
    
                                requestWithResults.Requests.Add(setStateRequest);
                            }
    
                            ExecuteMultipleResponse responseWithResults =
                                (ExecuteMultipleResponse)service.Execute(requestWithResults);
    
                        }
    
                    }
                    catch (Exception Ex)
                    {
    
                        throw new InvalidPluginExecutionException(Ex.ToString());
                    }
                }
            }

    I registered the plugin as follows:

    

    I used the Account entity, but you can adjust it with Case entity.

    Hope it helps.

    Monday, November 3, 2014 12:15 PM
  • Thanks Elvis.

    I will try it with Case entity and let you know. Appreciate it!

    Tuesday, November 4, 2014 2:29 PM
  • Elvis,

    It worked like magic! Also, I am trying to update value of a lookup field along with the status change with SetStateRequest.

    Is it possible to do so?

    Thanks


    Wednesday, November 5, 2014 5:04 PM
  • Hi Roxanna,

    Sorry for the late response. Code adjusted:

            public void Execute(IServiceProvider serviceProvider)
            {
                //Extract the tracing service for use in debugging sandboxed plug-ins.
                ITracingService tracingService =
                    (ITracingService)serviceProvider.GetService(typeof(ITracingService));
    
                // Obtain the execution context from the service provider.
                IPluginExecutionContext context = (IPluginExecutionContext)
                    serviceProvider.GetService(typeof(IPluginExecutionContext));
    
                var factory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
    
                var service = factory.CreateOrganizationService(context.UserId);
    
                //The InputParameters collection contains all the data passed in the message request.
                if (context.InputParameters.Contains("SubordinateId") &&
                    context.InputParameters["SubordinateId"] is Guid)
                {
    
                    try
                    {
    
                        Guid subordinateId = (Guid)context.InputParameters["SubordinateId"];
    
                        var fetchTask = @"<fetch version='1.0' output-format='xml-platform' mapping='logical' distinct='false'>
                                      <entity name='task'>
                                        <attribute name='activityid' />
                                        <attribute name='new_lookuptestfield' />
                                        <order attribute='new_lookuptestfield' descending='false' />
                                        <filter type='and'>
                                          <filter type='and'>
                                            <condition attribute='regardingobjectid' operator='eq' uitype='account' value='" + subordinateId + @"' />
                                            <condition attribute='statecode' operator='eq' value='0' />
                                          </filter>
                                        </filter>
                                      </entity>
                                    </fetch>";
    
                        EntityCollection ecTask = service.RetrieveMultiple(new FetchExpression(fetchTask));
    
                        if (ecTask.Entities.Count > 0)
                        {
                            // Create an ExecuteMultipleRequest object.
                            ExecuteMultipleRequest requestWithResults = new ExecuteMultipleRequest()
                            {
                                // Assign settings that define execution behavior: continue on error, return responses. 
                                Settings = new ExecuteMultipleSettings()
                                {
                                    ContinueOnError = false,
                                    ReturnResponses = true
                                },
                                // Create an empty organization request collection.
                                Requests = new OrganizationRequestCollection()
                            };
    
                            foreach (var item in ecTask.Entities)
                            {
    
                                SetStateRequest setStateRequest = new SetStateRequest();
                                setStateRequest.EntityMoniker = new EntityReference("task", item.Id);
                                setStateRequest.State = new OptionSetValue(2);
                                setStateRequest.Status = new OptionSetValue(6);
    
                                if (!item.Attributes.Contains("new_lookuptestfield"))
                                {
                                    var fetchTeste = @"<fetch version='1.0' output-format='xml-platform' mapping='logical' distinct='false'>
                                                  <entity name='new_teste'>
                                                    <attribute name='new_testeid' />
                                                    <attribute name='new_name' />
                                                    <order attribute='new_name' descending='false' />
                                                    <filter type='and'>
                                                      <condition attribute='new_name' operator='eq' value='Test1' />
                                                    </filter>
                                                  </entity>
                                                </fetch>";
    
                                    EntityCollection ecTeste = service.RetrieveMultiple(new FetchExpression(fetchTeste));
    
                                    Entity test1 = ecTeste.Entities.FirstOrDefault();
    
                                    item["new_lookuptestfield"] = new EntityReference("new_teste", test1.Id);
    
                                    UpdateRequest updateRequest = new UpdateRequest
                                    {
                                        Target = item
                                    };
    
                                    requestWithResults.Requests.Add(updateRequest);
                                }
    
                                requestWithResults.Requests.Add(setStateRequest);
    
                            }
    
                            ExecuteMultipleResponse responseWithResults =
                                (ExecuteMultipleResponse)service.Execute(requestWithResults);
    
                        }
    
                    }
                    catch (Exception Ex)
                    {
    
                        throw new InvalidPluginExecutionException(Ex.ToString());
                    }
                }
            }
    Elvis


    Wednesday, November 19, 2014 3:50 PM
  • Thanks Elvis,

    I tried it but no change is happening for the lookup field that I am trying to change.

    Is it because after canceling the tasks the lookup field became Read only? If so can we change lookup field first and then cancel the task?

    Thanks

    Wednesday, November 19, 2014 8:42 PM
  • I tried to debug the plugin but all I am seeing is this error after starting profiler.

    Thanks

    Wednesday, November 19, 2014 8:51 PM
  • I made several changes to the first code. This way, I recommend that you:

    1 - Forget the first code;

    2 - Copy the second code;

    3 - Make yours adjustments (replace field names, etc.);

    4 - Test it.

    One of the most important changes I made is: the updateRequest line must come before the setStateRequet line. Reason: after a task is canceled, it becomes read-only and you are not allowed to make changes to it.

    If you do not succeed and you using On-Premises, try the following steps to debug your plugin:

    1 - Build the code;

    2 - Copy the DLL and PDB files from Visual Studio folder to C:\Program Files\Microsoft Dynamics CRM\Server\bin\assembly;

    3 - Register de plugin;

    4 - Add a break point to the code;

    5 - Attach w3wp.exe process to Visual Studio;

    6 - Invoke the plugin.

    Elvis

    Monday, November 24, 2014 12:03 PM