Global Error Handling in ASP.NET Web API 2(webapi2 中的全局异常处理)
目前,在Web API中没有简单的方法来记录或处理全局异常(webapi1中)。一些未处理的异常可以通过exception filters进行处理,但是有许多情况exception filters无法处理。例如:
1.从控制器构造函数中抛出的异常。
2.从message handlers中抛出的异常。
3.路由过程中抛出的异常。
4.响应内容序列化过程中引发的异常。
我们希望提供一种简单、一致的方法来记录和处理这些异常(如果可能的话)。
处理异常主要有两种情况,一种是我们可以发送错误响应,另一种是我们只能记录异常。
后一种情况的一个例子是在流式响应内容中间抛出异常时;在这种情况下,发送新的响应消息太晚了,因为状态代码、头部和部分内容已经边界,所以我们只能简单地中止连接。即使无法处理异常以产生新的响应消息,我们应该仍然支持记录异常。在我们能够检测到错误的情况下,我们可以返回一个适当的错误响应,如下所示:
public IHttpActionResult GetProduct(int id)
{
var product = products.FirstOrDefault((p) => p.Id == id);
if (product == null) { return NotFound(); } return Ok(product);
}
现有选项
除了现有的exception filters之外,message handlers现在还可以用来观察所有500-level responses,但是对这些响应采取行动是困难的,因为它们缺乏关于原始错误的上下文。message handlers对于它们能够处理的情况也有一些与exception filters相同的限制。虽然Web API确实具有捕获错误条件的跟踪基础结构,但是跟踪基础结构用于诊断目的,并且不是为生产环境设计也不适合在生产环境中运行。全局exception handling and logging应该才是可以在生产期间运行并插入现有监视解决方案(例如,ELMAH)的服务。
新的解决方案概述(webapi2)
我们提供两个新的用户可替换的服务,即 IExceptionLogger and IExceptionHandler,用来记录和处理未处理的异常。这两个服务非常相似,有两个主要区别:
1、我们支持注册多个exception loggers,但只支持一个exception handler。
2、Exception loggers总是被调用,即使我们即将中止连接。只有当我们仍然能够选择要发送的响应消息时,才会调用exception handler。
两个服务都提供对异常上下文的访问,该异常上下文包含从检测到异常的点开始的相关信息,特别是HttpRequestMessage、HttpRequestContext、抛出的异常和异常源(以下详细信息)。
一、使用原则
因为在小版本中添加了该功能,所以没有破坏性的改变,影响解决方案的一个重要约束是,没有任何破坏性的改变,无论是合同类型还是行为方式。这个约束排除了我们希望针对将异常转换为500个响应的现有捕获块进行的一些清理。这个额外的清理是我们可以考虑的后续重大释放。如果这对你很重要,请在ASP.NET Web API用户语音上投票。
保持与Web API构造的一致性是Web API的过滤器流水线处理横切关注点的好方法,该关注点具有在操作特定的、控制器特定的或全局范围内应用逻辑的灵活性。
包括exception filters在内的筛选器总是具有action和controller上下文,甚至在全局范围内注册时也是如此。该契约对于过滤器(filters)是有意义的,但是它意味着exception filters,甚至是全局范围的exception filters,对于某些异常处理情况(如message handlers中的异常,其中不存在action或controller上下文)并不适合。
如果我们想使用过滤器(filters)提供的灵活范围来进行异常处理,我们仍然需要exception filters。但是,如果我们需要在controller context之外处理异常,那么我们还需要一个单独的结构用于完全的全局异常处理(一些没有控controller context和action context约束的构造)。
二、使用场景
1、Exception loggers
是解决Web API捕获的所有未处理异常的解决方案。
2、Exception handlers
是为Web API捕获的未处理异常定制所有可能的响应的解决方案。
3、Exception filters
是处理与特定action或controller相关的子集未处理异常的最简单的解决方案。
三、使用详情
ExceptionLogger和ExceptionHandler接口是采用各自Context的简单异步方法:
public interface IExceptionLogger
{
Task LogAsync(ExceptionLoggerContext context,
CancellationToken cancellationToken);
}
public interface IExceptionHandler
{
Task HandleAsync(ExceptionHandlerContext context,
CancellationToken cancellationToken);
}
我们还为这两个接口提供基类。Overriding(重写)核心(sync or async)方法是在建议的时间内记录或处理所需的全部。对于日志记录,ExceptionLogger基类将确保每个异常只调用一次核心logging方法(即使稍后它在调用堆栈上进一步传播并再次被捕获)。ExceptionHandler基类将只针对调用堆栈顶部的异常调用核心处理方法,忽略遗留嵌套的捕获块。(这些基类的简化版本在下面的附录中。)IExceptionLogger和IExceptionHandler都通过ExceptionContext接收关于异常的信息。
public class ExceptionContext
{
public Exception Exception { get; set; }
public HttpRequestMessage Request { get; set; }
public HttpRequestContext RequestContext { get; set; }
public HttpControllerContext ControllerContext { get; set; }
public HttpActionContext ActionContext { get; set; }
public HttpResponseMessage Response { get; set; }
public string CatchBlock { get; set; }
public bool IsTopLevelCatchBlock { get; set; }
}
。。。。。。。。。。。。。。。。。。。。。。。。。未完。。。。。。。。。。。。。。。。。。。。。。
For both exception loggers and exception handlers, we don't do anything to recover if the logger or handler itself throws an exception. (Other than letting the exception propagate, leave feedback at the bottom of this page if you have a better approach.) The contract for exception loggers and handlers is that they should not let exceptions propagate up to their callers; otherwise, the exception will just propagate, often all the way to the host resulting in an HTML error (like the ASP.NET's yellow screen) being sent back to the client (which usually isn't the preferred option for API callers that expect JSON or XML).
对于exception loggers和exception handlers,如果logger或handler本身抛出异常,则不执行任何恢复操作(除了让这个exception传递之外)
exception loggers和handlers的约定:它们不应该让异常传递到调用者;否则,异常将只是传递,通常服务器出现错误后一个HTML的错误(如ASP.NET的黄色屏幕)会被发送回客户端(这对于希望使用JSON或XML的API调用者通常不应该这样做)。
使-用-实-例
(也可以参考GIT上作者为Tiago Santos的代码示例:https://github.com/taigosantos/AspNet-WebApi)
一、Tracing Exception Logger
下面的异常记录器将异常数据发送到配置的跟踪源(包括VisualStudio中的调试输出窗口)。
class TraceExceptionLogger : ExceptionLogger
{
public override void Log(ExceptionLoggerContext context)
{
Trace.TraceError(context.ExceptionContext.Exception.ToString());
}
}
二、Custom Error Message Exception Handler
下面的内容对客户端产生自定义错误响应,包括用于联系支持的电子邮件地址。
class OopsExceptionHandler : ExceptionHandler
{
public override void Handle(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<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
{
HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.InternalServerError);
response.Content = new StringContent(Content);
response.RequestMessage = Request;
return Task.FromResult(response);
}
}
}
Registering Exception Filters
如果使用“ASP.NET MVC 4 Web应用程序”项目模板创建项目,请将Web API配置代码放在WebApiConfig类中,位于App/_Start文件夹中:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.Filters.Add(new ProductStore.NotImplExceptionFilterAttribute());
// Other configuration code...
}
}
附录:以下为基类的实现细节
public class ExceptionLogger : IExceptionLogger
{
public virtual Task LogAsync(ExceptionLoggerContext context,
CancellationToken cancellationToken)
{
if (!ShouldLog(context))
{
return Task.FromResult(0);
}
return LogAsyncCore(context, cancellationToken);
}
public virtual Task LogAsyncCore(ExceptionLoggerContext context,
CancellationToken cancellationToken)
{
LogCore(context);
return Task.FromResult(0);
}
public virtual void LogCore(ExceptionLoggerContext context)
{
}
public virtual bool ShouldLog(ExceptionLoggerContext context)
{
IDictionary exceptionData = context.ExceptionContext.Exception.Data;
if (!exceptionData.Contains("MS_LoggedBy"))
{
exceptionData.Add("MS_LoggedBy", new List<object>());
}
ICollection<object> loggedBy = ((ICollection<object>)exceptionData[LoggedByKey]);
if (!loggedBy.Contains(this))
{
loggedBy.Add(this);
return true;
}
else
{
return false;
}
}
}
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;
}
}
具体请参考:https://docs.microsoft.com/en-us/aspnet/web-api/overview/error-handling/web-api-global-error-handling
Global Error Handling in ASP.NET Web API 2(webapi2 中的全局异常处理)的更多相关文章
- Exception Handling in ASP.NET Web API webapi异常处理
原文:http://www.asp.net/web-api/overview/error-handling/exception-handling This article describes erro ...
- Exception Handling in ASP.NET Web API
public static void RegisterGlobalFilters(GlobalFilterCollection filters) { filters.Add(new HandleErr ...
- ASP.NET Web API Basic Identity 中的基本身份验证
缺点 用户凭证在请求中发送. 凭据作为明文发送. 每个请求都会发送凭据. 无法注销,除非结束浏览器会话. 易于跨站点请求伪造(CSRF); 需要反CSRF措施. 优点 互联网标准. 受所有主要浏览器支 ...
- ASP.NET Web API 异常日志记录
如果在 ASP.NET MVC 应用程序中记录异常信息,我们只需要在 Global.asax 的 Application_Error 中添加代码就可以了,比如: public class MvcApp ...
- ASP.NET Web API 2中的错误处理
前几天在webapi项目中遇到一个问题:Controller构造函数中抛出异常时全局过滤器捕获不到,于是网搜一把写下这篇博客作为总结. HttpResponseException 通常在WebAPI的 ...
- [翻译]ASP.NET Web API 2 中的全局错误处理
目录 已存在的选项 解决方案预览 设计原则 什么时候去用 方案详情 示例 附录: 基类详情 原文链接 Global Error Handling in ASP.NET Web API 2 由于翻译水平 ...
- ASP.NET Web API之消息[拦截]处理
标题相当难取,内容也许和您想的不一样,而且网上已经有很多这方面的资料了,我不过是在实践过程中作下记录.废话少说,直接开始. Exception 当服务端抛出未处理异常时,most exceptions ...
- 【ASP.NET Web API教程】4.3 ASP.NET Web API中的异常处理
原文:[ASP.NET Web API教程]4.3 ASP.NET Web API中的异常处理 注:本文是[ASP.NET Web API系列教程]的一部分,如果您是第一次看本系列教程,请先看前面的内 ...
- ASP.NET Web API之消息[拦截]处理(转)
出处:http://www.cnblogs.com/Leo_wl/p/3238719.html 标题相当难取,内容也许和您想的不一样,而且网上已经有很多这方面的资料了,我不过是在实践过程中作下记录.废 ...
随机推荐
- EOF多行写入文件防止变量替换
问题描述 对多个变量及多行输出到文件,存在变量自动替换,当使用cat<<EOF不想对内容进行变量替换.命令替换.参数展开等 问题解决 转义特殊字符如 $ `等 一.对 $·\ 进行转义 c ...
- 查看最新的Google地址
nslookup www.google.com 8.8.8.8
- DropDMG for Mac(dmg 文件打包工具)破解版安装
1.软件简介 DropDMG 是 macOS 系统上的一款帮助用户快速打包 DMG 文件的 Mac 文件管理软件,DropDMG 不但可以将影像档加密.更可以配合 GZip .BZip2 .Ma ...
- 如果你喜欢python,那你迟早会喜欢上julia的!
你可曾想过有那么一门语言: 这门语言能够有C语言一样的速度,Ruby一样得活力(dynamism).像homoiconic一样的语言,它像Lisp一样有宏,但是也像Matlab一样有显而易见.熟悉的数 ...
- vue 更新了vue-cli到最新版本后引发的问题: require和import、vue-loader的问题
"vue-loader": "^12.1.0", "vue-loader": "^12.1.0", "vue- ...
- 【R作图】lattice包,画多个分布柱形图,hist图纵轴转换为百分比
一开始用lattice包,感觉在多元数据的可视化方面,确实做得非常好.各种函数,可以实现任何想要实现的展示. barchart(y ~ x) y对x的直方图 bwplot(y ~ x) 盒形图 den ...
- [转]protoc-gen-lua 编译、安装、使用教程
版权声明:本文转自http://blog.csdn.net/huutu 转载请带上 http://www.liveslives.com/ https://blog.csdn.net/cp7906216 ...
- 基于Python, Selenium, Phantomjs无头浏览器访问页面
引言: 在自动化测试以及爬虫领域,无头浏览器的应用场景非常广泛,本文将梳理其中的若干概念和思路,并基于代码示例其中的若干使用技巧. 1. 无头浏览器 通常大家在在打开网页的工具就是浏览器,通过界面上输 ...
- WPF之UI虚拟化
在WPF应用程序开发过程中,大数据量的数据展现通常都要考虑性能问题.有下面一种常见的情况:原始数据源数据量很大,但是某一时刻数据容器中的可见元素个数是有限的,剩余大多数元素都处于不可见状态,如果一次性 ...
- SASS常用语法
原文地址:这里 @charset "UTF-8"; /** * 自定义变量 */ $blue: #1875e7; div { color: $blue; } /** * 变量要嵌在 ...