zoukankan      html  css  js  c++  java
  • WCF在同步和异步调用情况下的异常捕获 Virus

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

    1 前言

    关于WCF的基本信息,我就不在这里介绍了。一来是因为园子中的很多人都介绍过了,而且很是详细,再不行,还可以看书。二来是因为自己的概念表达还不是很好,别误导了大家。

    在这里,我就直接讲解一种用法,然后贴点代码吧。

    在WCF有一种契约,叫做错误契约FaultContract。

    今天我就讲解一下,在同步和异步调用WCF服务的时候,客户端如何捕获服务端抛出来的异常。捕获之后,如何处理,那就是根据项目的要求了。是提示呢?还是记录日志呢?还是其他什么的。。。。。。。。。。。。

    2 正文

    其他对于同步和异步来说,WCF处理异常的手段是一致的。都是将异常信息,通过我们自定义的一个异常信息类,传输到客户端。客户端获取到这个类的信息,然后就知道了具体的异常。然后如何处理,就是客户端的事情了。

    2.1 服务定义

    错误契约定义

     [DataContract]
        public class CallException
        {
            public CallException() { }
            public CallException(string message, string detail)
            { Message = message;
            Detail = detail;
            }
            [DataMember]
            public string Message { get; set; }
            [DataMember]
            public string Detail { get; set; }
        }

    接口定义

     [ServiceContract]
        public interface IService1
        {
            [OperationContract]
            [FaultContract(typeof(CallException))]
            User GetUserByID(int id,string communCode, out CallException callException);
    
            [OperationContract]
            [FaultContract(typeof(CallException))]
            [ServiceKnownType(typeof(User ))]
            BaseClass.EntityBase  GetByIDWithAuthentication(int id, out CallException callException);
        }

    接口实现

     [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
        [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
        [Common.MyServiceBehavior()]
        public class Service1Impl : BaseClass.ServiceBase, IService1
        {
           
            #region IService1 Members
    
            public User GetUserByID(int id, string communCode, out CallException callException)
            {
                callException = null;
                User user = null;
                BLL.UserBLL userBll = Common.ServiceLocator.LoadService<BLL.UserBLL>();
                user= userBll.GetUserByID(id, out callException);
                return user;
            }
    
            //[Common.AuthenticationBehavior()]
            public BaseClass.EntityBase GetByIDWithAuthentication(int id, out CallException callException)
            {
                callException = null;
                User user = null;
                BLL.UserBLL userBll = Common.ServiceLocator.LoadService<BLL.UserBLL>();
                user = userBll.GetByID(id, out callException);
                return user;
            }
    
            #endregion
        }

    业务逻辑类

     public class UserBLL : BaseClass.BLLBase
        {
            public UserBLL(Common.DALHelper dalHelper)
            {
                _dalHelper = dalHelper;
            }
            private Common.DALHelper _dalHelper;
    
    
            [Common.ExceptionCallHandler("你?没?有瓺权ā限T", "", "", "你?没?有瓺权ā限T啊?BLL")]
            public User GetByID(int id, out CallException callException)
            {
                callException = null;
                if (id < 10)
                {
                    callException = new CallException()
                    {
                        Message = "获?取?用?户§",
                        Detail = "必?须?大洙于等台于?0"
                    };
                    throw new FaultException<CallException>(callException, "parameter error");
                }
                else
                {
                    User user = null;
                    int b = 0;
                    user = _dalHelper.UserDal.GetByID(id, ref b, out callException);
                    return user;
                }
            }
            [Common.ExceptionCallHandler("你?没?有瓺权ā限T", "", "", "你?没?有瓺权ā限T啊?BLL")]
            public User GetUserByID(int id, out CallException callException)
            {
                User user = null;
                callException = null;
                if (id < 10)
                {
                    callException = new CallException()
                    {
                        Message = "获?取?用?户§",
                        Detail = "必?须?大洙于等台于?0"
                    };
                }
                else
                {
                    int b = 0;
                    user = _dalHelper.UserDal.GetByID(id, ref b, out callException);
                } return user;
            }
        }

    在业务逻辑类中判断参数的合法性,不合法抛出异常。大家看到有两个方法,一个是直接抛出异常,一个是没有抛出任何异常。后面将这两个的用处。

    2.2 同步调用

    同步调用,我们用控制台程序来模拟客户端。

    同步方式调用WCF的时候,我们可以直接try。。。catch。。。来捕获这个异常信息,然后进行处理。

    代码如下:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.ServiceModel;
    using System.ServiceModel.Channels;
    
    namespace ConsoleConsumer
    {
        class Program
        {
            static void Main(string[] args)
            {
                Service1.Service1Client client = new Service1.Service1Client();
                using (OperationContextScope scope = new OperationContextScope((IContextChannel)client.InnerChannel))
                {
                    MessageHeaders messageHeadersElement = OperationContext.Current.OutgoingMessageHeaders;
                    messageHeadersElement.Add(MessageHeader.CreateHeader("username", "", "kd"));
                    messageHeadersElement.Add(MessageHeader.CreateHeader("password", "", "kd"));
                }
                Console.WriteLine("请?输?入?ID:阰");
               int id =int.Parse ( Console.ReadLine());
                Service1.CallException callException = null;
                try
                {
                    
                    client.GetByIDWithAuthentication(out callException, id);
                    Console.WriteLine("成é功|调獭用?");
                }
                catch (FaultException<Service1.CallException> ex)
                {
                    Console.WriteLine("半?路·接ó获?CallException Error:{0},{1}", ex.Detail.Message, ex.Detail.Detail);
                }
                catch (Exception ex)
                {
                    Console.WriteLine("最?后ó一?关? Error:{0},{1}", ex.Message, ex.HelpLink);
                }
    
                Console.Read();
            }
        }
    }

    主要是看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就可以获取异常信息了,如果不为空,说明有异常存在。为空,说明没有异常,访问正常。

     void client_GetUserByIDCompleted(object sender, Service1.GetUserByIDCompletedEventArgs e)
            {
    
                #region
    
                if (e.callException != null)
                {
                    ChildWindow win = new ChildWindow();
                    win.Title = e.callException.Message;
                    win.Content = e.callException.Detail;
                    win.MinHeight = 50;
                    win.MinWidth = 200;
                    win.Show();
                }
                else
                {
                    ChildWindow win = new ChildWindow();
                    win.Title = "ok";
                    win.Content = "it is ok";
                    win.MinHeight = 50;
                    win.MinWidth = 200;
                    win.Show();
                }
                #endregion
    
            }

    3 结论

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

    源码下载:/Files/virusswb/WcfDemo.zip

  • 相关阅读:
    vue中使用clipboard.js复制分本
    聊聊IOCP,聊聊异步编程
    dubbo RPC超时异常小结
    redis4.0 集群,jedis客户端连接配置
    Centos7 Zookeeper
    阿里云Centos 7.4 mssql-server
    Redis4.0 Cluster — Centos7
    Elasticsearch学习笔记 一
    Centos7安装ES 和 Docker搭建ES
    使用Docker快速创建.Net Core2.0 Nginx负载均衡节点
  • 原文地址:https://www.cnblogs.com/virusswb/p/1861470.html
Copyright © 2011-2022 走看看