在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(); }
您可以查看Web API团队的以下示例:
http://aspnet.codeplex.com/SourceControl/latest#Samples/WebApi/Elmah/ReadMe.txt
- 无法反序列化当前的JSON对象,为什么?
- Ninject Web Api“确保控制器具有无参数的公共构造函数。”
- ASP Web Api – IoC – 解析HttpRequestMessage
- 将JSON HttpContent发布到ASP.NET Web API
- 在WebApi或MVC控制器中使用ConfigureAwait(false)有任何危险吗?
- 我必须向我的Web API REST方法添加显式线程吗?
- 使用AttributeRouting在WebAPI中指定默认控制器/操作路由
- Azure移动服务错误:在程序集中找到多个具有名称的静态类作为引导程序
- 在WebAPI中使用ContinueWith进行死锁