开源的 .NET 工作流引擎 Elsa 开源

前言

微软的Workflow Foundation基于.NET Framework,并且没有向.NET Core迁移的计划。

我们的很多项目使用了工作流引擎,这些项目向.NET Core以及更高版本迁移时遇到了不少问题,一直在寻找/开发适合的工作流引擎。.

找到一些开源的项目,可以解决一些问题,还有些项目不是基于.NET生态的,但我希望能有一个长期稳定的基于.NET生态的项目,能够满足多种场景,可以替换原来的Workflow Foundation。

特性

1、同时支持编程工作流定义和配置工作流定义,最好有图形化的管理工具。

2、支持长期工作流。

3、支持有限状态机类型的工作流定义。

4、工作流引擎可以集成在应用中,也可以独立部署为工作流服务器,采用Web API的方式调用。

在我们跟踪的工作流相关项目中,Elsa一直在稳步发展,最新的版本(2.9)已经基本可以满足我们的上述要求了,在以后的版本也会增加对有限状态机的支持。

这里简单介绍一下如何创建工作流服务器和图形化的工作流配置管理应用。

正文

首先,使用Visual Studio 2022创建一个空的ASP.NET Core Web应用,名称为MyElsaServer。

项目创建完成后,使用NuGet包管理器,安装如下程序包:

Install-Package Elsa
Install-Package Elsa.Activities.Http
Install-Package Elsa.Persistence.EntityFramework.Sqlite
Install-Package Elsa.Server.Api

然后,修改项目的Properties/launchSettings.json,去掉通过IIS Express启动的选项:

{
  "profiles": {
    "MyElsaServer": {
      "commandName": "Project",
      "dotnetRunMessages": true,
      "launchBrowser": true,
      "applicationUrl": "http://localhost:5298",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    }
  }
}

最后,修改Program.cs:

using Elsa.Persistence.EntityFramework.Core.Extensions;
using Elsa.Persistence.EntityFramework.Sqlite;

var builder = WebApplication.CreateBuilder(args);


var elsaSection = builder.Configuration.GetSection("Elsa");

// Elsa services.
builder.Services
    .AddElsa(elsa => elsa
        .UseEntityFrameworkPersistence(ef => ef.UseSqlite())
        .AddConsoleActivities()
        .AddHttpActivities(elsaSection.GetSection("Server").Bind)
        .AddJavaScriptActivities()
    );

// Elsa API endpoints.
builder.Services.AddElsaApiEndpoints();

// Allow arbitrary client browser apps to access the API.
// In a production environment, make sure to allow only origins you trust.
builder.Services.AddCors(cors => cors.AddDefaultPolicy(policy => policy
    .AllowAnyHeader()
    .AllowAnyMethod()
    .AllowAnyOrigin()
    .WithExposedHeaders("Content-Disposition"))
);

var app = builder.Build();

app
    .UseCors()
    .UseHttpActivities()
    .UseRouting()
    .UseEndpoints(endpoints =>
     {
       // Elsa API Endpoints are implemented as regular ASP.NET Core API controllers.
       endpoints.MapControllers();
     })
    .UseWelcomePage();
app.Run();

最后,在appSettings.json中增加服务器地址的定义:

  "Elsa": {
    "Http": {
      "BaseUrl": "http://localhost:5298"
    }
  }

启动项目,会出现欢迎界面:

开源的 .NET 工作流引擎 Elsa 开源

服务器可以运行了,但还没有定义工作流,现在我们创建图形化的工作流定义和管理应用,向工作流服务器发布工作流,并查看工作流的执行情况。

在解决方案中增加一个新的ASP.NET Core Web空项目,命名为MyElsaDashboard,修改Properties/launchSettings.json,将项目改为自启动:

{
  "profiles": {
    "MyElsaDashboard": {
      "commandName": "Project",
      "dotnetRunMessages": true,
      "launchBrowser": true,
      "applicationUrl": "http://localhost:5060",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    }
  }
}

在项目中添加如下程序包:

Install-Package Elsa.Designer.Components.Web

修改Program.cs:

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
var app = builder.Build();

app.UseStaticFiles();
app.UseRouting();
app.UseEndpoints(endpoints => { endpoints.MapFallbackToPage("/_Host"); });

app.Run();

然后在项目中创建Pages文件夹,在文件夹中添加两个Razepage页面,名称为_ViewImports.cshtml和_Host.cshtml,_ViewImports的内容如下:

@ addTagHelper *, Microsoft .AspNetCore.Mvc.TagHelpers

_Host.cshtml的内容如下:

@page "/"
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8"/>
    <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
    <title>Elsa Workflows</title>
    <link rel="icon" type="image/png" sizes="32x32" href="/_content/Elsa.Designer.Components.Web/elsa-workflows-studio/assets/images/favicon-32x32.png">
    <link rel="icon" type="image/png" sizes="16x16" href="/_content/Elsa.Designer.Components.Web/elsa-workflows-studio/assets/images/favicon-16x16.png">
    <link rel="stylesheet" href="/_content/Elsa.Designer.Components.Web/elsa-workflows-studio/assets/fonts/inter/inter.css">
    <link rel="stylesheet" href="/_content/Elsa.Designer.Components.Web/elsa-workflows-studio/elsa-workflows-studio.css">
    <script src="/_content/Elsa.Designer.Components.Web/monaco-editor/min/vs/loader.js"></script>
    <script type="module" src="/_content/Elsa.Designer.Components.Web/elsa-workflows-studio/elsa-workflows-studio.esm.js"></script>
</head>
<body>
<elsa-studio-root server-url="http://localhost:5298" monaco-lib-path="_content/Elsa.Designer.Components.Web/monaco-editor/min">
    <elsa-studio-dashboard></elsa-studio-dashboard>
</elsa-studio-root>
</body>
</html>

请注意上面的server-url属性,这里指向我们前面创建的Elsa服务器地址。

现在我们修改解决方案的启动项目,设置为两个项目同时启动:

开源的 .NET 工作流引擎 Elsa 开源

在Visual Studio中执行启动,管理界面如下:

开源的 .NET 工作流引擎 Elsa 开源

选择Workflow Definitions进入流程定义管理界面,点击“Create Workflow”创建新的流程:

开源的 .NET 工作流引擎 Elsa 开源

点击Start,然后选择Http->Http EndPoint,定义流程的入口url:

开源的 .NET 工作流引擎 Elsa 开源

设置完成后按Save保存,可以看到多个一个环节,在这个环节下点击“+”图标可以继续添加环节,这里选择HttpResponse:

开源的 .NET 工作流引擎 Elsa 开源

在Advanced选择卡中,选择Status Code为Ok,添加完成后,流程如下:

开源的 .NET 工作流引擎 Elsa 开源

流程定义完成了,点击Publish发布流程到流程服务器。

流程发布后,可以在流程服务器执行流程。

我们在浏览器访问http://localhost:5298/hello-world,可以看到流程执行的结果:

开源的 .NET 工作流引擎 Elsa 开源

回到流程管理应用,选择Workflow Instances,可以看到刚刚执行完成的流程实例:

开源的 .NET 工作流引擎 Elsa 开源

点击流程Id,可以查看流程执行的详细过程:

开源的 .NET 工作流引擎 Elsa 开源

到此,我们完成了工作流服务和管理应用的创建。

示例代码

Githubd地址:https://github.com/zhenl/MyElsa