使用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"这一串,一定要记得“,”号后面要带一个空格,切记是带一个,既不能多也不能少,否则服务主机注册失败。

posted @ 2010-01-12 19:18  Ron.Liang  阅读(1959)  评论(5编辑  收藏  举报