Sitecore: Assign workflow to an item programmatically
Asked Answered
S

4

5

I have configured a workflow, starts with "Draft" state as usual. And I have configured the workflow for standard values of the template. It works perfect in Content editor. (When I create an item using the content editor, once I create the item, Workflow gets assigned to the item and it's state becomes "Draft".)

But when I create an item programmatically under the above template it does not assign the workflow. What should I do to assign workflow? Please share any code samples if you have.

Thanks.

Sitecore.Data.Items.TemplateItem template = this.MasterDatabase.GetItem("/sitecore/templates/user defined/sample types");
Sitecore.Data.Items.Item parent = this.MasterDatabase.GetItem(parentId); 

Sitecore.Data.Items.Item newItem;                
// Create new item and retrieve it
newItem = template.CreateItemFrom("sampleName", parent);

newItem.Editing.BeginEdit();

newItem.Name = StringFormatter.CreateItemNameFromID(this.newItem);
newItem.Fields["Title"].Value = "Sample Title"

newItem.Editing.EndEdit();
Shend answered 23/11, 2012 at 11:43 Comment(0)
S
4

Solved the issue with Standard Fields,

newItem.Editing.BeginEdit();                    
newItem.Fields["__Workflow"].Value = "{4D1F00EF-CA5D-4F36-A51E-E77E2BAE4A24}"; //Set workflow
newItem.Fields["__Workflow state"].Value = "{7F39DF46-B4B9-4D08-A0D4-32DE6FD643D1}"; //Set   workflow state to Unposted.
newClassified.Editing.EndEdit();  
Shend answered 29/11, 2012 at 12:34 Comment(4)
I looked all over the place and this seems to be the best answer, I wonder why it doesn't happen more automatically.Russell
Don't use this way to set the hardcoded Guids. Use jRobbins answer to set it properly.Bilection
For our particular need, hard-coded IDs was fine for us. One thing to note is that you can use Sitecore.FieldIDs.Workflow and Sitecore.FieldIDs.WorkflowState instead of __Workflow[...]. For example: itemVersion.Fields[Sitecore.FieldIDs.WorkflowState].Value = approvedState.ToString();.Hoy
Regarding "hard-coded IDs", in fact we had to use hard coded ids' in any Sitecore project (things like Code values, workflow states (check thether it's in a particular state) etc.), best practice is to have a seperate set of static classes for these hard coded item ids'.Shend
S
11

I would not use Dhanuka777's answer as it does not utilise Sitecore's Workflow State Commands and the useful functionality that comes with it e.g. email generation. It also requires hardcoding Guids.

Benefits of the below code:

  • Utilise Sitecore’s State Commands and the nice functionality they have e.g. generating emails to alert users etc
  • Don’t store the Guids of the States and Commands inside the solution
  • Independent of Sitecore's Context
  • Abstract so it can be used for all Workflows in Sitecore.
    public bool UpdateWorkflow(WorkflowState newWorkflowState, Item item)
    {
        Assert.ArgumentNotNull(newWorkflowState, "The new WorkflowState can not be null");
        Assert.ArgumentNotNull(item, "Item can not be null");

        bool successful = false;

        WorkflowState currentWorkflowState = GetWorkflowStateForItem(item);

        if (currentWorkflowState != newWorkflowState)
        {
            IWorkflow workflow = GetWorkflowOfItem(item);

            if (workflow != null)
            {
                List<WorkflowCommand> applicableWorkflowCommands = workflow.GetCommands(currentWorkflowState.StateID).ToList();

                foreach (var applicableWorkflowCommand in applicableWorkflowCommands)
                {
                    Item commandItem = _database.GetItem(applicableWorkflowCommand.CommandID);

                    string nextStateId = commandItem["Next state"];

                    if (nextStateId == newWorkflowState.StateID)
                    {
                        WorkflowResult workflowResult = workflow.Execute(applicableWorkflowCommand.CommandID, item, "", false);
                        successful = workflowResult.Succeeded;
                        break;
                    }
                }
            }
        }
        else
        {
            successful = true;
        }

        return successful;
    }

    public WorkflowState GetWorkflowStateForItem(Item item)
    {
        var workflow = GetWorkflowOfItem(item);
        return workflow != null ? workflow.GetState(item) : null;
    }

    public IWorkflow GetWorkflowOfItem(Item item)
    {
        return _database.WorkflowProvider.GetWorkflow(item);
    }

    private Database _database
    {
        get
        {
            return Sitecore.Data.Database.GetDatabase("master");
        }
    }
Selaginella answered 16/8, 2013 at 9:22 Comment(1)
I don't think this overly complicated code with 4(!) nested if statements should be the "proper" way to do something. moreover doesn't seems to answer the question: how to assign a workflow and a random workflow state to an item. Instead it basically moves the item to the next workflow state if the next state happens to be the desired state.Mackinaw
S
4

Solved the issue with Standard Fields,

newItem.Editing.BeginEdit();                    
newItem.Fields["__Workflow"].Value = "{4D1F00EF-CA5D-4F36-A51E-E77E2BAE4A24}"; //Set workflow
newItem.Fields["__Workflow state"].Value = "{7F39DF46-B4B9-4D08-A0D4-32DE6FD643D1}"; //Set   workflow state to Unposted.
newClassified.Editing.EndEdit();  
Shend answered 29/11, 2012 at 12:34 Comment(4)
I looked all over the place and this seems to be the best answer, I wonder why it doesn't happen more automatically.Russell
Don't use this way to set the hardcoded Guids. Use jRobbins answer to set it properly.Bilection
For our particular need, hard-coded IDs was fine for us. One thing to note is that you can use Sitecore.FieldIDs.Workflow and Sitecore.FieldIDs.WorkflowState instead of __Workflow[...]. For example: itemVersion.Fields[Sitecore.FieldIDs.WorkflowState].Value = approvedState.ToString();.Hoy
Regarding "hard-coded IDs", in fact we had to use hard coded ids' in any Sitecore project (things like Code values, workflow states (check thether it's in a particular state) etc.), best practice is to have a seperate set of static classes for these hard coded item ids'.Shend
L
2

I looked all over for a good answer to this. I was creating a new item and wanted to start its workflow. jRobbins's answer didn't work for me because it throws an exception if the current workflow state of the item is null and it didn't offer a good way of setting the initial workflow state.

The following worked for me:

var workflow = Factory.GetDatabase("master").WorkflowProvider.GetWorkflow(workflowId);
workflow.Start(item);

This sets the workflow of my new item plus sets its workflow state to the initial state.

Lovett answered 7/5, 2014 at 15:53 Comment(0)
R
1

After making sure I'd set a default workflow on the standard values, the following combination, with thanks to posters above, worked perfectly:

var workflowId = item.Fields["__Default workflow"].Value;
var workflow = Factory.GetDatabase("master").WorkflowProvider.GetWorkflow(workflowId);
workflow.Start(item);
Rorie answered 13/8, 2014 at 12:5 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.