WCF异常处理

1:WCF异常在配置文件

<configuration>
  <system.serviceModel>
    <behaviors>
      <serviceBehaviors>
        <behavior name="serviceDebuBehavior">
          <serviceDebug includeExceptionDetailInFaults="true" />
        </behavior>
      </serviceBehaviors>
    </behaviors>

    <services>      
      <service name="Artech.WcfServices.Service.CalculatorService" behaviorConfiguration="serviceDebuBehavior">
        <endpoint address="http://127.0.0.1:3721/calculatorservice"
                  binding="ws2007HttpBinding"
                  contract="Artech.WcfServices.Service.Interface.ICalculator" />
      </service>
    </services>
  </system.serviceModel>
</configuration>

2:也可以直接在服务上直接用特性进行设定

[ServiceBehavior(IncludeExceptionDetailInFaults=true)]
public class CalculatorService:ICalculator
{
}

上面两种方式实现的效果是一样的;

 

3:自定义异常信息

  (1)直接通过FaultException直接指定错误的信息

using System.ServiceModel;
namespace Artech.WcfServices.Service
{
    public class CalculatorService : ICalculator
    {
        public int Divide(int x, int y)
        {
            if (0 == y)
            {
                throw new FaultException("被除数y不能为零!");
            }
            return x / y;

        }
    }
}


 相应的配置文件内容为:

<configuration>
  <system.serviceModel>
    <behaviors>
      <serviceBehaviors>
        <behavior name="serviceDebuBehavior">
          <serviceDebug includeExceptionDetailInFaults="true" />
        </behavior>
      </serviceBehaviors>
    </behaviors>

    <services>      
      <service name="Artech.WcfServices.Service.CalculatorService" behaviorConfiguration="serviceDebuBehavior">
        <endpoint address="http://127.0.0.1:3721/calculatorservice"
                  binding="ws2007HttpBinding"
                  contract="Artech.WcfServices.Service.Interface.ICalculator" />
      </service>
    </services>
  </system.serviceModel>
</configuration>

(2)通过FaultException<TDetail>采用自定义类型封装错误

首先我们看一下一个实例;注意Interface层里的CalculaltionError.cs这个是自定义封装的错误类;

CalculaltionError.cs类代码如下:它是一个数据契约

using System.Text;
using System.Runtime.Serialization;

namespace Artech.WcfServices.Service.Interface
{
    [DataContract]
    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; }
    }

}

契约里的定义如下:为了确保错误细节对象能够被正常序列化和反序列化,

要按照如下的方式通过FaultContractAttribute特性为操作定义基于CalculationError类型的错误契约

(错误契约的一些注意点在下面会讲到);

namespace Artech.WcfServices.Service.Interface
{
    [ServiceContract(Namespace = "http://www.artech.com/")]
    public interface ICalculator
    {
        [OperationContract]
        [FaultContract(typeof(CalculationError))]
        int Divide(int x, int y);
    }   
}


服务实现里直接抛出一个FaultException<CalculationError>,并创建一个CalculationError对象作为该异常对象的细节;

using System.ServiceModel;
namespace Artech.WcfServices.Service
{
    public class CalculatorService : ICalculator
    {
        public int Divide(int x, int y)
        {
            if (0 == y)
            {
                var error = new CalculationError("Divide", "被除数y不能为零!");
                throw new FaultException<CalculationError>(error, error.Message);
            }
            return x / y;
        }
    }
}

服务实现的配置文件内容如下:

<configuration>
  <system.serviceModel>
    <behaviors>
      <serviceBehaviors>
        <behavior name="serviceDebuBehavior">
          <serviceDebug includeExceptionDetailInFaults="true" />
        </behavior>
      </serviceBehaviors>
    </behaviors>

    <services>      
      <service name="Artech.WcfServices.Service.CalculatorService" behaviorConfiguration="serviceDebuBehavior">
        <endpoint address="http://127.0.0.1:3721/calculatorservice"
                  binding="ws2007HttpBinding"
                  contract="Artech.WcfServices.Service.Interface.ICalculator" />
      </service>
    </services>
  </system.serviceModel>
</configuration>


客户端调用相关的异常处理;获得FaultException<CalculationError>类型的异常

using System.ServiceModel;
using Artech.WcfServices.Service.Interface;
namespace Artech.WcfServices.Clients
{
    class Program
    {
        static void Main(string[] args)
        {
            using (ChannelFactory<ICalculator> channelFactory = new ChannelFactory<ICalculator>("calculatorservice"))
            {
                ICalculator calculator = channelFactory.CreateChannel();
                using (calculator as IDisposable)
                {
                    try
                    {
                        int result = calculator.Divide(1, 0);
                    }
                    catch (FaultException<CalculationError> ex)
                    {
                        Console.WriteLine("运算错误");
                        Console.WriteLine("运算操作:{0}", ex.Detail.Operation);
                        Console.WriteLine("错误消息: {0}", ex.Detail.Message);
                        (calculator as ICommunicationObject).Abort();
                    }
                }                
            }
            Console.Read();

        }
    }

}


客户端配置信息如下:

<configuration>
  <system.serviceModel>
    <client>
      <endpoint name="calculatorservice"
                address= "http://127.0.0.1:3721/calculatorservice"
                binding="ws2007HttpBinding"
                contract="Artech.WcfServices.Service.Interface.ICalculator"/>
    </client>
  </system.serviceModel>
</configuration>


*接下来讲解关于错误契约的注意点:

对于错误契约的运用不仅仅在将自定义的错误细节类型应用到服务契约相应操作上时才要显式地在操作方法上应用FaultContracAttribute特性;对于一些基元类型(比如Int32, String等)也要这么做;

public class CalculatorService : ICalculator
    {
        public int Divide(int x, int y)
        {
            if (0 == y)
            {
                throw new FaultException<String>("不能为0");
            }
            return x / y;
        }
    }

契约如下:

namespace Artech.WcfServices.Service.Interface
{
    [ServiceContract]
    public interface ICalculator
    {
        [OperationContract]
        [FaultContract(typeof(string))]
        int Divide(int x, int y);
    }   
}

当然它是可以多次声明针对多个异常的处理

namespace Artech.WcfServices.Service.Interface
{
    [ServiceContract]
    public interface ICalculator
    {
        [OperationContract]
        [FaultContract(typeof(CalculationError))]
        [FaultContract(typeof(string))]
        int Divide(int x, int y);
    }   
}

若是两个是相同类型的则要增加Name 或者Namespace来区别开;若是Name一样类型不一样同样会报错;

[ServiceContract]
    public interface ICalculator
    {
        [OperationContract]
        [FaultContract(typeof(CalculationError),Name="CalualationError")]
        [FaultContract(typeof(CalculationError),Name="CalualationException")]
        int Divide(int x, int y);
    }

(4)通过XmlSerializer对错误细节对象进行序列化([XmlSerializerFormat(SupportFaults=true)])因为WCF默认是采用序列化器是DataContractSerializer(WCF提供的两种序列化器DataContractSerializer 和 XmlSerializer)

[ServiceContract]
    public interface ICalculator
    {
        [OperationContract]
        [FaultContract(typeof(CalculationError))]
        [XmlSerializerFormat(SupportFaults=true)]
        int Divide(int x, int y);
    }

封装的错误类如下:

[Serializable]
    public class CalculationError
    {
        [XmlAttributeAttribute("op")]
        public string Operation { get; set; }
        [XmlElement("Error")]
        public string Message { get; set; }
    }



本文出自勇哥的网站《少有人走的路》wwww.skcircle.com,转载请注明出处!讨论可扫码加群:

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

会员中心
搜索
«    2025年4月    »
123456
78910111213
14151617181920
21222324252627
282930
网站分类
标签列表
最新留言
    热门文章 | 热评文章 | 随机文章
文章归档
友情链接
  • 订阅本站的 RSS 2.0 新闻聚合
  • 扫描加本站机器视觉QQ群,验证答案为:halcon勇哥的机器视觉
  • 点击查阅微信群二维码
  • 扫描加勇哥的非标自动化群,验证答案:C#/C++/VB勇哥的非标自动化群
  • 扫描加站长微信:站长微信:abc496103864
  • 扫描加站长QQ:
  • 扫描赞赏本站:
  • 留言板:

Powered By Z-BlogPHP 1.7.2

Copyright Your skcircle.com Rights Reserved.

鄂ICP备18008319号


站长QQ:496103864 微信:abc496103864