이 기사는 ASP.NET (Classic 또는 MVC)의 WF (Windows Workflow Foundation)를 지원하기 위해 수행 해야하는 단계를 빠르게 자세히 설명합니다. 매우 작은 데모 응용 프로그램을 사용 하여이 작업을 수행 할 수있는 방법을 보여 드리겠습니다.
ASP.NET에 WF를 통합하는 것은 지난 몇 가지 프로젝트에서해야 할 일입니다. 그래서 나는 이것을 달성하기 위해 필요한 최소의 코드를 보여주는 작은 샘플 응용 프로그램을 구축 할 것이라고 생각했습니다. 샘플 응용 프로그램을 단계별로 구축합시다 ...
비고 :이 기사는 WF의 입문서가 아닙니다. WF에 대한 기본적인 이해가 필요합니다.
SQL Server Management Studio를 시작하고 "Workflow"라는 새 데이터베이스를 만듭니다. WF의 지속성을 지원하기 위해 몇 개의 테이블과 논리 (저장 절차 등)를 만들어야합니다. 디렉토리 "c : wind 이 순서로 다음 두 가지를 실행하십시오.
SQL Server 데이터베이스에서 WF의 지속성을 지원하기 위해 필요한 두 개의 테이블과 10 개의 저장 절차가 생성됩니다. 이제이 기사의 소스 코드를 다운로드하여 추출하고 DDL.SQL 스크립트를 실행하십시오. 이 스크립트는 고객이라는 하나의 테이블을 만듭니다.
다음과 같은 것처럼 보이는 데이터베이스 구조를 사용해야합니다.
그림 1- 워크 플로 데이터베이스

이 기사의 샘플 솔루션을 열면 "데이터베이스"라는 하나의 코드 라이브러리 프로젝트가 있습니다. 포함하는 것은 하나의 엔티티, 즉 고객이 포함 된 LINQ에서 SQL 클래스 파일입니다.
그림 2- 고객 엔티티

샘플 응용 프로그램을 사용하면 고객을 만들 수 있습니다. 사용자 이름을 입력하기 만하면됩니다. 그 후 새로운 워크 플로가 시작되어 고객을 승인하거나, 거부하거나 아무것도하지 않도록 선택할 수 있습니다. 조치를 취하지 않으면 특정 시간 초과 후 고객이 삭제됩니다.
그림 3- 워크 플로

이 샘플에는 하나의 상태 기계 워크 플로가 있습니다. 이러한 워크 플로의 경우 초기 및 완성 된 상태를 제공해야합니다. 위의 그림에서 볼 수 있듯이 적절하게 명명 된 두 개의 상태 만 포함됩니다.
이 워크 플로우에는 사용자 이름이라는 하나의 매개 변수가 필요합니다. 초기 상태에 도착하면 상태 성분이 실행되고 새로운 고객이 고객 테이블에 생성되고 지속됩니다. 기본적으로 모든 고객은 승인이 필요합니다.
그림 4- 승인을 기다리는 고객

이 워크 플로를 별도의 프로젝트에 넣었습니다.
그림 5- 솔루션

상태 성분이 완료되면 워크 플로를 실행하면 3 가지 가능한 이벤트 중 하나가 들립니다.
타임 아웃 이벤트는 지연성에 의존합니다. 이 행사를 직접 해고 할 필요는 없지만 다른 두 가지 이벤트를 해고 할 책임이 있습니다. 따라서 지역 서비스를 만들었습니다.
Listing 1- ICUSTOMERSERVICE 인터페이스
[ ExternalDataExchange ]
public interface ICustomerService
{
event EventHandler < ExternalDataEventArgs > Approved ;
event EventHandler < ExternalDataEventArgs > Rejected ;
}워크 플로 런타임에서 로컬 서비스에 대한 하나의 구현 만 등록 할 수 있으며 CustomersOrvice의 구현은 다음과 같습니다.
Listing 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)를 지정하여 승인 또는 거부 된 이벤트를 트리거 할 수 있습니다.
고객을 생성, 승인 또는 거부하는 데 관련된 논리는 많지 않지만 CustomerManager 클래스 에이 모든 것을 넣습니다. 이 방법은 자명합니다. 이 클래스를 사용하면 모든 고객 목록을 검색하고 신규 고객을 추가하며 고객을 승인, 거부 및 삭제할 수 있습니다.
Listing 3- CustomerManager 클래스
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 ) { //... }
}워크 플로는이 CustomerManager 유형을 사용하여 모든 작업을 수행합니다.
Voila, 기초가 마련되었습니다. WF Persistence를 지원하는 데이터베이스를 설정하고 고객을 작성, 승인 및 거부하기위한 워크 플로우를 만들었으며 워크 플로우 인스턴스를 수행하는 데 도움이되는 로컬 서비스를 만들었습니다.
이제이 모든 것이 작동하도록 새로운 ASP.NET 웹 응용 프로그램을 만들 수 있습니다. ASP.NET 프로젝트에 대한 원래 이름 "WebApplication"을 생각해 냈습니다.
그림 6- 웹 응용 프로그램

이 사이트에는 default.aspx라는 하나의 페이지 만 포함되어 있습니다. 이 페이지에는 고객 목록이 표시되고 새로운 고객을 추가하고 기존 고객을 승인하거나 거부 할 수 있습니다.
그림 7- Default.aspx 페이지

WF를 지원하도록 웹 응용 프로그램을 구성하겠습니다. 이 기사에 표시된 구성 코드는 가독성을 위해 축약됩니다. 정식 버전의 샘플 소스 코드를 다운로드하십시오.
응용 프로그램 구성 파일 (web.config)을 열고 구성 섹션에 다음 줄을 추가하십시오.
< configSections >
<!-- ... -->
< section name = " WorkflowRuntime "
type = " System.Workflow.Runtime.Configuration.WorkflowRuntimeSection...etc. " />
</ configSections >.NET가 구성 노드에 추가 해야하는 다음 구성 비트를 읽으려면 WorkFlowRuntimessection 유형을 사용해야한다는 것을 알 수 있도록 구성 노드 에이 줄을 추가해야합니다.
< 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 노드는 워크 플로 런타임에 대한 수동 WorksFlowSchedulerService 및 SQLWorkFlowPersistenceService 서비스를로드합니다. 워크 플로우를 지속하려면 sqlworkflowpersistenceService를로드하고 ASP.NET의 경우 기본 WorksClowschedUlerservice 서비스 대신 수동 WorksFlowSchedulerService를 사용하는 것이 좋습니다.
각 워크 플로 인스턴스는 별도의 스레드에서 실행됩니다. 워크 플로 런타임은 워크 플로 스케줄러 서비스를 사용하여이를 관리합니다. 기본적으로 런타임은 DefaultWorkFlowSchedulerService 유형을 사용합니다. 모든 워크 플로 인스턴스는 비동기 방식으로 실행됩니다.
ASP.NET의 경우 수동 작업 플로우 스케일러 서비스를 사용하는 것이 가장 좋습니다. 워크 플로우를 동시에 실행할 수 있기 때문입니다. 워크 플로 런타임은이 경우 호스트 응용 프로그램의 호출 스레드를 사용합니다.
이를 통해 ASP.NET가 응답을 보내기 전에 워크 플로에서 응답을 기다릴 수 있습니다. 물론이 경우 워크 플로에서 장기적인 작업을 실행하는 것이 현명하지 않습니다. (PS :이 주제에 대한 자세한 내용은이 블로그 게시물을 확인하십시오.)
수동 작업 플로우 시드 디어 서비스 서비스를 사용하는 경우 useActiveTimers 속성을 true로 설정하십시오. 이 설정을 거짓의 기본값으로 설정하면 만료 된 후 지연 활성화가 자동으로 재개되지 않습니다. true로 설정되면 워크 플로 런타임은 메모리 인 메모리 타이머를 사용하여 주기적으로 만료 된 지연 활성을 확인합니다.
응용 프로그램이 사용 워크 플로 파운데이션으로 구성되었으므로 워크 플로 런타임을 호스팅해야합니다.
ASP.NET 에서이 작업을 수행하기에 이상적인 장소는 Global.asax 파일입니다. Application_start (...) 이벤트 핸들러에 다음 코드를 추가하십시오.
Listing 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의 새로운 인스턴스가 생성되고 externaldataexchangeservice가 생성되어 런타임에 추가됩니다. 다음으로 로컬 서비스 ICUSTOMERSERVICE 인스턴스를 생성하여 externAldataExChangeservice 인스턴스에 추가합니다. 마지막으로 런타임이 시작되어 응용 프로그램의 상태에 저장됩니다.
마찬가지로 응용 프로그램이 목록 5에 표시된대로 종료되면 워크 플로 런타임을 중지해야합니다.
Listing 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 ( ) ;
}
} 추가 버튼을 클릭하면 새 워크 플로를 시작해야합니다. 수동 작업 플로우 시드 디어 서비스 서비스를 사용하는 경우 워크 플로우 인스턴스를 실행하는 것을 완전히 제어합니다. Listing 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 ) ; 고객을 만든 후에는 그의 계정을 승인하거나 거부 할 수 있습니다. 다시 말해, 당신은 그의 계정을 만들 때 시작된 워크 플로를 계속해야합니다.
Listing 7에 표시된 코드는 Listing 6의 코드와 유사합니다. 유일한 차이점은 로컬 서비스 인스턴스 (고객 서비스)를 검색하고 on 승인 (...) 메소드를 호출해야한다는 것입니다. 승인 된 메소드는 승인 된 이벤트를 트리거합니다. 성공적인 배송시 스케줄러에게 워크 플로를 계속 실행하도록 지시 할 수 있습니다.
목록 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 ) ;
}고객의 계정을 거부하는 것은 비슷합니다. 승인 된 이벤트 대신 거부 된 이벤트를 보내면됩니다. 조치를 취하지 않으면 1 분 후에 지연성이 트리거되고 고객의 계정이 자동으로 삭제됩니다.
그리고 그게 전부입니다.