開源的.Net 工作流引擎Elsa初試——建立工作流伺服器和圖形化工作流配置管理應用

尋找無名的特質發表於2022-06-04

微軟的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"
    }
  }

啟動專案,會出現歡迎介面:

伺服器可以執行了,但還沒有定義工作流,現在我們建立圖形化的工作流定義和管理應用,向工作流伺服器釋出工作流,並檢視工作流的執行情況。
在解決方案中增加一個新的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伺服器地址。
現在我們修改解決方案的啟動專案,設定為兩個專案同時啟動:

在Visual Studio中執行啟動,管理介面如下:

選擇Workflow Definitions進入流程定義管理介面,點選“Create Workflow”建立新的流程:

點選Start,然後選擇Http->Http EndPoint,定義流程的入口url:

設定完成後按Save儲存,可以看到多個一個環節,在這個環節下點選“+”圖示可以繼續新增環節,這裡選擇HttpResponse:

在Advanced選擇卡中,選擇Status Code為Ok,新增完成後,流程如下:

流程定義完成了,點選Publish釋出流程到流程伺服器。
流程釋出後,可以在流程伺服器執行流程。我們在瀏覽器訪問http://localhost:5298/hello-world,可以看到流程執行的結果:

回到流程管理應用,選擇Workflow Instances,可以看到剛剛執行完成的流程例項:

點選流程Id,可以檢視流程執行的詳細過程:

到此,我們完成了工作流服務和管理應用的建立,上述示例程式碼可以從github下載:https://github.com/zhenl/MyElsa

相關文章