【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);
原文地址:https://www.cnblogs.com/easy5weikai/p/3825361.html