如何为WCF服务创build全局exception处理程序?

我想logging所有的exception服务器端

在ASP.NET中,我在Global.asax.cs中写这样的东西,但是这也可以用于WCF服务吗?

public class Global : HttpApplication { protected void Application_Error(object sender, EventArgs e) { Exception unhandledException = Server.GetLastError(); //Log exception here ... } } 

更新:我不想有一个尝试…赶上我的.svc文件中的每个[OperationContract]。 我简短…我想确保我的服务抛出的所有exception都由log4netlogging。 我不是在谈论客户端如何处理exception。

您可以通过实现IErrorHandler并将其与服务关联来创buildWCF错误logging器。 通常(对于日志logging),您将从HandleError (允许其他处理程序执行)返回false ,并将错误logging在HandleError (使用Exception )或ProvideFault (使用ref Message fault )中。

我通过编写一个自定义行为(从BehaviorBaseinheritance)来应用这个处理程序,在ApplyDispatchBehavior添加error handling程序到endpointDispatcher.ChannelDispatcher.ErrorHandlers如果它不在那里)。

行为可以通过configuration来应用。

自己经历了这个问题,经过多次研究,包括其他答案链接的文章,这里正是人们需要这个。

这里是您将需要的ErrorHandler类

 Imports System.ServiceModel.Configuration Imports System.ServiceModel.Description Imports System.ServiceModel.Dispatcher ''' <summary> ''' This class defines a global ErrorHandler, that allows us to control the ''' fault message returned to the client and perform custom error processing ''' like logging. ''' </summary> Public Class ErrorHandler Implements IErrorHandler ''' <summary> ''' This method will be called whenever an exception occurs. Therefore, ''' we log it and then return false so the error can continue to propagate up the chain. ''' </summary> ''' <param name="ex">Exception being raised.</param> ''' <returns>False to let the error propagate up the chain, or True to stop the error here.</returns> Public Function HandleError(ByVal ex As Exception) As Boolean Implements IErrorHandler.HandleError 'Unknown error occurred at the Service layer, log the event logEvent("Encountered an unknown error at the Service layer.", ex, EventLogEntryType.Error) Return False End Function ''' <summary> ''' This method is optionally used to transform standard exceptions into custom ''' FaultException(Of TDetail) that can be passed back to the service client. ''' </summary> ''' <param name="ex">Exception being raised.</param> ''' <param name="version">SOAP version of the message.</param> ''' <param name="fault">Message object that is returned to the client.</param> Public Sub ProvideFault(ByVal ex As Exception, ByVal version As Channels.MessageVersion, ByRef fault As Channels.Message) Implements IErrorHandler.ProvideFault End Sub End Class ''' <summary> ''' This class defines a ServiceBehavior, that will allow us to add our ''' custom ErrorHandler class, defined above, to each channel we have a ''' service running on. ''' </summary> Public Class ErrorServiceBehavior Implements IServiceBehavior Public Sub AddBindingParameters(serviceDescription As ServiceDescription, serviceHostBase As ServiceHostBase, endpoints As ObjectModel.Collection(Of ServiceEndpoint), bindingParameters As Channels.BindingParameterCollection) Implements IServiceBehavior.AddBindingParameters End Sub Public Sub ApplyDispatchBehavior(serviceDescription As ServiceDescription, serviceHostBase As ServiceHostBase) Implements IServiceBehavior.ApplyDispatchBehavior 'Enumerate all channels and add the error handler to the collection Dim handler As New ErrorHandler() For Each dispatcher As ChannelDispatcher In serviceHostBase.ChannelDispatchers dispatcher.ErrorHandlers.Add(handler) Next End Sub Public Sub Validate(serviceDescription As ServiceDescription, serviceHostBase As ServiceHostBase) Implements IServiceBehavior.Validate End Sub End Class ''' <summary> ''' This class defines a BehaviorExtensionElement, so that we can ''' use the ErrorServiceBehavior class, defined above, in our App.config. ''' </summary> Public Class ErrorHandlerBehavior Inherits BehaviorExtensionElement Protected Overrides Function CreateBehavior() As Object Return New ErrorServiceBehavior() End Function Public Overrides ReadOnly Property BehaviorType As Type Get Return GetType(ErrorServiceBehavior) End Get End Property End Class 

然后,需要在App.config文件中为您的服务项目添加/更新这些部分…

 <system.serviceModel> <extensions> <behaviorExtensions> <!-- Add in our custom error handler --> <add name="ErrorLogging" type="Service.ErrorHandlerBehavior, Service, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" /> </behaviorExtensions> </extensions> <services> <service name="Service.Service" behaviorConfiguration="Service.ServiceBehavior"> <endpoint address="" binding="wsHttpBinding" bindingConfiguration="wsHttp" contract="SentinelService.IService"/> <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" /> </service> </services> <behaviors> <serviceBehaviors> <behavior name="Service.ServiceBehavior"> <serviceMetadata httpGetEnabled="True" /> <serviceDebug includeExceptionDetailInFaults="False" /> <!-- Add in our custom error handler, from behaviorExtensions element --> <ErrorLogging /> </behavior> </serviceBehaviors> </behaviors> 

具体而言,需要添加behaviorExtension,其名称需要添加到行为部分,行为部分需要命名,并且该行为部分需要成为服务的behaviorConfiguration。

但是,请谨慎使用behaviorExtension上的“type”属性,但必须精确。 如果您不确定您可以使用以下来确定它GetType(ErrorHandlerBehavior).AssemblyQualifiedName

如果你有兴趣,这是我使用的logEvent函数背后的代码…

 ''' <summary> ''' Logs a message and optional exception to the application event log. ''' </summary> ''' <param name="message">String message to log.</param> ''' <param name="ex">Exception to log.</param> ''' <param name="eventType">EventLogEntryType indicating the message severity.</param> Public Sub logEvent(ByVal message As String, Optional ByVal ex As Exception = Nothing, _ Optional ByVal eventType As EventLogEntryType = EventLogEntryType.Information) 'Initialize report Dim report As String = message + vbNewLine + vbNewLine 'Create eventLogger Dim eventLogger As New EventLog() 'Register event source, add any Exception information to the report, and then log it Try 'Register the app as an Event Source If Not EventLog.SourceExists("MyAppName") Then EventLog.CreateEventSource("MyAppName", "Application") End If If ex IsNot Nothing Then 'Force eventType to error eventType = EventLogEntryType.Error 'Add Exception Information to report report += "Exception Information:" + vbNewLine Dim currentException As Exception = ex Dim exCount As Integer = 1 While (currentException IsNot Nothing) report += Space(5) + If(exCount = 1, "Message:", "Inner Exception:") + vbNewLine report += Space(10) + currentException.Message + vbNewLine report += Space(5) + "StackTrace:" + vbNewLine report += Space(10) + currentException.StackTrace + vbNewLine report += vbNewLine currentException = currentException.InnerException exCount += 1 End While End If Catch reportException As Exception 'This catch ensures that no matter what some error report is logged. report += vbNewLine + vbNewLine + "PARTIAL REPORT!!!...AN ERROR WAS ENCOUNTERED GENERATING ERROR REPORT." Finally Try 'Log report eventLogger.Source = "MyAppName" eventLogger.WriteEntry(report, eventType) Catch logEventException As Exception 'Eat it...nothing can be done at this point and we do 'not want the application to crash over an error report 'if we can prevent it End Try End Try End Sub 

这不是一个答案本身,而是SkyBlade002提供的伟大答案的附录 ,提供给定的代码在C#中,以方便任何C#编码器:

这是我的代码(在ErrorHandler.cs中):

 /// <summary> /// This class defines a global ErrorHandler, that allows us to control the fault message returned to the client and /// perform custom error processing like logging. /// </summary> public class ErrorHandler : IErrorHandler { private static readonly ILog Log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); /// <summary> /// Enables the creation of a custom <see cref="T:System.ServiceModel.FaultException`1" /> that is returned from an /// exception in the course of a service method. /// </summary> /// <remarks> /// This method is optionally used to transform standard exceptions into custom FaultException(Of TDetail) that /// can be passed back to the service client. /// </remarks> /// <param name="error">The <see cref="T:System.Exception" /> object thrown in the course of the service operation.</param> /// <param name="version">The SOAP version of the message.</param> /// <param name="fault"> /// The <see cref="T:System.ServiceModel.Channels.Message" /> object that is returned to the client, or /// service, in the duplex case. /// </param> public void ProvideFault(Exception error, MessageVersion version, ref Message fault) {} /// <summary> /// This method will be called whenever an exception occurs. Therefore, /// we log it and then return false so the error can continue to propagate up the chain. /// </summary> /// <param name="error">Exception being raised.</param> /// <returns>False to let the error propagate up the chain, or True to stop the error here.</returns> public bool HandleError(Exception error) { Log.Error(ex); //TODO your own logging return false; } 

这是我的代码(在ErrorHandlerBehavior.cs中):

 /// <summary> /// This class defines a BehaviorExtensionElement, so that we can use the ErrorServiceBehavior class, defined above, in /// our App.config. /// </summary> public class ErrorHandlerBehavior : BehaviorExtensionElement { /// <summary> /// Gets the type of behavior. /// </summary> public override Type BehaviorType { get { return typeof (ErrorServiceBehavior); } } /// <summary> /// Creates a behavior extension based on the current configuration settings. /// </summary> /// <returns> /// The behavior extension. /// </returns> protected override object CreateBehavior() { return new ErrorServiceBehavior(); } } 

这是我的代码(在ErrorServiceBehavior.cs中):

 /// <summary> /// This class defines a ServiceBehavior, that will allow us to add our custom ErrorHandler class, defined above, to /// each channel we have a service running on. /// </summary> public class ErrorServiceBehavior : IServiceBehavior { /// <summary> /// Provides the ability to inspect the service host and the service description to confirm that the service can run /// successfully. /// </summary> /// <param name="serviceDescription">The service description.</param> /// <param name="serviceHostBase">The service host that is currently being constructed.</param> public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) {} /// <summary> /// Provides the ability to pass custom data to binding elements to support the contract implementation. /// </summary> /// <param name="serviceDescription">The service description of the service.</param> /// <param name="serviceHostBase">The host of the service.</param> /// <param name="endpoints">The service endpoints.</param> /// <param name="bindingParameters">Custom objects to which binding elements have access.</param> public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters) {} /// <summary> /// Provides the ability to change run-time property values or insert custom extension objects such as error handlers, /// message or parameter interceptors, security extensions, and other custom extension objects. /// </summary> /// <param name="serviceDescription">The service description.</param> /// <param name="serviceHostBase">The host that is currently being built.</param> public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) { //Enumerate all channels and add the error handler to the collection var handler = new ErrorHandler(); foreach (ChannelDispatcher dispatcher in serviceHostBase.ChannelDispatchers) { dispatcher.ErrorHandlers.Add(handler); } } }