Skip to main content

Cancel Workflow job programmatically - CRM v.4

How many times you had to created a workflow on some date like Due date which keeps changing as per client's request. While this may sound simple in business, on CRM you have a workflow that may be waiting till this date and send a reminder exactly a week before.

So you need to keep calling this workflow every time the date is updated, to make the matters more complicated, all the previous jobs that had initiated due to past modification will keep running and chasing that date which is never going to occur. What you do now, manually cancel those to save system resources and stop the never ending system jobs.

There is a way to do it through SDK, in my case I call this function as a custom workflow activity in the first step of the workflow which Cancels any previous jobs of this workflow.

  #region Cancel My WFs

            QueryExpression qe = new QueryExpression();
            qe.EntityName = EntityName.asyncoperation.ToString();
            ColumnSet cs = new ColumnSet();
            cs.Attributes = new string[] { "name", "regardingobjectid", "createdon","statuscode","statecode" };
           
            FilterExpression fe = new FilterExpression();
            fe.FilterOperator = LogicalOperator.And;

            ConditionExpression ce1 = new ConditionExpression();
            ce1.Operator = ConditionOperator.Equal;
            ce1.AttributeName = "regardingobjectid"; // Your record id
            ce1.Values = new object[] { new Guid("EE87FB7E-6C1F-E111-AF92-0050569F0AE2") };

            ConditionExpression ce2 = new ConditionExpression();
            ce2.Operator = ConditionOperator.Equal;
            ce2.AttributeName = "name"; // GUID of the Waiting Workflow: WF_InDeal_NextEndofTermNotificationDate_Update
            ce2.Values = new object[] { "Your_WF_Name" };

            ConditionExpression ce3 = new ConditionExpression();
            ce3.Operator = ConditionOperator.NotEqual;
            ce3.AttributeName = "statuscode"; // GUID of the Waiting Workflow: WF_InDeal_NextEndofTermNotificationDate_Update
            Status CancelledStatus = new Status(); CancelledStatus.Value = 32;
            ce3.Values = new object[] { CancelledStatus };

            fe.Conditions = new ConditionExpression[] { ce1,ce2};
            fe.FilterOperator = LogicalOperator.And;
            //fe.AddCondition(ce1);
            //fe.AddCondition(ce2);

            qe.ColumnSet = cs;
            qe.Criteria = fe;

            req = new RetrieveMultipleRequest();
            req.ReturnDynamicEntities = true;
            req.Query = qe;
            RetrieveMultipleResponse resp = null;
            resp = (RetrieveMultipleResponse)serv.Execute(req);
            if (resp.BusinessEntityCollection.BusinessEntities.Length  > 0)
            {
                BusinessEntityCollection bec = resp.BusinessEntityCollection;
                asyncoperation asyncOperation = null;
                DynamicEntity dynamicEntity = null;
                TargetUpdateAsyncOperation targetUpdateAsyncOperation = null;
               
                string Status = "";
                for (int i = 0; i < bec.BusinessEntities.Length-1 ; i++)
                {
                    Status = ((UpdateProductBasePrice.crmService.StatusProperty)(((UpdateProductBasePrice.crmService.DynamicEntity)(bec.BusinessEntities[i])).Properties[4])).Value.name;
                    if (!Status.Equals("Canceled"))
                    {
                        asyncOperation = new asyncoperation();
                        dynamicEntity = (DynamicEntity)bec.BusinessEntities[i];
                        asyncOperation.asyncoperationid = new Key();
                        asyncOperation.asyncoperationid.Value = new Guid(((UpdateProductBasePrice.crmService.KeyProperty)(dynamicEntity.Properties[5])).Value.Value.ToString());
                        asyncOperation.statuscode = new Status();
                        asyncOperation.statuscode.Value = 32;
                        asyncOperation.statecode = new AsyncOperationStateInfo();
                        asyncOperation.statecode.Value = AsyncOperationState.Completed;

                        targetUpdateAsyncOperation = new TargetUpdateAsyncOperation();
                        targetUpdateAsyncOperation.AsyncOperation = asyncOperation;

                        UpdateRequest updateAsync = new UpdateRequest();
                        updateAsync.Target = targetUpdateAsyncOperation;

                        try
                        {
                            serv.Execute(updateAsync);
                        }
                        catch (System.Web.Services.Protocols.SoapException soapEx)
                        {
                            continue;
                        }
                    }
                }

            }
            return;
            #endregion 

Comments

alfred said…
All you have to do to get this free service is to sign-up on their site and then paste a bit of javascript in your site's footer, so that accesses to all pages get metered. Each account you open can only cover one site, thus if you have ten sites, you'll have to register ten times.

javascript jobs

Popular posts from this blog

CRM 2011 Useful JavaScript tidbits

http://www.powerobjects.com/blog/2011/01/14/crm-2011-useful-javascript-tidbits/ Get the value from a CRM field var varMyValue = Xrm.Page.getAttribute(“CRMFieldSchemaName”).getValue() ; Set the value of a CRM field Xrm.Page.getAttribute(“po_CRMFieldSchemaName”).setValue(‘My New Value’); Hide/Show a tab/section Xrm.Page.ui.tabs.get(5).SetVisible(false); Xrm.Page.ui.tabs.get(5).SetVisible(true); Call the onchange event of a field Xrm.Page.getAttribute(“CRMFieldSchemaName”).fireOnChange(); Get the selected value of picklist Xrm.Page.getAttribute(“CRMFieldSchemaName”).getSelectedOption().text; Set the requirement level Xrm.Page.getAttribute(“CRMFieldSchemaName”).setRequiredLevel(“none”); Xrm.Page.getAttribute(“CRMFieldSchemaName”).setRequiredLevel(“required”); Xrm.Page.getAttribute(“CRMFieldSchemaName”).setRequiredLevel(“recommended”); Set the focus to a field Xrm.Page.getControl(“CRMFieldSchemaName”).setFocus(true); Stop an on save event event.returnValue = false; Return array

Abort event through plugins

Suppose you are writing a pre -event plugin in which you compare to  old and new values and on certain condition would like to cancel the Save or  Update and stop the execution, it was simple in CRM 3 with an Abort() method while in CRM 4, you have to manually raise and throw a  Invalid-Plugin-Exception, while this gives a dirty error message on your MSCRM screen, you can make it better by entering you own Message explaining why the record could not be saved: throw new InvalidPluginExecutionException("Execution has been stopped due to this reason");

Using MS CRM Calendar in your custom ASP .NET pages *** Not fully Supported Customisations ***

Hi, Have you been creating custom pages in line with MS CRM for creating , viewing and updating entity records ? Have you placed controls such as Date picker Lookup on your custom page and have tried in vein to make those look like MS CRM ? I found a way to use the same MS CRM calendar control as it appears in the application... For getting this calendar on your asp .net page, follow the steps below: 1) Create a copy of the date.js javascript file located in your-server/crmsite-folder/_static/_controls/datetime folder, give the copy some name like date_myapp.js. 2) Open the following .js files from different sub folders in side the  your-server/crmsite-folder/_static      folder :       Global.js       encodedecode.js       xmlutil.js       util.js       remotecommand.js              Copy and whole content of each file one by one and keep pasting the same to the end of your date_myapp.js file. 3) Now open any CRM entity record page, for example a new Account crea