1、WCF基本异常处理模式

1)、在默认的情况下,客户端是不可以捕捉到服务端抛出的异常错误信息,我们可以通过配置和代码的方式打开调试信息,让客户端获取到服务端抛出的异常:

  • 配置方式:

  <behaviors>

    <serviceBehaviors>

      <behaviors name ="serviceDebugBehaviors">

        <seviceDebug includeExceptionDetailInFaults="true"/>

      </behaviors>

    </serviceBehaviors>

  </behaviors>

  <services>

    <service behaviorConfiguration ="serviceDebugBehaviors" .....>

  </services>

  • 代码方式:在相应的服务上添加ServiceBehavior特性,配置IncludeExceptionDetailInFaults属性为True即可。

  [ServiceBehavior(IncludeExceptionDetailInFaults = true)]

  public class CalculatorServices:ICalculator

  {}

尽管可以通过两种方式,可以让客户获取到服务端抛出的异常,但是,这样的话,服务端所有的异常都会明明白白的展现在客户端,在某些情况下还是不安全的,那么我们如何自定义错误信息呢,也就是如何选择性的抛出服务端的异常错误信息呢,就是下面讲的错误契约的作用。

2)、错误契约:

  在服务端我们通常通过FaultException<TDetail>泛型类型包装我们自定义的错误信息,下面举个例子说明如何使用错误契约:

  • 首先定义一个自定义的异常数据类型:

  [DataContract(Namespace=http://www.hanshuai.com)]

  public class CalculationError

  {

    public CalculationError(string operation,string message)

    {

      this.Operation=operation;

      this.Message=message;

    }

    [DataMember]

    public string Operation{get;set;}

    [DataMember]

    public string Message{get;set;}

  }

  • 在服务契约中:

  [ServiceContract]

  public interface ICalculator

  {

    [OperationContract]

    [FaultContract(typeof(CalculationError))]//指定错误契约类型CalculationError

    int Divide(int x,int y);

  }

  • 在服务实现的时候:

  public class CalculatorService:ICalculator

  {

    public int Divide(int x,int y)

    {

      if(0==y)//被除数为0

      {

        var error =new CalculationError("Divide","被除数y不能为0");

        throw new FaultException<CalculationError>(error,error.Message);//抛出异常

      }

      return x / y;

    }

  }

这样,当我们在客户端调用Divide方法的时候,如果y为0,就会抛出“被除数y不能为0”的错误信息。

  try

  {

    int result =calculator.Divide(1,0);

  }

  catch(FaultException<CalculationError> ex)

  {

    ex.Detail.Operation;//服务端自定义的错误操作

    ex.Detail.Message;

  }

到此,基本可以了解到,如何在服务端自定义错误信息,但是,对于错误契约,有几个特别的细节需要注意下:

  • 在服务契约中,一个操作方法上可以多个错误契约,如:

  [FaultContract(typeof(CalculationError)]

  [FaultContract(typeof(string)]

  int Divide(int x, int y);

  但是,多个错误契约的错误类型不可以相同,如果相同,必须通过name属性,指定不同的名称,另外,不同的错误类型,应用在同一个草错方法上,不可以指定相同的name和namespace 如下页是不允许的:

  [FaultContract(typeof(CalculationError),name ="Fault",namespace ="http://www.hanshuai.com"]

  [FaultContract(typeof(string),name ="Fault",namespace ="http://www.hanshuai.com"]

  int Divide(int x, int y);

 

posted on 2013-08-28 10:47  Kelly_HanShuai  阅读(89)  评论(0)    收藏  举报