這個範例中,我們將要使用一個ASP.Net所製作出的網頁去呼叫一個Workflow Foundation的流程。在這邊我們假設一個在寫網頁程式時常常會遇到的流程來當範例。
狀況假設:
[ 做一個會員申請的網頁,當使用者填寫他要申請的Usename跟他的密碼後,然後按下送出,我們要判斷這個帳號有沒有被申請過;假如被申請過的話要回覆申請人,這個
帳號已經有人申請了;假如這個帳號沒有被申請過的話,我們就新增帳號進到資料庫。 ]
這種類型的流程在開發中是非常見到的,在以往的程式撰寫,縱使程式架構很良善、也是避免不了要將剛剛講的邏輯寫在程式當中。最後當成是越寫越多的時候,讀
Code又成為Loading很重的一個工作。因為一定會看到一堆 if....else....的程式碼。程式設計師又要重這些不易閱讀的地方來了解流程 !!! ><|||~~
如果我們把剛剛說的流程變成了以下這個圖,是不是很一目了然呢 ? 看圖就知道這個申請帳號的流程到底做了那些動作。 那再說回來,有了這個流程以後。如何讓ASP.Net
的網頁去呼叫它就是本章節的重點了。

在每個範例中我都盡量不要讓他變得很複雜,以免整個範例變的非常不好練習。所以都盡量用最少的需求去完成這個範例。這個範例中將會開發一個ASP.Net網頁來呼叫這個
申請帳號的流程。下圖是我們待會要新增出來的網頁。

|
開啟一個新的WWF專案。
這個範例中我們要使用的是 [ 循序工作流程程式庫 ] 。檔案名稱我們命名為 [ Lab4_ASPNet_WWF ] 。

循序工作流程內容佈置!
在循序工作流程裡面我們拉出如下圖的Activity。一共拉出 4個 [ CodeActivity ] 跟 1個 [ IfElseActivity ]。在這裡我們將元件名稱改為中文使得整個流程變的非常容易閱讀。
這個流程的動作我們來分解一下:
1. 一個開始會有一個元件去確認資料庫有沒有你申請的這個帳號。
2. IF 元件去判斷這個帳號是不是在資料庫中被申請過?
3.如果沒申請過就新增資料到資料庫去。然後回覆申請人申請成功。
4.如果申請過要回覆申請人這個帳號已經申請過了。
資料庫準備!
在這個範例中我們需要一個放有使用者帳號與密碼的資料表。這邊我們就用SQL Server來製作這個資料庫。大家可以去取得試用版的SQL Server。這部份詳細的設定我們就不
在此描述。我先預設大家都會使用SQL Server 建立資料表了。 我建立了一個 [ Workflow Foundation ] 資料庫,裡面有一個 [ Customers ]資料表。 而資料表裡面有三個欄位;
分別是PK、Username、Password。
在資料表中我塞了一些資料,這部份是待會WF 流程要進來判斷你申請的Username(帳號)是否有存在於資料庫中用的比對資料。

新增變數
接著我們在[ 循序工作流程 ] 面板下按下滑鼠右鍵,進入程式碼編輯區域;然後我們在裡面新增四個變數。用途如下:
1. _Username : 這個字串變數用來接收ASP.Net 的網頁送進來使用者輸入的Username 值。
2. _Password : 這個字串變數用來接收ASP.Net 的網頁送進來使用者輸入的Password 值。
3. _checkdata : 這個布林變數用來記錄資料庫有沒有這筆資料的結果。
4. _Result : 這個字串變數用來儲存通知前端網頁的訊息。
因為 _Username、 _Password、_Result 這些變數被封裝了,所以要替他們建立 存取的方式,以利前端作業好呼叫取用。因此在下圖會看到三個方法,分別是
public string Username 、public string Password、public string Result 這三個方法。

撰寫 [檢查資料庫有沒有這個帳號]的CodeActivity元件要做的事情。
這個元件是要去資料庫檢查有沒有你輸入的這個Username。所以他會送出 select * from Customers where Username = '" + _Username + "' 的指令去資料庫做查詢的動作。
我們將結果以 DataReader.read 的方法回傳一個 True 或 false ;我們將這個回傳值存放在我們剛剛宣告的 _checkdata 變數中。


注意!!因為有用到Oledb元件,所以在最前端記得加入 using System.Data.Oledb 將元件參考進來。

設定 IFElse Activity 的條件判斷式!
在 IFElse 元件上要有一個個驚嘆號,點這個驚嘆號到[ 屬性 ] 視窗來設定條件判斷屬性。

在 [ Condition ] 屬性中我們選擇 [ 宣告式規則條件 ] 然後在 [ ConditionName ] 選擇 [...] 進入條件判斷的設定視窗。

在選取條件視窗中我們新增一個條件。會開啟一個 [ 規則條件編輯器 ]。

在規則條件編輯器裡面輸入 !this._checkdata 。 因為我們上一個 CodeActivity 元件中會判斷資料庫裡面有沒有現在這個Username。而判斷結果會存放在 _checkdata 這個變數中
。而這個 IFElse Activity 是用來篩選,當 _checkdata 是 False 的時候,就代表這裡面沒有資料。所以流程會走向左邊的新增帳號這個區塊。 而 _checkdata 是 True 的時候,就
代表資料庫裡面有這個Username資料,流程要走向右邊回覆申請人已經申請過的區塊。

編寫 沒申請過 區塊的程式 !
在沒申請過的區塊中有兩個 CodeActivity。它們的工作分別是將資料新增資料庫跟通知前端使用者已經新增完畢。撰寫的程式參考大概如下圖。再者告知使用者的部份,我
們只有一行簡單的程式碼是 _Result = "新增成功" 。這個變數之後會供ASP.Net網頁取得來顯示在網頁上告知User流程運作的執行結果。


編寫 申請過 區塊的程式!
在申請過的區塊中只有一個 [ CodeActivity ] 元件。點選這個元件兩下會跳到編輯視窗。在這部分我們輸入 _Result = "資料庫已經有這個帳號了" 這段程式碼。將這個
_Result 變數的狀態改變。


建置專案!
都設定完成了,這邊開始建置專案了 。如果運氣好的話~會看到建置成功!!!!
新增 ASP.Net 專案 !
這邊我們加入一個新的網站。網站名稱我定為 [ Lab4_ASPNet ]。
加入 Lab4_ASPNet_WWF 的組件參考!
在ASP.Net 網頁專案中將剛剛 Workflow foundation 專案編譯的 Dll 檔案加入參考。這樣ASP.Net網頁才可以使用Workflow foundation 的流程。
ASP.Net 網頁製作 !!
首先我們在ASP.Net 的網頁專案裡面的 Default.aspx 網頁拉出以下物件,3 個 Lable、兩個 textbox 。其中設定如下:
1. 第 1 個 Label 在 屬性中的Text 輸入 [ 輸入Username : ]。
2. 第 2 個 Label 在 屬性中的Text 輸入 [ 輸入Password : ]。
3. 第 3 個 Label 在 屬性中的 ID 輸入 [ ResultMsg ],這個 Label 是用來顯示WF流程執行結果的Label。
4. 第 1 個 Textbox 在 屬性中的ID 輸入 [ 輸入username : ]。
5. 第 2 個 Textbox 在 屬性中的ID 輸入 [ 輸入 password : ]。

然後將下列三個元件加入參考 : System.workflow.Activities 、System.workflow.ComponentModel 、 System.workflow.Runtime .

接下來進入Default.aspx 網頁檔案裡面引用下列這些元件,:
1. using System.Workflow.Runtime;
2. using System.Workflow.Activities;
3. using System.Workflow.ComponentModel;
4. using System.Collections.Generic;
5. using System.Threading;
6. using System.Data.OleDb;
然後在[ public partial class _Default : System.Web.UI.Page ]上打上[ private static AutoResetEvent _waitHandle = new AutoResetEvent(false); ]

接著到 [ 送出 ]的按鈕點兩下,在Button1_Click事件中編輯下列程式。首先我們要建立 WorkflowRuntime 執行週期。然後因為在我們設計的WF流程中有兩個變數是我們需要
傳給他的。所以我們要建立一個 Dictionary 物件來傳遞 Username 和 Password 的值給WWF 流程。
在 wf.WorkflowCompleted += new EventHandler<WorkflowCompletedEventArgs>(workflowCompleted) 的部份,我們將下方我們建立的一個 Void 方法委派給WorkflowCompleted
事件,也就是當WF流程執行完畢的時候會去呼叫這個方法。

這個方法在WF 流程被執行完畢時被呼叫,他會將流程中傳回的 Result 變數指派給ASP.Net 網頁中我們所建立的 Label 標籤,來顯示這個流程執行結果。

完成 !
所有設定都完成了。在此我們來測試一下剛剛練習的成果 。當按下執行的時候,你在 Textbox 框框中輸入你的 Username 與 Password。當資料庫裡面已經有你所申請的
Username 與 Password 的時候,下方的訊息就會回應你"資料庫已經有這個帳號了"。如果資料庫沒有這個帳號存在,則會告訴你 "新增成功" 。
|