Automate Sitecore Workflow Approval Process and Email Report

Automation is the key to tech. It is the process by which tasks which were previously done by humans, are performed entirely by machines. In this post, I shall take you through how to automate Sitecore Workflow Approval for a more efficient way of working.

Why do you need Auto Approve?

Every project has a different set of requirements, and one of the requirements I was tasked to do was to automate the Workflow approval process. You may think, what is the purpose of having a workflow if you want things to be approved automatically. Well, as mentioned earlier, there are different scenarios that may deem such a requirement necessary.

It is not because of the risk in approving content that may be incorrect. It is due to that fact that there are a lot of items in the workflow coming in from the translation agency and in order to verify the content, it requires physical approval to push on to Stage. The automation to be implemented here will help us to know that translations are coming in and send it to the respective content team member to verify. Once verification is done, then in one simple, a user can push it Live.

Read More

Get Sitecore Workflow Items

In this post, you’ll see how to get Sitecore workflow items that are in the specific state of the workflow. I’ve described both the possible ways by which you can do it, Code and Sitecore PowerShell. 🙂

We need, workflow Id and workflow state Id.

var db = Factory.GetDatabase("master");
var workflow = db.WorkflowProvider.GetWorkflow(txtWorkflowID.Text);
var listofWorkflowItems = workflow.GetItems(txtWorkflowStateID.Text);

Above code, will get list of items in the given workflow state. I needed the report of these items along with the URLs. So I added the following code to get the required data. I are going to make use of this piece of code and bring in some more automation in further requirement. I’ll share more details in the upcoming posts.

Layout look as following:

<body>
    <form id="form1" runat="server">
        <h2>Get List of Workflow Items!</h2>
        <table>
            <tr>
                <td>Workflow ID:</td>
                <td>
                    <asp:TextBox ID="txtWorkflowID" runat="server" Width="400" Text="{115CBA9C-D124-49D5-B9D1-314B32155AAB}"></asp:TextBox></td>
            </tr>
            <tr>
                <td>Workflow State ID:</td>
                <td>
                    <asp:TextBox ID="txtWorkflowStateID" runat="server" Width="400" Text="{C8CB5D17-7F02-4A34-B2AE-36D1DB4A7089}"></asp:TextBox></td>
            </tr>
            <tr>
                <td>
                    <asp:Label ID="lblSummary" CssClass="positionAbsolute" Visible="false" Text="" runat="server"></asp:Label></td>
            </tr>
            <tr>
                <td>
                    <asp:Button ID="btnGetWorkflowItems" runat="server" Text="Get Items in Workflow" OnClick="btnGetItemsInWorkflow_Click" />

                </td>
            </tr>
            <tr>
                <td>
                    <asp:Label ID="lblCount" runat="server"></asp:Label></td>
            </tr>
            <tr>
                <td colspan="4">
                    <asp:GridView ID="grdLanguageReport" CssClass="table-style-three" runat="server"></asp:GridView>
                </td>
            </tr>
        </table>
    </form>
</body>

I created the DataTable and fed in the required data into it. Converted the path to URL if an item has any renderings.

Code:

        StringBuilder sb;
        DataTable tb;
        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);
            if (Sitecore.Context.User.IsAuthenticated == false)
            {
                Response.Redirect("login.aspx?returnUrl=GetWorkflowItems.aspx");
            }
        }

        protected void btnGetItemsInWorkflow_Click(object sender, EventArgs e)
        {
            lblSummary.Text = "";
            try
            {
                if (!string.IsNullOrEmpty(txtWorkflowID.Text) && !string.IsNullOrEmpty(txtWorkflowStateID.Text))
                {
                    tb = new DataTable();
                    tb.Columns.Add("Item ID");
                    tb.Columns.Add("Item Path");
                    tb.Columns.Add("Item URL");

                    var db = Factory.GetDatabase("master");
                    if (db != null)
                    {
                        var workflow = db.WorkflowProvider.GetWorkflow(txtWorkflowID.Text);

                        var listofWorkflowItems = workflow.GetItems(txtWorkflowStateID.Text);
                        if (listofWorkflowItems == null || listofWorkflowItems.Count() == 0)
                        {
                            lblSummary.Text = "No Items found";
                            lblSummary.Visible = true;
                        }
                        else
                        {
                            List<string> listofItemsInTheWorkflow = new List<string>();

                            foreach (var ii in listofWorkflowItems)
                            {
                                var currentItem = db.GetItem(ii.ItemID);

                                DataRow itemRow = tb.NewRow();
                                itemRow["Item ID"] = ii.ItemID.ToString();

                                //For Item Path == Get Item ID
                                itemRow["Item Path"] = currentItem.Paths.FullPath;

                                //convert Item Path to URL
                                string getURLWithLanguage = "";
                                if (currentItem.Fields["__Renderings"] != null && currentItem.Fields["__Renderings"].ToString() != string.Empty)
                                {
                                    string urlWithLanguage = "https://www.companywebsite.com/" + ii.Language + "/";
                                    
                                    //Here you can do additional processing if needed
                                    
                                    getURLWithLanguage = currentItem.Paths.FullPath.Replace("/sitecore/content/Home/", urlWithLanguage);
                                    
                                }

                                itemRow["Item URL"] = getURLWithLanguage.ToLower();
                                tb.Rows.Add(itemRow);
                            }
                        }
                    }
                    lblCount.Text = "Total items: " + tb.Rows.Count.ToString();
                    grdLanguageReport.DataSource = tb;
                    grdLanguageReport.DataBind();
                }
            }
            catch (Exception ex)
            {
                lblSummary.Text = ex.StackTrace.ToString();
            }

There is an option to provide the Sitecore Workflow Id and State Id in the text box, and fetch the results based on it. You can add the feature to download the report into a sheet.

Another best way to get it done is using Sitecore PowerShell, if you have power to access on a required environment.

Provide the workflow state ID, find the referrence items using Get-ItemReferrer and then do the required processing. As simple as that.

$workflowStateID = Get-Item -Path master: -ID "{46DA5376-10DC-4B66-B464-AFDAA29DE84F}"
$referringItems = Get-ItemReferrer -Item $workflowStateID

#EmptyArray
$listofWorkflowItems = @()

#$listofWorkflowItems

#Skip System Items
Foreach($item in $referringItems) { 

    $itemPaths = $item.Paths.FullPath
    if($item.Paths.FullPath.contains('/sitecore/content/'))
    {
        $rendering = $item | Get-Rendering
        
        $addInList = New-Object System.Object
        $addInList | Add-Member -type NoteProperty -name ID -Value $item.ID
        $addInList | Add-Member -type NoteProperty -name Path -Value $item.FullPath
        if($rendering){
            $addInList | Add-Member -type NoteProperty -name URL -Value $item.FullPath.Replace("/sitecore/content/Home","https://www.nikkipunjabi.com")
        }
        
        $listofWorkflowItems += $addInList
    }
}

$listofWorkflowItems | Show-ListView

Output:

Hope this will help you as well if you are looking for any similar solution.

Happy Sitecoring!