WebAPi之异常处理(Exception)以及日志记录(NLog)(十六)

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

WebAPi之异常处理(Exception)以及⽇志记录(NLog)(⼗六)
前⾔
上⼀篇⽂章我们介绍了关于⽇志记录⽤的是Log4net,确实也很挺强⼤,但是别忘了我们.NET有专属于我们的⽇志框架,那就是NLog,相对于Log4net⽽⾔,NLog可以说也是⼀个很好的记录⽇志的框架,并且其中的异步⽇志等都有⾮常⼤的改善,本⽂借此⽤了最新的NLog来在Web APi中进⾏记录⽇志。

NLog
第⼀步则是下载我们需要的程序包,包括程序集以及配置⽂件
利⽤NLog记录⽇志同样可以实现如我们上篇⽂章利⽤Log4net来实现的那样,所以在这⾥就不多说,下⾯我们来讲另外⼀种⽅式,那就是利⽤.NET内置的跟踪级别类来进⾏记录⽇志。

从⽽达到我们所需。

在NLog.config配置⽂件中,我们添加如下进⾏⽇志的记录【注意:只是简单的利⽤了NLog,它还是⽐较强⼤,更多的详细内容请到官⽹或通过其他途径进⾏学习】
<targets>
<target name="logfile" xsi:type="File" fileName="${basedir}/WebAPiNLog/${date:format=yyyyMMdd}.log" /> //在根⽬录下的WebAPiNlog⽂件下⽣成⽇志
</targets>
<rules>
<logger name="*" minlevel="Trace" writeTo="logfile" />
</rules>
第⼆步
既然是利⽤.NET内置的跟踪级别类来实现,那么我们就需要实现其接⼝ ITraceWriter ,该接⼝需要实现如下⽅法
// 摘要:
// 当且仅当在给定 category 和 level 允许跟踪时,调⽤指定的 traceAction 以允许在新的 System.Web.Http.Tracing.TraceRecord
// 中设置值。

//
// 参数:
// request:
// 当前 .Http.HttpRequestMessage。

它可以为 null,但这样做将阻⽌后续跟踪分析将跟踪与特定请求关联。

//
// category:
// 跟踪的逻辑类别。

⽤户可以定义⾃⼰的跟踪。

//
// level:
// 写⼊此跟踪时所在的 System.Web.Http.Tracing.TraceLevel。

//
// traceAction:
// 启⽤了跟踪时要调⽤的操作。

在此操作中,调⽤⽅应填充给定 System.Web.Http.Tracing.TraceRecord 的各个字段。

void Trace(HttpRequestMessage request, string category, TraceLevel level, Action<TraceRecord> traceAction);
【注意】利⽤内置的跟踪级别则需要引⽤如下命名空间
using System.Web.Http.Tracing;
⾸先创建⼀个NLogger类并实现如上接⼝,当然我们也得创建NLog实例并利⽤其实例进⾏级别处理,如下:
private static readonly Logger NlogLogger = LogManager.GetCurrentClassLogger();
接着我们该如何做呢?我们需要利⽤ TraceLevel 跟踪级别,同时结合NLog得到相应的级别信息,可能创建对象实例的过程⽐较长,我们可以利⽤Lazy<>来实现延迟加载,代码如下:
private static readonly Lazy<Dictionary<TraceLevel, Action<string>>> LoggingMap = new Lazy<Dictionary<TraceLevel, Action<string>>>
(() => new Dictionary<TraceLevel, Action<string>>
{{ , },
{ TraceLevel.Debug, NlogLogger.Debug },
{ TraceLevel.Error, NlogLogger.Error },
{ TraceLevel.Fatal, NlogLogger.Fatal },
{ TraceLevel.Warn, NlogLogger.Warn }
});
然后,我们定义⼀个属性来返回其实例的值,如下
private Dictionary<TraceLevel, Action<string>> Logger
{
get { return LoggingMap.Value; }
}
紧接着我们就是实现上述ITraceWriter接⼝
public void Trace(.Http.HttpRequestMessage request, string category, TraceLevel level, Action<TraceRecord> traceAction)
{
if (level != TraceLevel.Off) //如果没⽤禁⽤⽇志跟踪
{
if (traceAction != null && traceAction.Target != null)
{
category = category + Environment.NewLine + "Action Parameters : " + JsonConvert.SerializeObject(traceAction.Target);
}
var record = new TraceRecord(request, category, level);
if (traceAction != null) traceAction(record);
Log(record);
}
}
我们记录请求的参数,URL,以及Token、返回的JSON等等,上述Log⽅法则如下
private void Log(TraceRecord record)
{
var message = new StringBuilder();
if (!string.IsNullOrWhiteSpace(record.Message))
message.Append("").Append(record.Message + Environment.NewLine);
if (record.Request != null)
{
if (record.Request.Method != null)
message.Append("Method: " + record.Request.Method + Environment.NewLine);
if (record.Request.RequestUri != null)
message.Append("").Append("URL: " + record.Request.RequestUri + Environment.NewLine);
if (record.Request.Headers != null && record.Request.Headers.Contains("Token") && record.Request.Headers.GetValues("Token") != null && record.Request.Headers.GetValues("Token").FirstOrDefault() != null) message.Append("").Append("Token: " + record.Request.Headers.GetValues("Token").FirstOrDefault() + Environment.NewLine);
}
if (!string.IsNullOrWhiteSpace(record.Category))
message.Append("").Append(record.Category);
if (!string.IsNullOrWhiteSpace(record.Operator))
message.Append("").Append(record.Operator).Append("").Append(record.Operation);
}
第三步
我们⾃定义⽇志特性取名为 NLogFilterAttribute ,我们在访问Action时来进⾏记载⽇志也就是需要继承于 ActionFilterAttribute ,简单来说代码如下:
public class NLogFilterAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(HttpActionContext filterContext)
{......}
}
那么问题来了,.NET默认确确实实是⾛得内置的跟踪级别,我们如何让其实现我们上述实现的接⼝的级别呢?
此时我们之前所学就派上了⼀点⽤场,我们将其服务容器的关于ITraceWriter接⼝实现进⾏替换我们⾃定义实现的接⼝即可,⽤如下⼀句即可
GlobalConfiguration.Configuration.Services.Replace(typeof(ITraceWriter), new NLogHelper());
接下来就是从服务容器中获取我们⾃定义实现的跟踪级别
var trace = GlobalConfiguration.Configuration.Services.GetTraceWriter();
然后调⽤⽐如说隔离级别中的Info,获取其访问的控制器名、Action名称以及JSON等数据,如下:
(filterContext.Request,
"Controller : " + filterContext.ControllerContext.ControllerDescriptor.ControllerType.FullName + Environment.NewLine +
"Action : " + filterContext.ActionDescriptor.ActionName,
"JSON", filterContext.ActionArguments);
我们简单个给出所请求的控制器以及需要返回的数据,如下:
public class AboutController : ApiController
{
[POST("about")]
public string about()
{
var test = new
{
name = "xpy0928",
gender = "男",
age = 12
};
return Newtonsoft.Json.JsonConvert.SerializeObject(test);
}
}
接下来我们利⽤WebAPiTestOnHelpPage进⾏测试,看结果是否如我们所期望
结果如我们所期待的那样
但是我们的重点是是否⽣成了相应的⽇志,我们⼀起来看下:
到此,关于利⽤.NET内置的跟踪级别结合NLog来实现⽇志的记录也就告⼀段落,接下来我们来看看异常处理
Exception
既然异常处理,那么我们当然就得利⽤⾃定义异常特性实现 ExceptionFilterAttribute ,其基本实现如下:
public class CustomExceptionAttribute:ExceptionFilterAttribute
{
public override void OnException(HttpActionExecutedContext actionExecutedContext)
{....}
}
关于其实现和上⾯⼤同⼩异,如下
GlobalConfiguration.Configuration.Services.Replace(typeof(ITraceWriter), new NLogHelper());
var trace = GlobalConfiguration.Configuration.Services.GetTraceWriter();
trace.Error(actionExecutedContext.Request, "Controller : " + actionExecutedContext.ActionContext.ControllerContext.ControllerDescriptor.ControllerType.FullName + Environment.NewLine + "Action : " + actionExecutedContext.ActionCo var exceptionType = actionExecutedContext.Exception.GetType();
if (exceptionType == typeof(ValidationException))
{
var resp = new HttpResponseMessage(HttpStatusCode.BadRequest) { Content = new StringContent(actionExecutedContext.Exception.Message), ReasonPhrase = "ValidationException", };
throw new HttpResponseException(resp);
}
else if (exceptionType == typeof(UnauthorizedAccessException))
{
throw new HttpResponseException(actionExecutedContext.Request.CreateResponse(HttpStatusCode.Unauthorized));
}
else
{
throw new HttpResponseException(actionExecutedContext.Request.CreateResponse(HttpStatusCode.InternalServerError));
}
此时我们还需要在⽇志NLogger类中添加如下⼀句
//处理异常
if (record.Exception != null && !string.IsNullOrWhiteSpace(record.Exception.GetBaseException().Message))
{
var exceptionType = record.Exception.GetType();
message.Append(Environment.NewLine);
message.Append("").Append("Error: " + record.Exception.GetBaseException().Message + Environment.NewLine);
}
如此就基本实现了利⽤NLog记录异常,当然我们可以⾃定义个异常类来更好的管理异常例如,如下:
public class ApiExceptions:Exception
{
int ErrorCode { get; set; }
string ErrorDescription { get; set; }
HttpStatusCode HttpStatus { get; set; }
}
总结
本节我们学习了利⽤NLog来实现记录异常通过集合内置的跟踪级别。

NLog是属于.NET所以就单独拿来讲讲,其强⼤也是不可⾔喻的。

相关文档
最新文档