如何在調用WCF服務之前彈出一個確認對話框?
昨天有人在微博上問我如下一個問題:
老蔣,客戶端調用wcf的一個接口函數時,有沒有什麼辦法可以先彈出一個確認框,確認後再執行調用。因為這個接口函數再很多地方都執行了調用,所以我想在某個入口進行統一地彈出一個確認框...
其實這個問題可以通過WCF的擴展來完成,具體來說這個擴展涉及到一個我們不太常用的組件“InteractiveChannelInitializer”,在我的《WCF全麵解析》中對它有過概括性的介紹。InteractiveChannelInitializer實現了接口IInteractiveChannelInitializer,從名稱可以看出這是一個“交互性”的“信道初始化器”,在一般情況下我們用它來動態地指定客戶端調用憑證(比如在彈出的登錄對話框中輸入用戶名和密碼)。而上麵這個問題就可以通過自定義InteractiveChannelInitializer來實現,我為此寫了一個簡單的實例(源代碼從這裏下載)。
右圖所示的是實例的運行界麵。我們以Windows Form應用的方式編寫了一個“計算器”,計算結果通過調用WCF服務來獲取。在每次調用服務之前都會彈出一個確認對話框,真正的服務調用隻有在用戶確認之後方能進行。
用於實現“服務調用確認”的自定義InteractiveChannelInitializer(InvocationConfirmationInteractiveChannelInitializer)定義如下。我們在BeginDisplayInitializationUI方法中彈出一個確認對話框,並將用戶的確認選擇封裝到一個簡單的AsyncResult對象中返回。在EndDisplayInitializationUI方法中,通過AsyncResult對象確認用戶是否取消本次服務調用,如果是則拋出一個自定義的InvocationCancelException異常。
1: public class InvocationConfirmationInteractiveChannelInitializer : IInteractiveChannelInitializer
2: {
3: public const string ConfirmMessage = "程序執行過程涉及到WCF服務調用,是否繼續?";
4: public IAsyncResult BeginDisplayInitializationUI(IClientChannel channel, AsyncCallback callback, object state)
5: {
6: bool cancel = MessageBox.Show(ConfirmMessage, "WCF服務調用確認", MessageBoxButtons.YesNo) == DialogResult.No;
7: return new SimpleAsynsResult(cancel);
8: }
9:
10: public void EndDisplayInitializationUI(IAsyncResult result)
11: {
12: SimpleAsynsResult asyncResult = (SimpleAsynsResult)result;
13: if((bool)asyncResult.AsyncState)
14: {
15: throw new InvocationCancelException("WCF服務調用被取消");
16: }
17: }
18: }
19:
20: public class SimpleAsynsResult:IAsyncResult
21: {
22: public SimpleAsynsResult(object state)
23: {
24: this.AsyncState = state;
25: }
26:
27: public object AsyncState { get; private set; }
28: public WaitHandle AsyncWaitHandle { get; private set; }
29: public bool CompletedSynchronously
30: {
31: get { return true; }
32: }
33: public bool IsCompleted
34: {
35: get { return true; }
36: }
37: }
我們通過一個自定義的ContractBehavior(InvocationConfirmationBehaviorAttribute )將上麵自定義的InvocationConfirmationInteractiveChannelInitializer應用到客戶端運行時。如下麵的代碼片斷所示,在實現的ApplyClientBehavior方法中,我們創建了一個InvocationConfirmationInteractiveChannelInitializer對象並將其添加到客戶端運行時的InteractiveChannelInitializers集合中。
1: [AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface)]
2: public class InvocationConfirmationBehaviorAttribute : Attribute, IContractBehavior
3: {
4: public void AddBindingParameters(ContractDescription contractDescription, ServiceEndpoint endpoint, BindingParameterCollection bindingParameters) { }
5: public void ApplyClientBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, ClientRuntime clientRuntime)
6: {
7: clientRuntime.InteractiveChannelInitializers.Add(new InvocationConfirmationInteractiveChannelInitializer());
8: }
9: public void ApplyDispatchBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, DispatchRuntime dispatchRuntime) { }
10: public void Validate(ContractDescription contractDescription, ServiceEndpoint endpoint) { }
11: }
以特性形式定義的InvocationConfirmationBehaviorAttribute直接以如下的方式直接應用到作為服務契約的ICalcualtor接口中:
1: [ServiceContract(Name = "CalculatorService", Namespace ="https://www.artech.com/")]
2:
3: public interface ICalculator
4: {
5: [OperationContract]
6: double Add(double x, double y);
7: }
那麼在進行服務調用的時候,確認對話框會自動彈出來。如果用戶選擇終止當前服務調用,那麼InvocationCancelException異常會被拋出來,我們隻需要捕捉該類型的異常即可。如下所示的是“=”按鈕的Click事件代碼:
1: public partial class Form1 : Form
2: {
3: //其他成員
4: private void buttonCalculate_Click(object sender, EventArgs e)
5: {
6: this.textBoxResult.Text = string.Empty;
7: using (ChannelFactory<ICalculator> channelfactory = new ChannelFactory<ICalculator>("calculatorservice"))
8: {
9: ICalculator calculator = channelfactory.CreateChannel();
10: try
11: {
12: double op1 = double.Parse(this.textBoxOp1.Text);
13: double op2 = double.Parse(this.textBoxOp2.Text);
14: double result = calculator.Add(op1,op2);
15: this.textBoxResult.Text = result.ToString();
16: }
17: catch (InvocationCancelException)
18: {
19: }
20: catch (Exception ex)
21: {
22: MessageBox.Show(ex.Message);
23: }
24: }
25: }
26: }
微信公眾賬號:大內老A
微博:www.weibo.com/artech
如果你想及時得到個人撰寫文章以及著作的消息推送,或者想看看個人推薦的技術資料,可以掃描左邊二維碼(或者長按識別二維碼)關注個人公眾號(原來公眾帳號蔣金楠的自媒體將會停用)。
本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁麵明顯位置給出原文連接,否則保留追究法律責任的權利。
最後更新:2017-10-25 16:33:44