本文快速详细介绍了您需要执行的步骤,以便在ASP.NET(经典或MVC)中支持Windows Workflow Foundation(WF)。让我们使用一个非常小的演示应用程序向您展示如何执行此操作。
将WF集成在ASP.NET中是我在工作的最后几个项目中必须做的事情。因此,我认为我会构建一个少量的示例应用程序,向您显示实现此目的所需的最少代码。让我们逐步构建示例申请...
备注:本文不是WF的入门。需要对WF的一些基本理解。
启动SQL Server Management Studio并创建一个名为“ Workflow”的新数据库。您需要创建一些表和逻辑(存储过程等),以支持WF的持久性。在目录中“ C: Windows Microsoft.net Framework V3.0 Windows Worksflow Foundation sql en”您会找到4个SQL文件。按以下顺序执行以下两个:
这创建了两个表和10个存储过程,以支持SQL Server数据库中的WF持续性。现在,下载本文的源代码,提取并执行DDL.SQL脚本。该脚本创建一个称为客户的表。
您应该结束一个看起来像这样的数据库结构:
图1-工作流数据库

当您打开本文的示例解决方案时,您会找到一个名为“数据库”的代码库项目。它包含的只是一个Linq到SQL类文件,其中包含一个实体,即客户。
图2-客户实体

示例应用程序允许您创建客户。您要做的就是输入用户名。之后,开始了一个新的工作流程,您可以选择批准客户,拒绝他或什么都不做。如果您不采取行动,则在一定超时后,客户将被删除。
图3-工作流程

在此示例中,有一个状态机工作流程。对于这样的工作流,您必须提供初始和完整的状态。如上图所示,它仅包含两个适当命名的状态。
此工作流需要一个称为用户名的参数。当它到达初始状态时,执行了状态化攻击性,并在客户表中创建并坚持使用新客户。默认情况下,所有客户都需要批准。
图4-等待批准的客户

我将这个工作流程放在一个单独的项目中。
图5-解决方案

当状态化攻击完成后,执行工作流将聆听3个可能的事件之一:
超时事件依赖于延迟性。您不必自己解雇此事件,但是您负责解雇其他两个事件。因此,我创建了本地服务。
清单1- icustomerService接口
[ ExternalDataExchange ]
public interface ICustomerService
{
event EventHandler < ExternalDataEventArgs > Approved ;
event EventHandler < ExternalDataEventArgs > Rejected ;
}您只能在工作流运行时注册一个本地服务的实现,而客户服务的实现如下:
清单2-客户服务
public class CustomerService : ICustomerService
{
public event EventHandler < ExternalDataEventArgs > Approved ;
public event EventHandler < ExternalDataEventArgs > Rejected ;
private bool FireEvent ( EventHandler < ExternalDataEventArgs > theEvent , ExternalDataEventArgs args )
{ //...}
public bool OnApproved ( Guid instanceId )
{
return FireEvent ( Approved , new ExternalDataEventArgs ( instanceId ) ) ;
}
public bool OnRejected ( Guid instanceId )
{
return FireEvent ( Rejected , new ExternalDataEventArgs ( instanceId ) ) ;
}
}此本地服务使您可以通过指定要继续执行的工作流的实例ID(GUID)来触发批准的或拒绝的事件。
创建,批准或拒绝客户的逻辑不多,但是我将所有内容都放在CustomManager类中。这些方法是不言自明的。此课程使您可以检索所有客户的列表,添加新客户,批准,拒绝和删除客户。
列表3-定制员类
public class CustomerManager
{
public IEnumerable < Customer > GetCustomers ( ) { //... }
public Customer GetCustomerById ( Guid customerId ) { //... }
public void ApproveCustomer ( Guid customerId ) { //... }
public void RejectCustomer ( Guid customerId ) { //... }
public void DeleteCustomer ( Guid customerId ) { //... }
public void AddCustomer ( Guid customerId , string userName ) { //... }
}该工作流使用此定制类型类型来执行其所有工作。
瞧,基础是奠定的。您已经设置了一个支持WF持久性的数据库,创建了用于创建,批准和拒绝客户的工作流程,并创建了一项本地服务,该服务将帮助您指导工作流程实例。
现在,让我们创建一个新的ASP.NET Web应用程序,该应用程序将使所有这些都起作用。我为ASP.NET项目提出了原始名称“ WebApplication”。
图6-网络应用项目

该站点仅包含一个称为default.aspx的页面。此页面显示客户列表,允许您添加新客户并批准或拒绝现有客户。
图7 -default.aspx页面

让我们配置Web应用程序,以便它支持WF。本文中显示的配置代码缩写为可读性。下载完整版本的示例源代码。
打开您的应用程序配置文件(web.config),然后将以下行添加到“配置”部分。
< configSections >
<!-- ... -->
< section name = " WorkflowRuntime "
type = " System.Workflow.Runtime.Configuration.WorkflowRuntimeSection...etc. " />
</ configSections >您需要将此行添加到配置节点中,以便.NET知道它必须使用WorkFlowRuntimeSection类型来读取以下配置,您需要将其添加到配置节点。
< WorkflowRuntime >
< CommonParameters >
< add name = " ConnectionString " value = " your connection string " />
</ CommonParameters >
< Services >
< add type = " System.Workflow.Runtime.Hosting.ManualWorkflowSchedulerService,...etc. "
useActiveTimers = " true " />
< add type = " System.Workflow.Runtime.Hosting.SqlWorkflowPersistenceService,...etc. "
UnloadOnIdle = " true " LoadIntervalSeconds = " 5 " />
</ Services >
</ WorkflowRuntime >WorkFlowRuntime节点为工作流运行时加载ManualWorkFlowsChedulerService和SQLWorkFlowPersisservice服务。如果要持续工作流程,并且对于ASP.NET,建议使用ManualworkFlowsChedulerService而不是DefaultWorkWorkflowsChedulerService Service,则必须加载SQLWorkFlowPersistService。
每个工作流实例在单独的线程上执行。 Workflow运行时使用Workflow Scheduler服务管理此操作。默认情况下,运行时使用DefaultWorkflowsChedulerService类型。所有工作流程实例都以异步方式执行。
对于ASP.NET,最好使用ManualWorkflowsChedulerService,因为它允许您同步运行工作流程。在这种情况下,工作流运行时使用了从主机应用程序中的调用线程。
这使您可以在ASP.NET发送响应之前等待工作流的响应。当然,在这种情况下,执行工作流程中的任何长期运行任务是不明智的。 (PS:查看此博客文章以获取有关此主题的更多信息。)
使用ManualWorkflowsChedulerService时,请确保将UseActiveTimers属性设置为true。如果将此设置设置为false的默认值,则任何延迟活动都不会在过期后自动恢复。如果设置为true,则工作流运行时将使用内存计时器定期检查过期的延迟活动。
现在,您的应用程序已配置为使用WorkFlow Foundation,您需要托管工作流运行时。
在ASP.NET中,这样做的理想场所是在global.asax文件中。只需将以下代码添加到application_start(...)事件处理程序。
列表4- global.asax application_start
protected void Application_Start ( object sender , EventArgs e )
{
WorkflowRuntime runtime = new WorkflowRuntime ( "WorkflowRuntime" ) ;
ExternalDataExchangeService exchangeService = new ExternalDataExchangeService ( ) ;
runtime . AddService ( exchangeService ) ;
CustomerService customerService = new CustomerService ( ) ;
exchangeService . AddService ( customerService ) ;
runtime . StartRuntime ( ) ;
Application [ "WorkflowRuntime" ] = runtime ;
}创建了WorkFlowRuntime的新实例,然后创建并将其添加到运行时。接下来,我们创建一个本地服务IcustomerService的实例,然后将其添加到外部Dataexchangeservice实例中。最后,运行时开始并存储在应用程序的状态中。
同样,当应用程序结束时,您需要停止工作流运行时,如列表5所示。
列表5 -global.asax Application_end
protected void Application_End ( object sender , EventArgs e )
{
WorkflowRuntime runtime = Application [ "WorkflowRuntime" ] as WorkflowRuntime ;
if ( runtime != null )
{
runtime . StopRuntime ( ) ;
runtime . Dispose ( ) ;
}
} 单击“添加”按钮时,您需要启动新的工作流程。当使用ManualWorkflowsChedulerService时,您将完全控制运行工作流程实例。在清单6中,您可以看到您需要遵循以下步骤:
清单6-创建一个新客户
WorkflowRuntime runtime = ( WorkflowRuntime ) Application [ "WorkflowRuntime" ] ;
Dictionary < string , object > arguments = new Dictionary < string , object > ( ) ;
arguments . Add ( "UserName" , txtUserName . Text . Trim ( ) ) ;
WorkflowInstance workflow = runtime . CreateWorkflow ( typeof ( CustomerApprovalWorkflow ) , arguments ) ;
workflow . Start ( ) ;
ManualWorkflowSchedulerService scheduler =
( ManualWorkflowSchedulerService ) runtime . GetService ( typeof ( ManualWorkflowSchedulerService ) ) ;
scheduler . RunWorkflow ( workflow . InstanceId ) ; 创建客户后,您可以批准或拒绝他的帐户。换句话说,您需要继续创建他的帐户时开始的工作流程。
清单7中显示的代码类似于清单6的代码。唯一的区别是您必须检索本地服务的实例(CustomerService),并称其为征用(...)方法。掌握的方法触发了批准的事件。成功交付后,您可以指示调度程序继续运行工作流程。
清单7-批准客户
WorkflowRuntime runtime = ( WorkflowRuntime ) Application [ "WorkflowRuntime" ] ;
ManualWorkflowSchedulerService scheduler =
( ManualWorkflowSchedulerService ) runtime . GetService ( typeof ( ManualWorkflowSchedulerService ) ) ;
CustomerService customerService = ( CustomerService ) runtime . GetService < ICustomerService > ( ) ;
if ( customerService . OnApproved ( customerId ) )
{
scheduler . RunWorkflow ( customerId ) ;
}拒绝客户的帐户相似。您只需要发送被拒绝的事件而不是批准的事件。如果您不采取行动,则将在一分钟后触发延迟率,并且客户的帐户将自动删除。
这就是其中的全部。