如何将Workflow Foundation封装为API?寻求WCF/ASP.NET托管工作流现代方案
现代化封装Workflow Foundation为API的方案(WCF/ASP.NET托管)
我之前帮好几个团队搞定过Workflow Foundation封装成API的需求,尤其是针对VS2017环境的现代化改造——毕竟老示例确实大多跑不起来了。下面给你两个实用方案,都是能直接在VS2017里落地的:
一、ASP.NET Core 托管方案(推荐,现代化轻量)
VS2017支持ASP.NET Core 2.1及以上版本,这个方案比WCF更适合做API层,生态也更活跃,后续维护起来更省心。
1. 项目初始化
- 打开VS2017,新建ASP.NET Core Web应用程序,选「API」模板
- 通过NuGet安装
Microsoft.Workflow.Core和Microsoft.Workflow.Runtime(注意选适配.NET Core 2.1的版本,VS2017里搜的时候筛选一下版本范围)
2. 封装工作流服务层
核心是写一个工作流管理类,负责实例化、运行工作流,同时处理外部数据的传入和按需查询:
using System; using System.Activities; using System.Collections.Generic; using System.Threading.Tasks; public class WorkflowService { // 运行工作流并传入外部参数 public async Task<IDictionary<string, object>> RunWorkflow(Type workflowType, IDictionary<string, object> inputParams) { var workflowInvoker = new WorkflowInvoker(workflowType); // 把外部数据传入工作流的输入参数 var outputs = await workflowInvoker.InvokeAsync(inputParams); return outputs; } // 按需查询工作流实例中的数据(这里用缓存演示,生产环境建议用持久化存储) public object GetWorkflowData(Guid workflowInstanceId, string dataName) { var cachedInstance = WorkflowInstanceCache.GetInstance(workflowInstanceId); return cachedInstance?.GetVariable(dataName); } } // 简单的工作流实例缓存类(用于演示按需查询,生产环境替换为SQL Server持久化) public static class WorkflowInstanceCache { private static readonly Dictionary<Guid, DynamicActivity> _instances = new Dictionary<Guid, DynamicActivity>(); public static void AddInstance(Guid id, DynamicActivity instance) => _instances[id] = instance; public static DynamicActivity GetInstance(Guid id) => _instances.TryGetValue(id, out var inst) ? inst : null; }
3. 编写API控制器
创建一个WorkflowController,暴露接口给外部系统调用:
using Microsoft.AspNetCore.Mvc; using System.Collections.Generic; [Route("api/[controller]")] [ApiController] public class WorkflowController : ControllerBase { private readonly WorkflowService _workflowService; // 依赖注入工作流服务 public WorkflowController(WorkflowService workflowService) { _workflowService = workflowService; } // 触发工作流运行,接收外部数据 // POST api/workflow/run [HttpPost("run")] public async Task<IActionResult> RunWorkflow([FromBody] WorkflowRunRequest request) { // 根据传入的工作流类型全名获取类型(比如"MyWorkflowProject.ApprovalWorkflow") var workflowType = Type.GetType(request.WorkflowTypeName); if (workflowType == null) return BadRequest("指定的工作流类型无效"); var outputs = await _workflowService.RunWorkflow(workflowType, request.InputParams); return Ok(outputs); } // 按需查询工作流实例中的数据 // GET api/workflow/data/{instanceId}/{dataName} [HttpGet("data/{instanceId}/{dataName}")] public IActionResult GetWorkflowData(Guid instanceId, string dataName) { var data = _workflowService.GetWorkflowData(instanceId, dataName); if (data == null) return NotFound("未找到该工作流实例的指定数据"); return Ok(data); } } // 接收外部请求的模型类 public class WorkflowRunRequest { public string WorkflowTypeName { get; set; } public Dictionary<string, object> InputParams { get; set; } }
二、WCF托管方案(兼容旧系统)
如果你的项目依赖WCF生态,VS2017也完全支持,下面是简化的现代化封装方案:
1. 项目初始化
- 新建WCF服务应用程序(VS2017里的官方模板)
- 通过NuGet安装最新版的
System.Activities包(适配.NET Framework 4.6及以上,VS2017默认支持)
2. 定义WCF服务契约
先写好对外的接口契约,明确调用方法:
using System.Collections.Generic; using System.ServiceModel; using System.Threading.Tasks; [ServiceContract] public interface IWorkflowService { [OperationContract] Task<Dictionary<string, object>> RunWorkflow(string workflowTypeName, Dictionary<string, object> inputParams); [OperationContract] object GetWorkflowData(System.Guid instanceId, string dataName); }
3. 实现服务类
把工作流的逻辑封装到服务实现里:
using System; using System.Activities; using System.Collections.Generic; using System.Threading.Tasks; public class WorkflowService : IWorkflowService { public async Task<Dictionary<string, object>> RunWorkflow(string workflowTypeName, Dictionary<string, object> inputParams) { var workflowType = Type.GetType(workflowTypeName); if (workflowType == null) throw new FaultException("指定的工作流类型无效"); var invoker = new WorkflowInvoker(workflowType); var outputs = await invoker.InvokeAsync(inputParams); return outputs as Dictionary<string, object>; } public object GetWorkflowData(Guid instanceId, string dataName) { // 和ASP.NET方案的缓存逻辑一致,生产环境替换为持久化存储 var instance = WorkflowInstanceCache.GetInstance(instanceId); return instance?.GetVariable(dataName); } }
4. 配置WCF服务
修改Web.config,配置HTTP绑定让外部可以通过HTTP调用:
<system.serviceModel> <services> <service name="YourNamespace.WorkflowService"> <endpoint address="" binding="basicHttpBinding" contract="YourNamespace.IWorkflowService"> <identity> <dns value="localhost" /> </identity> </endpoint> <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" /> <host> <baseAddresses> <add baseAddress="http://localhost:8733/Design_Time_Addresses/YourNamespace/WorkflowService/" /> </baseAddresses> </host> </service> </services> <behaviors> <serviceBehaviors> <behavior> <serviceMetadata httpGetEnabled="True" httpsGetEnabled="True"/> <serviceDebug includeExceptionDetailInFaults="False"/> </behavior> </serviceBehaviors> </behaviors> </system.serviceModel>
针对VS2017的关键注意事项
- NuGet包版本:Workflow相关包要和你的.NET版本匹配——ASP.NET Core选
Microsoft.Workflow.Core1.1.x+,.NET Framework选System.Activities4.x+ - 工作流持久化:如果是长期运行的工作流(比如审批流程),不要用缓存,改用
WorkflowApplication结合SQL Server实例存储,VS2017里可以通过Microsoft.Workflow.Runtime包配置 - 调试技巧:把API/WCF服务设为启动项目,用Postman(ASP.NET Core)或WCF测试客户端(WCF)直接调用接口,就能在VS2017里调试工作流逻辑了
内容的提问来源于stack exchange,提问作者nasytnyk
相关产品推荐
相关产品推荐

