如何解决使用 Elsa 工作流 ForEach 循环活动
我的工作流程是在这样的信号上触发的:
public async Task<IActionResult> StartApprovalProcess([FromBody] long requestId)
{
if (!ModelState.IsValid)
return BadRequest(ModelState);
// Get data object
var payload = await _mainService.GetBudgetReleaseRequestPayload(requestId);
var input = new Variables();
input.Setvariable("Payload",payload);
// Signal the workflow to start
await _workflowInvoker.TriggerSignalAsync("StartApprovalPhase",input);
return Ok("BRR registered");
}
这是我的有效载荷类:
public class BudgetReleaseRequestApprovalPhasePayloadModel
{
public BudgetReleaseRequestApprovalPhasePayloadModel(BudgetReleaseRequestApprovalPhasePayloadDto model)
{
Id = model.Id;
Description = model.Description;
Amount = model.Amount;
RequesterId = model.RequesterId;
SubmissionDate = model.SubmissionDate;
CostCenterName = model.CostCenterName;
ExpenseTypeName = model.ExpenseTypeName;
RequestTypeName = model.RequestTypeName;
AccountCode = model.AccountCode;
AccountName = model.AccountName;
BpsReferenceNumber = model.BpsReferenceNumber;
ApproversList = new List<BudgetReleaseRequestApproverviewmodel>();
foreach (var budgetReleaseRequestApprover in model.ApproversList)
{
ApproversList.Add(new BudgetReleaseRequestApproverviewmodel(budgetReleaseRequestApprover));
}
}
public long Id { get; set; }
public string Description { get; set; }
public decimal Amount { get; set; }
public string RequesterId { get; set; }
public DateTime SubmissionDate { get; set; }
public string CostCenterName { get; set; }
public string ExpenseTypeName { get; set; }
public string RequestTypeName { get; set; }
public string AccountCode { get; set; }
public string AccountName { get; set; }
public string BpsReferenceNumber { get; set; }
public string AmountFormatted => $"{Amount:N2} AED";
public string DateFormatted => $"{SubmissionDate:dd-MMM-yyyy}";
public string CostCenterandType => $"{CostCenterName}/{ExpenseTypeName}";
public string AccountDetail => $"{AccountCode} - {AccountName}";
public int ApproversCount => ApproversList.Count;
public IList<BudgetReleaseRequestApproverviewmodel> ApproversList { get; set; }
}
这里是作为集合的类:
public class BudgetReleaseRequestApproverviewmodel
{
public BudgetReleaseRequestApproverviewmodel(BudgetReleaseRequestApprover model)
{
RequestId = model.RequestId;
RequestApproverId = model.RequestApproverId;
ApproverId = model.ApproverId;
RequesterId = model.RequesterId;
ApproverSequence = model.ApproverSequence;
ActionId = model.ActionId;
RequestActionId = model.RequestActionId;
}
public long RequestId { get; set; }
public byte RequestApproverId { get; set; }
public string ApproverId { get; set; }
public string RequesterId { get; set; }
public byte ApproverSequence { get; set; }
public Guid? ActionId { get; set; }
public byte? RequestActionId { get; set; }
}
我遵循了主要指南 (https://sipkeschoorstra.medium.com/building-workflow-driven-net-core-applications-with-elsa-139523aa4c50),并且知道我们需要实现一个处理程序,以便在这两种模型的工作流程中使用 Liquid 表达式:
public class LiquidConfigurationHandler : INotificationHandler<EvaluatingLiquidExpression>
{
public Task Handle(EvaluatingLiquidExpression notification,CancellationToken cancellationToken)
{
var context = notification.TemplateContext;
context.MemberAccessstrategy.Register<BudgetReleaseRequestApprovalPhasePayloadModel>();
context.MemberAccessstrategy.Register<BudgetReleaseRequestApproverviewmodel>();
return Task.CompletedTask;
}
}
这是我的测试工作流程:
{
"activities": [{
"id": "abc63216-76e7-42b2-ab7b-5cdb6bbc3ed9","type": "Signaled","left": 122,"top": 365,"state": {
"signal": {
"expression": "StartApprovalPhase","Syntax": "Literal"
},"name": "","title": "Signal: Start Approval Phase","description": "Trigger the workflow when this signal is received."
},"blocking": false,"executed": false,"faulted": false
},{
"id": "ac7669d6-b7e6-4139-825e-5f2b9c1dbdb8","type": "SendEmail","left": 553,"top": 379,"state": {
"from": {
"expression": "my.email@acme.co","to": {
"expression": "my.email@acme.co","subject": {
"expression": "Workflow Testing","body": {
"expression": "<p>BRR #{{ Input.Payload.Id }}</p>\r\n<p>Name: {{ Input.Payload.Description }}</p>\r\n<p>Amount: {{ Input.Payload.AmountFormatted }}</p>\r\n<p>Date: {{ Input.Payload.DateFormatted }}</p>\r\n<br />\r\n<p>Approvers: {{ Input.Payload.ApproversCount }}</p>","Syntax": "Liquid"
},"title": "Email: Test","description": ""
},{
"id": "2efcffa9-8e18-45cf-aac8-fcfdc8846df8","type": "ForEach","left": 867,"top": 474,"state": {
"collectionExpression": {
"expression": "{{ Input.Payload.ApproversList }}","iteratorName": "","title": "",{
"id": "7966b931-f683-4b81-aad4-ad0f6c628191","left": 1042,"top": 675,"subject": {
"expression": "Looping #","body": {
"expression": "Loop Details",{
"id": "5f246eda-271d-46ed-8efe-df0f26d542be","left": 1163,"top": 325,"state": {
"name": "","from": {
"expression": "my.email@acme.co","subject": {
"expression": "Loop Over","body": {
"expression": "Loop Finished","faulted": false
}
],"connections": [{
"sourceActivityId": "2efcffa9-8e18-45cf-aac8-fcfdc8846df8","destinationActivityId": "5f246eda-271d-46ed-8efe-df0f26d542be","outcome": "Done"
},{
"sourceActivityId": "abc63216-76e7-42b2-ab7b-5cdb6bbc3ed9","destinationActivityId": "ac7669d6-b7e6-4139-825e-5f2b9c1dbdb8",{
"sourceActivityId": "ac7669d6-b7e6-4139-825e-5f2b9c1dbdb8","destinationActivityId": "2efcffa9-8e18-45cf-aac8-fcfdc8846df8",{
"sourceActivityId": "2efcffa9-8e18-45cf-aac8-fcfdc8846df8","destinationActivityId": "7966b931-f683-4b81-aad4-ad0f6c628191","outcome": "Iterate"
},{
"sourceActivityId": "7966b931-f683-4b81-aad4-ad0f6c628191","outcome": "Done"
}
]
}
这是我的结果:
- 信号:有效
- 第一封电子邮件:作品:
-
ForEach 失败,我在调试中发现:
失败:Elsa.Expressions.WorkflowExpressionEvaluator[0] 评估 JavaScript 表达式“{{ Input.Payload.ApproversList }}”时出错。消息:输入未定义 参考错误:输入未定义 失败:Elsa.Services.ActivityInvoker[0] 调用工作流 de8e12d4645e4480abccbbe562b48448 的活动 2efcffa9-8e18-45cf-aac8-fcfdc8846df8 时出错 Elsa.Exceptions.WorkflowException:评估 JavaScript 表达式“{{ Input.Payload.ApproversList }}”时出错。消息:输入未定义 ---> ReferenceError:输入未定义 --- 内部异常堆栈跟踪结束 --- 在 Elsa.Expressions.WorkflowExpressionEvaluator.EvaluateAsync(IWorkflowExpression 表达式,类型类型,WorkflowExecutionContext 工作流执行上下文,CancellationToken 取消令牌) 在 Elsa.Extensions.WorkflowExpressionEvaluatorExtensions.EvaluateAsync[T](IWorkflowExpressionEvaluator 评估器,IWorkflowExpression
1 expression,WorkflowExecutionContext workflowExecutionContext,CancellationToken cancellationToken) at Elsa.Activities.ControlFlow.Activities.ForEach.OnExecuteAsync(WorkflowExecutionContext context,CancellationToken cancellationToken) at Elsa.Services.ActivityInvoker.InvokeAsync(WorkflowExecutionContext workflowContext,IActivity activity,Func
2 invokeAction)失败:Elsa.Services.WorkflowInvoker[0] dbupdateException 从 Elsa.WorkflowEventHandlers.PersistenceWorkflowEventHandler 抛出的 IWorkflowEventHandler Microsoft.EntityFrameworkCore.dbupdateException:更新条目时出错。有关详细信息,请参阅内部异常。 ---> Newtonsoft.Json.JsonSerializationException:检测到类型为“Jint.Engine”的属性“Engine”的自引用循环。路径“Exception.InnerException.Error.Engine.Global”。
我需要迭代 BudgetReleaseRequestApproverviewmodel
、发送电子邮件、等待操作、重复,但我无法弄清楚循环。
解决方法
此答案基于我在 GitHub issue 上提供的评论,这是 OP 问题的重复。为了完整起见,我提供以下内容。
尝试对 ForEach 活动使用 input
函数(确保所选语法为 JavaScript):
input('PayLoad').ApproverList
这将获得名为 "PayLoad"
的输入。
我不知道 Liquid 是否应该起作用。从 UX 的角度来看,我们应该要么确保它有,要么在没有的情况下甚至不允许该选项。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。