Wednesday, October 31, 2012

CRM 2011 Recurring workflows - Running only one instance at the same time

Maybe some of you already read the post of how to implement a recurring workflow in Dynamics CRM 2011, I have read it from http://crmbusiness.wordpress.com/2011/05/24/crm-2011-how-to-schedule-recurring-workflows-in-crm-2011/ , the article is copied below.

When I implemented this approach with a client, I had the next problem, The user was clicking on a ribbon button and that button was calling a JScript code that performed a call to a workflow using something similar to this: (http://andreaswijayablog.blogspot.com/2011/07/crm-2011-custom-button-on-custom-entity.html)

function callworkfow(id) {
    try {
        var guid;

        if (id == null) {
            guid = Xrm.Page.data.entity.getId();
        }
        else
            guid = id;

        // assign workflow guid
        var WorkflowId = "89BA3166-948E-4B12-8A55-4BE01DEDAB0B";

        var xml = "" +
    "<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
    "<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\">" +
    Xrm.Page.context.getAuthenticationHeader() +
    "<soap:Body>" +
    "<execute xmlns=\"http://schemas.microsoft.com/crm/2007/WebServices\">" +
    "<request xsi:type=\"ExecuteWorkflowRequest\">" +
    "<entityid>" + guid + "</EntityId>" +
    "<workflowid>" + WorkflowId + "</WorkflowId>" + //WorkflowId = guid of the workflow
    "</Request>" +
    "</Execute>" +
    "</soap:Body>" +
    "</soap:Envelope>";

        var xmlHttpRequest = new ActiveXObject("Msxml2.XMLHTTP");
        xmlHttpRequest.Open("POST", "/mscrmservices/2007/CrmService.asmx", false);
        xmlHttpRequest.setRequestHeader("SOAPAction", "http://schemas.microsoft.com/crm/2007/WebServices/Execute");
        xmlHttpRequest.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
        xmlHttpRequest.setRequestHeader("Content-Length", xml.length);
        xmlHttpRequest.send(xml);

        var resultXml = xmlHttpRequest.responseXML;

        if (id == null)
            alert("Success");
        return (resultXml.xml);
    }
    catch (e) {
        alert("Failed to Execute");
    }
}


But, the problem here was that I needed to have only one instance of the workflow running at the same time, and the way it was implemented was creating a new instance of the workflow everytime the button was clicked, and as far as I know the CRM webservice does not have a way to retrieve Async Operations in case I need to be sure that any instance of the workflow was running before calling it, and neither the Plugins can be attached to Async Operations, so.. (If you already followed the tutorial from http://crmbusiness.wordpress.com/2011/05/24/crm-2011-how-to-schedule-recurring-workflows-in-crm-2011/ ), what I did to solve this problem is the next:


Change the workflow to run only as Child and on i.e. Appointments CREATION

---------------  USER ---------------------------------------------------------------------------------------------------------------------
- User clicks on the ribbon button, this will trigger the jscript code
-------------------------------------------------------------------------------------------------------------------------------------------------

--------------- JSCRIPT Code that will be called from the ribbon button------------------------------------------------
- A jscript code searches for an appointment with subject "Only one workflow instance"
   - If the appointment is found, then do nothing.. (Because this means that the workflow is running already)
   - But if the appointment was not found, then  CREATE an appointment with subject "Only one workflow instance", this will trigger the workflow.
--------------------------------------------------------------------------------------------------------------------------------------------------

--------------  WORKFLOW process -------------------------------------------------------------------------------------------------
- Workflow starts
- Do the work that needs to do..
- Waits X time
- Calls itself as again (This starts a new iteration)..
- Workflow ends..
--------------------------------------------------------------------------------------------------------------------------------------------------

Also you can manage it using a plugin that triggers on the pre-create of i.e. Appointment.

I hope this helps!