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

WCF 異常處理最佳實踐:從 FaultContract 到 IErrorHandler

     編輯:關於.NET

為何傳統 try-catch 失效

WCF 服務拋出的 .NET 例外無法直接序列化傳遞給客戶端。若服務直接 throw new DirectoryNotFoundException(...),客戶端 catch (DirectoryNotFoundException) 永不會命中,只能捕獲泛型 FaultException 或 Exception,且會導致通道進入 Faulted 狀態,後續呼叫拋出 CommunicationObjectFaultedException,服務實例(PerSession/Singleton)甚至被終結。

正解:FaultContract + FaultException<T>

  1. 服務合約標註:[FaultContract(typeof(DirectoryNotFoundException))]
  2. 服務實作拋出強型別錯誤:
    throw new FaultException<DirectoryNotFoundException>(
        new DirectoryNotFoundException(),
        new FaultReason($"Directory {homeDir} is not found."));
  3. 客戶端捕獲:catch (FaultException<DirectoryNotFoundException> ex) —— 可取得詳細錯誤資訊,通道保持開啟,服務實例存活,後續呼叫正常。

替代方案一:IncludeExceptionDetailInFaults(僅開發/診斷用)

在 [ServiceBehavior(IncludeExceptionDetailInFaults = true)] 或組態開啟,客戶端可捕獲非 FaultException 詳細資訊,但通道仍會錯誤,**嚴禁生產環境開啟**(洩露堆疊細節)。

替代方案二:IErrorHandler 擴展(全域統一處理)

適合不想在每個操作加 FaultContract、或需統一記錄日誌的場景。

  1. 服務類別實作 IErrorHandler:
    ProvideFault() 將一般例外轉為 FaultException<T>;
    HandleError() 處理記錄日誌等副作用。
  2. 實作 IServiceBehavior,在 ApplyDispatchBehavior() 中將自身加入 ChannelDispatcher.ErrorHandlers。
public void ProvideFault(Exception error, MessageVersion version, ref Message fault)
{
    if (error is DirectoryNotFoundException)
    {
        var fe = new FaultException<DirectoryNotFoundException>(
            new DirectoryNotFoundException(), new FaultReason(error.Message));
        fault = Message.CreateMessage(version, fe.CreateMessageFault(), fe.Action);
    }
}
public void ApplyDispatchBehavior(ServiceDescription desc, ServiceHostBase host)
{
    foreach (ChannelDispatcher d in host.ChannelDispatchers)
        d.ErrorHandlers.Add(this);
}

此法下,服務拋出原生例外,客戶端仍能收到強型別 FaultException<T>,通道不中斷,服務實例不終結。

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