簡介
透過使用WWF,你可以建立基於處理器流程的工作流程並且把它們部署在任何類型的.NET應用程式中。此外,本文也討論了ASP.NET開發者面對的一些特有的問題-這些問題可能透過使用工作流程來解決,如維持狀態和頁面導航等。
在2005年9月,微軟在它的一年兩次的專業開發者會議上公開了Windows Workflow Foundation(WWF,Windows工作流程基礎)。作為WinFX API的支柱之一,WWF提供給開發者一個普通框架-在其上開發過程驅動的和以工作流程為中心的應用程式。
目前,有些組織試圖將整個商業流程自動化;他們的標準答案就是集合一隊開發者來開發對應的程式碼。儘管這種方式對於這些組織帶來良好的作用,然而也有一些固有的問題。為了深入理解這個問題,你需要理解一個工作流程的基本特徵。
一個工作流程本質是一種方法-用來歸檔包含在完成一個單元的工作中的活動。典型地,在處理過程中,工作"流"流過一項或更多活動。這些活動可以透過機器或人工來實現,並且有可能像在一個互聯網應用程序定義頁面順序一樣得簡單,也有可能像管理必須為任何數目的人都要看到、更改並同意的文件或產品一樣得複雜。
因為如此多的工作流程必須考慮到人工參預,所以可能需要花費很長工期才能完成,時間可能為幾小時到數月或更長。例如,參預在過程中的人可能無法找到,不在本地或忙於另外的任務;因此,工作流程必須在所有非活動期間能夠把自身持續性儲存。而且,透過編碼獨立實現的過程可能對非技術人員難於理解而對開發者卻難於更改。這一點和其它一些因素正是例如WindowsWF等通用工作流程框架的目標-其目的就在於使創建、改變和管理工作流程更容易-這是通過向它們提供一個可視化接口或通過定義一組普通API來實現的。
你可以把WWF工作流程放置在任何類型的.NET應用程式中-包括Windows表單程序,控制台應用程序,Windows服務和ASP.NET Web應用程式。每種類型都需要專門的考慮。儘管一些現有範例已經足夠說明如何把工作流程宿主到Windows表單程式和控制台應用程式中,但是本文將集中於討論ASP.NET開發者的問題-他們希望把工作流程整合到自己的應用程式中。
作者註:本文所提供的程式碼是以Windows WF Beta 1和Visual Studio 2005 Beta 2 為工具建立的。你可以在www.windowsworkflow.net找到安裝Windows WF的資訊。儘管本文討論了Windows WF的一些基礎問題,但還有其它一些這方面的可用資源。我假定讀者至少了解一點Windows WF。本文的目的是深度分析Windows WF和ASP.NET,而不是從一個高層次討論Windows WF。
一、 Windows WF和MVC模式
在開發一個ASP.NET應用程式時,你可能會使用WWF的一個普通的方法是實作一種模型-視圖-控制器(MVC)方法。實質上,MVC的目標是把描述層、應用程式邏輯和應用程式流程邏輯分開。
搞清楚這個將十分有益於一個ASP.NET應用程式的開發,請考慮一個幫助桌面票工作流程的場所。假定有一個商業用戶透過填寫一個ASP.NET Web表單並點擊一個提交按鈕來啟動該工作流程。接下來,伺服器就會通知一個使用Windows表單應用程式和幫助桌面的員工--"有新票可用了"。該幫助桌面僱員然後將在這一問題上工作,並在最後關閉該票。如果使用Windows WF來開發這個工作流程情形,那麼所有的處理邏輯和流程可以包含在工作流程本身,而該ASP.NET應用程式將完全不需要了解這個邏輯。
這種場所提供了一些穩固的證據-把描述與邏輯分開是一件好事情。因為這個處理幫助桌面請求的過程是非常普通的,如果使用C#或VB.NET程式碼在若干不同的.NET應用程式中實現這一邏輯,那麼你將會冒著重複編碼的危險甚至更壞的情形--用完全不同的程式碼導致同樣的商業處理過程的不同實作。但是如果你使用WWF來實現這一過程,那麼需要這一過程的應用程式開發者將只需在一個地方修改這些步驟-工作流程本身-而不必擔心這樣會改變應用程式邏輯。程式碼複製和在哪裡實現該過程可以透過Windows WF的使用來加以緩和。
當使用Windows WF在ASP.NET中實作MVC架構時,開發者應該嘗試建立獨立於應用程式的工作流程-而該工作流程仍然宿主於該應用程式中。這將有助於保持邏輯獨立於描述並且保持在該網路應用程式中的工作步驟順序和頁面流程之間的高度獨立性。
一個WWF開發新手可能試圖用一固定數目的活動以某種順序去開發一個工作流程,然後開發一組ASP.NET Web表單--這些表單以與之相同的順序從一個表單流向另一個表單。很遺憾,儘管這看起來挺符合邏輯,但實際上這是非常不俱生產效率的,因為你將會再次實現這個工作流程邏輯。 Web頁面X不需要知道是否它需要轉到頁面Y或頁面Z來正確地實現該工作流程步驟。替代的是,該工作流程(模型)應該告訴ASP.NET(控制器)下一步該做什麼;然後ASP.NET應該決定要顯示哪個頁面。這樣,每個頁面幾乎不需要了解整個過程;它只需要知道怎樣完成一個不同的活動並且讓該工作流程來關心頁面是如何從一處流向另一處的。這種分離在開發者處理頁面流時帶來了極大的靈活性。例如,如果你決定改變該頁面顯示順序,那麼你可以從工作流程中輕鬆實現這一點,而不需要改變該ASP.NET應用程式中的一行程式碼。
二、 一個簡單的工作流程MVC實例
為了說明這個思想,我將向你們展示一個簡單ASP.NET應用程式和工作流程。這個過度簡化的工作流程描述了一個進度-收集一些來自於一外部應用程式的私人信息,然後顯示它。步驟如下:
1. 呼叫一個方法--這表示請求一個人的名字;該工作流程使用了InvokeMethod活動(見圖1)。
2. 等待直到一個事件被激發--這意味著收到一個名字;在這一步驟中,該工作流程使用了EventSink活動。
3. 使用一類似調用,從宿主獲得一個電子郵件地址。
4. 等待一個事件意味著收到一個位址。
5. 在收到名字和電子郵件以後,該工作流程啟動一個InvokeMethod活動來發送個人資料到呼叫者應用程式。在一種真實世界情形,這最後一步並不重要。更可能的是,你將呼叫一個Web服務來傳送資料到另外的系統,或把它放進一個資料庫。
圖1.範例工作流程:這個工作流程描述了隱含在範例ASP.NET應用程式中的過程
為了在ASP.NET中實現這個工作流程,你需要一個頁面來收集人名,一個頁面來收集電子郵件地址和一個頁面來顯示個人資料。記住,資料登入表單應該絲毫不知道之前或之後所發生的一切。對於顯示頁面也是如此。然而,該ASP.NET應用程式必須了解要把哪個頁面顯示給使用者;這正是引入控制器的目的之所在。這個範例使用一個Http處理器來實作該解決方案。這個稱為WorkflowController的客製化的處理器負責下列任務:
·獲得到工作流程運作時刻的一個參考。
·取得一個到已有的或啟動一個新的工作流程實例的參考(這依賴於是否已啟動一個工作流程實例)。
·建立控制器和工作流程之間的通訊。
·處理來自該工作流程的事件。
·告訴ASP.NET需要顯示哪個頁面,這取決於現在正執行該工作流程中的哪一層。
你已經看到,這個客製化的處理器實質上負責處理所有的與WWF和頁面控制相關的工作--讓單一的ASP.NET頁面對在後台正在進行的動作保持"緘默"。 Web表單需要擔心的唯一的事情是執行手頭上特定的任務並且把必要的資料傳遞到控制器。
預設地,WWF以一個非同步的模型工作。這意味著,當一個應用程式宿主啟動一個工作流程實例時,控制權立即返回該宿主,而該工作流程繼續在另一個執行緒上執行。這在一個Windows表單應用程式中可能是很有用的-其中十分期盼用戶介面的連續響應性。透過使用這個非同步的模型,工作流程可以在背景執行而該使用者可以繼續操作該應用程式。然而,在一個網頁應用程式中,可能不期望這種類型的行為,因為在伺服器完成一個單元的工作後控制通常將只返回到使用者。這正是Windows WF的可擴充性的體現。在Windows WF中,開發者可以利用或建立"執行時刻服務"來監控甚至修改該工作流程執行時刻。此範例包括:
·持續性服務-儲存執行和空閒時間之間的工作流程狀態
·追蹤服務-輸出有關工作流程執行的資訊到某種媒體
·事務服務-幫助維持工作流程執行過程中的資料完整性
另外,執行緒服務讓開發者控制工作流程實例的執行方式。如前面所討論的,工作流程執行時刻預設地將在一個獨立於宿主的執行緒上異步地運行實例。但是由於這很可能不是ASP.NET所期望的,所以你需要交換預設工作流程執行緒服務。幸運的是,微軟已經為此提供了一個解決方案--ASPNetThreadingService。為了實現這項變化,你或可以以手動編碼方式把ASPNetThreadingService加入到工作流程執行時刻服務,或在web.config檔中完成這項任務。本文中的範例應用程式使用了設定方式。在web.config(見列表1)的工作流程執行時刻/服務節中,新增類似下列的這一行:
<add type=
"System.Workflow.Runtime.Hosting.ASPNetThreadingService,
System.Workflow.Runtime, Version=3.0.00000.0,
Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
三、 實作控制器邏輯
接下來,你需要以一個Http處理器來實作控制器邏輯。為了建構這個控制器,所有你需要做的是建立一個稱為WorkflowController處理器的類別-它實作IHttp處理器介面。到目前為止,你還沒有看到任何關於Windows WF的特別的東西-這是特別針對於ASP.NET的功能(請繼續往下讀)。
在這個WorkflowController處理器類別中,名為ProcessRequest的IHttp處理器介面方法處理一個來自於該ASP.NET應用程式的Web請求。這裡,你需要取得到一個靜態的工作流程執行時刻實例的一個參考,為該工作流程建立事件處理器,並且啟動工作流程的執行。在啟動一個工作流程實例之前,你需要檢查是否該要求的查詢字串值包含一個代表一個工作流程實例ID的GUID。如果存在這個ID,你就知道已經有一個實例正在運行,這樣你可以得到一個到該實例的參考並繼續執行。如果不存在這個ID,你需要透過呼叫工作流程執行時刻Start Workflow方法來建立一個新的實例並且開始執行過程。
啟動一個執行個體後,事件處理器將管理進出工作流程的通訊。因為本文的目的不是討論本地通訊服務,所以在此我不會詳細討論這個主題,而是分析其高級的實現技術,並再次討論這在一個ASP.NET應用程式中是如果工作的。為了便利通訊處理,你將需要若干.NET介面--用來描述出/入該工作流程和宿主的資訊。你會在本文所附WorkflowClassLibrary工程源碼中找到這一些。你也會找到一些實作這些介面的類別以及實作工作流程機制所必須的對應功能。
讓我們再簡單地看一下web.config檔。注意,在早期討論的ASPNetThreadingService元素附近,我們使用了三個元素來描述通訊服務類別:
<add type="Workflow.RuntimeServices.GetNameService,
Workflow.Library, Version=1.0.0.0, Culture=neutral,
PublicKeyToken=c4620ae819b5257e"/>
<add type="Workflow.RuntimeServices.GetEmailService,
Workflow.Library, Version=1.0.0.0, Culture=neutral,
PublicKeyToken=c4620ae819b5257e"/>
<add type="Workflow.RuntimeServices.SendDataService,
Workflow.Library, Version=1.0.0.0, Culture=neutral,
PublicKeyToken=c4620ae819b5257e"/>
這裡還有一個元素,它指導工作流程運行時刻庫來使用SqlStatePersistenceService。這種另外的服務把一個工作流程的狀態持續性儲存到一個在頁面請求之間的SQL伺服器資料庫之中。它們。 config中有一行,它增加一個HttpModule-它支援在ASP.NET中的Windows WF運行時刻庫;還有一行用於設定更早些時候討論的Http處理器控制器。
中
存在許多的東西。
技術。