Workflow not working if the item created/updated programmatically

Hi,

I am facing issue related to Workflow.

We have basic workflow and assigned to template standard value. When I log-in with user (with read/write permission), I can edit the item and workflow works fine.

But if the same item edited programmatically, (using the same user), then item simply get updated without any workflow status.

I am using the same user in the code for updating the item:

const string testUser = @"sitecore\testuser";
if (Sitecore.Security.Accounts.User.Exists(testUser))
{
var user = Sitecore.Security.Accounts.User.FromName(testUser, true);

using (new Sitecore.Security.Accounts.UserSwitcher(user))
{
        // Edit the items
}
}

I can see item is updated with the mentioned user, but version is not created before updating.

Please let me know what might be the issue here and what is the best way to fix.

Note: I am using Glass Mapper API to add/update the items

 

Thanks,

Sharath

  • Hi Sharath,

    In order to programatically progress a Sitecore item through workflow you should use Sitecore's workflow api, simply editing the item is not enough.

    Here is a code snippet that demonstrates how to use the workflow api:

    // couple of using statements you will need
    
    using Sitecore.Workflows;
    using Sitecore.Workflows.Simple;
    
    // get the workflow associated with the item
    
    IWorkflow workflow = item.Database.WorkflowProvider.GetWorkflow(item);
    
    // get the workflow state the item is currently in
    
    WorkflowState state = workflow.GetState(item);
    
    // depending on your scenario you may want to check if the item is already in the final state before proceeding
    
    if (!state.FinalState)
    {
        // get the workflow command in the current workflow state that you want to execute (get by id is safer, using DisplayName for illustration)
    
        WorkflowCommand command = workflow.GetCommands(state.StateID).FirstOrDefault(c => c.DisplayName == "Approve");
    
        if (command != null)
        {
            using (new SecurityDisabler())
            {
                workflow.Execute(command.CommandID, item, string.Empty, false, new object[0]);
            }                                        
        }
    }

  • In reply to Nick Allen:

    Thanks Nick for the details provided. I tried this along with some other changes but I still not able achieve the results same as happens in content editor. Basically I want to edit/save the item programmatically and put it to draft mode and other user should be able to see in their workbox to review and submit the changes. I can edit and change to draft status, but those item not appearing any other users workbox. If I do the same chamges manually and keep it in draft mode, then I can see those items in other users's workbox were those items can be reviewed and submitted. Thanks again.

    -Sharath
  • In reply to Sharath Kumar:

    Were you ever able to figure this out?
  • In reply to Sharath Kumar:

    Were you ever able to figure this out?
  • I was working with workflow only for projects on sitecore 7, but I think it will work for newer versions too. So I use this methods, might be they help you:

    private IWorkflow SetWorkflow(Item item, string workflowId)
    {
        Assert.ArgumentNotNull(item, "item");
        Assert.ArgumentNotNullOrEmpty(workflowId, "workflowId");
    
        IWorkflowProvider workflowProvider = item.Database.WorkflowProvider;
    
        IWorkflow itemWorkflow = workflowProvider.GetWorkflow(item);
    
        IWorkflow workflow = workflowProvider.GetWorkflow(workflowId);
        if (workflow == null) return null;
    
        if (itemWorkflow == null || workflow.WorkflowID != itemWorkflow.WorkflowID)
        {
            workflow.Start(item);
        }
    
        return workflow;
    }

    private WorkflowResult SetWorkflowState(Item item, ID stateId)
    {
        Assert.ArgumentNotNull(item, "item");
        Assert.ArgumentNotNull(stateId, "stateId");
    
        IWorkflow workflow = item.Database.WorkflowProvider.GetWorkflow(item);
    
        if (workflow == null) return new WorkflowResult(false, "No workflow assigned to item: " + item.ID);
    
        if (!workflow.GetStates().Any(state => state.StateID.Equals(stateId.ToString(), StringComparison.OrdinalIgnoreCase)))
            return new WorkflowResult(false, "Cannot find workflow state: " + stateId);
    
        using (new EditContext(item))
        {
            item[FieldIDs.WorkflowState] = stateId.ToString();
        }
    
       return new WorkflowResult(true, "OK", stateId);
    }

    private WorkflowResult ExecuteCommand(Item item, string commandId)
    {
        Assert.ArgumentNotNull(item, "item");
        Assert.ArgumentNotNullOrEmpty(commandId, "commandId");
    
        IWorkflow workflow = item.Database.WorkflowProvider.GetWorkflow(item);
    
        if (workflow == null) return new WorkflowResult(false, "No workflow assigned to item: " + item.ID);
    
        WorkflowCommand command = workflow.GetCommands(item[FieldIDs.WorkflowState]).FirstOrDefault(c => c.CommandID.Equals(commandId, StringComparison.OrdinalIgnoreCase));
    
        if (command == null) return new WorkflowResult(false, "Workflow command not found: " + commandId);
            return workflow.Execute(command.CommandID, item, string.Empty, false, new object[0]);
    }

    also you can try this:

    item.Fields[FieldIDs.Workflow].Value = /*ID*/;
    item.Fields[FieldIDs.WorkflowState].Value = /*ID*/;

     Discussion on stackoverflow, about the variant above