异常处理 – 如何处理WebAPI中的控制器构造函数中的异常?
|
说我有一个构造函数,它的初始化可能会由于我无法控制的原因而抛出异常. FantasticApiController(IAwesomeGenerator awesome,IBusinessRepository repository,IIceCreamFactory factory)
{
Awesome = awesome;
Repository = repository;
IceCream = factory.MakeIceCream();
DoSomeInitialization(); // this can throw an exception
}
通常,当WebAPI中的Controller操作抛出异常时,我可以通过一个csutom ExceptionFilterAttribute来处理它: public class CustomErrorHandler
{
public override void OnException(HttpActionExecutedContext context)
{
// Critical error,this is real bad.
if (context.Exception is BubonicPlagueException)
{
Log.Error(context.Exception,"CLOSE EVERYTHING!");
Madagascar.ShutdownAllPorts();
}
// No big deal,just show something user friendly
throw new HttpResponseException(new HttpResponseMessage
{
Content = new StringContent("Hey something bad happened. " +
"Not closing the ports though"),StatusCode = HttpStatusCode.InternalServerError;
});
}
所以如果我有一个BoardPlane API方法抛出一个BubonicPlagueException,那么我的CustomerErrorHandler将关闭端口到马达加斯加,并按预期的方式将其记录为一个错误.在其他情况下,当它不是很严重时,我只显示一些用户友好的消息并返回500 InternalServerError. 但是在DoSomeInitialization引发异常的情况下,这绝对没有.如何处理WebAPI控制器构造函数中的异常? 解决方法创建WebApi控制器,因此通过HttpControllerActivators调用构造函数.默认的激活器是System.Web.Http.Dispatcher.DefaultHttpControllerActivator.选项1& 2在github这里https://github.com/markyjones/StackOverflow/tree/master/ControllerExceptionHandling/src 方案1的工作相当不错,涉及使用DI容器(您可能已经使用了一个).我使用Ninject作为我的例子,并使用“Interceptor”Read More拦截并尝试/捕获对DefaultHttpControllerActivator的Create方法的调用.我至少知道AutoFac和Ninject可以做一些类似于以下的事情: 创建拦截器 我不知道你的马达加斯加和日志项目的生命周期是什么,但是他们可以很好地注入到你的拦截器中 public class ControllerCreationInterceptor : Ninject.Extensions.Interception.IInterceptor
{
private ILog _log;
private IMadagascar _madagascar;
public ControllerCreationInterceptor(ILog log,IMadagascar madagascar)
{
_log = log;
_madagascar = madagascar;
}
但是,请记住在你的问题中,Log和Madagascar是一种静态全局的例子 public class ControllerCreationInterceptor : Ninject.Extensions.Interception.IInterceptor
{
public void Intercept(Ninject.Extensions.Interception.IInvocation invocation)
{
try
{
invocation.Proceed();
}
catch(InvalidOperationException e)
{
if (e.InnerException is BubonicPlagueException)
{
Log.Error(e.InnerException,"CLOSE EVERYTHING!");
Madagascar.ShutdownAllPorts();
//DO SOMETHING WITH THE ORIGIONAL ERROR!
}
//DO SOMETHING WITH THE ORIGIONAL ERROR!
}
}
}
最终注册拦截器在全局asax或App_Start(NinjectWebCommon) kernel.Bind<System.Web.Http.Dispatcher.IHttpControllerActivator>()
.To<System.Web.Http.Dispatcher.DefaultHttpControllerActivator>().Intercept().With<ControllerCreationInterceptor>();
选项2是实现自己的Controller Activator实现IHttpControllerActivator接口,并在Create方法中处理创建Controller的错误.您可以使用装饰器图案来包装DefaultHttpControllerActivator: public class YourCustomControllerActivator : IHttpControllerActivator
{
private readonly IHttpControllerActivator _default = new DefaultHttpControllerActivator();
public YourCustomControllerActivator()
{
}
public System.Web.Http.Controllers.IHttpController Create(System.Net.Http.HttpRequestMessage request,System.Web.Http.Controllers.HttpControllerDescriptor controllerDescriptor,Type controllerType)
{
try
{
return _default.Create(request,controllerDescriptor,controllerType);
}
catch (InvalidOperationException e)
{
if (e.InnerException is BubonicPlagueException)
{
Log.Error(e.InnerException,"CLOSE EVERYTHING!");
Madagascar.ShutdownAllPorts();
//DO SOMETHING WITH THE ORIGIONAL ERROR!
}
//DO SOMETHING WITH THE ORIGIONAL ERROR!
return null;
}
}
}
一旦你有自己的定制激活器,默认的激活器可以是全局asax中的switched out: GlobalConfiguration.Configuration.Services.Replace(typeof(IHttpControllerActivator),new YourCustomControllerActivator()); 选项3当然,如果您在构造函数中的初始化不需要访问实际的Controllers方法,属性等,即假设可以从构造函数中删除…那么将初始化变为一个过滤器 public class MadagascarFilter : AbstractActionFilter
{
public override void OnActionExecuting(System.Web.Http.Controllers.HttpActionContext actionContext)
{
try{
DoSomeInitialization(); // this can throw an exception
}
catch(BubonicPlagueException e){
Log.Error(e,"CLOSE EVERYTHING!");
Madagascar.ShutdownAllPorts();
//DO SOMETHING WITH THE ERROR
}
base.OnActionExecuting(actionContext);
}
public override void OnActionExecuted(System.Web.Http.Filters.HttpActionExecutedContext actionExecutedContext)
{
base.OnActionExecuted(actionExecutedContext);
}
public override bool AllowMultiple
{
get { return false; }
}
} (编辑:安卓应用网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- ASP.NET MVC 3 Razor:如何在JavaScript字符串变量中获取Ac
- asp.net-mvc-3 – Url.Action没有给出预期的结果.不需要的路
- asp.net-mvc – Asp.net MVC 3路由区域失败
- asp.net-core – 如何在Visual Studio 2015 RC中为ASP.NET
- ASP.NET对txt文件相关操作(读
- asp.net-mvc – ASP.NET MVC 2中的验证是如何实际工作的?
- asp.net – 当我将’启用32位应用程序’更改为False时,为什
- ASP.NET 高性能分页代码
- asp.net – 如何自动执行功能/集成测试和数据库回滚
- asp.net-mvc-3 – 使用AutoMapper携带元数据查看模型的技术
- asp.net – 如何获取HttpPostedFileBase文件的大
- asp.net-mvc – 安装KB2993928后,ASP.NET MVC4解
- asp.net-mvc – asp.net mvc 3 webgrid排序依然?
- ASP.NET 常用 文件上传方法
- asp.net-mvc – 无法加载文件或程序集’System.W
- asp.net-mvc-3 – 如何在自定义编辑器模板中获取
- asp默认文档不能在IIS7上运行
- 强制ASP.NET GridView的寻呼机显示
- asp.net-mvc – RESTful服务:WCF与ASP.NET MVC
- 在MVC中使用Json.Net序列化和反序列化Json对象
