使用ReceiveAndSendReply活動模板和WorkflowServiceHost可以很容易地創建一個工作流服務。它可以像一個普通 WCF服務一樣與其他應用程序進行通信。大部分的配置也相當簡單。選擇Receive活動並加以配置,和SendReply活動類似。大部分的工作用在設置OperationContract或者ServiceContract上面。
出現了錯誤該怎麼辦
事實上是沒有任何屬性可以用來指定返回的錯誤。
拋出FaultException
當Workflow服務拋出一個FaultException的時候,非常期待它被及時處理。異常能被當作SOAP錯誤被發送到客戶端,假設客戶端也是.NET,可以將它作為一個FaultException進行捕獲。
拋出FaultException<T>
通常,當您想給異常添加一些額外的信息,您就需要創建一個額外的類,並用FaultContract屬性聲明服務契約,來指定返回的錯誤。在客戶端需要添加服務元數據,做一個添加服務引用來創建所需的類型。但是,對於工作流服務,沒有用於添加屬性的服務契約類。就沒有屬性給我們使用來實現這些目的。那麼,我們如何指定與工作流服務交互的異常契約呢?
解決方案
竅門是給工作流上相關的Receive活動添加第二個SendReply。第二個SendReply活動返回錯誤契約。添加第二個SendReply活動很簡單,只需右鍵單擊Receive活動,並選擇創建SendReply活動就行了。下一步創建一個變量來保存的錯誤信息。
我使用的FaultDetail很簡單,它將所有收到的數據發送回客戶端。
1 using System.Runtime.Serialization;
2 namespace ServicesAndFaults{
3 [DataContract]
4 public class FaultDetail
5 {
6 [DataMember]
7 public int Data { get; set; }
8 }
9 }
10
對於第二個SendReply活動,創建和拋出一個FaultException。工作流流程圖如下所示:
下面的表達式用來初始化錯誤異常
下面的SendReply活動是返回錯誤,配置如下的:
有了這個設置,可以在客戶端添加Service Reference和使用下面的代碼得到預期的結果
1 static void Main(string[] args)
2 {
3 var proxy = new ServiceClient();
4 try
5 {
6 Console.WriteLine(proxy.GetData(42));
7 }
8 catch (FaultException<FaultDetail> ex)
9 {
10 Console.WriteLine("FaultException<FaultDetail> with {0}", ex.Detail.Data);
11 }
12 catch (FaultException ex)
13 {
14 Console.WriteLine(ex);
15 }
16 Console.ReadLine();
17 }
服務控制台應用程序中工作流輸出如下。請注意,最後一條消息,“the workflow finishing”沒有出現。不要奇怪,我們拋出一個異常其實沒有被捕獲,它終止了工作流。
但想讓工作流繼續跑下去!
有時上面的處理方式很好,但有時候並不是。例如你在一個訂單上工作了1個月了,你會僅僅因為一個異常而終止所有的工作嗎?當然不會。
第二種方法返回給調用客戶端的個錯誤,只不過是SendReply活動中自定義的FaultException或FaultException <T>。客戶端不會知道其中的差別,但工作流程還會繼續運行。因此,我需要做的是移出Throw 活動,讓第二個SendReply活動實現它的工作。
這一次,服務控制台應用程序輸出如下:
本文配套源碼