1

My Customer has a regulatory compliance requirement to add secondary authentication prior to any workflow approval, so the approach that I have taken is by defining a custom Action which opens a DialogForm and it handles the authentication part.

It works great, but there is one problem where the state of the workflow changes automatically to the next state when a modal is closed before a user is authenticated.

For example, if a workflow has 3 states (Draft -> Submit (If this has that authentication requirement, then the user has to get stuck in the same state until the user authenticates) -> Approve)

I know the existing out of the box Approve action is handling this scenario but I was not able to track the right dll to see the code. Any help is greatly appreciated.

  • We had the similar requirement where we open up a pop-up and based on the response from user move it to "Approved" or "Draft". We set the Next State for the command as current state and added a custom action which decides where the flow needs to be re-directed. – Gobinath Saminathan Feb 8 at 16:49
  • @Gobinath Interesting approach, but If we do it that way then we lose out of the box functionality of the processor like adding the history which I know will be and there might be something else that the processor might also be taking care for us. Do you have the sample code of that? If yes, can you share the code here? – Abhi Feb 8 at 19:29
  • Yes it might not be a perfect solution but We strictly wanted to control the next state in our code so we decided to update the state in code after the user response and also we don't want to loose the out-of-box features.. But for your case, you can check the Sitecore.Kernel for the classes & logic used in the out-of-box workflow.. l – Gobinath Saminathan Feb 8 at 20:32
  • @Gobinath If I understand correctly, you told you guys have used a pop up and not dialog form right? – Abhi Feb 8 at 20:45
  • Something like this, public void Process(WorkflowPipelineArgs workflowActionArgument) { Sitecore.Context.ClientPage.Start(this, "DialogProcessor"); } private void DialogProcessor(ClientPipelineArgs clientPipelineArgument) { if (clientPipelineArgument.IsPostBack) { Read the response of your dialog box and handle here } else { SheerResponse.Input(pass required details based on your need) } } I guess it is worth analyzing the Out-of box workflow code and implement your requirements.. – Gobinath Saminathan Feb 8 at 21:02
0

Thanks, Gobinath I was able to implement the solution based on your sample code and I am adding the code for missing pieces like below

  1. How to refresh the Sitecore item on ContentEditor without having to refresh the browser.
  2. Having a new field to preserve the out of the box next state feature, I added a new field to the new template which inherited the Action template.

            public void Process(WorkflowPipelineArgs args)
            {
                Assert.ArgumentNotNull((object)args, nameof(args));
                Item workflowItem = args.DataItem;
    
                string nextStateId = args.CommandItem.Fields["Authentication Next State"]?.GetValue(true);
    
                NameValueCollection parameters = new NameValueCollection();
               //Add paramters here if needed any
    
                Context.ClientPage.Start(this, "Run", new ClientPipelineArgs() { Parameters = parameters });
            }
    
            private void Run(ClientPipelineArgs args)
            {
                if (args.IsPostBack)
                {
                    if (args.HasResult)
                    {
                        string isUserAuthenticated = args.Result?.ToLower();
    
                        if (isUserAuthenticated == "true")
                        {
                            string itemId = args.Parameters["workflowItemId"];
                            string nextStateId = args.Parameters["nextStateId"];
    
                            Item item = Global.ContentDatabase.GetItem(itemId);
                            string workflowNextState = Global.ContentDatabase.GetItem(nextStateId)?.DisplayName;
    
                            if (!string.IsNullOrWhiteSpace(workflowNextState))
                            {
    
                                WorkflowResult result = ChangeWorkflowState(item, workflowNextState);
    
                                if (result.Succeeded)
                                {
                                    string itemLang = args.Parameters["workflowItemLanguage"];
                                    string itemVersion = args.Parameters["workflowItemVersion"];
    
                                    //Refresh the item on content editor
                                    string load = $"item:load(id={itemId},language={itemLang},version={itemVersion})";
                                    Context.ClientPage.ClientResponse.Timer(load, 0);
                                }
                                else
                                {
                                    SheerResponse.Alert(result.Message);
                                }
                            }
                        }
                    }
                }
                else
                {
                    string controlUri = UIUtil.GetUri("control:AuthenticationDialog");
    
                    SheerResponse.ShowModalDialog(controlUri, true);
                    args.WaitForPostBack();
                }
            }
    

To set the result from the Modal

SheerResponse.SetDialogValue("add the result");

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.