zoukankan      html  css  js  c++  java
  • 【WCF--初入江湖】06 WCF契约服务行为和异常处理

    06 WCF契约服务行为和异常处理

    一、WCF契约服务行为

      【1】
      服务行为可以修改和控制WCF服务的运行特性。
      在实现了WCF服务契约后,可以修改服务的很多执行特性。
      这些行为(或者特性)是通过配置运行时属性或者通过自定义行为来控制的。

         【2】分类

      WCF的行为分为两类:

        服务行为(Service Behavior)

        操作行为(Operation Behavior)

        【3】应用的位置

          应用在实现接口的类上,而不是接口上。

    [ServiceBehavior]
    public class ServiceClass:IService1
    {
       [OperationBehavior]
       public int AddNumber(int x,int y)
       {
         return x+y;
       }

      【4】服务的行为配置有两种方式:

      【4-1】使用代码配置

    示例:在宿主中,使用 

    ServiceHost的Description.Behaviors.Add()方法
                //地址
                Uri pipeaddress = new Uri("net.pipe://localhost/NetNamedPipeBinding");
                Uri tcpaddress = new Uri("net.tcp://localhost:8088/TcpBinding");
    。。。
                //服务宿主对象
                host = new ServiceHost(typeof(WcfServiceLibrary1.Service1), pipeaddress, tcpaddress);
    。。。
                //添加元数据 行为
                ServiceMetadataBehavior mBehavior = new ServiceMetadataBehavior();
                host.Description.Behaviors.Add(mBehavior);

     或者是:

    [ServiceBehavior]
    public class ServiceClass:IService1
    {
       [OperationBehavior]
       public int AddNumber(int x,int y)
       {
         return x+y;
       }
       [OperationBehavior]
       public int SubtractNumber(int x,int y)
       {
         return x-y;
       }
    }

      【4-2】使用配置文件配置

    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
      <system.serviceModel>
        <services>
          <service name="WcfServiceLibrary1.Service1" behaviorConfiguration="textBehavior">
     。。。。。。
          </service>
        </services>
        <behaviors>
          <serviceBehaviors>
            <behavior name="textBehavior">
              <serviceMetadata/>
              <serviceDebug/>
            </behavior>
          </serviceBehaviors>
        </behaviors>
      </system.serviceModel>
    </configuration>

     【5】[ServiceBehavior]的属性

    AutomaticSessionShutdown                     客户端关闭会话时服务是否自动关闭
    ConcurrencyMode                              线程的支持,默认:服务是单线程
    IgnoreExtensionDataObject                    跟序列化有关
    IncludeExceptionDetaillnFaults               如何处理未被处理的异常
    InstanceContextMode                          服务实例对象创建的模式,PerCall 表示每次来一个请求为其创建一个对象的实例,调用后回收;PerSession是每次一个请求来只创建一个该服                                             务对象的实例直至其销毁,调用后进行回收,并且会话间不能共享; Single表示只允许创建一个该服务的实例,调用后不回收
    ReleaseServiceInstanceOnTransactionComplete  
    TransactionAutoCompleteOnSessionClose
    TransactionlsolationLevel
    TtansactionTimeout
    AutoDisposeParameters
    ReleaseInstanceMode 操作完后回收对象、调用操作前回收、根据自动方式回收
    TransactionAutoComplete 使用自动提交事务,默认为true

    一个配示例:

     <system.serviceModel>
        <extensions>
          <behaviorExtensions>
            <add name="unity" type="ByteartRetail.Infrastructure.UnityExtensions.UnityBehaviorExtensionElement, ByteartRetail.Infrastructure,  Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
          </behaviorExtensions>
        </extensions>
        <behaviors>
          <serviceBehaviors>
            <behavior>
              <serviceMetadata httpGetEnabled="true" />
              <serviceDebug includeExceptionDetailInFaults="false" />
              <unity operationContextEnabled="true" instanceContextEnabled="true" contextChannelEnabled="true" serviceHostBaseEnabled="true" />
            </behavior>
          </serviceBehaviors>
        </behaviors>

     另一个:

     <serviceBehaviors>
            <behavior name="WcfService1.Service1Behavior">
              <serviceAuthorization ></serviceAuthorization>
              <serviceTimeouts/>
              <serviceThrottling maxConcurrentCalls="" maxConcurrentInstances="" maxConcurrentSessions=""/>
              <serviceMetadata httpGetEnabled="true"/>
              <serviceDebug includeExceptionDetailInFaults="false"/>
            </behavior>
          </serviceBehaviors>

    二、异常处理

       【1】种类:

        FaultException                创建非类型化的错误,在服务端进行创建,然后用SOAP方式返回客户端

               TimeoutException

               CommunicationException

    FaultException异常:

    #region 程序集 System.ServiceModel.dll, v4.0.0.0
    // C:Program Files (x86)Reference AssembliesMicrosoftFramework.NETFrameworkv4.5System.ServiceModel.dll
    #endregion
    
    using System;
    using System.Runtime.Serialization;
    using System.Security;
    using System.ServiceModel.Channels;
    
    namespace System.ServiceModel
    {
        // 摘要: 
        //     用于在客户端应用程序中捕获通过协定方式指定的 SOAP 错误。
        //
        // 类型参数: 
        //   TDetail:
        //     可序列化错误详细信息类型。
        [Serializable]
        public class FaultException<TDetail> : FaultException
        {
            // 摘要: 
            //     初始化使用指定详细信息对象的 System.ServiceModel.FaultException<TDetail> 类的新实例。
            //
            // 参数: 
            //   detail:
            //     用作 SOAP 错误详细信息的对象。
            public FaultException(TDetail detail);
            //
            // 摘要: 
            //     将流反序列化为 System.ServiceModel.FaultException 对象时,使用指定的序列化信息和上下文初始化 System.ServiceModel.FaultException<TDetail>
            //     类的新实例。
            //
            // 参数: 
            //   info:
            //     从 context 中重新构造 System.ServiceModel.FaultException 对象时必需的序列化信息。
            //
            //   context:
            //     从中重新构造 System.ServiceModel.FaultException 对象的流。
            protected FaultException(SerializationInfo info, StreamingContext context);
            //
            // 摘要: 
            //     初始化使用指定详细信息对象和错误原因的 System.ServiceModel.FaultException<TDetail> 类的新实例。
            //
            // 参数: 
            //   detail:
            //     用作 SOAP 错误详细信息的对象。
            //
            //   reason:
            //     SOAP 错误的原因。
            public FaultException(TDetail detail, FaultReason reason);
            //
            // 摘要: 
            //     初始化使用指定详细信息和错误原因的 System.ServiceModel.FaultException<TDetail> 类的新实例。
            //
            // 参数: 
            //   detail:
            //     用作 SOAP 错误详细信息的对象。
            //
            //   reason:
            //     SOAP 错误的原因。
            public FaultException(TDetail detail, string reason);
            //
            // 摘要: 
            //     初始化 System.ServiceModel.FaultException<TDetail> 类的新实例,该类使用指定的详细信息对象、错误原因和错误代码。
            //
            // 参数: 
            //   detail:
            //     用作 SOAP 错误详细信息的对象。
            //
            //   reason:
            //     SOAP 错误的原因。
            //
            //   code:
            //     SOAP 错误的错误代码。
            public FaultException(TDetail detail, FaultReason reason, FaultCode code);
            //
            // 摘要: 
            //     初始化 System.ServiceModel.FaultException<TDetail> 类的新实例,该类使用指定的详细信息对象、错误原因和错误代码。
            //
            // 参数: 
            //   detail:
            //     用作 SOAP 错误详细信息的对象。
            //
            //   reason:
            //     SOAP 错误的原因。
            //
            //   code:
            //     SOAP 错误的错误代码。
            public FaultException(TDetail detail, string reason, FaultCode code);
            //
            // 摘要: 
            //     初始化 System.ServiceModel.FaultException<TDetail> 类的新实例,该类使用指定的详细信息对象以及 SOAP
            //     错误原因、代码和操作值。
            //
            // 参数: 
            //   detail:
            //     用作 SOAP 错误详细信息的对象。
            //
            //   reason:
            //     SOAP 错误的原因。
            //
            //   code:
            //     SOAP 错误的错误代码。
            //
            //   action:
            //     SOAP 错误的操作。
            public FaultException(TDetail detail, FaultReason reason, FaultCode code, string action);
            //
            // 摘要: 
            //     初始化 System.ServiceModel.FaultException<TDetail> 类的新实例,该类使用指定的详细信息对象以及 SOAP
            //     错误原因、代码和操作值。
            //
            // 参数: 
            //   detail:
            //     用作 SOAP 错误详细信息的对象。
            //
            //   reason:
            //     SOAP 错误的原因。
            //
            //   code:
            //     SOAP 错误的错误代码。
            //
            //   action:
            //     SOAP 错误的操作。
            public FaultException(TDetail detail, string reason, FaultCode code, string action);
    
            // 摘要: 
            //     获取包含错误条件详细信息的对象。
            //
            // 返回结果: 
            //     System.ServiceModel.FaultException<TDetail> 对象的类型参数的详细信息对象。
            public TDetail Detail { get; }
    
            // 摘要: 
            //     创建一个 System.ServiceModel.Channels.MessageFault 对象,该对象可用于创建表示 SOAP 错误的 System.ServiceModel.Channels.Message。
            //
            // 返回结果: 
            //     创建的错误消息。
            public override MessageFault CreateMessageFault();
            //
            // 摘要: 
            //     实现在将对象序列化到流中时调用的 System.Runtime.Serialization.ISerializable.GetObjectData(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)
            //     方法。
            //
            // 参数: 
            //   info:
            //     序列化时向其添加对象数据的序列化信息。
            //
            //   context:
            //     序列化对象的目标。
            [SecurityCritical]
            public override void GetObjectData(SerializationInfo info, StreamingContext context);
            //
            // 摘要: 
            //     返回 System.ServiceModel.FaultException<TDetail> 对象的字符串。
            //
            // 返回结果: 
            //     SOAP 错误的字符串。
            public override string ToString();
        }
    }
    View Code

    服务端:

        public class Service1 : IService1
        {
            public void Divide(int x, int y)
            {
                try 
                {
                    int z = x / y;
                }
                catch(Exception e)
                {
                    throw new FaultException("试图除零",new FaultCode("除法操作"));
                }
            }
        }

    客户端:

                server.Service1Client client = new wcfClient.server.Service1Client();
    
                try
                {
                    client.Divide(3, 2);
                    client.Abort();
                    client.Divide(3, 0);
                }
                catch (FaultException fe)
                {
                    MessageBox.Show(fe.Reason.ToString());
                }
                catch (TimeoutException te)
                {
                    MessageBox.Show("调用超时");
                }
                catch (CommunicationException ce)
                {
                    MessageBox.Show("通信异常!");
                }

          【2】FaultContract:自定义错误信息:FaultData

        // 摘要: 
        //     指定服务操作遇到处理错误时返回的一个或多个 SOAP 错误。
        [AttributeUsage(AttributeTargets.Method, AllowMultiple = true, Inherited = false)]
        public sealed class FaultContractAttribute : Attribute

    使用步骤:

      第一步:

        [ServiceContract(Namespace = "http://www.Keasy5.com")]
        public interface IOrderService 
        {
            [OperationContract]
            [FaultContract(typeof(FaultData))]
            int GetShoppingCartItemCount(Guid userID);

    FaultData.cs

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Runtime.Serialization;
    using System.Text;
    using System.Threading.Tasks;
    using System.ServiceModel;
    
    namespace Keasy5.DataObject
    {
        /// <summary>
        /// Represents the data to be transferred through the
        /// network which contains the fault exception information.
        /// </summary>
        [DataContract]
        public class FaultData
        {
            #region Public Properties
            /// <summary>
            /// Gets or sets the message of the fault data.
            /// </summary>
            [DataMember(Order = 0)]
            public string Message { get; set; }
            /// <summary>
            /// Gets or sets the full message of the fault data.
            /// </summary>
            [DataMember(Order = 1)]
            public string FullMessage { get; set; }
            /// <summary>
            /// Gets or sets the stack trace information of the fault exception.
            /// </summary>
            [DataMember(Order = 2)]
            public string StackTrace { get; set; }
            #endregion
    
            #region Public Static Methods
            /// <summary>
            /// Creates a new instance of <c>FaultData</c> class from the specified <see cref="System.Exception"/> object.
            /// </summary>
            /// <param name="ex">The <see cref="System.Exception"/> object which carries the error information.</param>
            /// <returns>A new instance of <c>FaultData</c> class.</returns>
            public static FaultData CreateFromException(Exception ex)
            {
                return new FaultData
                {
                    Message = ex.Message,
                    FullMessage = ex.ToString(),
                    StackTrace = ex.StackTrace
                };
            }
            /// <summary>
            /// Creates a new instance of <see cref="FaultReason"/> class from the specified <see cref="Exception"/> object.
            /// </summary>
            /// <param name="ex">The <see cref="System.Exception"/> object which carries the error information.</param>
            /// <returns>A new instance of <see cref="FaultReason"/> class.</returns>
            public static FaultReason CreateFaultReason(Exception ex)
            {
                return new FaultReason(ex.Message);
            }
            #endregion
        }
    }
    View Code

      第二步:

        // 注意: 使用“重构”菜单上的“重命名”命令,可以同时更改代码、svc 和配置文件中的类名“OrderService”。
        // 注意: 为了启动 WCF 测试客户端以测试此服务,请在解决方案资源管理器中选择 OrderService.svc 或 OrderService.svc.cs,然后开始调试。
        [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]
        public class OrderService : IOrderService
        {
            private readonly IOrderService orderServiceImpl = ServiceLocator.Instance.GetService<IOrderService>();
            public Int32 GetShoppingCartItemCount(Guid userID)
            {
                try
                {
                    return orderServiceImpl.GetShoppingCartItemCount(userID);
                }
                catch (Exception ex)
                {
                    throw new FaultException<FaultData>(FaultData.CreateFromException(ex), FaultData.CreateFaultReason(ex));
                }
            }

     使用了这个构造函数:

            //
            // 摘要: 
            //     初始化使用指定详细信息对象和错误原因的 System.ServiceModel.FaultException<TDetail> 类的新实例。
            //
            // 参数: 
            //   detail:
            //     用作 SOAP 错误详细信息的对象。
            //
            //   reason:
            //     SOAP 错误的原因。
            public FaultException(TDetail detail, FaultReason reason);
  • 相关阅读:
    UE4美术之数学基础知识(一)
    如何用Unity制作逼真的自然场景?
    git拉取和上传项目代码
    Chaosblade-故障使用工具
    如何对数据库做优化
    分布式和集群的概念
    token、cookie、session的区别
    Json中的json.tojsonString()方法
    JSON的put方法
    fastjson中的相关方法
  • 原文地址:https://www.cnblogs.com/easy5weikai/p/3825361.html
Copyright © 2011-2022 走看看