C# .NET 6 使用WorkFlow Core 创建工作审批流

net,workflow,core · 浏览次数 : 14

小编点评

本文介绍了工作流思想的发展历程、实现方式以及如何使用工作流技术提高工作效率。首先,文章回顾了工作流技术的起源,从20世纪60年代开始,经历了七八十年代的尝试和90年代的高峰发展。接着,文章以一个具体的OA系统为例,详细讲解了如何在工作流系统中实现材料的申报和个人请假的审批流程。 1. **工作流概念与应用**:文章首先介绍了工作流思想的起源,指出早在20世纪60年代就有研究者提出,并在70年代尝试实现,但由于技术限制未能成功。 2. **实现方式选择**:文章选择了使用第三方框架WorkFlow Core来实现工作流系统,并详细介绍了使用JSON或YAML文件来定义工作流程的方式。 3. **工作流系统架构**:文章详细描述了工作流系统的架构,包括工步的定义、工作流的构建以及如何在项目启动文件中进行配置和启动工作流。 4. **控制器与流程注册**:文章展示了如何通过API控制器来调用工作流,并提供了模拟申请请假单的流程,包括管理员审批的逻辑。 5. **效果展示**:文章通过效果图演示了请假单流程的效果,展示了工作流在实际操作中的应用。 6. **JSON和工作流注入**:文章最后介绍了如何使用JSON文件来定义工作流程,并通过注入这些定义到工作流系统的实例中来触发流程的执行。这为前端与后端的交互提供了一种简单且灵活的方式。 综上所述,本文通过详细的步骤和示例代码,向读者展示了一个工作流系统的实现过程,以及如何在不同时代背景下,采用不同的技术和实现手段来支持工作的自动化和流程优化。

正文

1,背景

  工作流思想在上世纪60年代就有人提出过;70年代就有人开始尝试,但是由于当时许多的限制,工作流一直没有成功的被实现;80年代才出现第一批成功的工作流系统;90年代工作流技术走向了第一个发展高峰期;90年代后至今工作流出现了很多版本,但是主旨还是不变的,为了使我们的工作变得更加高效。

  通俗点,我们经常使用的OA系统上。关于一个材料的申报,又或者个人的请假。这些流程就属于工作流(工作审批流)。其中对于审批人和各个节点是可以动态操作的。

  工作流可以通过数据库设计的形式实现,也可以使用第三方的框架Elsa,Workflow Core。本文使用第二种,并详细的介绍一下代码实现和json实现工作流程。

2,安装

  使用Nuget包管理工具安装以下的包:  

    Workflow Core 3.10.0          核心包不解释

    WorkflowCore.DSL 3.10.0        json或者yaml注入需要

    WorkflowCore.Persistence.MySQL    持久化

3,文档

  JSON / YAML Definitions - Workflow Core (workflow-core.readthedocs.io)

 

  WorkFlowCore 加载Json文件 - 编程代码 (cscoder.cn)

 

4,例子

1,创建项目

  控制台或者WebApi项目均可,这里拿WebApi项目举例。(版本用的是.net 6)

2,添加工步

  工步文件需要继承StepBody。现在添加一个Hello.cs和Goodbye的工步,代码如下:

using WorkflowCore.Interface;
using WorkflowCore.Models;

namespace WorkFlowCore_Test.WorkFlows.HelloWord.Steps
{
    public class Hello : StepBody
    {
        public override ExecutionResult Run(IStepExecutionContext context)
        {
            Console.WriteLine("Hello World!");
            return ExecutionResult.Next();
        }
    }
}

 

using WorkflowCore.Interface;
using WorkflowCore.Models;

namespace WorkFlowCore_Test.WorkFlows.HelloWord.Steps
{
    public class Goodbye : StepBody
    {
        public override ExecutionResult Run(IStepExecutionContext context)
        {
            Console.WriteLine("Goodbye World!");
            return ExecutionResult.Next();
        }
    }
}

3,添加工作流文件

  工作流文件需要继承IWorkflow。现在开始添加:

using WorkflowCore.Interface;
using WorkFlowCore_Test.WorkFlows.HelloWord.Steps;

namespace WorkFlowCore_Test.WorkFlows.HelloWord
{
    public class HelloWorldWorkflow : IWorkflow
    {
        public string Id => "HelloWorld";

        public int Version => 1;

        public void Build(IWorkflowBuilder<object> builder)
        {
            builder
                .StartWith<Hello>()
                .Then<Goodbye>();
        }
    }
}

4,配置和启动

  基本数据都准备好了之后,在项目启动文件进行一下配置。代码如下:

using Microsoft.AspNetCore.Mvc;
using System.Xml.Linq;
using WorkflowCore.Interface;
using WorkflowCore.Services;
using WorkflowCore.Services.DefinitionStorage;
using WorkFlowCore_Test.Utils;
using WorkFlowCore_Test.WorkFlows.AskForLeave.Model;
using WorkFlowCore_Test.WorkFlows.AskForLeave;
using WorkFlowCore_Test.WorkFlows.HelloWord;
using WorkFlowCore_Test.WorkFlows.IfStatement;
using WorkFlowCore_Test.WorkFlows.IfStatement.Model;
using WorkFlowCore_Test.WorkFlows.Json.Steps;
using WorkFlowCore_Test.WorkFlows.SimpleDecision;

namespace WorkFlowCore_Test
{
    public class Program
    {
        public static void Main(string[] args)
        {
            var builder = WebApplication.CreateBuilder(args);
            // Add services to the container.
            builder.Services.AddAuthorization();
            builder.Services.AddControllers();
            builder.Services.AddLogging(); // WorkflowCore需要用到logging service
            //持久化
            builder.Services.AddWorkflow(cfg =>
            {
                cfg.UseMySQL("server=127.0.0.1;Database=Workflow;Uid=root;Pwd=xunpai123.", true, true);
            });
            builder.Services.AddWorkflowDSL();//用来注入json和yaml

            var app = builder.Build();

            //核心注入方法
            UseWorkflow(app);

            app.UseAuthorization();
            app.MapControllers();
            app.Run();
        }


        public static void UseWorkflow(WebApplication app)
        {
            var host = app.Services.GetService<IWorkflowHost>();

            #region 工步注册
            //c#代码注册
            host?.RegisterWorkflow<HelloWorldWorkflow>();
            //json注册
            #endregion

            host?.Start();
            // 通过DI获取IHostApplicationLifetime实例
            var applicationLifetime = app.Services.GetService(typeof(IHostApplicationLifetime)) as IHostApplicationLifetime;
            applicationLifetime?.ApplicationStopping.Register(() =>
            {
                host?.Stop();
            });
        }


    }
}

 

  这个时候我们添加api控制器进行调用这个helloworld的流程。代码如下:

using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Diagnostics;
using System.Net.Http.Json;
using System.Text.Json.Nodes;
using WorkflowCore.Interface;
using WorkflowCore.Models;
using WorkflowCore.Services;
using WorkflowCore.Services.DefinitionStorage;
using WorkFlowCore_Test.Utils;
using WorkFlowCore_Test.WorkFlows.AskForLeave.Model;
using WorkFlowCore_Test.WorkFlows.SimpleDecision;

namespace WorkFlowCore_Test.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class TestApiController : ControllerBase
    {
        private IWorkflowController WorkflowService;
        private IWorkflowHost WorkflowHost;
        public TestApiController(IWorkflowController workflowService, IWorkflowHost workflowHost)
        {
            WorkflowService = workflowService;
            WorkflowHost = workflowHost;
        }

        [Route("WorkFlowCoreTestDemo")]
        [HttpGet]
        public string WorkFlowCoreTestDemo()
        {
            //var initialData = new LeaveRequestData
            //{
            //    RequestId = "11111",
            //    RequestMsg = "开始请假"
            //};

            //WorkflowHost.StartWorkflow("LeaveRequestWorkflow", 1, initialData);

            WorkflowService.StartWorkflow("HelloWorld");
            return "true";
        }

        

    }
}

5,效果展示

  启动后调用我们的控制器方法,然后观看console 的变化,如图:

 

6,请假单流程

  请假单的流程创建的话需要用到等待的函数,等待管理员进行审核后进行下一步的操作。请假单的流程代码如下:

    public class LeaveRequestData
    {
        public string RequestId { get; set; }
        public bool ManagerApproved { get; set; }
        public bool HRApproved { get; set; }
        public string RequestMsg { get; set; }
    }
using WorkflowCore.Interface;
using WorkFlowCore_Test.WorkFlows.AskForLeave.Model;
using WorkFlowCore_Test.WorkFlows.AskForLeave.Steps;
using WorkFlowCore_Test.WorkFlows.SimpleDecision.Steps;

namespace WorkFlowCore_Test.WorkFlows.AskForLeave
{
    public class AskForLeaveWorkflow : IWorkflow<LeaveRequestData>
    {
        public string Id => "LeaveRequestWorkflow";
        public int Version => 1;

        public void Build(IWorkflowBuilder<LeaveRequestData> builder)
        {
            builder.StartWith(context => Console.WriteLine("提交请假申请"))
                .Activity("manage-audit", (data) => data.RequestMsg)
                    .Output(data => data.ManagerApproved, step => step.Result)
                .Then<ManagerApprovalStep>().Input(step => step.AuditDataInfo, data => data)
                .If(data => data.ManagerApproved)
                    .Do(then => then.StartWith(context => Console.WriteLine("经理审核")));

            
        }
    }
}

  然后创建好之后,在启动文件进行注册一下:

            host?.RegisterWorkflow<AskForLeaveWorkflow, LeaveRequestData>();

  好了,接下来我们就可以用接口的形式进行模拟了。首先我们新增一个接口用来模拟申请请求代码如下:

        [Route("WorkFlowCoreTestDemo")]
        [HttpGet]
        public string WorkFlowCoreTestDemo()
        {
            var initialData = new LeaveRequestData
            {
                RequestId = "11111",
                RequestMsg = "开始请假"
            };

            WorkflowHost.StartWorkflow("LeaveRequestWorkflow", 1, initialData);

            //WorkflowService.StartWorkflow("HelloWorld");
            return "true";
        }

  然后创建一个管理员的审批方法,用来审核通过或者拒绝。代码如下:

        [Route("WorkFlowCoreTestDemo4")]
        [HttpGet]
        public async Task<string> WorkFlowCoreTestDemo4()
        {
            //获取待决活动
            var approval = await WorkflowHost.GetPendingActivity("manage-audit", "worker1");
           

            if (approval != null)
            {
                Console.WriteLine("需要批准的" + approval.Parameters);
                //提交活动成功
                await WorkflowHost.SubmitActivitySuccess(approval.Token, true);//true,代表审批通过。逻辑验证在步骤里面
            }
            return "请假工作流";
        }

  好了,这样就形成闭环了。大家可以在postman上请求测试一下,观察console的变化了。

7,json注入

  最后就是json注入的方式了,这种方式也是目前我比较倾向的方式,和前端对接就很方便的。前端按照固定的格式给后端传入json数据,后端根据json数据解析工步进行开启工作流。

  首先需要创建一个json文件,json文件代码如下:

{
  "Id": "HelloWorldJson",
  "Version": 1,
  "Steps": [
    {
      "Id": "Hello",
      "StepType": "",
      "NextStepId": "Bye"
    },
    {
      "Id": "Bye",
      "StepType": ""

    }
  ]
}

  然后在启动文件配置,注入一下json工作流:

//json注册
var loader = app.Services.GetService<IDefinitionLoader>();     
var json = System.IO.File.ReadAllText("WorkFlows/Json/JsonYaml.json");// 假设文件位于程序运行目录
// 【json注入时候,stepType写这个程序集的类名】获取并打印全限定名,包括程序集名称
//Type myClassType = typeof(HelloWorldStep);
//string fullAssemblyClassName = myClassType.AssemblyQualifiedName;
loader?.LoadDefinition(json, Deserializers.Json);

  到这里就可以了,创建一个api方法来调用看看:

        [Route("WorkFlowCoreTestDemo6")]
        [HttpGet]
        public string WorkFlowCoreTestDemo6()
        {
            WorkflowHost.StartWorkflow("HelloWorldJson", 1, null);
            return "";
        }

  到这里就可以实现json注入工作流了。不过细心的朋友就发现了,我给的json文件中的step的type为什么是空的呢?是因为StepType取的是项目程序集工步的类名称,因为我的电脑项目和你们的项目不一样,所以这里没有写。大家可以自行百度搜搜看,我这里还是放一下我的json例子吧。

{
  "Id": "HelloWorldJson",
  "Version": 1,
  "Steps": [
    {
      "Id": "Hello",
      "StepType": "WorkFlowCore_Test.WorkFlows.Json.Steps.HelloWorldStep, WorkFlowCore-Test, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null",
      "NextStepId": "Bye"
    },
    {
      "Id": "Bye",
      "StepType": "WorkFlowCore_Test.WorkFlows.Json.Steps.HelloWorldStep, WorkFlowCore-Test, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"

    }
  ]
}

 

5,结语

  例子备注写的比较多,就不多赘述了。有问题的话就留言吧,感谢观看~

与C# .NET 6 使用WorkFlow Core 创建工作审批流相似的内容:

C# .NET 6 使用WorkFlow Core 创建工作审批流

1,背景 工作流思想在上世纪60年代就有人提出过;70年代就有人开始尝试,但是由于当时许多的限制,工作流一直没有成功的被实现;80年代才出现第一批成功的工作流系统;90年代工作流技术走向了第一个发展高峰期;90年代后至今工作流出现了很多版本,但是主旨还是不变的,为了使我们的工作变得更加高效。 通俗点

C#/.NET/.NET Core优秀项目和框架2024年4月简报

前言 公众号每月定期推广和分享的C#/.NET/.NET Core优秀项目和框架(每周至少会推荐两个优秀的项目和框架当然节假日除外),公众号推文中有项目和框架的介绍、功能特点、使用方式以及部分功能截图等(打不开或者打开GitHub很慢的同学可以优先查看公众号推文,文末一定会附带项目和框架源码地址)。

C#/.NET/.NET Core优秀项目和框架2024年6月简报

前言 公众号每月定期推广和分享的C#/.NET/.NET Core优秀项目和框架(每周至少会推荐两个优秀的项目和框架当然节假日除外),公众号推文中有项目和框架的介绍、功能特点、使用方式以及部分功能截图等(打不开或者打开GitHub很慢的同学可以优先查看公众号推文,文末一定会附带项目和框架源码地址)。

上周热点回顾(6.3-6.9)

热点随笔: · C#开源实用的工具类库,集成超过1000多种扩展方法 (追逐时光者)· RabbitMQ 进阶使用之延迟队列 → 订单在30分钟之内未支付则自动取消 (青石路)· .Net 中间件 - 新开源代码生成器 -ReZero (阿妮亚)· C#.Net筑基-String字符串超全总结 [深

上周热点回顾(4.22-4.28)

热点随笔: · 上架即封神!3.6k Star 的开源游戏模拟器,Delta 冲上 App Store 免费榜 (削微寒)· DDD领域驱动设计总结和C#代码示例 (Eric zhou)· 见鬼了!我家的 WiFi 只有下雨天才能正常使用... (米开朗基杨)· 他又来了,.net开源智能家居之小米

.NET周刊【6月第4期 2024-06-23】

国内文章 C#.Net筑基-集合知识全解 https://www.cnblogs.com/anding/p/18229596 .Net中提供了数组、列表、字典等多种集合类型,分为泛型和非泛型集合。泛型集合具有更好的性能和类型安全性。集合的基础接口包括IEnumerator、IEnumerable、I

【Dotnet 工具箱】基于 .NET 6 和 Angular 构建项目任务管理平台

1.Reha 时间管理大师 Rhea 是一个基于 C# 和 .NET 6 开发的在线任务管理平台,类似于 禅道、Jira、Redmine, 滴答清单等。 支持多视图多维度统一管理任务。多级结构,工作区,空间,文件夹,列表,可以更灵活的进行任务管理。 应用支持多主题和主题色切换,灵活搭配,随心所欲。

C#.NET与JAVA互通之DES加密V2024

C#.NET与JAVA互通之DES加密V2024 配置视频: 环境: .NET Framework 4.6 控制台程序 JAVA这边:JDK8 (1.8) 控制台程序 注意点: 1.由于密钥、明文、密文的输入输出参数,都是byte数组(byte[]),所以:字符串转byte数组(byte[])环节,

C#/.NET/.NET Core拾遗补漏合集(24年6月更新)

前言 在这个快速发展的技术世界中,时常会有一些重要的知识点、信息或细节被忽略或遗漏。《C#/.NET/.NET Core拾遗补漏》专栏我们将探讨一些可能被忽略或遗漏的重要知识点、信息或细节,以帮助大家更全面地了解这些技术栈的特性和发展方向。 欢迎加入DotNetGuide技术社区交流群 GitHub

DotNetGuide荣登GitHub C#中文 Trending 月榜第一

前言 发现最近有一大批应届生同学和Java转.NET的同学加入了我们的DotNetGuide技术社区交流6群(其他5个群都已满500人,6群也已有340多个小伙伴了)今天看到DotNetGuide荣登GitHub C#中文 Trending 月榜第一,看到有这么多的小伙伴对C#/.NET感兴趣,并且