你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn。
适用于:Azure 逻辑应用(标准)
如果你要将业务逻辑与 Azure 逻辑应用中的标准工作流集成,可以使用 Visual Studio Code 创建并生成 Azure 逻辑应用规则引擎项目。 规则控制有关业务流程运作方式的业务逻辑。
要从工作流程运行规则,可以用本地自定义函数来处理包含 .NET 事实的规则集。 对于仅使用 XML 事实的规则集,你可以使用内置的 执行规则引擎 操作,目前处于预览阶段。
本指南演示如何创建 Azure 逻辑应用规则引擎项目:
创建 Azure 逻辑应用 规则引擎项目的前提条件和设置,包括使用 Microsoft 规则编辑器创建项目的业务规则。
从 Microsoft BizTalk Server 导出现有规则(如果有)。
使用 Visual Studio Code 为 Azure 逻辑应用 规则引擎创建一个标准 Logic Apps 项目。
通过本地自定义函数处理 .NET 事实,或仅使用执行规则引擎操作(仅执行 XML 事实)来从你的工作流程中运行规则集。
先决条件
下载并安装 Microsoft 规则编辑器,可以使用它来创建规则集、业务规则和词汇。
若要为规则引擎项目生成业务,请参阅以下文档:
对于此版本,只有 Visual Studio Code 支持 Azure 逻辑应用规则引擎项目的开发体验。 若要满足使用 Visual Studio Code 的先决条件,请参阅使用 Visual Studio Code 在单租户 Azure 逻辑应用中创建标准逻辑应用工作流。
为了使用 .NET 事实,Azure 逻辑应用 规则引擎使用了 Visual Studio Code 中的自定义代码函数功能。 若要满足使用此功能的先决条件,请参阅从 Azure 逻辑应用中的标准工作流创建和运行 .NET Framework 代码。
创建项目之前
为了帮助确保规则引擎项目创建成功,请查看并执行以下常规任务和最佳做法:
确定业务规则是否适合你的业务流程。
规划如何将业务规则合并到应用程序中。
标识出要在应用程序中使用规则来表示的业务逻辑。
术语“业务逻辑”指很多事物。 例如,业务逻辑可能是“超过 500 美元的采购订单需要经理批准”。
标识规则元素的数据源。 可以选择性地定义词汇(表示底层绑定的特定于领域的术语)。
从词汇定义或直接从数据绑定定义要使用的规则。 根据这些规则创建一个代表业务逻辑的规则集。
从 Microsoft BizTalk Server 导出规则
若要重用 Microsoft BizTalk Server 中的现有规则,可将其导出。 但是,目前不支持 DB 事实。 在导出规则之前,请使用 Microsoft BizTalk 规则编辑器将其删除或重构为其他类型的事实。
在“Microsoft BizTalk Server”中,启动“业务规则引擎部署”向导。
在“欢迎使用规则引擎部署向导”页面上,选择“下一步”。
在“部署任务”页面上,选择“将策略/词汇从数据库导出到文件”,然后选择“下一步”。
在“策略存储”页面上的“SQL 服务器名称”列表中,选择你的 SQL 服务器。 在选定服务器上的“配置数据库”列表中,选择“BizTalkRuleEngineDb”,然后选择“下一步”。
在“导出策略/词汇”页面上的“策略”列表中,选择所需的策略。 若要查找并选择定义文件,请选择“浏览”。
准备就绪后,选择“下一步”。
确认服务器、数据库和策略或词汇信息,然后选择“下一步”。
导入或导出完成后,选择“下一步”。
检查导入或导出的完成状态,然后选择“完成”。
创建 Azure 逻辑应用规则引擎项目
项目模板创建了一个函数项目和一个逻辑应用项目。 只有当规则集包含 .NET 事实时,才需要函数项目和自定义代码。 对于仅使用XML事实的规则集,请在工作流程中使用内置的 执行规则引擎 操作。
在 Visual Studio Code 中的活动栏上,选择“Azure”图标。 (键盘:Shift+Alt+A)
在打开的 Azure 窗口中,在“工作区”部分工具栏的“Azure 逻辑应用”菜单中选择“新建逻辑应用工作区”。
在“选择文件夹”框中,浏览到并选择为项目创建的本地文件夹。
当出现“创建新的逻辑应用工作区”提示框时,请提供工作区的名称:
此示例继续使用 MyLogicAppRulesWorkspace。
出现 逻辑应用工作区提示框的“选择项目模板 ”时,选择 包含规则引擎项目的逻辑应用。
按照后续提示提供以下示例值:
项 示例值 函数项目的函数名称 RulesFunction 函数项目的命名空间名称 Contoso Logic App: LogicApp 工作流模板:
- 有状态工作流
- 无状态工作流有状态工作流 工作流名称 MyRulesWorkflow 选择“在当前窗口中打开”。
完成此步骤后,Visual Studio Code 会创建工作区,其中默认包括函数项目和逻辑应用规则引擎项目,例如:
Node 说明 < 工作区名称> 包含你的函数项目和逻辑应用工作流项目。 功能 包含你的函数项目的构件。 例如,<function-name>.cs 文件是可在其中创作代码的代码文件。 LogicApp 包含用于逻辑应用规则引擎项目的构件,包括工作流。
为 .NET 事实数据编写规则引擎代码
如果你的规则集只使用XML事实,跳过此部分, 使用内置的执行规则引擎操作。 如果你的规则集包含 .NET 事实,请按照本节描述创建本地自定义函数。
在工作区中,展开“Functions”节点(如果尚未展开)。
打开 <function-name.cs 文件,本示例中该文件的名称为 RulesFunction.cs>。
默认情况下,此文件包含具有以下代码元素的示例代码,它具有前面提供的示例值(如果适用):
- 命名空间名称
- 类名
- 函数名称
- 函数参数
- 返回类型
- 复杂类型
以下示例显示了名为
RulesFunction的函数的完整示例代码://------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. //------------------------------------------------------------ namespace Contoso { using System; using System.Collections.Generic; using System.Threading.Tasks; using Microsoft.Azure.Functions.Extensions.Workflows; using Microsoft.Azure.WebJobs; using Microsoft.Azure.Workflows.RuleEngine; using Microsoft.Azure.Workflows.RuleEngine.Common; using Microsoft.Extensions.Logging; using System.Xml; using System.Text; /// <summary> /// Represents the RulesFunction flow invoked function. /// </summary> public class RulesFunction { private readonly ILogger<RulesFunction> logger; private FileStoreRuleExplorer ruleExplorer; public RulesFunction(ILoggerFactory loggerFactory) { logger = loggerFactory.CreateLogger<RulesFunction>(); this.ruleExplorer = new FileStoreRuleExplorer(loggerFactory); } /// <summary> /// Executes the logic app workflow. /// </summary> /// <param name="ruleSetName">The rule set name.</param> /// <param name="documentType">document type of input xml.</param> /// <param name="inputXml">input xml type fact</param> /// <param name="purchaseAmount">purchase amount, value used to create .NET fact </param> /// <param name="zipCode">zip code value used to create .NET fact .</param> [FunctionName("RulesFunction")] public Task<RuleExecutionResult> RunRules( [WorkflowActionTrigger] string ruleSetName, string documentType, string inputXml, int purchaseAmount, string zipCode) { /***** Summary of steps below ***** * 1. Get the rule set to Execute * 2. Check if the rule set was retrieved successfully * 3. create the rule engine object * 4. Create TypedXmlDocument facts for all xml document facts * 5. Initialize .NET facts * 6. Execute rule engine * 7. Retrieve relevant updates facts and send them back */ try { var ruleSet = this.ruleExplorer.GetRuleSet(ruleSetName); // Check if ruleset exists if(ruleSet == null) { // Log an error in finding the rule set this.logger.LogCritical($"RuleSet instance for '{ruleSetName}' was not found(null)"); throw new Exception($"RuleSet instance for '{ruleSetName}' was not found."); } // Create rule engine instance var ruleEngine = new RuleEngine(ruleSet: ruleSet); // Create a typedXml Fact(s) from input xml(s) XmlDocument doc = new XmlDocument(); doc.LoadXml(inputXml); var typedXmlDocument = new TypedXmlDocument(documentType, doc); // Initialize .NET facts var currentPurchase = new ContosoNamespace.ContosoPurchase(purchaseAmount, zipCode); // Provide facts to rule engine and run it ruleEngine.Execute(new object[] { typedXmlDocument, currentPurchase }); // Send the relevant results(facts) back var updatedDoc = typedXmlDocument.Document as XmlDocument; var ruleExectionOutput = new RuleExecutionResult() { XmlDoc = updatedDoc.OuterXml, PurchaseAmountPostTax = currentPurchase.PurchaseAmount + currentPurchase.GetSalesTax() }; return Task.FromResult(ruleExectionOutput); } catch(RuleEngineException ruleEngineException) { // Log any rule engine exceptions this.logger.LogCritical(ruleEngineException.ToString()); throw; } catch(XmlException xmlException) { // Log any xml exceptions this.logger.LogCritical("Encountered exception while handling xml. " + xmlException.ToString()); throw; } catch(Exception ex) { // Log any other exceptions this.logger.LogCritical(ex.ToString()); throw; } } /// <summary> /// Results of the rule execution /// </summary> public class RuleExecutionResult { /// <summary> /// rules updated xml document /// </summary> public string XmlDoc { get; set;} /// <summary> /// Purchase amount post tax /// </summary> public int PurchaseAmountPostTax { get; set;} } } }RulesFunction的函数定义包含一个默认的RunRules方法,可以使用该方法开始操作。 此示例RunRules方法演示如何将参数传递给 Azure 逻辑应用规则引擎。 在此示例中,该方法传递规则集名称、输入文档类型、XML 事实和其他值以供进一步处理。< function-name>.cs 文件还包括
ILogger接口,该接口支持将事件记录到 Application Insights 资源。 可以将跟踪信息发送到 Application Insights,并将该信息与工作流中的跟踪信息一起存储。 函数<名称>.cs文件还包括FileStoreRuleExplorer访问规则集的对象。 如您所见,FileStoreRuleExplorer的构造函数使用loggerFactory也将遥测信息发送到 Application Insights。private readonly ILogger<RulesFunction> logger; private FileStoreRuleExplorer ruleExplorer; public RulesFunction(ILoggerFactory loggerFactory) { logger = loggerFactory.CreateLogger<RulesFunction>(); this.ruleExplorer = new FileStoreRuleExplorer(loggerFactory); } <...>Azure 逻辑应用规则引擎的运行方式如下所述:
引擎使用
FileStoreRuleExplorer对象来访问规则集。 规则集文件存储在标准逻辑应用的 Rules 目录中。在本示例中,规则集文件名为
SampleRuleSet.xml,它是使用 Microsoft 规则编辑器创建的,或使用 Microsoft BizTalk Server 导出的。
var ruleSet = this.ruleExplorer.GetRuleSet(ruleSetName); // Check if ruleset exists if(ruleSet == null) { // Log an error in finding the rule set this.logger.LogCritical($"RuleSet instance for '{ruleSetName}' was not found(null)"); throw new Exception($"RuleSet instance for '{ruleSetName}' was not found."); }重要
规则集保存对其事实的引用。 Microsoft 规则编辑器查找事实程序集来验证规则集以供编辑。 若要在 Microsoft 规则编辑器中打开诸如
SampleRuleSet.xml之类的规则集,必须将其与相应的 .NET 事实程序集放在一起。 否则会发生异常。引擎使用
ruleSet对象来创建RuleEngine对象的实例。RuleEngine对象使用Execute方法接收规则的事实。在此示例中,
Execute方法接收两个事实:一个名为typedXmlDocument的 XML 事实和一个名为currentPurchase的 .NET 事实。引擎运行后,数据的值将被引擎执行产生的值覆盖:
// Create rule engine instance var ruleEngine = new RuleEngine(ruleSet: ruleSet); // Create a typedXml Fact(s) from input xml(s) XmlDocument doc = new XmlDocument(); doc.LoadXml(inputXml); var typedXmlDocument = new TypedXmlDocument(documentType, doc); // Initialize .NET facts var currentPurchase = new ContosoNamespace.ContosoPurchase(purchaseAmount, zipCode); // Provide facts to rule engine and run it ruleEngine.Execute(new object[] { typedXmlDocument, currentPurchase }); // Send the relevant results(facts) back var updatedDoc = typedXmlDocument.Document as XmlDocument;- 引擎使用
RuleExecutionResult自定义类将值返回给RunRules方法:
var ruleExectionOutput = new RuleExecutionResult() { XmlDoc = updatedDoc.OuterXml, PurchaseAmountPostTax = currentPurchase.PurchaseAmount + currentPurchase.GetSalesTax() }; return Task.FromResult(ruleExectionOutput);将示例函数代码替换为你自己的代码,并为你自己的方案编辑默认
RunRules方法。此示例继续使用示例代码,不进行任何更改。
为 .NET 事实编译并生成代码
如果你的规则集只使用XML事实,并且计划使用内置的 执行规则引擎 操作,请跳过此部分。 如果你的规则集包含 .NET 事实,写完代码后编译确认没有构建错误。 你的函数项目会自动包含构建任务,这些任务会编译并将任何自定义代码库,包括你的 .NET 事实汇编,添加到逻辑应用项目中的 lib\custom 文件夹,工作流会在那里寻找需要运行的自定义函数。 这些任务将程序集置于 lib\custom\net472 文件夹中。
在 Visual Studio Code 的“终端”菜单中,选择“新建终端”。
在显示的工作目录列表中,选择“Functions”作为新终端的当前工作目录。
Visual Studio Code 会打开终端窗口,其中包含一个命令提示符。
在 终端 窗口中的命令提示符下,输入 dotnet restore .\RulesFunction.csproj。
命令提示符再次出现后,输入 dotnet build .\RulesFunction.csproj。
如果你的生成成功,则终端窗口将报告生成成功。
确认你的逻辑应用项目中存在以下项:
在工作区中,展开以下文件夹:LogicApp>lib\custom>net472。 确认名为 net472 的子文件夹包含运行代码所需的多个程序集文件,包括名为 function-name<.dll 的文件>。
在工作区中,展开以下文件夹:LogicApp>lib\custom><函数名称>。 确认名为 <function-name> 的子文件夹包含 function.json 文件,该文件包含有关你编写的函数代码的元数据。 工作流设计器使用此文件来确定调用你的代码时所需的输入和输出。
以下示例显示了逻辑应用项目中示例生成的程序集和其他文件:
从工作流调用规则
使用本地自定义函数调用 .NET 事实
对于包含 .NET 事实的规则集,请使用本地自定义函数。 确认你的代码已编译且逻辑应用规则引擎项目包含代码运行所需的文件后,打开逻辑应用项目中包含的默认工作流。
在工作区的“LogicApp”下,展开 <workflow-name> 节点,打开 workflow.json 的快捷菜单,然后选择“打开设计器”。
在打开的工作流设计器上,你的逻辑应用项目包含的默认工作流会随以下触发器和操作一起显示:
- 内置名为“收到 HTTP 请求时”的请求触发器。
- 名为“在此逻辑应用中调用本地规则函数”的内置操作。
- 名为“响应”的内置响应操作,仅在使用请求触发器时使用它来回复调用方。
选择名为“在此逻辑应用中调用本地规则函数”的操作。
该操作的信息窗格会在右侧打开。
查看并确认 Function Name 参数值已设为要运行的规则函数。 查看或更改函数使用的任何其他参数值。
使用“执行规则引擎”操作调用 XML 事实
对于仅使用 XML 事实的规则集,可以使用内置的 执行规则引擎 操作。 你不必编写、编译或调用本地自定义函数。
重要
执行规则引擎操作处于预览阶段,仅支持 XML 事实。 要使用 .NET 事实,调用本地自定义函数。
在工作区的“LogicApp”下,展开 <workflow-name> 节点,打开 workflow.json 的快捷菜单,然后选择“打开设计器”。
在工作流设计器中,在你想运行规则集的触发器或动作下方,按照一般步骤添加名为 执行规则引擎 的动作,将 动作添加到你的工作流程中。
在动作信息窗格中,从 规则集 列表中选择你想运行的规则集。 本示例选择验证。
打开 高级参数 列表。
对于所选规则集期望的每个XML事实,列表包含一个以 前缀Fact:开头的参数。 本例选择了 事实:后端。
选择你想提供的每个事实参数。
对于每个事实参数,提供对应的XML文档。
你可以输入 XML 或选择早期工作流程操作中的 XML 输出。 本示例使用前面的Compose XML with schema 操作输出的Body XML。
当动作运行时,规则引擎会将所选规则集应用到XML事实上。 你可以在后续的工作流程操作中使用动作输出。 在这个例子中,工作流程使用 带有模式的解析 XML 来处理所得的 XML。
调试代码和工作流
当你使用包含 .NET 事实的规则集的本地自定义函数时,以下步骤适用。 对于仅支持XML且使用内置 执行规则引擎 动作的规则集,请调试工作流程,并在工作流运行历史中查看动作输入和输出。
重复以下步骤以启动 Azurite 存储模拟器三次:为以下每个 Azure 存储服务启动一次:
- Azure Blob 服务
- Azure 队列服务
- Azure 表服务
在 Visual Studio Code 的“视图”菜单中选择“命令面板”。
在出现的提示中,找到并选择“Azurite:启动 Blob 服务”。
在显示的工作目录列表中,选择 LogicApp。
为 Azurite:启动队列服务和 Azurite:启动表服务重复这些步骤。
当屏幕底部的 Visual Studio Code 任务栏显示三个存储服务正在运行时,你就成功了,例如:
在 Visual Studio Code 活动栏上,选择“运行并调试”。 (键盘:Ctrl+Shift+D)
从“运行并调试”列表中,选择“附加到逻辑应用 (LogicApp)”(如果尚未选择),然后选择“运行”(绿色箭头)。
“终端”窗口随即打开,并显示已开始的调试过程。 然后,将显示“调试控制台”窗口,并显示调试状态。 在 Visual Studio Code 底部,任务栏变为橙色,表示 .NET 调试程序已加载。
若要设置任何断点,在你的函数定义 (<function-name.cs) 或工作流定义 (workflow.json) 中,找到需要断点的行号,然后选择左侧的列,例如>:
若要在工作流中手动运行请求触发器,请打开工作流的“概述”页。
在“概述”页工具栏中,选择“运行触发器”。
工作流开始运行后,调试器会激活你的第一个断点。
在“运行”菜单或调试程序工具栏中,选择“调试操作”。
工作流运行完成后,“概述”页会显示已完成的运行以及有关该运行的基本详情。
要查看有关工作流运行的详细信息,请选择已完成的运行。 或者,在“持续时间”列旁边的列表中,选择“显示运行”。
若要使用规则引擎项目将逻辑应用部署到 Azure 逻辑应用,请按照 准备部署中的步骤作。