ASP.NET Web API编程——异常捕获
1 向客户端发送错误消息
使用throw new HttpResponseException()向客户端抛出错误信息。
HttpResponseException包含两个重载的构造函数,其中一个是构造函数参数类型为HttpResponseMessage,通过其设置状态码,错误消息短语以及消息体内容来向客户端抛出比较详细的错误信息。另一个参数类型为HttpStatusCode,只能设定状态码。
2自定义异常过滤器
扩展IExceptionFilter来定义异常过滤器。异常过滤器不会捕获类型为HttpResponseException的异常,下面的异常也无法被异常过滤器捕获:
1)controller构造器抛出的异常
2)消息处理器抛出的异常
3)路由过程中抛出的异常
4)响应内容序列化与反序列化过程中抛出的异常
代码示例:
public class CustomExceptionFilterAttribute : ExceptionFilterAttribute
{
public override void OnException(HttpActionExecutedContext context)
{
if (context.Exception!=null)
{
LogHelper.LogError(context.Exception);
}
}
}
3 扩展ExceptionHandler和ExceptionLogger
扩展ExceptionHandler可以捕获大部分异常,包括一些无法被异常过滤器捕获的异常。但是HttpResponseException类型的异常不会被捕获。
示例代码:
/// <summary>
/// 自定义的异常处理程序
/// </summary>
public class GlobalExceptionHandler : ExceptionHandler
{
/// <summary>
/// 处理异常
/// </summary>
/// <param name="context"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public override Task HandleAsync(ExceptionHandlerContext context,CancellationToken cancellationToken)
{
if (!ShouldHandle(context))
{
return Task.FromResult();
}
context.Result = new ErrorResult
{
Request = context.ExceptionContext.Request,
Content = "呀! 有异常,请联系管理员"
};
return Task.FromResult();
}
/// <summary>
/// 判断是否应该处理
/// 后期扩展,重写方法可过滤掉不需处理的异常
/// </summary>
/// <param name="context"></param>
/// <returns></returns>
public override bool ShouldHandle(ExceptionHandlerContext context)
{
return true;
}
private class ErrorResult : 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);
}
}
}
public class GlobalExceptionLogger : ExceptionLogger
{
public override Task LogAsync(ExceptionLoggerContext context,CancellationToken cancellationToken)
{
if (!ShouldLog(context))
{
return Task.FromResult();
}
if (context.Exception != null)
{
string msg = ClientInfoAnalysis.GetClientInfo();
LogHelper.LogError(context.Exception, msg);
}
return Task.FromResult();
}
/// <summary>
/// 判断是否应记录异常
/// 后期重写此方法,可过滤掉不需要记录的异常信息
/// </summary>
/// <param name="context"></param>
/// <returns></returns>
public override bool ShouldLog(ExceptionLoggerContext context)
{
if ((context.Exception is System.Web.HttpException))
{
return false;
}
return true;
}
}
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// 加载log4net配置文件
LogConfigLoading.Load(AppSettings.Log4netPathForWeb); // 加载Web API服务
config.Services.Replace(typeof(IAssembliesResolver), new ServiceAssembliesResolver(AppSettings.ServicesLocation)); // 全局异常信息处理
config.Services.Replace(typeof(IExceptionHandler), new GlobalExceptionHandler()); // 全局异常记录
config.Services.Add(typeof(IExceptionLogger), new GlobalExceptionLogger());
}
}
4某些异常无法被捕获的异常
问题描述
对于在服务加载过程中的异常,无法通过异常过滤器,即实现了System.Web.Http.Filters.IExceptionFilter接口的过滤器来捕获,也不能通过注册ExceptionLogger来达到目的。解决方法如下:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
try
{
config.Services.Replace(typeof(IAssembliesResolver), new ServiceAssembliesResolver(SysSettings.ServicesLocation));
}
catch (Exception ex)
{
LogHelper.Error(ex);
} //其他代码
}
}
其中ServiceAssembliesResolver为:
public class ServiceAssembliesResolver : DefaultAssembliesResolver
{
//服务插件路径
private string path;
public ServiceAssembliesResolver(string path):base()
{
this.path = path;
}
public override ICollection<Assembly> GetAssemblies()
{
//获得已有的服务
ICollection<Assembly> baseAssemblies = base.GetAssemblies();
//初始化
List<Assembly> assemblies = new List<Assembly>(baseAssemblies);
//加载每一个服务插件
foreach (string file in Directory.GetFiles(path, "*.dll"))
{
var controllersAssembly = Assembly.LoadFrom(file);
assemblies.Add(controllersAssembly);
} return assemblies;
}
}
但上述方法很可能不起作用,根本原因在于将config.Services.Replace(typeof(IAssembliesResolver), new ServiceAssembliesResolver(SysSettings.ServicesLocation));放入try-catch块中,若ServiceAssembliesResolver在实例化的时候不抛出异常,而是当调用GetAssemblies时抛出异常(例如服务插件存储文件夹被删除),此时无法记录异常。那么问题就在于GetAssemblies方法何时被调用,通过跟踪代码发现Register中的所有代码都执行完成才会加载服务。解决办法是在ServiceAssembliesResolver.GetAssemblies中捕获异常并记录下来。
ASP.NET Web API编程——异常捕获的更多相关文章
- ASP.NET Web API编程——路由
路由过程大致分为三个阶段: 1)请求URI匹配已存在路由模板 2)选择控制器 3)选择操作 1匹配已存在的路由模板 路由模板 在WebApiConfig.Register方法中定义路由,例如模板默认生 ...
- ASP.NET Web API编程——序列化与内容协商
1 多媒体格式化器 多媒体类型又叫MIME类型,指示了数据的格式.在HTTP协议中多媒体类型描述了消息体的格式.一个多媒体类型包括两个字符串:类型和子类型. 例如: text/html.image/p ...
- ASP.NET Web API编程——构建api帮助文档
1 概要 创建ASP.NET Web Api 时模板自带Help Pages框架. 2 问题 1)使用VS创建Web Api项目时,模板将Help Pages框架自动集成到其中,使得Web Api项目 ...
- ASP.NET Web API编程——文件上传
首先分别介绍正确的做法和错误的做法,然后分析他们的不同和错误之处,以便读者在实现此功能时可避开误区 1正确的做法 public class AvaterController : BaseApiCont ...
- ASP.NET Web API编程——模型验证与绑定
1.模型验证 使用特性约束模型属性 可以使用System.ComponentModel.DataAnnotations提供的特性来限制模型. 例如,Required特性表示字段值不能为空,Range特 ...
- ASP.NET Web API编程——版本控制
版本控制 版本控制的方法有很多,这里提供一种将Odata与普通web api版本控制机制统一的方法,但也可以单独控制,整合控制与单独控制主要的不同是:整合控制通过VersionController ...
- ASP.NET Web API编程——文件下载
断点续传基本原理 HTTP协议中与断点续传相关的HTTP头为:Range和Content-Range标头,断点续传实现流程: 1)客户端请求下载一个文件,文件的总长度为n:已经下载了一部分文件,长度为 ...
- ASP.NET Web API编程——客户端调用
可以使用HttpClient这个调用Web API,下面是HttpClient的定义,列举了一些常用的方法,其中还有一些没有列举,包括重载的方法. public class HttpClient : ...
- Asp.net Web Api添加异常筛选器
一.定义一个异常筛选器 using System;using System.Collections.Generic;using System.Linq;using System.Web;using S ...
随机推荐
- HTML5坦克大战(韩顺平版本)
HTML5坦克大战(韩顺平版本) 2017-3-22 22:46:22 by SemiconductorKING 去年暑假学习了一下HTML5实现简单的坦克大战,觉得对JavaScript初学者来说, ...
- NodeJs接口token认证express框架passport实现方式Bearer认证
1.生成一个简单的express项目(命令:express passport-test),项目结构如下: 2.添加项目依赖: npm install passport --save npm insta ...
- Java - Latch和Barrier的区别
之所以把Latch与Barrier放在一起比较是因为他们给人一种相似的感觉. 他们都是阻塞一些行为直至某个事件发生,但Latch是等待某个事件发生,而Barrier是等待线程. 先比较一下JCIP中对 ...
- Oracle Spatial GIS相关研究
1.Oracle Spatial 概念相关 Oracle Spatial 是Oracle 数据库强大的核心特性,包含了用于存储矢量数据类型.栅格数据类型和持续拓扑数据类型的原生数据类型.Oracle ...
- java通过超链接和servlet配置实现服务器文件下载
1.在页面上面我们可以简单的写成: <td align="center""> <a href="<c:url value="/ ...
- Android加载大图片实例详解
摘要:在Android下采用ARGB表示颜色,每个像素占四个字节.其加载图片申请空间时与图片的实际大小没有关系,与像素有关系.
- Spring 中的scope
scope有Singleton.Prototype.request.session.global session.其中主要的是singleton和prototype. singleton指的是IOC容 ...
- Oracle中实现find_in_set
CREATE OR REPLACE FUNCTION FIND_IN_SET(piv_str1 varchar2, piv_str2 varchar2, p_sep varchar2 := ',') ...
- npm全局安装失效修复
一.windows下 先查看npm包的默认安装目录 npm config get prefix 修改配置 npm config set prefix "nodeJs的安装目录" 二 ...
- C#子窗体闪烁问题解决
在父窗体随意为之添加 protected override CreateParams CreateParams { get { XtraForm xa = _App.Framework.MainFor ...