WCF在同步和异步调用情况下的异常捕获-阿里云开发者社区

开发者社区> 像教授> 正文

WCF在同步和异步调用情况下的异常捕获

简介:
+关注继续查看
WCF在同步和异常调用情况下的异常捕获 1 前言
关于WCF的基本信息,我就不在这里介绍了。一来是因为园子中的很多人都介绍过了,而且很是详细,再不行,还可以看书。二来是因为自己的概念表达还不是很好,别误导了大家。
在这里,我就直接讲解一种用法,然后贴点代码吧。
在WCF有一种契约,叫做错误契约FaultContract。
今天我就讲解一下,在同步和异步调用WCF服务的时候,客户端如何捕获服务端抛出来的异常。捕获之后,如何处理,那就是根据项目的要求了。是提示呢?还是记录日志呢?还是其他什么的。。。。。。。。。。。。
2 正文
其他对于同步和异步来说,WCF处理异常的手段是一致的。都是将异常信息,通过我们自定义的一个异常信息类,传输到客户端。客户端获取到这个类的信息,然后就知道了具体的异常。然后如何处理,就是客户端的事情了。
2.1 服务定义
错误契约定义

  1. [DataContract]  
  2.     public class CallException  
  3.     {  
  4.         public CallException() { }  
  5.         public CallException(string message, string detail)  
  6.         { Message = message;  
  7.         Detail = detail;  
  8.         }  
  9.         [DataMember]  
  10.         public string Message { getset; }  
  11.         [DataMember]  
  12.         public string Detail { getset; }  
  13.     } 

 
接口定义

  1. [ServiceContract]  
  2.     public interface IService1  
  3.     {  
  4.         [OperationContract]  
  5.         [FaultContract(typeof(CallException))]  
  6.         User GetUserByID(int id,string communCode, out CallException callException);  
  7.  
  8.         [OperationContract]  
  9.         [FaultContract(typeof(CallException))]  
  10.         [ServiceKnownType(typeof(User ))]  
  11.         BaseClass.EntityBase  GetByIDWithAuthentication(int id, out CallException callException);  
  12.     } 
 
 
接口实现
 
 

  1. [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]  
  2.    [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]  
  3.    [Common.MyServiceBehavior()]  
  4.    public class Service1Impl : BaseClass.ServiceBase, IService1  
  5.    {  
  6.         
  7.        #region IService1 Members  
  8.  
  9.        public User GetUserByID(int id, string communCode, out CallException callException)  
  10.        {  
  11.            callException = null;  
  12.            User user = null;  
  13.            BLL.UserBLL userBll = Common.ServiceLocator.LoadService<BLL.UserBLL>();  
  14.            user= userBll.GetUserByID(id, out callException);  
  15.            return user;  
  16.        }  
  17.  
  18.        //[Common.AuthenticationBehavior()]  
  19.        public BaseClass.EntityBase GetByIDWithAuthentication(int id, out CallException callException)  
  20.        {  
  21.            callException = null;  
  22.            User user = null;  
  23.            BLL.UserBLL userBll = Common.ServiceLocator.LoadService<BLL.UserBLL>();  
  24.            user = userBll.GetByID(id, out callException);  
  25.            return user;  
  26.        }  
  27.  
  28.        #endregion  
  29.    } 
业务逻辑类

  1. public class UserBLL : BaseClass.BLLBase  
  2.    {  
  3.        public UserBLL(Common.DALHelper dalHelper)  
  4.        {  
  5.            _dalHelper = dalHelper;  
  6.        }  
  7.        private Common.DALHelper _dalHelper;  
  8.  
  9.  
  10.        [Common.ExceptionCallHandler("你没有权限""""""你没有权限啊BLL")]  
  11.        public User GetByID(int id, out CallException callException)  
  12.        {  
  13.            callException = null;  
  14.            if (id < 10)  
  15.            {  
  16.                callException = new CallException()  
  17.                {  
  18.                    Message = "获取用户",  
  19.                    Detail = "必须大于等于10" 
  20.                };  
  21.                throw new FaultException<CallException>(callException, "parameter error");  
  22.            }  
  23.            else 
  24.            {  
  25.                User user = null;  
  26.                int b = 0;  
  27.                user = _dalHelper.UserDal.GetByID(id, ref b, out callException);  
  28.                return user;  
  29.            }  
  30.        }  
  31.        [Common.ExceptionCallHandler("你没有权限""""""你没有权限啊BLL")]  
  32.        public User GetUserByID(int id, out CallException callException)  
  33.        {  
  34.            User user = null;  
  35.            callException = null;  
  36.            if (id < 10)  
  37.            {  
  38.                callException = new CallException()  
  39.                {  
  40.                    Message = "获取用户",  
  41.                    Detail = "必须大于等于10" 
  42.                };  
  43.            }  
  44.            else 
  45.            {  
  46.                int b = 0;  
  47.                user = _dalHelper.UserDal.GetByID(id, ref b, out callException);  
  48.            } return user;  
  49.        }  
  50.    } 
 
 
在业务逻辑类中判断参数的合法性,不合法抛出异常。大家看到有两个方法,一个是直接抛出异常,一个是没有抛出任何异常。后面将这两个的用处。
2.2 同步调用
同步调用,我们用控制台程序来模拟客户端。
同步方式调用WCF的时候,我们可以直接try。。。catch。。。来捕获这个异常信息,然后进行处理。
代码如下:

  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Text;  
  5. using System.ServiceModel;  
  6. using System.ServiceModel.Channels;  
  7.  
  8. namespace ConsoleConsumer  
  9. {  
  10.     class Program  
  11.     {  
  12.         static void Main(string[] args)  
  13.         {  
  14.             Service1.Service1Client client = new Service1.Service1Client();  
  15.             using (OperationContextScope scope = new OperationContextScope((IContextChannel)client.InnerChannel))  
  16.             {  
  17.                 MessageHeaders messageHeadersElement = OperationContext.Current.OutgoingMessageHeaders;  
  18.                 messageHeadersElement.Add(MessageHeader.CreateHeader("username""""kd"));  
  19.                 messageHeadersElement.Add(MessageHeader.CreateHeader("password""""kd"));  
  20.             }  
  21.             Console.WriteLine("请输入ID:");  
  22.            int id =int.Parse ( Console.ReadLine());  
  23.             Service1.CallException callException = null;  
  24.             try 
  25.             {  
  26.                   
  27.                 client.GetByIDWithAuthentication(out callException, id);  
  28.                 Console.WriteLine("成功调用");  
  29.             }  
  30.             catch (FaultException<Service1.CallException> ex)  
  31.             {  
  32.                 Console.WriteLine("半路接获CallException Error:{0},{1}", ex.Detail.Message, ex.Detail.Detail);  
  33.             }  
  34.             catch (FaultException<System.IO.EndOfStreamException> ex)  
  35.             {  
  36.                 Console.WriteLine("半路接获EndOfStreamException Error:{0},{1}", ex.Detail.Message, ex.Detail.HelpLink );  
  37.             }  
  38.             catch (Exception ex)  
  39.             {  
  40.                 Console.WriteLine("最后一关 Error:{0},{1}", ex.Message, ex.HelpLink);  
  41.             }  
  42.  
  43.             Console.Read();  
  44.         }  
  45.     }  
  46. }  
 
主要是看catch (FaultException<Service1.CallException> ex) 这一句。就好像是,WCF将我们的异常信息类包装到FaultException这个类中。然后ex.Detail就是CallException这个我们自定义的实体类型了。那就可以根据这个实体的属性进行异常的处理了。
2.3 异步调用
异步调用,我们用Silverlight来模型客户端程序。
我们都知道,异步调用,其实就是多线程。然后再callback中处理返回的数据。
这时候,就会发现不能try。。。catch。。。了。因为调用成功,还是失败,是在方法完成的委托函数中才知道的。没有地方给你写try。。。catch。。。了。
Service1.Service1Client client = new Service1.Service1Client(); client.GetUserByIDCompleted += new EventHandler<Service1.GetUserByIDCompletedEventArgs>(client_GetUserByIDCompleted); client.GetUserByIDAsync(int.Parse(textBox1.Text.Trim()), "123456");

 
void client_GetUserByIDCompleted(object sender, Service1.GetUserByIDCompletedEventArgs e) { }

 
是通过e来获取数据的。
但是异常信息需要通过通道传递的客户端,这点和同步调用是一样的。既然这样,那我们在定义服务端方法的时候,就添加一个out类型的参数,在服务端就将CallException这个实体赋值给这个参数。然后通过e.CallException就可以获取异常信息了,如果不为空,说明有异常存在。为空,说明没有异常,访问正常。

  1. void client_GetUserByIDCompleted(object sender, Service1.GetUserByIDCompletedEventArgs e)  
  2.       {  
  3.  
  4.           #region  
  5.  
  6.           if (e.callException != null)  
  7.           {  
  8.               ChildWindow win = new ChildWindow();  
  9.               win.Title = e.callException.Message;  
  10.               win.Content = e.callException.Detail;  
  11.               win.MinHeight = 50;  
  12.               win.MinWidth = 200;  
  13.               win.Show();  
  14.           }  
  15.           else 
  16.           {  
  17.               ChildWindow win = new ChildWindow();  
  18.               win.Title = "ok";  
  19.               win.Content = "it is ok";  
  20.               win.MinHeight = 50;  
  21.               win.MinWidth = 200;  
  22.               win.Show();  
  23.           }  
  24.           #endregion  
  25.  
  26.       } 

3 结论
不知道大家在捕获和处理WCF的异常的时候,是如何处理的?有更好的办法,欢迎大家一起讨论。
源码下载:



本文转自 virusswb 51CTO博客,原文链接:http://blog.51cto.com/virusswb/410798,如需转载请自行联系原作者

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
怎么设置阿里云服务器安全组?阿里云安全组规则详细解说
阿里云服务器安全组设置规则分享,阿里云服务器安全组如何放行端口设置教程
6911 0
阿里云服务器端口号设置
阿里云服务器初级使用者可能面临的问题之一. 使用tomcat或者其他服务器软件设置端口号后,比如 一些不是默认的, mysql的 3306, mssql的1433,有时候打不开网页, 原因是没有在ecs安全组去设置这个端口号. 解决: 点击ecs下网络和安全下的安全组 在弹出的安全组中,如果没有就新建安全组,然后点击配置规则 最后如上图点击添加...或快速创建.   have fun!  将编程看作是一门艺术,而不单单是个技术。
4479 0
使用OpenApi弹性释放和设置云服务器ECS释放
云服务器ECS的一个重要特性就是按需创建资源。您可以在业务高峰期按需弹性的自定义规则进行资源创建,在完成业务计算的时候释放资源。本篇将提供几个Tips帮助您更加容易和自动化的完成云服务器的释放和弹性设置。
7751 0
阿里云服务器安全组设置内网互通的方法
虽然0.0.0.0/0使用非常方便,但是发现很多同学使用它来做内网互通,这是有安全风险的,实例有可能会在经典网络被内网IP访问到。下面介绍一下四种安全的内网互联设置方法。 购买前请先:领取阿里云幸运券,有很多优惠,可到下文中领取。
9425 0
阿里云服务器如何登录?阿里云服务器的三种登录方法
购买阿里云ECS云服务器后如何登录?场景不同,云吞铺子总结大概有三种登录方式: 登录到ECS云服务器控制台 在ECS云服务器控制台用户可以更改密码、更换系统盘、创建快照、配置安全组等操作如何登录ECS云服务器控制台? 1、先登录到阿里云ECS服务器控制台 2、点击顶部的“控制台” 3、通过左侧栏,切换到“云服务器ECS”即可,如下图所示 通过ECS控制台的远程连接来登录到云服务器 阿里云ECS云服务器自带远程连接功能,使用该功能可以登录到云服务器,简单且方便,如下图:点击“远程连接”,第一次连接会自动生成6位数字密码,输入密码即可登录到云服务器上。
16821 0
阿里云服务器ECS登录用户名是什么?系统不同默认账号也不同
阿里云服务器Windows系统默认用户名administrator,Linux镜像服务器用户名root
1131 0
阿里云ECS云服务器初始化设置教程方法
阿里云ECS云服务器初始化是指将云服务器系统恢复到最初状态的过程,阿里云的服务器初始化是通过更换系统盘来实现的,是免费的,阿里云百科网分享服务器初始化教程: 服务器初始化教程方法 本文的服务器初始化是指将ECS云服务器系统恢复到最初状态,服务器中的数据也会被清空,所以初始化之前一定要先备份好。
3227 0
+关注
987
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
文娱运维技术
立即下载
《SaaS模式云原生数据仓库应用场景实践》
立即下载
《看见新力量:二》电子书
立即下载