WCF 서비스에 대한 전역 예외 처리기를 어떻게 만듭니 까?
모든 예외를 서버 측 에 기록하고 싶습니다 .
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]에 대해 try ... catch를 갖고 싶지 않습니다. 간단히 말해서 ... 내 서비스에서 발생하는 모든 예외가 log4net에 의해 기록되는지 확인하고 싶습니다. 클라이언트가 예외를 처리하는 방법에 대해 말하는 것이 아닙니다.
WCF 오류 로거를 구현 IErrorHandler
하고 서비스와 연결 하여 만들 수 있습니다 . 일반적으로 (로깅의 경우) false
에서 반환 하고 HandleError
(다른 처리기가 실행되도록 허용) 오류를에서 HandleError
(사용 Exception
) 또는에서 ProvideFault
(사용 ref Message fault
)에 기록합니다.
사용자 지정 동작 (에서 상속 BehaviorBase
) 을 작성하여이 처리기를 적용합니다.이 처리기는 (에서 ApplyDispatchBehavior
) 오류 처리기 endpointDispatcher.ChannelDispatcher.ErrorHandlers
가 아직없는 경우 추가합니다 .
이 동작은 구성을 통해 적용 할 수 있습니다.
이 문제를 직접 다루었 고 다른 답변에 링크 된 기사를 포함하여 많은 열린 연구 탭을 거친 후 누군가가 이것을 위해 정확히 필요한 것이 있습니다.
다음은 필요한 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);
}
}
}
'IT TIP' 카테고리의 다른 글
ASP.NET Core 1.0 Web API의 간단한 JWT 인증 (0) | 2020.12.25 |
---|---|
스레드 컨텍스트 전환 오버 헤드를 추정하는 방법은 무엇입니까? (0) | 2020.12.25 |
Git 하위 모듈 내에 추가 된 .gitignore 파일 (0) | 2020.12.25 |
메모장 ++에서 SHIFT + CTRL + Z 재정의 (0) | 2020.12.25 |
ssh가있는 SCP : scp를 사용하여 Windows에서 원격 서버로 로컬 파일 복사 (0) | 2020.12.25 |