오류 처리 및 오류 보고에 대한 확장 제어
ErrorHandling 샘플에서는 WCF(Windows Communication Foundation) 서비스에서 IErrorHandler 인터페이스를 사용하여 오류 처리 및 오류 보고에 대한 제어를 확장하는 방법을 보여 줍니다. 샘플은 시작을 기반으로 하며 오류를 처리하기 위한 몇 가지 코드가 서비스에 추가되었습니다. 클라이언트에서는 몇 가지 오류 조건을 발생시키고 서비스에서는 해당 오류를 가로채서 파일에 기록합니다.
참고 항목
이 샘플의 설치 절차 및 빌드 지침은 이 항목의 끝부분에 나와 있습니다.
서비스에서는 IErrorHandler 인터페이스를 사용하여 오류를 가로채고, 처리를 수행하고, 오류를 보고하는 방법에 영향을 줄 수 있습니다. 인터페이스에는 구현할 수 있는 두 개의 메서드 ProvideFault(Exception, MessageVersion, Message) 및 HandleError가 있습니다. ProvideFault(Exception, MessageVersion, Message) 메서드를 사용하면 예외에 대한 응답으로 생성되는 오류 메시지를 추가, 수정 또는 제거할 수 있습니다. HandleError 메서드를 사용하면 오류가 발생한 경우 오류 처리를 허용하고 추가 오류 처리를 실행할 수 있는지 여부를 제어할 수 있습니다.
이 샘플에서 CalculatorErrorHandler
형식은 IErrorHandler 인터페이스를 구현합니다. 다음 위치에서
HandleError 메서드에서 CalculatorErrorHandler
는 c:\logs에 있는 Error.txt 텍스트 파일에 오류 로그를 기록합니다. 샘플에서는 오류를 기록한 후 제거하지 않으므로 해당 오류를 클라이언트에 다시 보고할 수 있습니다.
public class CalculatorErrorHandler : IErrorHandler
{
// Provide a fault. The Message fault parameter can be replaced, or set to
// null to suppress reporting a fault.
public void ProvideFault(Exception error, MessageVersion version, ref Message fault)
{
}
// HandleError. Log an error, then allow the error to be handled as usual.
// Return true if the error is considered as already handled
public bool HandleError(Exception error)
{
using (TextWriter tw = File.AppendText(@"c:\logs\error.txt"))
{
if (error != null)
{
tw.WriteLine("Exception: " + error.GetType().Name + " - " + error.Message);
}
tw.Close();
}
return true;
}
}
ErrorBehaviorAttribute
는 서비스에 오류 처리기를 등록하는 데 사용되는 메커니즘입니다. 이 특성에서는 단일 형식 매개 변수를 받습니다. 그 형식은 IErrorHandler 인터페이스를 구현해야 하며 비어 있는 public 생성자가 있어야 합니다. 그러면 이 특성에서 해당 오류 처리기 형식의 인스턴스를 만들어 서비스에 설치합니다. 이 작업을 수행하려면 IServiceBehavior 인터페이스를 구현한 다음 ApplyDispatchBehavior 메서드를 사용하여 오류 처리기의 인스턴스를 서비스에 추가하면 됩니다.
// This attribute can be used to install a custom error handler for a service.
public class ErrorBehaviorAttribute : Attribute, IServiceBehavior
{
Type errorHandlerType;
public ErrorBehaviorAttribute(Type errorHandlerType)
{
this.errorHandlerType = errorHandlerType;
}
void IServiceBehavior.Validate(ServiceDescription description, ServiceHostBase serviceHostBase)
{
}
void IServiceBehavior.AddBindingParameters(ServiceDescription description, ServiceHostBase serviceHostBase, System.Collections.ObjectModel.Collection<ServiceEndpoint> endpoints, BindingParameterCollection parameters)
{
}
void IServiceBehavior.ApplyDispatchBehavior(ServiceDescription description, ServiceHostBase serviceHostBase)
{
IErrorHandler errorHandler;
try
{
errorHandler = (IErrorHandler)Activator.CreateInstance(errorHandlerType);
}
catch (MissingMethodException e)
{
throw new ArgumentException("The errorHandlerType specified in the ErrorBehaviorAttribute constructor must have a public empty constructor.", e);
}
catch (InvalidCastException e)
{
throw new ArgumentException("The errorHandlerType specified in the ErrorBehaviorAttribute constructor must implement System.ServiceModel.Dispatcher.IErrorHandler.", e);
}
foreach (ChannelDispatcherBase channelDispatcherBase in serviceHostBase.ChannelDispatchers)
{
ChannelDispatcher channelDispatcher = channelDispatcherBase as ChannelDispatcher;
channelDispatcher.ErrorHandlers.Add(errorHandler);
}
}
}
샘플에서는 계산기 서비스를 구현합니다. 클라이언트에서는 잘못된 값이 있는 매개 변수를 공급하여 고의로 서비스에 두 개의 오류를 일으킵니다. CalculatorErrorHandler
에서는 IErrorHandler 인터페이스를 사용하여 로컬 파일에 오류를 기록한 다음 클라이언트에 다시 보고될 수 있도록 합니다. 클라이언트에서는 0으로 나누기와 argument-out-of-range 조건을 발생시킵니다.
try
{
Console.WriteLine("Forcing an error in Divide");
// Call the Divide service operation - trigger a divide by 0 error.
value1 = 22;
value2 = 0;
result = proxy.Divide(value1, value2);
Console.WriteLine("Divide({0},{1}) = {2}", value1, value2, result);
}
catch (FaultException e)
{
Console.WriteLine("FaultException: " + e.GetType().Name + " - " + e.Message);
}
catch (Exception e)
{
Console.WriteLine("Exception: " + e.GetType().Name + " - " + e.Message);
}
샘플을 실행하면 작업 요청 및 응답이 클라이언트 콘솔 창에 표시됩니다. 0으로 나누기와 argument-out-of-range 조건이 오류로 보고되는 것을 볼 수 있습니다. 클라이언트를 종료하려면 클라이언트 창에서 Enter 키를 누릅니다.
Add(15,3) = 18
Subtract(145,76) = 69
Multiply(9,81) = 729
Forcing an error in Divide
FaultException: FaultException - Invalid Argument: The second argument must not be zero.
Forcing an error in Factorial
FaultException: FaultException - Invalid Argument: The argument must be greater than zero.
Press <ENTER> to terminate client.
c:\logs\errors.txt 파일에는 서비스에서 오류에 대해 기록한 정보가 포함되어 있습니다. 서비스에서 디렉터리에 기록을 수행하려면 서비스가 실행되는 프로세스(일반적으로 ASP.NET 또는 네트워크 서비스)에 디렉터리에 대한 쓰기 권한이 있는지 확인해야 합니다.
Fault: Reason = Invalid Argument: The second argument must not be zero.
Fault: Reason = Invalid Argument: The argument must be greater than zero.
샘플을 설치, 빌드 및 실행하려면
Windows Communication Foundation 샘플의 일회 설치 절차를 수행했는지 확인합니다.
솔루션을 빌드하려면 Windows Communication Foundation 샘플 빌드의 지침을 따릅니다.
error.txt 파일을 보관할 c:\logs 디렉터리를 만들었는지 확인합니다. 또는
CalculatorErrorHandler.HandleError
에 사용된 파일 이름을 수정합니다.단일 컴퓨터 또는 다중 컴퓨터 구성에서 샘플을 실행하려면 Windows Communication Foundation 샘플 실행의 지침을 따릅니다.