在WCF中的異常處理方法

來源:互聯網
上載者:User
在 WCF 中,用戶端調用服務時,可能拋出的異常有以下三種類型。

1. 通訊異常。諸如網路錯誤,地址錯誤,伺服器沒有啟動等等。這類異常多是 CommunicationException (或其具體繼承類型)。
2. 狀態異常。比如訪問了已經關閉的代理對象,契約錯誤,以及安全設定錯誤等。常見的有 ObjectDisposedException。
3. 服務異常。由伺服器觸發,多是 FaultException。

針對服務異常,不同的執行個體管理方式會有不同的策略。

1. Pre-Call: 服務執行個體被釋放,用戶端拋出 FaultException,用戶端代理對象無法繼續使用。
2. Pre-Session: 服務執行個體被釋放,會話終止。用戶端拋出 FaultException,用戶端代理對象無法繼續使用。
3. Singleton: 服務執行個體依舊運行,會話終止。用戶端拋出 FaultException,用戶端代理對象無法繼續使用。

基於平台中立和技術整合的需要,WCF 以標準 Soap Faults 方式傳遞異常資訊。WCF 提供了 FaultException 和 FaultException<T> 兩個類型來操控 Soap Faults。通過 FaultException<T> 我們可以向用戶端傳遞一個錯誤資訊(FaultReason)以及一個附加的詳細資料(Detail)。理論上,這個附加資訊是任何可以序列化的對象。throw new FaultException<int>(123, "abc");
throw new FaultException<Exception>(new Exception("abc"));

如果想傳遞一個附帶中繼資料的自訂詳細資料,可以使用 FaultContract。[DataContract]
public class ExceptionData
{
  [DataMember]
  public string Message;
}

[ServiceContract]
public interface IService
{
  [OperationContract]
  [FaultContract(typeof(ExceptionData))]
  void Test();
}

public class Service : IService, IDisposable
{
  public void Test()
  {
    ExceptionData d = new ExceptionData();
    d.Message = "xxxxxx";

    throw new FaultException<ExceptionData>(d, "abc");
  }

  public void Dispose()
  {
    Console.WriteLine("Dispose...");
  }
}

當然,我們也可以直接拋出一個被稱之為 "Unknown Faults" 的 FaultException 異常執行個體。還有另外一種情況,你已經寫好了代碼,有很多……很多……的代碼,要是一個個修改會非常……非常……麻煩,那麼怎麼在不做大的代碼修改情況下傳遞詳細異常資訊給用戶端呢?

方法1: ServiceBehavior(IncludeExceptionDetailInFaults=true)][ServiceBehavior(IncludeExceptionDetailInFaults=true)]
public class Service : IService, IDisposable
{
  public void Test()
  {
    throw new Exception("abc");
  }

  public void Dispose()
  {
    Console.WriteLine("Dispose...");
  }
}

方法2: ServiceDebugBehavior

這個比方法1要更方便一些,我們除了可以寫代碼外,還可以用設定檔。ServiceHost host = new ServiceHost(typeof(Service), new Uri("http://localhost:8080/Service"));
host.AddServiceEndpoint(typeof(IService), new BasicHttpBinding(), "");

ServiceDebugBehavior debug = host.Description.Behaviors.Find<ServiceDebugBehavior>();
debug.IncludeExceptionDetailInFaults = true;

host.Open();

看看這兩種方法拋出的異常是什麼樣的。未處理 System.ServiceModel.FaultException`1
  Message="abc"
  Source="mscorlib"
  StackTrace:
    Server stack trace:
      在 ConsoleApplication1.localhost.IService.Test()
      在 ConsoleApplication1.localhost.ServiceClient.Test() 位置 D:\...\localhost.cs:行號 60
      在 ConsoleApplication1.Program.Main(String[] args) 位置 D:\...\Program.cs:行號 62

不錯,除了 Error Message,還有詳細的 stack trace,方便調試。也正因為這樣,此種方法也不適合在正式項目中使用,作為系統架構設計的一部分,我們應該事先設計好異常處理。

如果服務方法是 IsOneWay=true,因不接收返回訊息,用戶端也就不會觸發異常了。而 Callback 無非是伺服器和用戶端掉換個身份而已,道理相同。public interface ICallback
{
  [OperationContract]
  void DoCallback();
}

[ServiceContract(CallbackContract=typeof(ICallback))]
public interface IService
{
  [OperationContract]
  void Test();
}

[ServiceBehavior(ConcurrencyMode=ConcurrencyMode.Reentrant)]
public class Service : IService, IDisposable
{
  public void Test()
  {
    try
    {
      OperationContext.Current.GetCallbackChannel<ICallback>().DoCallback();
    }
    catch (FaultException e)
    {
      Console.WriteLine(e);
    }
  }

  public void Dispose()
  {
    Console.WriteLine("Dispose...");
  }
}

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.