c# - ASP.NET Web API에서 "ExceptionHandler"를 사용하여 처리되지 않은 예외를 처리하기위한 완벽한 샘플이 필요합니까?





asp.net-web-api exception-handling (5)


웹 API 팀의 다음 샘플을 살펴볼 수 있습니다.

http://aspnet.codeplex.com/SourceControl/latest#Samples/WebApi/Elmah/ReadMe.txt

나는이 링크 http://www.asp.net/web-api/overview/web-api-routing-and-actions/web-api-global-error-handling 확인했다. 이 링크에서 그들은 이렇게 언급했다.

class OopsExceptionHandler : ExceptionHandler
{
    public override void HandleCore(ExceptionHandlerContext context)
    {
        context.Result = new TextPlainErrorResult
        {
            Request = context.ExceptionContext.Request,
            Content = "Oops! Sorry! Something went wrong." +
                      "Please contact [email protected] so we can try to fix it."
        };
    }

    private class TextPlainErrorResult : IHttpActionResult
    {
        public HttpRequestMessage Request { get; set; }

        public string Content { get; set; }

        public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
        {
            HttpResponseMessage response = 
                             new HttpResponseMessage(HttpStatusCode.InternalServerError);
            response.Content = new StringContent(Content);
            response.RequestMessage = Request;
            return Task.FromResult(response);
        }
    }
}

내 웹 API 작업에서이 클래스를 호출하는 방법을 모르겠습니다. 그래서 어느 ExceptionHandler 사용하여 완전한 샘플을 제공 할 수 있습니다.




Jon Susiak의 답변에 따라 다음을 사용해야합니다.

config.Services.Replace(typeof (IExceptionHandler), new OopsExceptionHandler());

Add 아니라 통화 Replace Add . 그 이유는 다음 링크에있는 기사와 같습니다.

ASP.NET 웹 API 2의 전역 오류 처리

솔루션 개요

사용자가 교체 할 수있는 새로운 서비스 인 IExceptionLogger와 IExceptionHandler를 제공하여 처리되지 않은 예외를 기록하고 처리합니다.

서비스는 두 가지 주요한 차이점과 매우 유사합니다.

우리는 여러 예외 로거의 등록을 지원 하나 예외 핸들러 하나만을 지원합니다 .

그리고 이미 기본적으로 등록 된 핸들러가 있으므로 다른 핸들러를 추가 할 수 없습니다.

public DefaultServices(HttpConfiguration configuration)
    {
      if (configuration == null)
        throw System.Web.Http.Error.ArgumentNull("configuration");
      this._configuration = configuration;
      this.SetSingle<IActionValueBinder>((IActionValueBinder) new DefaultActionValueBinder());
      this.SetSingle<IApiExplorer>((IApiExplorer) new ApiExplorer(configuration));
      this.SetSingle<IAssembliesResolver>((IAssembliesResolver) new DefaultAssembliesResolver());
      this.SetSingle<IBodyModelValidator>((IBodyModelValidator) new DefaultBodyModelValidator());
      this.SetSingle<IContentNegotiator>((IContentNegotiator) new DefaultContentNegotiator());
      this.SetSingle<IDocumentationProvider>((IDocumentationProvider) null);
      this.SetMultiple<IFilterProvider>((IFilterProvider) new ConfigurationFilterProvider(), (IFilterProvider) new ActionDescriptorFilterProvider());
      this.SetSingle<IHostBufferPolicySelector>((IHostBufferPolicySelector) null);
      this.SetSingle<IHttpActionInvoker>((IHttpActionInvoker) new ApiControllerActionInvoker());
      this.SetSingle<IHttpActionSelector>((IHttpActionSelector) new ApiControllerActionSelector());
      this.SetSingle<IHttpControllerActivator>((IHttpControllerActivator) new DefaultHttpControllerActivator());
      this.SetSingle<IHttpControllerSelector>((IHttpControllerSelector) new DefaultHttpControllerSelector(configuration));
      this.SetSingle<IHttpControllerTypeResolver>((IHttpControllerTypeResolver) new DefaultHttpControllerTypeResolver());
      this.SetSingle<ITraceManager>((ITraceManager) new TraceManager());
      this.SetSingle<ITraceWriter>((ITraceWriter) null);
      this.SetMultiple<ModelBinderProvider>((ModelBinderProvider) new TypeConverterModelBinderProvider(), (ModelBinderProvider) new TypeMatchModelBinderProvider(), (ModelBinderProvider) new KeyValuePairModelBinderProvider(), (ModelBinderProvider) new ComplexModelDtoModelBinderProvider(), (ModelBinderProvider) new ArrayModelBinderProvider(), (ModelBinderProvider) new DictionaryModelBinderProvider(), (ModelBinderProvider) new CollectionModelBinderProvider(), (ModelBinderProvider) new MutableObjectModelBinderProvider());
      this.SetSingle<ModelMetadataProvider>((ModelMetadataProvider) new DataAnnotationsModelMetadataProvider());
      this.SetMultiple<ModelValidatorProvider>((ModelValidatorProvider) new DataAnnotationsModelValidatorProvider(), (ModelValidatorProvider) new DataMemberModelValidatorProvider());
      this.SetMultiple<ValueProviderFactory>((ValueProviderFactory) new QueryStringValueProviderFactory(), (ValueProviderFactory) new RouteDataValueProviderFactory());
      this.SetSingle<IModelValidatorCache>((IModelValidatorCache) new ModelValidatorCache(new Lazy<IEnumerable<ModelValidatorProvider>>((Func<IEnumerable<ModelValidatorProvider>>) (() => ServicesExtensions.GetModelValidatorProviders((ServicesContainer) this)))));

      this.SetSingle<IExceptionHandler>((IExceptionHandler) new DefaultExceptionHandler());

      this.SetMultiple<IExceptionLogger>();
      this._serviceTypesSingle = new HashSet<Type>((IEnumerable<Type>) this._defaultServicesSingle.Keys);
      this._serviceTypesMulti = new HashSet<Type>((IEnumerable<Type>) this._defaultServicesMulti.Keys);
      this.ResetCache();
    }



IExceptionHandler 저수준 메커니즘을 직접 구현할 필요는 없습니다.

대신 ExceptionHandler 에서 상속 받고 Handle 메서드를 재정의 할 수 있습니다.

public class MyExceptionHandler : ExceptionHandler
{
  public override void Handle(ExceptionHandlerContext context)
  {
    //TODO: Do what you need to do
    base.Handle(context);
  }
}

ExceptionHandlerIExceptionHandler 구현하고 비동기와 같은 기본 핵심 메커니즘 (예외를 처리해야하는지 여부 등)을 관리합니다.

다음과 같은 예외 처리기를 사용하십시오.

config.Services.Replace(typeof(IExceptionHandler), new MyExceptionHandler());

출처

http://www.asp.net/web-api/overview/web-api-routing-and-actions/web-api-global-error-handling 는 IExceptionHandler를 구현하는 방법을 설명하고 있지만 일부 오타가 있으며 코드가 WebApi의 최신 버전을 반영하지 않습니다.

System.Web.Http.ExceptionHandling 네임 스페이스에 대한 문서는 없습니다 ( NuDoqNuDoq ).

그래서 .. GitHub에서 소스 코드를 살펴본 .NET 어셈블리 디 컴파일러사용하여 IExceptionHandler 구현하고 가상 메서드가있는 ExceptionHandler 클래스를 보았습니다.

ExceptionHandler는 다음과 같습니다.

namespace System.Web.Http.ExceptionHandling
{
    /// <summary>Represents an unhandled exception handler.</summary>
    public abstract class ExceptionHandler : IExceptionHandler
    {
        /// <returns>Returns <see cref="T:System.Threading.Tasks.Task" />.</returns>
        Task IExceptionHandler.HandleAsync(ExceptionHandlerContext context, CancellationToken cancellationToken)
        {
            if (context == null)
            {
                throw new ArgumentNullException("context");
            }
            ExceptionContext arg_14_0 = context.ExceptionContext;
            if (!this.ShouldHandle(context))
            {
                return TaskHelpers.Completed();
            }
            return this.HandleAsync(context, cancellationToken);
        }

        /// <summary>When overridden in a derived class, handles the exception asynchronously.</summary>
        /// <returns>A task representing the asynchronous exception handling operation.</returns>
        /// <param name="context">The exception handler context.</param>
        /// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
        public virtual Task HandleAsync(ExceptionHandlerContext context, CancellationToken cancellationToken)
        {
            this.Handle(context);
            return TaskHelpers.Completed();
        }

        /// <summary>When overridden in a derived class, handles the exception synchronously.</summary>
        /// <param name="context">The exception handler context.</param>
        public virtual void Handle(ExceptionHandlerContext context)
        {
        }

        /// <summary>Determines whether the exception should be handled.</summary>
        /// <returns>true if the exception should be handled; otherwise, false.</returns>
        /// <param name="context">The exception handler context.</param>
        public virtual bool ShouldHandle(ExceptionHandlerContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException("context");
            }
            ExceptionContext exceptionContext = context.ExceptionContext;
            ExceptionContextCatchBlock catchBlock = exceptionContext.CatchBlock;
            return catchBlock.IsTopLevel;
        }
    }
}

ShouldHandleExceptionContextCatchBlock.IsTopLevel 사용하여 구현 HandleAsyncHandle 호출 함을 명확하게 볼 수 있습니다. :)

완전한 문서가 나타날 때까지 이것이 도움이되기를 바랍니다.




귀하의 WebApi 설정에서 라인을 추가해야합니다 :

config.Services.Replace(typeof (IExceptionHandler), new OopsExceptionHandler());

또한 IExceptionHandler를 구현하는 기본 ExceptionHandler 클래스를 작성했는지 확인하십시오.

public class ExceptionHandler : IExceptionHandler
{
    public virtual Task HandleAsync(ExceptionHandlerContext context, 
                                    CancellationToken cancellationToken)
    {
        if (!ShouldHandle(context))
        {
            return Task.FromResult(0);
        }

        return HandleAsyncCore(context, cancellationToken);
    }

    public virtual Task HandleAsyncCore(ExceptionHandlerContext context, 
                                       CancellationToken cancellationToken)
    {
        HandleCore(context);
        return Task.FromResult(0);
    }

    public virtual void HandleCore(ExceptionHandlerContext context)
    {
    }

    public virtual bool ShouldHandle(ExceptionHandlerContext context)
    {
        return context.ExceptionContext.IsOutermostCatchBlock;
    }
} 

이 기능은 다른 곳에서 처리되지 않는 예외 (예 : 예외 필터) 만 처리합니다.








c# asp.net-web-api exception-handling