一、初识WCF异常
1.在WCF中异常机制特点:

    a.当一个客户端调用WCF服务产生异常后,只会导致当前调用结束,它并不影响其它客户端对该WCF的调用,WCF仍然可以为其它客户端继续服务。
    b.WCF产生的异常对象是CLR中的对象类型,而WCF客户端却不一定是.NET,可能是Java或PHP等。所以WCF服务不能向客户端返回CLR异常对象。
下面看一段代码:
服务端代码:
    [ServiceContract]
    public interface ITestFault
    {
        [OperationContract]
        int TestMethod(int num);
    }
    public class TestFault:ITestFault
    {
       //这个方法接收一个整型的数值,然后把该值作为除数进行运算,并返回运算结果
        public int TestMethod(int num)
        {
            return 100 / num;
        }
    }

客户端代码:
   public static void Main(string[] args)
    {
        SRTestFault.TestFaultClient client = new Client.SRTestFault.TestFaultClient();
        client.Open();
        while (true)
        {
            string str = Console.ReadLine();
            int num = int.Parse(str);
            try
            {
                int result = client.TestMethod(num);
                Console.ForegroundColor = ConsoleColor.Cyan;
                Console.WriteLine(DateTime.Now.ToString() + "得到运算结果:" + result);
            }
            catch (Exception ex)
            {
                Console.ForegroundColor = ConsoleColor.Red;
                Console.WriteLine(DateTime.Now.ToString() + "产生异常:" + ex.Message);
            }
            finally
            {
                Console.ResetColor();
            }
        }
        client.Close();
    }

运行结果:

《图1》
我们启动了两个客户端,蓝色字代表运行正常,红色字代表运行出错
“客户端一”在接收0的时候,会在服务端产生除数为0的异常,从图中显示的异常信息我们可以看到到:服务端的异常对象并没有传递到客户端,客户端不知道服务端产生什么样的异常。并且,一旦产生异常后,该客户端与服务端的信道就会被中断无法再进行通信。
虽然“客户端一”与服务端的通信信道被中断了,但服务端并没有因为异常而停止运行。我们可以看到“客户端二”中仍然可以与服务端进行通信。

2.WCF异常的分类:
    a.通信错误,诸如网络错误,地址错误,服务器没有启动等等。客户端表现为Communication Exception。
    b.状态异常,代理已经关闭,或者通道Fault,等问题,这个比较常见。一般通道闲置时间过久,通道会出现这个状态错误的问题。安全验证失败也会导致这个错误。
    c.服务异常,服务调用时抛出的异常,这个服务内部异常会序列化传递给客户端,被客户端捕获。
   
3.WCF异常与实例的关系:
    a.Pre-Call实例模型: 服务实例被释放,客户端抛出 FaultException,产生异常的信道会被中断,相应的客户端代理对象无法继续使用,只能关闭。不影响其它客户端对服务的调用。
    b.Pre-Session实例模型:服务实例被释放,会话终止。客户端抛出 FaultException,产生异常的信道会被中断,相应的客户端代理对象无法继续使用,只能关闭。不影响其它客户端对服务的调用。
   c.Singleton实例模型:服务实例依旧运行。客户端抛出 FaultException,产生异常的信道会被中断,相应的客户端代理对象无法继续使用,只能关闭。不影响其它客户端对服务的调用。

二、服务端返回异常的详细信息
默认情况下,服务端产生运行异常后,并不会把异常的运行时信息传递到客户端。我们在客户端所得到的只是“由于内部错误,服务器无法处理请求”这样的错误提示。这样虽然能够有效地保护好服务器的内部信息,但也为我们客户端编程造成了很大的不方便。如何把服务端的错误信息传递到客户端是我们这篇文章中主要要解决的问题,下面我们用最简单的方法把服务端的异常信息发送到客户端。

1.使用ServiceBehavior特性向客户端传递异常信息。
把服务声明为[ServiceBehavior(IncludeExceptionDetailInFaults=true)],其中的IncludeExceptionDetailInFaults=true代表向客户端发送异常的详细信息
服务端代码:
    [ServiceContract]
    public interface ITestFault
    {
        [OperationContract]
        int TestMethod(int num);
    }
    [ServiceBehavior(IncludeExceptionDetailInFaults=true)]
    public class TestFault:ITestFault
    {
        public int TestMethod(int num)
        {
            return 100 / num;
        }
    }
客户端代码保持不变。
运行结果:

《图2》

2.使用配置文件中的serviceDebug配置节向客户端传递异常信息。
除了可以使用ServiceBehavior把服务端信息传递到客户端外,我们还可以修改Host的配置文件的serviceDebug配置节来向客户端传递异常信息
这种方式我们可以保持服务端代码与客户端代码不作任何修改。只修改App.Config文件,如图:

《图3》

《图4》
运行结果:

《图2》

这种两种方式可以很简单地把服务端的错误信息传送到客户端,但他们也有两个很大的缺陷:
1.会把服务端敏感的信息直接暴露给客户端,如:数据库的用户名、服务器堆栈信息等。有些信息可能被人恶意利用,来对服务端进行攻击。
2.客户端虽然把服务端产生的异常信息获取到了,但是客户端与服务端的信道会被破坏,导致客户端代理无法再与服务端通信,而只能关闭。

《图5》
(原创:灰灰虫的家http://hi.baidu.com/grayworm)

三、使用FaultException抛出简单异常
在WCF服务中我们可以使用FaultException以标准Soap方式向客户端传递简单Fault信息。

在研究FaultException之前我们先来看一下标准Soap格式的Fault

《图6》
从上面的图中我们可以看出一个SoapFault包含Code和Reason。
Code:Soap错误的代码;
Reason:Soap错误的原因,即错误信息;

FaultException常用构造函数:
public FaultException();
public FaultException(FaultReason reason);
public FaultException(string reason);
public FaultException(FaultReason reason,FaultCode code);
public FaultException(string reason,FaultCode code);

下面我们把上面的例子修改一下,WCF服务用FaultException向客户端抛出错误信息。
服务端代码:
    [ServiceContract]
    public interface ITestFault
    {
        [OperationContract]
        int TestMethod(int num);
    }
    public class TestFault:ITestFault
    {
        public int TestMethod(int num)
        {
            int returnValue = 0;
            try
            {
                returnValue = 100 / num;
            }
            catch (Exception ex)
            {
                FaultException fault = null;
                if (ex is DivideByZeroException)
                {
                    fault = new FaultException(new FaultReason("产生了除0的异常"), new FaultCode("Error:ox001"));
                }
                else
                {
                    fault = new FaultException(ex.Message);
                }
                throw fault;
            }
            return returnValue;
        }
    }
    在服务端代码我们使用了try-catch语句块把产生的异常包装成FaultException对象,抛向客户端

客户端代码:
    SRTestFault.TestFaultClient client = new Client.SRTestFault.TestFaultClient();
    client.Open();
    while (true)
    {
        string str = Console.ReadLine();
        int num = int.Parse(str);
        try
        {
            int result = client.TestMethod(num);
            Console.ForegroundColor = ConsoleColor.Cyan;
            Console.WriteLine(DateTime.Now.ToString() + "得到运算结果:" + result);
        }
        catch (FaultException ex)
        {
            Console.ForegroundColor = ConsoleColor.Red;
            Console.WriteLine(DateTime.Now.ToString() + "产生异常:错误代号-" + ex.Code.Name+",错误原因-" + ex.Reason);
        }
        catch(Exception ex)
        {
            Console.ForegroundColor = ConsoleColor.Red;
            Console.WriteLine(DateTime.Now.ToString() + "产生异常:" + ex.Message);
        }
        finally
        {
            Console.ResetColor();
        }
    }
    //client.Close();
    在客户端代码中,我们也使用了try-catch-finally语句块对服务端返回的错误信息进行捕捉,并显示在界面上。
   
运行结果:

《图7》

从图中可以看出,我们把服务器端产生的错误捕获出来,并显示在界面上;但客户端与服务端的信道并没有被破坏,我们仍可以继续向服务端发起新的调用。

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

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

转载于:https://www.cnblogs.com/LittleMobile/archive/2010/07/05/1771396.html

WCF 异常(原创:灰灰虫的家http://hi.baidu.com/grayworm)相关推荐

  1. 处理WCF异常的方式

    处理WCF异常的方式 参考文章: (1)处理WCF异常的方式 (2)https://www.cnblogs.com/shenba/archive/2011/12/31/2309106.html (3) ...

  2. WCF异常:HTTP 无法注册,另一应用程序正在使用 TCP 端口 80

    今天,调试服务的时候,忽然抛了个异常.异常信息是:"HTTP 无法注册 URL http://+/Temporary_Listen_Addresses/144ff7cb-10a4-4836- ...

  3. 国培2018、四川乡村教师访名校南通培训班联谊晚会——原创朗诵节目《家》

    (黎)家是什么, (赵)家是心灵憩息的港湾,是傍晚倦鸟的归宿, (黎)家是什么? (全体)家是夏季酸酸的柠檬,是清爽可口的葡萄干,是火红火红的沙糖桔. (赵) 我们这个家特别有趣, (女生➕挥手)有袁 ...

  4. 计算机的硬盘维修,电脑的硬盘出现了异常和坏道如何在家自己维修详细方法说明...

    硬盘使用久了,会非正常关机次数多了,那么我们在电脑上运行某个程序的时候,硬盘就可能会出现读盘出错的情况,提示我们文件已经损坏了,或者是我们使用电脑管家等软件清理垃圾的时候,垃圾的大小明显出现了异常,这 ...

  5. WCF学习(2)- 契约

    (原创:灰灰虫的家http://hi.baidu.com/grayworm) 契约是WCF中很重要的概念.它是用一种与平台无关的标准语法来描述WCF服务的功能.当客户端获取服务端WCF服务的时候,会根 ...

  6. WCF学习(二):契约

    (原创:灰灰虫的家http://hi.baidu.com/grayworm) 契约是WCF中很重要的概念.它是用一种与平台无关的标准语法来描述WCF服务的功能.当客户端获取服务端WCF服务的时候,会根 ...

  7. WCF开发实战系列四:使用Windows服务发布WCF服务

    WCF开发实战系列四:使用Windows服务发布WCF服务 (原创:灰灰虫的家http://hi.baidu.com/grayworm) 上一篇文章中我们通过编写的控制台程序或WinForm程序来为本 ...

  8. ajax请求如何判断超时,ajax请求超时判断(转载)

    ajax请求时有个参数可以借鉴一下 var ajaxTimeOut = $.ajax({ url:'', //请求的URL timeout : 1000, //超时时间设置,单位毫秒 type : ' ...

  9. ListView详解(二)

    五.分页在GridView中,分页一般有两种方式:一种是利用GridView自身带有的分页功能与DataSource控件配合使用实现分页.这种分页方式几乎不用编写代码,实现简单,但它是把所有数据读取到 ...

最新文章

  1. mysql带LIKE 关键字的查询
  2. iOS 组件化 —— 路由设计思路分析
  3. c语言void replace(str,ch)替换字符串,C++ 中字符串查找、字符串截取、字符串替换...
  4. oracle执行计划走偏处理步骤
  5. Cassandra - Insert after Delete fails silently
  6. Leetcode1143. 最长公共子序列(c#)
  7. S5PV210裸机之重定位
  8. 更新管理器_Win10设备管理器失去了通过互联网更新驱动程序的能力
  9. git基础管理--操作远程仓库
  10. 读取图像中任意点的像素值
  11. 平安科技一轮等多久_科技正等着我们成长
  12. java book_java_book java 图书管理系统 GUI - 下载 - 搜珍网
  13. vsCode 快捷键、插件
  14. 用ultraiso安装linux系统教程,使用UltraISO刻录光盘教程
  15. 电脑的dwg文件怎么打开
  16. 牛客网 月出皎兮,佼人僚兮。 树上启发式合并
  17. java架构师全套图解,使用/教程/实例
  18. 齐岳定制|Cyclopropene-PEG-Xylan|环丙烯-聚乙二醇-木聚糖
  19. HTML,JS与CSS
  20. linux 命令 修改密码,一条命令修改Linux密码

热门文章

  1. TortoiseHg使用(hg mercurial repository management)
  2. SQL Server 2012 中的 Service Broker功能的一些改进或增强
  3. windows server 2008 r2虚拟机故障群集迁移
  4. DNN 4.x CodeSmith模板
  5. redis3.0.3 安装与配置
  6. 键盘录入学生信息,保存到集合中
  7. ASCII + Url + Base64
  8. Python中生成一个指定长度的随机字符串实现示例
  9. AS安装APK失败的两种情况
  10. windows安装pycocotools错误:cl : Command line error D8021 : invalid numeric argument '/Wno-cpp'