在ASP.NET Web Api中使用“ExceptionHandler”需要一个完整的示例来处理未处理的exception?

我查看了这个链接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 support@contoso.com so we can try to fix it." }; } private class TextPlainErrorResult : IHttpActionResult { public HttpRequestMessage Request { get; set; } public string Content { get; set; } public Task ExecuteAsync(CancellationToken cancellationToken) { HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.InternalServerError); response.Content = new StringContent(Content); response.RequestMessage = Request; return Task.FromResult(response); } } } 

我不知道如何在我的Web API操作中调用此类。 所以任何人都可以使用这个ExceptionHandler给我完整的样本。

在您的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.CatchBlock.IsTopLevel; } } 

请注意,这只会处理其他地方未处理的exception(例如,通过exceptionfilter)。

您不需要自己实现IExceptionHandler低级机制。

相反,您可以简单地从ExceptionHandlerinheritance并覆盖Handle方法。

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

ExceptionHandler实现IExceptionHandler并管理基本核心机制(如异步和应该处理的exception)。

像这样使用你的exception处理程序:

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

资源

这个页面解释了如何实现IExceptionHandler,但是有一些拼写错误,代码没有反映最新版本的WebApi。

没有关于System.Web.Http.ExceptionHandling命名空间的文档(在NuDoq上有点 )。

所以.. 使用.NET程序集反编译器查看GitHub上的源代码 ,我看到ExceptionHandler类实现了IExceptionHandler并有一些虚方法。

ExceptionHandler看起来像这样:

 namespace System.Web.Http.ExceptionHandling { /// Represents an unhandled exception handler. public abstract class ExceptionHandler : IExceptionHandler { /// 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); } /// When overridden in a derived class, handles the exception asynchronously. /// A task representing the asynchronous exception handling operation. /// The exception handler context. /// The token to monitor for cancellation requests. public virtual Task HandleAsync(ExceptionHandlerContext context, CancellationToken cancellationToken) { this.Handle(context); return TaskHelpers.Completed(); } /// When overridden in a derived class, handles the exception synchronously. /// The exception handler context. public virtual void Handle(ExceptionHandlerContext context) { } /// Determines whether the exception should be handled. /// true if the exception should be handled; otherwise, false. /// The exception handler context. public virtual bool ShouldHandle(ExceptionHandlerContext context) { if (context == null) { throw new ArgumentNullException("context"); } ExceptionContext exceptionContext = context.ExceptionContext; ExceptionContextCatchBlock catchBlock = exceptionContext.CatchBlock; return catchBlock.IsTopLevel; } } } 

您可以清楚地看到,使用ExceptionContextCatchBlock.IsTopLevel实现了HandleAsync ,并且HandleAsync调用了Handle 🙂

我希望这会有所帮助,直到出现完整的文档。

根据Jon Susiak的回答,您需要使用:

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

请注意Replace呼叫,而不是Add 。 原因在于此链接中的文章:

ASP.NET Web API 2中的全局error handling

方案概述

我们提供了两个新的用户可替换服务IExceptionLogger和IExceptionHandler来记录和处理未处理的exception。

服务非常相似,有两个主要区别:

我们支持注册多个exception记录器,但只支持一个exception处理程序

并且由于默认情况下已经注册了处理程序,因此无法添加其他处理程序。

 public DefaultServices(HttpConfiguration configuration) { if (configuration == null) throw System.Web.Http.Error.ArgumentNull("configuration"); this._configuration = configuration; this.SetSingle((IActionValueBinder) new DefaultActionValueBinder()); this.SetSingle((IApiExplorer) new ApiExplorer(configuration)); this.SetSingle((IAssembliesResolver) new DefaultAssembliesResolver()); this.SetSingle((IBodyModelValidator) new DefaultBodyModelValidator()); this.SetSingle((IContentNegotiator) new DefaultContentNegotiator()); this.SetSingle((IDocumentationProvider) null); this.SetMultiple((IFilterProvider) new ConfigurationFilterProvider(), (IFilterProvider) new ActionDescriptorFilterProvider()); this.SetSingle((IHostBufferPolicySelector) null); this.SetSingle((IHttpActionInvoker) new ApiControllerActionInvoker()); this.SetSingle((IHttpActionSelector) new ApiControllerActionSelector()); this.SetSingle((IHttpControllerActivator) new DefaultHttpControllerActivator()); this.SetSingle((IHttpControllerSelector) new DefaultHttpControllerSelector(configuration)); this.SetSingle((IHttpControllerTypeResolver) new DefaultHttpControllerTypeResolver()); this.SetSingle((ITraceManager) new TraceManager()); this.SetSingle((ITraceWriter) null); this.SetMultiple((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) new DataAnnotationsModelMetadataProvider()); this.SetMultiple((ModelValidatorProvider) new DataAnnotationsModelValidatorProvider(), (ModelValidatorProvider) new DataMemberModelValidatorProvider()); this.SetMultiple((ValueProviderFactory) new QueryStringValueProviderFactory(), (ValueProviderFactory) new RouteDataValueProviderFactory()); this.SetSingle((IModelValidatorCache) new ModelValidatorCache(new Lazy>((Func>) (() => ServicesExtensions.GetModelValidatorProviders((ServicesContainer) this))))); this.SetSingle((IExceptionHandler) new DefaultExceptionHandler()); this.SetMultiple(); this._serviceTypesSingle = new HashSet((IEnumerable) this._defaultServicesSingle.Keys); this._serviceTypesMulti = new HashSet((IEnumerable) this._defaultServicesMulti.Keys); this.ResetCache(); }