zoukankan      html  css  js  c++  java
  • 使用IErrorHandle对WCF服务器进行异常处理

    概述:

    在实际的项目开发中,我们常常会处理各种各样的异常,在代码中不断充斥着try{}catch{}finally{}语句块,这些处理有些时候是不可缺少的,因为谁都没有办法保证自己写的代码无异常运行,外部环境造成了异常存在的可能性,但是我常常觉得,捕获异常的语句块经常把原本清晰的业务逻辑弄得七零八落的,当然,本篇的目的不是说异常捕获可完全避免,但到少WCF可以让我们稍微从异常处理中得到一点解脱。

    1、  首先来看常规的服务实现类在处理异常时的做法,下面是常规的捕获了一个除数为0的异常。

    常规异常捕获
    publicstring Div(int x, int y)
    {
    int result=0;
    try
    {
    result
    = x / y;
    }
    catch (DivideByZeroException ex)
    {
    throw ex;
    }
    returnstring.Format("{0}",result);
    }

     

    2、 再看看应用了IErrorHandler接口来处理异常后的代码。

    publicstring Div(int x, int y)
    {
    returnstring.Format("{0}",x/y);
    }

    有爽的感觉吗?如果没有,请仔细想想1000个方法中的异常处理。这就是WCF让程序自己抛出异常并自行捕获。

    3、 如何实现?

    3.1、要达到上述的效果,我们需要自定义一类并实现IErrorHandler接口,代码相当的简单,如下:

    publicclass FaultErrorHandler : IErrorHandler
    {
    #region IErrorHandler 成员
    publicbool HandleError(Exception error)
    {
    // TO DO 在这里可以做日志记录等。
    Console.WriteLine("Message:{0},StackTrace:{1}", error.Message, error.StackTrace);
    returntrue;
    }
    publicvoid ProvideFault(Exception error, MessageVersion version, ref Message fault)
    {
    FaultException fe
    =new FaultException(error.Message, FaultCode.CreateReceiverFaultCode(error.Source, error.StackTrace));
    MessageFault messagefault
    = fe.CreateMessageFault();
    fault
    = Message.CreateMessage(version, messagefault, "http://www.microsoft.com/");
    }
    #endregion
    }

    只有十来行代码,相当于我们以前的创建日志文件代码。

     

    3.2、为了可复用性,我们希望所有的服务都可以使用上面的这段代码,那么我们就必须要创建一个可以在配置文件中注册的服务配置类,也十分的简单,如下:

    publicsealedclass ServiceErrorBehavior : BehaviorExtensionElement, IServiceBehavior
    {
    publicvoid Validate(ServiceDescription description, ServiceHostBase serviceHostBase) { return; }
    publicvoid AddBindingParameters(ServiceDescription description, ServiceHostBase serviceHostBase, System.Collections.ObjectModel.Collection<ServiceEndpoint> endpoints, BindingParameterCollection parameters) { return; }
    publicvoid ApplyDispatchBehavior(ServiceDescription description, ServiceHostBase serviceHostBase)
    {
    IErrorHandler errorHandler
    =new FaultErrorHandler();
    // 这里省略异常处理等
    foreach (ChannelDispatcherBase channelDispatcherBase in serviceHostBase.ChannelDispatchers)
    {
    ChannelDispatcher channelDispatcher
    = channelDispatcherBase as ChannelDispatcher;
    channelDispatcher.ErrorHandlers.Add(errorHandler);
    }
    }
    publicoverride Type BehaviorType { get { returntypeof(ServiceErrorBehavior); } }
    protectedoverrideobject CreateBehavior() { returnnew ServiceErrorBehavior(); }
    }

    上面的代码也是十来行而已,相当的简单。这段代码的意思是说:为了可以在配置文件中注册一个配置,我实现了BehaviorExtensionElement类,并重写了BehaviorExtensionElement的BehaviorType属性和CreateBehavior方法,因为在服务启动时,服务主机会自动的获取BehaviorType类型和通过CreateBehavior方法创建一个扩展配置节点。实现的IServiceBehavior接口是为了在服务分发通道中添加自定的异常处理程序,这样,在服务发生异常时WCF服务就可以通过这个配置节点找到相应的ErrorHandler处理程序,并自动调用。

     

    4、在配置文件中注册自定义的扩展配置节,我们所需要做的工作只是把下面的几行代码copy到app.config中,并将其放在system.serviceModel节点下。

    <extensions>
    <behaviorExtensions>
    <add name="enforceGreetingFaults" type="Common.ServiceErrorBehavior, Common, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
    </behaviorExtensions>
    </extensions>

     

    4.1、然后,再把上面的扩展配置加入到服务配置中,即把enforceGreetingFaults加入到这里,绿色部分为上面的扩展节点名称:

    注册扩展配置
    <serviceBehaviors>
    <behavior name="WcfService.Service1Behavior">
    <serviceMetadata httpGetEnabled="false"/>
    <serviceDebug includeExceptionDetailInFaults="true"/>
    <enforceGreetingFaults />
    </behavior>
    </serviceBehaviors>

     

    5、 最后客户端一如既往的调用服务就OK了。

     

    6、 特别注意事项:在创建服务扩展节点也就是(behaviorExtensions)时,需要仔细检查type="Common.ServiceErrorBehavior,Common, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"这一串,一定要记得“,”号后面要带一个空格,切记是带一个,既不能多也不能少,否则服务主机注册失败。

  • 相关阅读:
    .NET Core SignalR 和 .NET SignalR 区别
    MySQL 连接出现 Authentication plugin 'caching_sha2_password' cannot be loaded
    Geohash 基本知识及 .NET 下计算相邻8个区域编码
    ASP.NET 下配置请求大小、请求时间等参数
    .NET Core、EF、Dapper、MySQL 多种方式实现数据库操作(动态注册实体类)
    .NET Core 开发常用命令(VS Code)
    ping
    exec与xargs区别
    doc转docx
    读取docx表格中的信息
  • 原文地址:https://www.cnblogs.com/viter/p/1645822.html
Copyright © 2011-2022 走看看