首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> 關於.NET

WCF 服務調用異常處理全景:異常類型層次、捕獲順序與服務端補償機制

     編輯:關於.NET

異常捕獲順序鐵律

try
{
    var client = new CalcClient();
    string result = client.Div(10, 0);
}
catch (TimeoutException ex) { /* 1. 超時 */ }
catch (FaultException ex) { /* 2. 強類型 SOAP Fault */ }
catch (FaultException ex) { /* 3. 非強類型 SOAP Fault */ }
catch (CommunicationException ex) { /* 4. 通信層異常 */ }
catch (Exception ex) { /* 5. 其它 */ }

異常類型繼承層次

FaultException 層次

TimeoutException 層次

System.Exception
  └─ System.SystemException
       ├─ System.TimeoutException          (超時)
       └─ System.ServiceModel.CommunicationException  (通信基類)
            └─ System.ServiceModel.FaultException      (SOAP Fault 基類)
                 └─ System.ServiceModel.FaultException (強類型 Fault)

服務端異常轉換實戰

場景 1:直接拋出 CLR 異常

public string Div(int x, int y)
{
    try { return (x / y).ToString(); }
    catch (DivideByZeroException ex) { throw ex; } // 客戶端捕獲:FaultException
}

場景 2:手動拋出 FaultException

catch (DivideByZeroException ex)
{
    throw new FaultException(ex.Message); // 客戶端捕獲:FaultException
}

場景 3:拋出強類型 FaultException

[FaultContract(typeof(GreetingError))]
public string Div(int x, int y)
{
    if (y == 0)
        throw new FaultException(new GreetingError("Divisor cannot be zero"));
    return (x / y).ToString();
}
// 客戶端捕獲:FaultException (第 2 優先級)

CommunicationException 觸發條件

通信層失敗:連接斷開、協議錯誤、序列化失敗。服務主動關閉通道需指定超時才能觸發:

// 錯誤:客戶端會超時
OperationContext.Current.Channel.Close(); 

// 正確:立即返回 CommunicationException
OperationContext.Current.Channel.Close(new TimeSpan(0,0,0,0,500)); // 500ms
// 或
OperationContext.Current.Channel.Abort();

服務端補償機制:ServiceBase 模式

public abstract partial class ServiceBase
{
    private IContextChannel _channel;
    
    protected ServiceBase()
    {
        _channel = OperationContext.Current.Channel;
        _channel.Opening  += (s,e) => { /* 日誌/驗證 */ };
        _channel.Opened   += (s,e) => { /* 初始化 */ };
        _channel.Closing  += (s,e) => { /* 清理資源 */ };
        _channel.Closed   += (s,e) => Abort(); // 關鍵:確保異常路徑也 Abort
        _channel.Faulted  += (s,e) => Abort(); // 故障狀態立即 Abort
    }
    
    void Abort() { _channel.Abort(); }
}

CommunicationException 捕獲效果

最佳實踐總結

  1. 服務端:盡量拋出 FaultException<T>,配合 [FaultContract],讓客戶端強類型捕獲
  2. 客戶端:嚴格按層次捕獲,TimeoutException 最優先,FaultException<T> 次之
  3. 通道管理:服務端 Closed/Faulted 事件中調用 Abort(),避免客戶端掛起
  4. 日誌記錄:在 IErrorHandler 或 ServiceBase 事件中統一記錄

總結

WCF 異常處理核心在於理解 FaultException<T> → FaultException → CommunicationException → TimeoutException 的捕獲優先級,並配合服務端通道生命週期管理確保異常能正確傳遞到客戶端。強類型 Fault 契約是構建健壯分散式系統的基石。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved