在 Web Applications中我们可以在Global.asax中通过Application_Error捕获应用程序错误。 在ASMX Web Services中我们可以写一个Soap Extension在程序异常被发送到客户端之前将其捕获并进行处理。 如果想在WCF中实现以下功能,当Server端程序出现异常时,程序可以捕获所有异常并进行写日志、通知管理员等处理。我们可以为每个Server端的方法加入try....catch...finally块,但这样写太麻烦。 实际上,在WCF中我们可以通过以下方式实现全局错误捕获: 1 MSDN中讲到,在System.ServiceModel.Dispatcher命名空间下有个IErrorHandler 接口。允许实施者对返回给调用方的错误消息进行控制,还可以选择执行自定义错误处理,例如日志记录。参见 http://msdn2.microsoft.com/zh-cn/library/system.servicemodel.dispatcher.ierrorhandler.aspx 2 实现方法示例:(以下示例仅仅按最简单的方式去实现WCF全局错误捕获) 定义一个类包含静态事件用于发生错误时触发该事件,代码如下:
using
System;
using
System.Collections.Generic;
using
System.Text;
using
System.ComponentModel;
namespace
BNCommon.ServiceHelper
...
{ public class BNServiceEvents ... { protected static EventHandlerList listEventDelegates = new EventHandlerList(); static readonly object HandleServiceMethodExecErrorKey = new object (); public delegate void HandleServiceMethodExecError(Exception ex); public static event HandleServiceMethodExecError EventServiceMethodExecError ... { add ... { listEventDelegates.AddHandler(HandleServiceMethodExecErrorKey, value); } remove ... { listEventDelegates.RemoveHandler(HandleServiceMethodExecErrorKey, value); } } public static void FireEventServiceMethodExecError(Exception ex) ... { HandleServiceMethodExecError handler = (HandleServiceMethodExecError)listEventDelegates[HandleServiceMethodExecErrorKey]; if (handler != null ) ... { handler(ex); } } } }
增加一个类实现System.ServiceModel.Dispatcher.IErrorHandler 接口,代码如下:
using
System;
using
System.Collections.Generic;
using
System.Text;
using
System.ServiceModel;
using
System.ServiceModel.Dispatcher;
using
System.ServiceModel.Description;
using
System.ServiceModel.Channels;
using
System.ServiceModel.Configuration;
namespace
BNCommon.ServiceHelper
...
{ public class BNErrorHandler : System.ServiceModel.Dispatcher.IErrorHandler ... { IErrorHandler 成员 #region IErrorHandler 成员 public bool HandleError(Exception error) ... { // 异常发生时触发事件 BNServiceEvents.FireEventServiceMethodExecError(error); return true ; } public void ProvideFault(Exception error, MessageVersion version, ref Message fault) ... { } #endregion } }
增加一个类实现System.ServiceModel.Description.IServiceBehavior接口并继承System.ServiceModel.Configuration.BehaviorExtensionElement用于将错误捕获行为加入Service行为集合中,代码如下:
using
System;
using
System.Collections.Generic;
using
System.Text;
using
System.ServiceModel;
using
System.ServiceModel.Dispatcher;
using
System.ServiceModel.Description;
using
System.ServiceModel.Channels;
using
System.ServiceModel.Configuration;
namespace
BNCommon.ServiceHelper
...
{ public class BNServiceOperationBehavior : BehaviorExtensionElement, IServiceBehavior ... { BehaviorExtensionElement成员 #region BehaviorExtensionElement成员 public override Type BehaviorType ... { get ... { return typeof (BNServiceOperationBehavior); } } protected override object CreateBehavior() ... { return new BNServiceOperationBehavior(); } #endregion IServiceBehavior 成员 #region IServiceBehavior 成员 public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, System.Collections.ObjectModel.Collection < ServiceEndpoint > endpoints, BindingParameterCollection bindingParameters) ... { return ; } public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) ... { foreach (ChannelDispatcher chanDisp in serviceHostBase.ChannelDispatchers) ... { chanDisp.ErrorHandlers.Add( new BNErrorHandler()); } } public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) ... { return ; } #endregion } }
在实例化ServiceHost时将扩展的Service行为加入行为集合中(也可以通过配置文件的方式实现,这里使用代码实现):
ServiceHost sh
=
new
ServiceHost(types[i]); sh.Description.Behaviors.Add(
new
BNServiceOperationBehavior());
在宿主程序中订阅BNServiceEvents.EventServiceMethodExecError事件进行处理,代码如下:
using
System;
using
System.Collections.Generic;
using
System.Text;
using
BNCommon.ServiceHelper;
namespace
BNClinicService.ServiceConsole
...
{ class Program ... { static void Main( string [] args) ... { System.Console.WriteLine( " Press <ENTER> to start service. " ); System.Console.ReadLine(); // 订阅异常事件 BNCommon.ServiceHelper.BNServiceEvents.EventServiceMethodExecError += new BNServiceEvents.HandleServiceMethodExecError(BNServiceEvents_EventServiceMethodExecError); // 启动服务 BNIIServiceLayer.SecurityServiceHosting.StartService(); System.Console.WriteLine( " Press <ENTER> to stop service. " ); System.Console.ReadLine(); // 停止服务 BNIIServiceLayer.SecurityServiceHosting.StopService(); } static void BNServiceEvents_EventServiceMethodExecError(Exception ex) ... { // 写日志.... BNIVSericeLayer.BNServiceLogEvent.FireLogEvent(BNIVSericeLayer.LogHelper.GetFaultLogModel(ex.Source, string .Empty, ex.Message, string .Empty)); // 其他处理.... } } }