首先以一个简单的例子演示一下远程调用发生异常的结果:

服务器端代码如下:

[ServiceContract]
public interface IService1
{
[OperationContract]
void ErrorTest();
} public class Service1 : IService1
{
public void ErrorTest() { throw new InvalidOperationException("异常测试");
}

该服务非常简单,直接抛一个异常。当运行客户端代码触发这个异常时,客户端会接收到如下异常:

  

从中我们可以看到:虽然服务器端抛出的是InvalidOperationException异常,但是客户端接收到的却是FaultException异常。从WCF测试客户端的传递的消息中也可以看出这一点。

  

WCF异常处理机制

  1. 通讯异常,这通常是因为链路的原因,比如服务没有启动,网络阻塞等。通常是CommunicationException或者其派生类
  2. 超时异常,这类异常是因为操作时间超时,超时时会抛出 TimeoutException
  3. 服务异常,由服务端根据具体的业务逻辑触发,当业务逻辑抛出异常时,会将其封装成FaultException抛给客户端。

通信异常和超时异常是由WCF框架所产生的,由于网络原因,它们出现是正常的,因此也被称为预期异常,是正常调用的时候需要处理的异常。而FaultException异常则是业务逻辑中异常情况时出现的异常,是由自己实现的代码中产生的,是非预期的异常。具体处理方式根据业务逻辑而定。

但值得注意的是:服务被设置为PerSession模式或者Single模式,服务异常还会导致服务对象被释放而终止服务。(这个是在网上看到的说明,但我自己试的时候没有挂,从WCF服务对象模型上来分析也不应该会挂,也没有看到MSDN上哪儿有写,待后续确认后再更新)

至于为什么要将CLR异常封装成FaultException后抛出,我的理解是:对于异常信息,是序列化后才发布给客户端的,也就是说,客户端也
得需要理解这个异常才能反序列化异常信息。因此,客户端必须知道异常的格式,由于WCF的客户端并非只有.net语言才能实现,因此需要发布异常格式,由
于CLR的异常比较多,加上还有自定义异常,无法公布所有异常格式,因此,将其统一成FaultException发布,这样客户端才能顺利解析。

了解了这个后,我们就知道InvalidOperationException异常为什么会变成了FaultException异常,但是存在的一个问题是:虽然客户端能感知到调用服务发生了异常,但仍然不知道异常信息,有时无法进行进一步处理。

Debug期间异常信息传递

在前面的异常信息中就有说明:有关该错误的详细信息,请打开服务器上的 IncludeExceptionDetailInFaults (从 ServiceBehaviorAttribute 或从 <serviceDebug> 配置行为)以便将异常信息发送回客户端。它告诉了我们有两个方式可以传递这个异常信息:

  1. 配置serviceBehaviors,将includeExceptionDetailInFaults设置为true

  

  1. 在服务上的ServiceBehaviorAttribute里面设置IncludeExceptionDetailInFaults

  

这两种方式是等效的,不过建议在配置文件里面使用,统一设置比较方便,也方便统一关闭。

经过这个设置后,再运行客户端代码,这次就可以看到异常信息了:

  

连异常的调用栈也能看到,方便我们进行异常定位。

<StackTrace> 在 WcfService.Service1.ErrorTest() 位置 Service1.cs:行号24
在 SyncInvokeErrorTest(Object , Object[] , Object[] )

不过,这个在另一方面也暴露了服务器的信息,对于这种网络程序来说是不安全的,因此只建议在Debug的时候使用,从serviceDebug的名字中也可以看出这一点。

构造FaultException

为了安全,前面所说的异常信息获取方式,只能在Debug期间使用,那么,对于Release版本,则需要我们自己手动把运行异常封装成FaultException返回。

    public class Service1 : IService1
{
public void ErrorTest()
{
try
{
throw new InvalidOperationException("异常测试");
}
catch (Exception e)
{
throw new FaultException(e.Message);
}
}
}

这次我们就能获取到异常信息了。

  

对于比较复杂的异常信息,可以自己构造一个FaultException<T>,如下是一个简单的示例:

    [ServiceContract]
public interface Iservice
{
[OperationContract]
[FaultContract(typeof(DataAccessFault))]
void Operation();
} public class Service : Iservice
{
public void Operation()
{
try
{
// Access database …
}
catch (DbException e)
{
DataAccessFault fault = new DataAccessFault();
fault.AdditionalDetails = e.Message;
throw new FaultException<DataAccessFault>(fault);
}
}
}

自己手动构造FaultException的方式比较麻烦,需要在每一个提供的接口中都捕获异常,并重新封装抛出,一来不好看,处理起来也比较麻烦。由于篇幅有限,下篇文章中介绍一个更为简单的方法。

WCF入门(七)——异常处理1的更多相关文章

  1. 无废话WCF入门教程六[一个简单的Demo]

    一.前言 前面的几个章节介绍了很多理论基础,如:什么是WCF.WCF中的A.B.C.WCF的传输模式.本文从零开始和大家一起写一个小的WCF应用程序Demo. 大多框架的学习都是从增.删.改.查开始来 ...

  2. WCF 入门(15)

    前言 度过了一个阳光明媚的周末. 一个阴霾的周日夜晚. 第15集 WCF里面的异常处理(1)  Exception handling in WCF 大致看了一下,这个WCF视频里面总共有6集,这个是第 ...

  3. WCF入门教程(四)通过Host代码方式来承载服务 一个WCF使用TCP协议进行通协的例子 jquery ajax调用WCF,采用System.ServiceModel.WebHttpBinding System.ServiceModel.WSHttpBinding协议 学习WCF笔记之二 无废话WCF入门教程一[什么是WCF]

    WCF入门教程(四)通过Host代码方式来承载服务 Posted on 2014-05-15 13:03 停留的风 阅读(7681) 评论(0) 编辑 收藏 WCF入门教程(四)通过Host代码方式来 ...

  4. 【转】WCF入门教程六[一个简单的Demo]

    一.前言 前面的几个章节介绍了很多理论基础,如:什么是WCF.WCF中的A.B.C.WCF的传输模式.本文从零开始和大家一起写一个小的WCF应用程序Demo. 大多框架的学习都是从增.删.改.查开始来 ...

  5. 学习WCF入门的第一个实例

    一.概述 WCF说白了就是一个基于终结点的通信手段!就是Service端提供一定的功能实现,然后暴露出一个或多个终结点,Client端调用Service端的功能(可以理解为调用一个函数),那么Clie ...

  6. WCF入门教程(五)配置文件

    WCF入门教程(五)配置文件 服务协定以及实现写好后,需要将相关服务公布出去,就需要HOST来承载,供客户端来调用. 承载服务有两种方式,一种通过配置文件,一种通过代码进行配置.上一章已经介绍了代码方 ...

  7. WCF入门教程(四)通过Host代码方式来承载服务

    WCF入门教程(四)通过Host代码方式来承载服务 之前已经讲过WCF对外发布服务的具体方式. WCF入门教程(一)简介 Host承载,可以是web,也可以是控制台程序等等.比WebService有更 ...

  8. WCF入门教程(三)定义服务协定--属性标签

    WCF入门教程(三)定义服务协定--属性标签 属性标签,成为定义协议的主要方式.先将最简单的标签进行简单介绍,以了解他们的功能以及使用规则. 服务协定标识,标识哪些接口是服务协定,哪些操作时服务协定的 ...

  9. WCF入门教程(二)如何创建WCF服务

    WCF入门教程(二)从零做起-创建WCF服务 通过最基本的操作看到最简单的WCF如何实现的.这是VS的SDK默认创建的样本 1.创建WCF服务库 2.看其生成结构 1)IService1.cs(协议) ...

  10. WCF入门教程(一)简介

    WCF入门教程(一)简介 1.WCF是什么? WCF( Windows Communication Foundation), 是Microsoft为构建面向服务的应用提供的分布式通信编程框架,是.NE ...

随机推荐

  1. 《JavaScript高级程序设计》心得笔记-----第三篇章

    第十章 1.    DOM1级定义了一个Node接口,以Node类型实现(除IE以外),为了确保跨浏览器兼容,最好用nodeType属性与数字数值进行比较(someNode. nodeType==1) ...

  2. 对session和cookie的一些理解

    由于项目需要,最近用session容器比较多,传载的同时加上了自己的一些理解,不足之处还请大家补充和纠正.);                  response.addCookie(c1);   * ...

  3. ARM公布“物联网”嵌入式mbed OS系统软件平台

    继ARM公司发布了为嵌入式微控制器设计的Cortex-M7架构处理器,ARM又公布了专为廉价低功耗“物联网”设计的新版软件及系统平台,以加速物联网设备的发展及部署.该软件为基于ARM现有Cortex- ...

  4. 双机倒换(NewStartHA,SKYbility,hacmp,hp unix双机)

    1.Suse linux  (NewStartHA):                # cli cli:~>service-migrate Select service to migrate: ...

  5. ADO.NET笔记——将DataReader作为函数返回值

    相关知识: 在很多情况下,可能把数据库的访问封装到一个函数中,通过该函数返回一个DataReader对象给调用者.例如定义函数:SqlDataReader returnDR(),然后再Main函数中调 ...

  6. SequoiaDB 1.5 版本发布

    SequoiaDB 1.5 – 2013.11.13 新特性    1. 新增聚合特性,API实现 GROUPBY, MAX 等功能:    2. 全新改版的Web管理界面:    3. 提供C#语言 ...

  7. 本地安装gem install --local redis-stat-0.4.13.gem

    因为主机环境不能联外网,悲哀,所以只能想办法下载包,上传到主机来安装 环境:el6.x86_64 1. gem 安装[http://centos.ustc.edu.cn/centos/6/os/x86 ...

  8. vmware虚拟机上网:NAT搭建局域网

    若是你不知道的情况下,可以编辑虚拟机网络配置,然后恢复默认,vmware会自动给你分配好ip,默认使用的是vmware8,下面的是使用默认的配置 看图 注意:子网的ip一定要在如上图所示的范围 适配器 ...

  9. c语言调试接口

    http://blog.chinaunix.net/uid-10106787-id-2985587.html 在C语言程序设计中,常会出现各种各样的bug:段错误.参数异常等等.我们需要尽快定位错误, ...

  10. ios7.0结合storyborad实现页面跳转的总结

    折腾了一整天,本文总结一下ios7.0页面跳转有关的内容 storyboard的潜规则 我接触ios很晚,环境已经是xcode5+ios7,所以对以前的IOS开发模式并不了解.在网上查阅了很多资料,发 ...