都市良人行好看吗,2015yy娱乐年度盛典,异界练级专家
在业务系统,异常处理是所有开发人员必须面对的问题,在一定程度上,异常处理的能力反映出开发者对业务的驾驭水平;本章将着重介绍如何在 webapi 程序中对异常进行捕获,然后利用 nlog 组件进行记录;同时,还将介绍两种不同的
异常捕获方式:管道捕获/服务过滤;通过本练习,将学习到如何捕获异常、处理异常跳转、记录异常信息。
首先,创建一个 webapi 项目,选择 asp.net core web 应用程序;
[httpget] public actionresult<ienumerable<string>> get() { throw new exception("出错了....."); return new string[] { "value1", "value2" }; }
在传统的 asp.net mvc 应用程序中,我们一般都使用服务过滤的方式去捕获和处理异常,这种方式非常常见,而且可用性来说,体验也不错,幸运的是 asp.net core 也完整的支持该方式,接下来创建一个全局异常处理类 customerexceptionfilter
public class customerexceptionfilter : attribute, iexceptionfilter { private readonly ilogger logger = null; private readonly ihostingenvironment environment = null; public customerexceptionfilter(ilogger<customerexceptionfilter> logger, ihostingenvironment environment) { this.logger = logger; this.environment = environment; } public void onexception(exceptioncontext context) { exception exception = context.exception; string error = string.empty; void readexception(exception ex) { error += string.format("{0} | {1} | {2}", ex.message, ex.stacktrace, ex.innerexception); if (ex.innerexception != null) { readexception(ex.innerexception); } } readexception(context.exception); logger.logerror(error); contentresult result = new contentresult { statuscode = 500, contenttype = "text/json;charset=utf-8;" }; if (environment.isdevelopment()) { var json = new { message = exception.message, detail = error }; result.content = jsonconvert.serializeobject(json); } else { result.content = "抱歉,出错了"; } context.result = result; context.exceptionhandled = true; } }
private readonly ilogger logger = null; private readonly ihostingenvironment environment = null; public customerexceptionfilter(ilogger<customerexceptionfilter> logger, ihostingenvironment environment) { this.logger = logger; this.environment = environment; }
public void configure(iapplicationbuilder app, ihostingenvironment env, iloggerfactory factory) { // 将 nlog factory.addconsole(configuration.getsection("logging")) .addnlog() .adddebug(); var nlogfile = system.io.path.combine(env.contentrootpath, "nlog.config"); env.configurenlog(nlogfile); if (env.isdevelopment()) { app.usedeveloperexceptionpage(); } app.usemvc(); }
<?xml version="1.0" encoding="utf-8" ?> <nlog xmlns="http://www.nlog-project.org/schemas/nlog.xsd" xmlns:xsi="http://www.w3.org/2001/xmlschema-instance" autoreload="true" internalloglevel="info"> <!-- load the asp.net core plugin --> <extensions> <add assembly="nlog.web.aspnetcore"/> </extensions> <!-- layout: https://github.com/nlog/nlog/wiki/layout%20renderers --> <targets> <target xsi:type="file" name="errorfile" filename="/data/logs/logfilter/error-${shortdate}.log" layout="${longdate}|${logger}|${uppercase:${level}}| ${message} ${exception}|${aspnet-request-url}" /> <target xsi:type="null" name="blackhole" /> </targets> <rules> <logger name="microsoft.*" minlevel="error" writeto="blackhole" final="true" /> <logger name="*" minlevel="error" writeto="errorfile" /> </rules> </nlog>
// this method gets called by the runtime. use this method to add services to the container. public void configureservices(iservicecollection services) { // 将异常过滤器注入到容器中 services.addscoped<customerexceptionfilter>(); services.addmvc() .setcompatibilityversion(compatibilityversion.version_2_1); }
[servicefilter(typeof(customerexceptionfilter))] [route("api/[controller]"), apicontroller] public class valuescontroller : controllerbase { // get api/values [httpget] public actionresult<ienumerable<string>> get() { throw new exception("出错了....."); return new string[] { "value1", "value2" }; } }
接下来利用 .netcore 的管道模式,在中间件中对异常进行捕获,首先,创建一个中间件
public class exceptionmiddleware { private readonly requestdelegate next; private readonly ilogger logger; private ihostingenvironment environment; public exceptionmiddleware(requestdelegate next, ilogger<exceptionmiddleware> logger, ihostingenvironment environment) { this.next = next; this.logger = logger; this.environment = environment; } public async task invoke(httpcontext context) { try { await next.invoke(context); var features = context.features; } catch (exception e) { await handleexception(context, e); } } private async task handleexception(httpcontext context, exception e) { context.response.statuscode = 500; context.response.contenttype = "text/json;charset=utf-8;"; string error = ""; void readexception(exception ex) { error += string.format("{0} | {1} | {2}", ex.message, ex.stacktrace, ex.innerexception); if (ex.innerexception != null) { readexception(ex.innerexception); } } readexception(e); if (environment.isdevelopment()) { var json = new { message = e.message, detail = error }; error = jsonconvert.serializeobject(json); } else error = "抱歉,出错了"; await context.response.writeasync(error); } }
// this method gets called by the runtime. use this method to configure the http request pipeline. public void configure(iapplicationbuilder app, ihostingenvironment env, iloggerfactory factory) { // 将 nlog factory.addconsole(configuration.getsection("logging")) .addnlog() .adddebug(); var nlogfile = system.io.path.combine(env.contentrootpath, "nlog.config"); env.configurenlog(nlogfile); // exceptionmiddleware 加入管道 app.usemiddleware<exceptionmiddleware>(); //if (env.isdevelopment()) //{ // app.usedeveloperexceptionpage(); //} app.usemvc(); }
在本例中,通过依赖注入和管道中间件的方式,演示了两种不同的全局捕获异常处理的过程;值得注意到是,两种方式对于 nlog 的使用,都是一样的,没有任何差别,代码无需改动;实际项目中,也是应当区分不同的业务场景,输出不同的
日志信息,不管是从安全或者是用户体验友好性上面来说,都是非常值得推荐的方式,全局异常捕获处理,完全和业务剥离。
如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复
Net Core Web Api项目与在NginX下发布的方法
asp.net core3.1 引用的元包dll版本兼容性问题解决方案
IdentityServer4实现.Net Core API接口权限认证(快速入门)
ASP.NET Core MVC通过IViewLocationExpander扩展视图搜索路径的实现
网友评论