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

服务器端代码如下:

[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的方式比较麻烦,需要在每一个提供的接口中都捕获异常,并重新封装抛出,一来不好看,处理起来也比较麻烦。由于篇幅有限,下篇文章中介绍一个更为简单的方法。

转载于:https://www.cnblogs.com/TianFang/archive/2013/01/02/2841981.html

WCF入门(七)——异常处理1相关推荐

  1. [WCF编程]1.WCF入门示例

    一.WCF是什么? Windows Communication Foundation(WCF)是由微软开发的一系列支持数据通信的应用程序框架,整合了原有的windows通讯的 .net Remotin ...

  2. 十五天精通WCF——第七天 Close和Abort到底该怎么用才对得起观众

    原文:十五天精通WCF--第七天 Close和Abort到底该怎么用才对得起观众 一:文起缘由 写这一篇的目的源自于最近看同事在写wcf的时候,用特别感觉繁琐而且云里雾里的嵌套try catch来防止 ...

  3. WCF 入门之旅(4): 怎样用客户端调用WCF服务

    WCF 入门之旅(4): 怎样用客户端调用WCF服务 前面的demo已经能够跑起来,现在开始考虑用客户端来测试所写的应用了,首先用个普通的应用程序来调用所写的wcf服务吧.其实最后运行wcf服务后的页 ...

  4. Spring Boot入门——全局异常处理

    Spring Boot入门--全局异常处理 参考文章: (1)Spring Boot入门--全局异常处理 (2)https://www.cnblogs.com/studyDetail/p/702758 ...

  5. [老老实实学WCF] 第七篇 会话

    原文:[老老实实学WCF] 第七篇 会话 老老实实学WCF 第七篇 会话 通过前几篇的学习,我们已经掌握了WCF的最基本的编程模型,我们已经可以写出完整的通信了.从这篇开始我们要深入地了解这个模型的高 ...

  6. WCF入门的了解准备工作

    了解WCF, 及WCF入门需要掌握哪里基本概念? 1.准备工作 >1.1 . XML >1.2 . Web Service >1.3 . 远程处理 (RPC) >1.4.  消 ...

  7. response.end后抛了异常_(七)异常处理

    (七)异常处理 异常 异常的体系结构 java.lang.Throwable|-----java.lang.Error:一般不便携针对性的代码进行处理|-----java.lang.Exception ...

  8. MySQL入门 (七) : 储存引擎与资料型态

    1 表格与储存引擎 表格(table)是资料库中用来储存纪录的基本单位,在建立一个新的资料库以后,你必须为这个资料库建立一些储存资料的表格: 每一个资料库都会使用一个资料夹,这些资料库资料夹用来储存所 ...

  9. 手动抛出异常_(七)异常处理

    (七)异常处理 异常 异常的体系结构 java.lang.Throwable|-----java.lang.Error:一般不便携针对性的代码进行处理|-----java.lang.Exception ...

  10. 服务端增加WCF服务全局异常处理机制

    转自:http://www.csframework.com/archive/1/arc-1-20150109-2193.htm 服务端增加WCF服务全局异常处理机制,任一WCF服务或接口方式出现异常, ...

最新文章

  1. Linux sendmail发送邮件失败诊断案例(一)
  2. 如何一小时杀入天池OCR比赛前排?
  3. springcloud 相同服务名_Spring 微服务从入门到入土
  4. python语言自学-零基础小白学习Python编程语言的正确姿势(纯干货)
  5. 查看python版本号-怎么查看python版本号
  6. DFS(二):骑士游历问题
  7. 解决WSL2中Vmmem内存占用过大问题
  8. JavaScript之引用类型介绍
  9. AI 线上峰会 | 人工智能技术解析与实战
  10. 【2017级面向对象程序设计寒假作业】第4次作业情况
  11. python中常用的函数有哪些_python里常用的函数类型
  12. 请描述osi七层模型,并简要概括各层功能
  13. 昨天我上午下单买的电池,已经到了长沙
  14. java生成随机数的三种方法
  15. php汉字转拼音百家姓版,百家姓全文查询,百家姓全文带拼音
  16. Linux主机安全加固方法使用开源软件fail2ban防护主机
  17. ERP编制物料清单 金蝶
  18. 数据库课程设计(电脑配件库存管理系统)
  19. 网络规划设计师上午真题及解析(2019)
  20. HTML5 参考手册 ———— 颜色名

热门文章

  1. Android你可能要用到的自定义View分享
  2. 从零开始学Vue(一)—— Vue.js 入门
  3. 与旧代码接口的注意事项
  4. apache kafkac系列lient发展-java
  5. [转]瀑布流布局浅析
  6. Sass中使用@each循环
  7. c++中istream类型到bool类型的隐式转换
  8. UPX3.03+UpolyX.5 Shell v1.0 汉化绿色版
  9. c# 委托和委托事件
  10. poj 3278 Catch That Cow (简单的bfs)