在 Sitecore 中更改工作流状态

Changing workflow state in Sitecore

我在以编程方式更改项目的工作流状态时遇到问题。无论我对该领域做什么,状态都不会改变。我试过 using (new SecurityDisabler()){} 并将项目置于编辑模式,然后手动更改字段。我注意到该项目本身的锁定设置为 <r />,这会导致问题吗?

这是我尝试做的一些示例代码:

        [HttpPost]
        [MultipleButton(Name = "action", Argument = "Submit")]
        public ActionResult Submit(LoI model)
        {
            if (model.Submitted || !model.Signed)
            {
                return Redirect("/Profile/LoI");
            }

            ModifyCandidateInfo(model, true);

            Session["message"] = Translate.Text("loi-submitted-message");
            Session["messageClass"] = "success";

            return Redirect("/Profile/LoI");
        }
    private static void ModifyCandidateInfo(LoI model, bool isSubmission)
    {
        using (new SecurityDisabler())
        {
            var candidateFolder = CBUtility.GetCandidateFolder();

            var loi= candidateFolder.GetChildren().SingleOrDefault(loi => loi.TemplateID == LoITemplateId);

            if (loi == null) return;

            loi.Editing.BeginEdit();

            EditFields(loi, model);

            EditChildren(loi, model);

            //Send emails upon submission
            if (isSubmission)
            {
                loi.ExecuteCommand("Submit",
                    loi.Name + " submitted for " + model.CandidateName);

                using (new SecurityDisabler())
                {
                    loi.Editing.BeginEdit();

                    loi.Fields["__Workflow state"].Value = "{F352B651-341B-4CCF-89FE-BD77F5E4D540}";
                    loi.Editing.EndEdit();
                }
            }

            loi.Editing.EndEdit();


        }

    }

我使用以下函数初始化了项目的工作流程:

public static void InitializeWorkflow(Item item, ID workflowId)
        {
            item.Editing.BeginEdit();
            var workflow =
                item.Database.WorkflowProvider.GetWorkflow(workflowId.ToString());
            workflow.Start(item);
            item.Editing.EndEdit();
        }

该项目以默认的起草状态开始,并执行了一个 "Submit" 命令来发送电子邮件。通过 Sitecore UI,如果我点击提交,它将进入下一个工作流程状态,但在我启动 ExecuteCommand 函数时不会以编程方式进入。您将在下面找到 ExecuteCommand 函数。

public static WorkflowResult ExecuteCommand(this Item item, string commandName, string comment)
        {
            using (new SecurityDisabler())
            {
                var workflow = item.Database.WorkflowProvider.GetWorkflow(item);
                if (workflow == null)
                {
                    return new WorkflowResult(false, "No workflow assigned to item");
                }

                var command = workflow.GetCommands(item[FieldIDs.WorkflowState])
                    .FirstOrDefault(c => c.DisplayName == commandName);
                return command == null
                    ? new WorkflowResult(false, "Workflow command not found")
                    : workflow.Execute(command.CommandID, item, comment, false);
            }
        }

命令正常启动并且电子邮件已发送,但我不明白为什么状态不会改变。有人可以向我提供其他建议或解决方案吗?

我是否正确读取了工作流状态 ID?我正在使用工作流状态的项目 ID。

我认为您的代码与我的实现非常相似。这是我的代码背景。

所有项目都具有名为 "WF" 的相同工作流,并且它具有三种工作流状态(工作中、等待批准和已批准)。具有 "WF" 的一个页面项目有一些渲染项目和那些数据源项目。假设内容编辑准备好提交和批准该项目及其相关项目。通过点击页面中的 "Submit" 和 "Approval" 按钮,所有页面项目的相关项目都具有与页面项目相同的工作流状态。

大部分代码来自 Marek Musielak,这段代码在我这边工作得很好。

public class UpdateWorkflowState
{
    // List all controls in page item
    public RenderingReference[] GetListOfSublayouts(string itemId, Item targetItem)
    {
        RenderingReference[] renderings = null;

        if (Sitecore.Data.ID.IsID(itemId))
        {
            renderings = targetItem.Visualization.GetRenderings(Sitecore.Context.Device, true);
        }
        return renderings;
    }

    // Return all datasource defined on one item
    public IEnumerable<string> GetDatasourceValue(WorkflowPipelineArgs args, Item targetItem)
    {
        List<string> uniqueDatasourceValues = new List<string>();
        Sitecore.Layouts.RenderingReference[] renderings = GetListOfSublayouts(targetItem.ID.ToString(), targetItem);

        LayoutField layoutField = new LayoutField(targetItem.Fields[Sitecore.FieldIDs.FinalLayoutField]);
        LayoutDefinition layoutDefinition = LayoutDefinition.Parse(layoutField.Value);
        DeviceDefinition deviceDefinition = layoutDefinition.GetDevice(Sitecore.Context.Device.ID.ToString());

        foreach (var rendering in renderings)
        {
            if (!uniqueDatasourceValues.Contains(rendering.Settings.DataSource))
                uniqueDatasourceValues.Add(rendering.Settings.DataSource);
        }

        return uniqueDatasourceValues;
    }

    // Check workflow state and update state
    public WorkflowResult ChangeWorkflowState(Item item, ID workflowStateId)
    {
        using (new EditContext(item))
        {
            item[FieldIDs.WorkflowState] = workflowStateId.ToString();
        }

        Sitecore.Layouts.RenderingReference[] renderings = GetListOfSublayouts(item.ID.ToString(), item);
        return new WorkflowResult(true, "OK", workflowStateId);
    }

    // Verify workflow state and update workflow state
    public WorkflowResult ChangeWorkflowState(Item item, string workflowStateName)
    {
        IWorkflow workflow = item.Database.WorkflowProvider.GetWorkflow(item);
        if (workflow == null)
        {
            return new WorkflowResult(false, "No workflow assigned to item");
        }

        WorkflowState newState = workflow.GetStates().FirstOrDefault(state => state.DisplayName == workflowStateName);

        if (newState == null)
        {
            return new WorkflowResult(false, "Cannot find workflow state " + workflowStateName);
        }

        unlockItem(newState, item);

        return ChangeWorkflowState(item, ID.Parse(newState.StateID));
    }

    // Unlock the item when it is on FinalState
    public void unlockItem(WorkflowState newState, Item item)
    {
        if (newState.FinalState && item.Locking.IsLocked())
        {
            using (new EditContext(item, false, false))
            {
                item["__lock"] = "<r />";
            }
        }
    }
}