.Net工作流elsa-workflows官方文档学习:简单的文件审批工作流
网页:https://elsa-workflows.github.io/elsa-core/docs/guides-document-approval
在本节中,我们将执行以下操作:
- 以编程方式定义长时间运行的工作流,在HTTP请求到达指定URL时执行,接受带有JSON负载的POST请求,该JSON负载表示要检查的文档。
- 相关活动组件:ReceiveHttpRequest,WriteHttpResponse,Fork,Join,SetVariable,Signaled,SendEmail和IfElse。
此工作流的目的是允许作者提交文档(建模为JSON对象),并允许审阅者批准或拒绝此文档。 此外,如果审阅者花费的时间太长而无法采取行动,则会定期提醒他。
我们将发布到工作流中的JSON有效负载如下所示:
{ "Id": "1", "Author": { "Name": "John", "Email": "john@gmail.com" }, "Body": "This is sample document." }
使用访问此模型的JavaScript表达式查看活动时,请牢记此结构。
创建ASP.NET Core项目
创建一个名为Elsa.Guides.ContentApproval.WebApp的新的空ASP.NET Core项目,并添加以下程序包:
- Elsa.Core
- Elsa.Activities.Email
- Elsa.Activities.Http
- Elsa.Activities.Timers
创建工作流类
using System; using System.Dynamic; using System.Net; using System.Net.Http; using Elsa.Activities.ControlFlow; using Elsa.Activities.Email.Activities; using Elsa.Activities.Http.Activities; using Elsa.Activities.Primitives; using Elsa.Activities.Timers.Activities; using Elsa.Activities.Workflows; using Elsa.Expressions; using Elsa.Services; using Elsa.Services.Models; namespace Elsa.Guides.DocumentApproval.WebApp { public class DocumentApprovalWorkflow : IWorkflow { public void Build(IWorkflowBuilder builder) { builder .StartWith<ReceiveHttpRequest>( x => { x.Method = HttpMethod.Post.Method; x.Path = new Uri("/documents", UriKind.Relative); x.ReadContent = true; } ) .Then<SetVariable>( x => { x.VariableName = "Document"; x.ValueExpression = new JavaScriptExpression<ExpandoObject>("lastResult().Body"); } ) .Then<SendEmail>( x => { x.From = new LiteralExpression("approval@acme.com"); x.To = new JavaScriptExpression<string>("Document.Author.Email"); x.Subject = new JavaScriptExpression<string>("`Document received from ${Document.Author.Name}`"); x.Body = new JavaScriptExpression<string>( "`Document from ${Document.Author.Name} received for review. " + "<a href=\"${signalUrl('Approve')}\">Approve</a> or <a href=\"${signalUrl('Reject')}\">Reject</a>`" ); } ) .Then<WriteHttpResponse>( x => { x.Content = new LiteralExpression( "<h1>Request for Approval Sent</h1><p>Your document has been received and will be reviewed shortly.</p>" ); x.ContentType = "text/html"; x.StatusCode = HttpStatusCode.OK; x.ResponseHeaders = new LiteralExpression("X-Powered-By=Elsa Workflows"); } ) .Then<SetVariable>( x => { x.VariableName = "Approved"; x.ValueExpression = new JavaScriptExpression<bool>("false"); } ) .Then<Fork>( x => { x.Branches = new[] { "Approve", "Reject", "Remind" }; }, fork => { fork .When("Approve") .Then<Signaled>(x => x.Signal = new LiteralExpression("Approve")) .Then("Join"); fork .When("Reject") .Then<Signaled>(x => x.Signal = new LiteralExpression("Reject")) .Then("Join"); fork .When("Remind") .Then<TimerEvent>( x => x.TimeoutExpression = new LiteralExpression<TimeSpan>("00:00:10"), name: "RemindTimer" ) .Then<IfElse>( x => x.ConditionExpression = new JavaScriptExpression<bool>("!!Approved"), ifElse => { ifElse .When(OutcomeNames.False) .Then<SendEmail>( x => { x.From = new LiteralExpression("reminder@acme.com"); x.To = new LiteralExpression("approval@acme.com"); x.Subject = new JavaScriptExpression<string>( "`${Document.Author.Name} is awaiting for your review!`" ); x.Body = new JavaScriptExpression<string>( "`Don't forget to review document ${Document.Id}.<br/>" + "<a href=\"${signalUrl('Approve')}\">Approve</a> or <a href=\"${signalUrl('Reject')}\">Reject</a>`" ); } ) .Then("RemindTimer"); } ); } ) .Then<Join>(x => x.Mode = Join.JoinMode.WaitAny, name: "Join") .Then<SetVariable>( x => { x.VariableName = "Approved"; x.ValueExpression = new JavaScriptExpression<object>("input('Signal') === 'Approve'"); } ) .Then<IfElse>( x => x.ConditionExpression = new JavaScriptExpression<bool>("!!Approved"), ifElse => { ifElse .When(OutcomeNames.True) .Then<SendEmail>( x => { x.From = new LiteralExpression("approval@acme.com"); x.To = new JavaScriptExpression<string>("Document.Author.Email"); x.Subject = new JavaScriptExpression<string>("`Document ${Document.Id} approved!`"); x.Body = new JavaScriptExpression<string>( "`Great job ${Document.Author.Name}, that document is perfect! Keep it up.`" ); } ); ifElse .When(OutcomeNames.False) .Then<SendEmail>( x => { x.From = new LiteralExpression("approval@acme.com"); x.To = new JavaScriptExpression<string>("Document.Author.Email"); x.Subject = new JavaScriptExpression<string>("`Document ${Document.Id} rejected`"); x.Body = new JavaScriptExpression<string>( "`Sorry ${Document.Author.Name}, that document isn't good enough. Please try again.`" ); } ); } ); } } }
ReceiveHttpRequest
.StartWith<ReceiveHttpRequest>( x => { x.Method = HttpMethod.Post.Method; x.Path = new Uri("/documents", UriKind.Relative); x.ReadContent = true; } )