WCF系列教程之WCF客户端异常处理
发布日期:2021-08-17 17:17:05 浏览次数:7 分类:技术文章

本文共 7564 字,大约阅读时间需要 25 分钟。

本文参考自:http://www.cnblogs.com/wangweimutou/p/4414393.html,纯属读书笔记,加深记忆

一、简介

当我们打开WCF基础客户通道,无论是显示打开还是通过调用操作自动打开、使用客户端或者通过对象调用操作,或者关闭基础客户端通道,都会在客户端应用程序中出现异常,WCF是基于网络的通讯服务,错误异常也是要基于消息传递的,在WCF中提供了一个错误消息处理的类FaultException,WCF客户端可以通过它,来接收服务端传递回来的异常信息。

 

二、WCF异常类型

1、意外异常:意外异常包括

(1)、灾难性故障(OutOfMemoryException)

(2)、编程错误(ArgumentException(参数异常)和InvalidOperationException(无效的操作异常))

通常没有有效的方法来处理意外错误,所以通产不应该在调用WCF客户端时捕获这些异常

 

2、预期异常:预期异常包括

(1)、TimeoutException

(2)、CommunicationException 

(3)、CommunicationException 的任何派生类

上面这些异常表明在通信的过程中出现问题,该问题可以通过终止WCF客户端并报告通信故障而得到安全的处理,因为外部因素可能导致任何应用程序中出现这些错误,所以正确的应用程序必须捕获这些异常并在发生异常时进行恢复。

(4)、如果发生预期异常,客户端或许可以继续使用,或许无法继续使用。若要确定客户端是否仍然可以使用,请检查 State 属性是否为 CommunicationState.Opened。如果此属性仍然处于打开状态,则客户端仍然可以使用。否则,则应中止客户端并释放对其的所有引用。具体参照代码如下:

if (proxy.State == CommunicationState.Opened){    Console.WriteLine("CommunicationState is Opened"); }

 

三、代码示例

工程结构如下图所示:

1、WCF服务层搭建:新建契约层、服务层、和WCF宿主,添加必须的引用(这里不会的参考本人前面的随笔),配置宿主,生成解决方案,打开Host.exe,开启服务。具体的代码如下:

ICalculate.cs

using System;using System.Collections.Generic;using System.Linq;using System.ServiceModel;using System.Text;using System.Threading.Tasks;namespace IService{    [ServiceContract]    public interface ICalculate    {        [OperationContract]        int Add(int a, int b);        [OperationContract]        int Divide(int value1, int value2);    }}

 

IUserInfo.cs

using System;using System.Collections.Generic;using System.Linq;using System.Runtime.Serialization;using System.ServiceModel;using System.Text;using System.Threading.Tasks;namespace IService{    [ServiceContract]    public interface IUserInfo    {        [OperationContract]        User[] GetInfo(int? id);    }    [DataContract]    public class User    {        [DataMember]        public int ID { get; set; }        [DataMember]        public string Name { get; set; }        [DataMember]        public int Age { get; set; }        [DataMember]        public string Nationality { get; set; }      }}

注:必须引入System.Runtime.Serialization命名空间,应为User类在被传输时必须是可序列化的,否则将无法传输

Calculate.cs

using IService;using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;using System.ServiceModel;namespace Service{    public class Calculate : ICalculate    {        public int Add(int a, int b)        {            return a + b;        }        public int Divide(int a, int b)        {            try            {                return a / b;            }            catch (DivideByZeroException) {                throw new FaultException("除数不能为0");//FaultException需要引用System.ServiceModel命名空间            }        }    }}

 

UserInfo.cs

using IService;using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;namespace Service{    public class UserInfo : IUserInfo    {        public User[] GetInfo(int? id)        {            List
Users = new List
(); Users.Add(new User { ID = 1, Name = "张三", Age = 11, Nationality = "China" }); Users.Add(new User { ID = 2, Name = "李四", Age = 12, Nationality = "English" }); Users.Add(new User { ID = 3, Name = "王五", Age = 13, Nationality = "American" }); if (id != null) { return Users.Where(x => x.ID == id).ToArray(); } else { return Users.ToArray(); } } }}

Program.cs

using System;using System.Collections.Generic;using System.Linq;using System.Text;using Service;using System.ServiceModel;namespace Host{    class Program    {        static void Main(string[] args)        {            using (ServiceHost host = new ServiceHost(typeof(Calculate)))            {                host.Opened += delegate { Console.WriteLine("服务已经启动,按任意键终止!"); };                host.Open();                Console.Read();            }        }    }}

App.Config

ok,打开Host.exe

服务开启成功!

 

2、新建一个名为Client的控制台应用程序作为WCF客户端,添加对http://localhost:1234/Calculate/的引用,将命名空间设置为CalculateClientNS,

 

点击确定,确保添加成功。然后开始编写Program.cs的代码

(1)、验证除数不能为0的异常抛出

using System;using System.Collections.Generic;using System.Linq;using System.ServiceModel;using System.Text;using System.Threading.Tasks;using Client.CalculateClientNS;namespace Client{    class Program    {        static void Main(string[] args)        {            try            {                CalculateClient calculate = new CalculateClient();                Console.WriteLine("1+2={0}", calculate.Add(1, 2));                Console.WriteLine("1/0={0}", calculate.Divide(1, 0));            }            catch (TimeoutException ex)            {                Console.WriteLine(ex.GetType() + ":" + ex.Message);                Console.ReadKey();            }            catch (CommunicationException ex)            {                Console.WriteLine(ex.GetType() + ":" + ex.Message);                Console.ReadKey();            }            catch (Exception ex)            {                Console.WriteLine(ex.GetType() + ":" + ex.Message);                Console.ReadKey();            }        }    }}

客户端接收到了服务器返回的除数不能为0的异常,然后抛出。

 

(2)、验证通讯超时的异常抛出,原理通过将连接后的时间设置为很小的值,那么服务端的运算肯定来不及,就会抛出超时的信息。

using System;using System.Collections.Generic;using System.Linq;using System.ServiceModel;using System.Text;using System.Threading.Tasks;using Client.CalculateClientNS;namespace Client{    class Program    {        static void Main(string[] args)        {            try            {                CalculateClient calculate = new CalculateClient();                calculate.InnerChannel.OperationTimeout = TimeSpan.FromSeconds(0.001);//设置下面调用的操作必须在0.001秒内完成.                Console.WriteLine("1+2={0}", calculate.Add(1, 2));            }            catch (TimeoutException ex)            {                Console.WriteLine(ex.GetType() + ":" + ex.Message);                Console.ReadKey();            }            catch (CommunicationException ex)            {                Console.WriteLine(ex.GetType() + ":" + ex.Message);                Console.ReadKey();            }            catch (Exception ex)            {                Console.WriteLine(ex.GetType() + ":" + ex.Message);                Console.ReadKey();            }        }    }}

验证通讯超时的异常抛出

(3)、验证通讯错误的异常抛出

using System;using System.Collections.Generic;using System.Linq;using System.ServiceModel;using System.Text;using System.Threading.Tasks;using Client.CalculateClientNS;namespace Client{    class Program    {        static void Main(string[] args)        {            try            {                CalculateClient calculate = new CalculateClient();                calculate.Abort();//关闭通道                Console.WriteLine("1+2={0}", calculate.Add(1, 2));            }            catch (TimeoutException ex)            {                Console.WriteLine(ex.GetType() + ":" + ex.Message);                Console.ReadKey();            }            catch (CommunicationException ex)            {                Console.WriteLine(ex.GetType() + ":" + ex.Message);                Console.ReadKey();            }            catch (Exception ex)            {                Console.WriteLine(ex.GetType() + ":" + ex.Message);                Console.ReadKey();            }        }    }}

 

转载于:https://www.cnblogs.com/GreenLeaves/p/6872646.html

转载地址:https://blog.csdn.net/weixin_30856725/article/details/98789295 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:iframe 解析
下一篇:Vue.js系列之一初识Vue

发表评论

最新留言

初次前来,多多关照!
[***.217.46.12]2024年03月31日 08时21分00秒

关于作者

    喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!

推荐文章