문제

우리는 우수한 것을 사용하고 있습니다 엘마 ASP.NET 3.5 웹 응용 프로그램에서 처리되지 않은 예외를 처리합니다. 이것은 나머지 기능을 사용하여 소비되는 WCF 서비스를 제외하고 모든 사이트에서 매우 잘 작동합니다. 애플리케이션 코드에서 처리하지 않는 작업 방법 내에서 예외가 발생하면 WCF는 서비스 계약 및 구성 설정에 따라 다양한 방식으로 처리합니다. 이것은 예외가 asp.net httpapplication.error 이벤트를 발사하지 않음을 의미합니다. 엘마 용도. 내가 이것을 다루기 위해 알고있는 두 가지 솔루션은 다음과 같습니다.

  • 시도 {} catch (예외) {elmah.errorsignal.fromCurrentContext (). REAT (ex); 던지다; } 캐치 블록 내에서 Elmah를 명시 적으로 호출합니다.
  • 사용 Ierrorhandler 설명대로 윌 휴즈 ' 블로그 게시물 WCF와 Elmah가 함께 놀게합니다 Elmah에게 별도의 오류 핸들러에 대한 호출을 고려합니다.

첫 번째 옵션은 매우 간단하지만 정확히 마른. 두 번째 옵션은 속성 및 ErrorHandler를 구현 한 후 사용자 정의 속성으로 각 서비스를 장식해야합니다. 나는 이것을 기반으로했다 일하지만 나는 이것이 올바른 접근 코드를 게시하기 전에.

내가 놓친 더 좋은 방법이 있습니까?

MSDN DOCUMENATION에 대한 Ierrorhandler 그 말을합니다 핸들 레터 방법은 벌목을 할 곳입니다 엘마 httpcontext.current에 액세스합니다.ApplicationInstance, httpcontext.current를 사용할 수 있지만이 메소드 내에서 Null입니다. ProversFault 메소드 내에서 Elmah를 호출하는 것은 ApplicationInstance가 설정되어 있기 때문에 해결 방법이지만 API 문서에 설명 된 의도와 일치하지 않습니다. 내가 여기서 뭔가를 놓치고 있습니까? 문서는 작동 스레드에서 호출되는 핸들러러 메소드에 의존해서는 안된다고 명시되어있어 ApplicationInstance 가이 범위에서 무효 인 이유 일 수 있습니다.

도움이 되었습니까?

해결책

내 블로그 게시물 (OP에서 참조)의 솔루션은 오류 상태에서 HTTP 응답 코드를 변경하기 위해 사용중인 기존 솔루션을 기반으로했습니다.

그래서 우리에게는 Elmah에게 예외를 전달하는 것이 한 줄 변경이었습니다. 더 나은 솔루션이 있다면, 그것에 대해 알고 싶습니다.

후손/참조 및 잠재적 개선의 경우 - 현재 솔루션의 코드는 다음과 같습니다.

Httperrorhandler 및 ServiceErrorbehaviourattribute 수업

using System;
using System.ServiceModel;
using System.ServiceModel.Dispatcher;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.Collections.ObjectModel;
using System.Net;
using System.Web;
using Elmah;
namespace YourApplication
{
    /// <summary>
    /// Your handler to actually tell ELMAH about the problem.
    /// </summary>
    public class HttpErrorHandler : IErrorHandler
    {
        public bool HandleError(Exception error)
        {
            return false;
        }

        public void ProvideFault(Exception error, MessageVersion version, ref Message fault)
        {
            if (error != null ) // Notify ELMAH of the exception.
            {
                if (System.Web.HttpContext.Current == null)
                    return;
                Elmah.ErrorSignal.FromCurrentContext().Raise(error);
            }
        }
    }
    /// <summary>
    /// So we can decorate Services with the [ServiceErrorBehaviour(typeof(HttpErrorHandler))]
    /// ...and errors reported to ELMAH
    /// </summary>
    public class ServiceErrorBehaviourAttribute : Attribute, IServiceBehavior
    {
        Type errorHandlerType;

        public ServiceErrorBehaviourAttribute(Type errorHandlerType)
        {
            this.errorHandlerType = errorHandlerType;
        }

        public void Validate(ServiceDescription description, ServiceHostBase serviceHostBase)
        {
        }

        public void AddBindingParameters(ServiceDescription description, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection parameters)
        {
        }

        public void ApplyDispatchBehavior(ServiceDescription description, ServiceHostBase serviceHostBase)
        {
            IErrorHandler errorHandler;
            errorHandler = (IErrorHandler)Activator.CreateInstance(errorHandlerType);
            foreach (ChannelDispatcherBase channelDispatcherBase in serviceHostBase.ChannelDispatchers)
            {
                ChannelDispatcher channelDispatcher = channelDispatcherBase as ChannelDispatcher;
                channelDispatcher.ErrorHandlers.Add(errorHandler);
            }
        }
    }
}

사용 예제

ServiceErrorbehaviour 속성으로 WCF 서비스를 장식하십시오.

[ServiceContract(Namespace = "http://example.com/api/v1.0/")]
[ServiceErrorBehaviour(typeof(HttpErrorHandler))]
public class MyServiceService
{
  // ...
}

다른 팁

haveciorextensionElement를 만들 때 구성을 사용하여 동작을 활성화 할 수도 있습니다.

public class ErrorBehaviorExtensionElement : BehaviorExtensionElement
{
    public override Type BehaviorType
    {
        get { return typeof(ServiceErrorBehaviourAttribute); }
    }

    protected override object CreateBehavior()
    {
        return new ServiceErrorBehaviourAttribute(typeof(HttpErrorHandler));
    }
}

구성 :

<system.serviceModel>
    <extensions>
      <behaviorExtensions>
        <add name="elmah" type="Namespace.ErrorBehaviorExtensionElement, YourAssembly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
      </behaviorExtensions>
    </extensions>
    <behaviors>
      <serviceBehaviors>
        <behavior>
          <elmah />
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>

그렇게하면 RIA 서비스와 함께 Elmah를 사용할 수도 있습니다!

나는 Will의 작업을 기반 으로이 작업을 수행했지만 코드를 게시하기 전에 이것이 올바른 접근법인지 확인하고 싶습니다.

나는 이것이 훌륭한 접근법이라고 생각합니다 (이 게시물에 대한 의지에 대한 Kudos!). 나는 의지를 생각하지 않거나 당신은 여기서 아무것도 놓쳤다. IerrorHandler를 구현하는 것은 통신 채널이 결함 (찢어짐)을 일으킬 수있는 모든 가능한 서버 측 예외를 캡처하는 것이 선호되는 방법입니다. 따라서 Elmah와 같은 일부 로깅에서 연결하는 자연스러운 장소입니다.

마크

이것은 일부 사람들에게는 분명할지 모르지만 나는 httpcontext.current가 Will Hughes의 훌륭한 대답을 모두 따르는 이유를 알아 내려고 꽤 오랫동안 보냈습니다. 당황스럽게도, 나는 이것이 내 WCF 서비스가 MSMQ 메시지에 의해 활성화되기 때문이라는 것을 깨달았습니다.

나는 다시 작성했다 ProvideFault() 방법:

if (HttpContext.Current == null)
{
    ErrorLog.GetDefault(null).Log(new Error(error));
}
else
{
    ErrorSignal.FromCurrentContext().Raise(error);
}

WCF 데이터 서비스를 사용하여 제안 된 답변을 얻을 수 없었습니다. 동작 속성 등을 연결했지만 여전히 오류가 발생하지 않았습니다. 대신 서비스 구현에 다음을 추가했습니다.

protected override void HandleException(HandleExceptionArgs args)
{
    Elmah.ErrorSignal.FromCurrentContext().Raise(args.Exception);
    base.HandleException(args);
}

나는 나머지 물건으로 명시 적으로 이것을 시도하지 않았고 Elmah를 직접 사용하지 않았지만, 조사 할 가치가있는 또 다른 옵션은 IdispatchMessageInspector ierrorhandler 대신.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top