WCF处理异常

来源:互联网 发布:park hyun seo 编辑:程序博客网 时间:2024/05/29 00:34

WCF异常处理

000011 初识WCF异常

000011.1 WCF中异常机制特点:
    a.当一个客户端调用WCF服务产生异常后,只会导致当前调用结束,它并不影响其它客户端对该WCF的调用,WCF仍然可以为其它客户端继续服务。
    b.WCF产生的异常对象是CLR中的对象类型,而WCF客户端却不一定是.NET,可能是Java或PHP等。所以WCF服务不能向客户端返回CLR异常对象。

注:在使用控制台承载WCF服务时,一旦一个服务出现异常(在服务端抛出一般的异常--非FaultException或FaultException<TDail>,在客户端已捕获异常),这个通道就会关闭,代理对象再次调用其他方法会出现“无法用于通信,因处于‘错误’状态”的提示;而在用IIS承载服务时,一个服务出现异常(在服务端抛出一般的异常--非FaultException或FaultException<TDail>,在客户端已捕获异常),通道并没有关闭,代理可以继续运行,调用其他服务没有出现异常。

000011.2 WCF异常的分类
    a.通信错误,诸如网络错误,地址错误,服务器没有启动等等。客户端表现为Communication Exception。
    b.状态异常,代理已经关闭,或者通道Fault,等问题,这个比较常见。一般通道闲置时间过久,通道会出现这个状态错误的问题。安全验证失败也会导致这个错误。
    c.服务异常,服务调用时抛出的异常,这个服务内部异常会序列化传递给客户端,被客户端捕获。

000011.3 WCF异常实例的关系
    a.Pre-Call实例模型: 服务实例被释放,客户端抛出 FaultException,产生异常的信道会被中断,相应的客户端代理对象无法继续使用,只能关闭。不影响其它客户端对服务的调用。
    b.Pre-Session实例模型:服务实例被释放,会话终止。客户端抛出 FaultException,产生异常的信道会被中断,相应的客户端代理对象无法继续使用,只能关闭。不影响其它客户端对服务的调用。
   c.Singleton实例模型:服务实例依旧运行。客户端抛出 FaultException,产生异常的信道会被中断,相应的客户端代理对象无法继续使用,只能关闭。不影响其它客户端对服务的调用。

000011 捕获WCF异常

000011.1 通过Exception捕获异常

在服务端抛出的异常正常情况下客户端是无法访问的,只能通过Exception去捕获,在客户端显示“由于内部错误,服务器无法处理请求”的相同的错误提示,客户端无法知道到底是什么引起了该方法的调用失败。在这种情况下我们可以通过在提供的服务上启用[ServiceBehavior(IncludeExceptionDetailInFaults=true)]特性,让客户端知悉服务失败的原因,也可以通过配置文件的方式更改在当前解决方案中的所有服务,让这些服务都明确报告自己失败的信息。


但是这种方式在客户端仍然只能以Exception的方式去捕获,对一些我们想知道具体错误的原因还没有很好的解决,比如参数异常(ArgumentException)想知道具体那个参数导致了错误等。。

000011.2 通过FaultException捕获异常

如果想在客户端调用服务时,出现的异常不影响以后的调用或者能获知简单的异常信息,则服务端应抛出FaultException异常。它可以在出现异常时不强制中断通信通道,在出错时代理然可以继续工作,不影响后续的调用。

优点:
    1.把服务端异常信息封装成标准的Soap错误格式,通过Http传递,在客户端可以得到服务端返回标准Soap错误,并从中取得出服务端异常信息。
    2.服务端抛出FaultException后,并不会破坏客户端与服务端的信道,客户端仍可以通过此信道向服务端发出调用。

缺点:只能向客户端返回简单的错误。

000011.3 通过FaultException<TDail>捕获异常

如果想要定义自己的异常信息,则需要在服务端定义一个TDail数据契约,且在此契约上应用[FaultContract(typeof(MyTypeContract))],MyTypeContract是自定义的契约类型。


在服务端就可以对异常进行包装抛出我们自定义的异常信息:


客户端通过捕获这种异常,可以获取详细的异常信息:

000012 WCF扩展应用

000012.1 自定义处理异常

使用IErrorHandler实现自定义错误逻辑处理


接口在定义了两个方法的声明:
1.void ProvideFault(Exception error,MessageVersion version,ref Message fault)方法:
触发时机:异常发生之后,向客户端发送错误之前被触发。
在这个方法中被触发的过程中,客户端一直等待服务端运行结束,客户端处于阻塞状态。所以尽量不要在这个方法中编写耗时太长的代码,防止客户端等待超时。

参数:
error:刚刚产生的异常对象,它可以是常规的CLR异常,也可以是SoapFault异常。如果在ProvideFault不编写任何代码的话,就会把该异常对象做为“未处理的异常”继续往上仍。
version:产生的Soap错误的版本。以Soap1.1或Soap1.2格式向客户端返回错误信息。
(ref) fault:输出参数,返回给客户端的错误消息。我们可以把刚刚的生的异常对象error经过包装或替换,形成一个新的错误消息fault,再把这个消息返回给客户端。

实现如下:


000012.2 自定义的错误处理类注册到通信信道中去

在承载进程运行时,系统会调用IServiceBehavior接口的ApplyDispatchBehavior()方法,向所有信道中注册自定义错误类。一旦运行发生错误就是触发相应的自定义错误处理程序。
这样并不会破坏通信信道。

 

客户端代码不用做变化。

原创粉丝点击