NLog在Asp.Net MVC的实战应用
Asp.Net MVC FilterAttribute特性、读取xml反序列化、NLog实战系列文章
注:如果你理解了AOP,那么看这篇文章的第三部分可能更轻松点;
如果你理解了单例模式和反射原理, 那么看这篇文章的第二部分的第二小部分可能更轻松点;
首先新建一个MVC project。
一、NLog的配置。
作者:Jarosław Kowalski <jaak@jkowalski.net>
翻译:CrazyCoder
原文:http://www.nlog-project.org/config.html
更多关于NLog的中文文章,请参考《NLog文章系列》。
(1)在当前project中引用NLog相关dll文件。
此时会发现project底下多了两个文件。可以自己新建一个Config文件夹,把这两个文件移进去。
(2)接下来就是根据自己个人需求配置NLog。
$1、到Web.Config添加以下配置。
1 <configuration> 2 <configSections> 3 <section name="nlog" type="NLog.Config.ConfigSectionHandler, NLog" /> 4 </configSections> 5 <nlog> 6 <include file="${basedir}/Config/NLog.config" /><!--包含文件 此处配置为前面引用NLog时添加的NLog.config文件--> 7 </nlog> 8 </configuration>
$2、一个新添加的NLog.config是没有指定"输出目标“和"规则"的,所以我们自己添加targets和rules。
1 <targets> 2 <target name="toLogFile" xsi:type="File" 3 archiveAboveSize="2097152" 4 fileName="d:/LogFiles/NLogTest/${shortdate}.log" 5 archiveFileName="d:/LogFiles/NLogTest/{#}.txt" 6 archiveNumbering="DateAndSequence" 7 archiveEvery="Day" 8 maxArchiveFiles="90" 9 archiveDateFormat="yyyy-MM-dd" 10 layout="TimeStamp:${date} —${machinename} - ${message}" 11 /> 12 <wrapper-target xsi:type="AsyncWrapper" name="asyncFile"> 13 <target-ref name="toLogFile"/> 14 </wrapper-target> 15 </targets> 16 17 <rules> 18 <!-- add your logging rules here --> 19 <logger name="*" minlevel ="Info" writeTo="asyncFile"></logger> 20 </rules>
二、编写异常错误的处理代码。
$1、读取ErrorCode配置文件中数据。
1 namespace NlogTest.Common 2 { 3 [XmlRoot("ErrorConfig")] 4 public class ErrorCodeConfig 5 { 6 [XmlArray("ErrorCodes")] 7 [XmlArrayItem("Error", typeof(ErrorCode))] 8 public List<ErrorCode> ErrorCodes { get; set; } 9 10 public static ErrorCodeConfig Config 11 { 12 get 13 { 14 return XmlHelper.XmlToEntity<ErrorCodeConfig>("ErrorCode"); 15 } 16 } 17 18 public static ErrorCode GetError(string errorCode) 19 { 20 return Config.ErrorCodes.FirstOrDefault(e => e.Code == errorCode); 21 } 22 } 23 24 public class ErrorCode 25 { 26 [XmlAttribute("code")] 27 public string Code { get; set; } 28 29 [XmlAttribute("msg")] 30 public string Message { get; set; } 31 32 [XmlAttribute("PartialPage")] 33 public string PartialPage { get; set; } 34 35 [XmlAttribute("level")] 36 public string Level { get; set; } 37 } 38 }
xmlHelper类:
1 namespace NlogTest.Common 2 { 3 public class XmlHelper 4 { 5 public static string GetXmlPath(string XmlName) 6 { 7 string filePath = string.Empty; 8 filePath = System.Web.HttpContext.Current.Server.MapPath(string.Concat("", "~/Config/"+XmlName + ".Config")); 9 10 return filePath; 11 } 12 13 public static List<T> XmlToEntityList<T>(string XmlName) 14 { 15 string xmlPath = GetXmlPath(XmlName); 16 XmlSerializer serializer = new XmlSerializer(typeof(List<T>)); 17 Object obj = new Object(); 18 19 if (File.Exists(xmlPath)) 20 { 21 using (StreamReader reader = new StreamReader(xmlPath)) 22 { 23 try 24 { 25 obj = serializer.Deserialize(reader); 26 } 27 catch (Exception ex) 28 { 29 //Here put your code witch dealing with exception 30 } 31 } 32 } 33 return (List<T>)obj; 34 } 35 36 public static T XmlToEntity<T>(string XmlName) 37 { 38 string xmlPath = GetXmlPath(XmlName); 39 XmlSerializer serializer = new XmlSerializer(typeof(T)); 40 Object obj = new Object(); 41 42 if (File.Exists(xmlPath)) 43 { 44 using (StreamReader reader = new StreamReader(xmlPath)) 45 { 46 try 47 { 48 obj = serializer.Deserialize(reader); 49 } 50 catch (Exception ex) 51 { 52 //Here put your code witch dealing with exception 53 } 54 } 55 } 56 return (T)obj; 57 } 58 } 59 }
ErrorConfig文件:
1 <?xml version="1.0" encoding="utf-8"?> 2 <ErrorConfig> 3 <ErrorCodes> 4 5 <Error code="1000500" description="GeneralServiceError" msg="" PartialPage="ErrorPartial/GlobalError" level="Error"/> 6 7 57 </ErrorCodes> 58 </ErrorConfig>
$2、 封装一个Log处理异常错误的类库—LogUtil.
1 public class LogUtil 2 { 3 private static object mutex = new object(); 4 5 private static Logger logger = LogManager.GetCurrentClassLogger(); 6 7 private static LogUtil _instance = null; 8 9 public static LogUtil Instance 10 { 11 get 12 { 13 if (_instance == null) 14 { 15 lock (mutex) 16 { 17 if (_instance == null) 18 { 19 _instance = new LogUtil(); 20 } 21 } 22 } 23 return _instance; 24 } 25 } 26 27 public static void Log(int errorCode, string message = null, Exception ex = null) 28 { 29 ErrorCode errObj = ErrorCodeConfig.GetError(errorCode.ToString()); 30 if (errObj == null) 31 { 32 Instance.LogWarn("Error code " + errorCode + " has no definition."); 33 return; 34 } 35 36 StringBuilder msgBuilder = GenerateMessage(errorCode.ToString(), message, ex); 37 38 string methodName = "Log" + errObj.Level; 39 MethodInfo method = typeof(LogUtil).GetMethod(methodName); 40 if (method == null) 41 { 42 Instance.LogWarn("log level wrong,please check ErrorCode.Config.level name is " + errObj.Level); 43 return; 44 } 45 method.Invoke(Instance, new object[] { msgBuilder.ToString() }); 46 47 } 48 49 public static void LogDebug(string message) 50 { 51 logger.Log(LogLevel.Debug, message); 52 } 53 54 public static void LogError(string message) 55 { 56 logger.Log(LogLevel.Error, message); 57 } 58 59 public void LogErrorException(Exception ex) 60 { 61 LogException(LogLevel.Error, ex); 62 } 63 64 public void LogFatalException(Exception ex) 65 { 66 LogException(LogLevel.Fatal, ex); 67 } 68 69 public void LogFatal(string message) 70 { 71 logger.Log(LogLevel.Fatal, message); 72 } 73 74 public static void LogInfo(string message) 75 { 76 logger.Log(LogLevel.Info, message); 77 } 78 79 public void LogOff(string message) 80 { 81 logger.Log(LogLevel.Off, message); 82 } 83 84 public void LogTrace(string message) 85 { 86 logger.Log(LogLevel.Trace, message); 87 } 88 89 public void LogWarn(string message) 90 { 91 logger.Log(LogLevel.Warn, message); 92 } 93 94 95 private static void LogException(LogLevel level, Exception ex) 96 { 97 logger.Log(level, GetExceptionMessage(ex)); 98 } 99 100 private static string GetExceptionMessage(Exception ex) 101 { 102 string message = ex.Message; 103 string stackTrace = ex.StackTrace; 104 if (string.IsNullOrEmpty(stackTrace) && ex.InnerException != null) 105 { 106 stackTrace = ex.InnerException.StackTrace; 107 } 108 return message + "::" + stackTrace; 109 } 110 111 private static StringBuilder GenerateMessage(string errorCode, string message, Exception ex) 112 { 113 StringBuilder msgBuilder = new StringBuilder(); 114 msgBuilder.Append("ErrorCode is " + errorCode); 115 msgBuilder.Append("\r\n"); 116 if (!string.IsNullOrEmpty(message)) 117 { 118 msgBuilder.Append(message); 119 msgBuilder.Append("\r\n"); 120 } 121 if (ex != null) 122 { 123 msgBuilder.Append(GetExceptionMessage(ex)); 124 msgBuilder.Append("\r\n"); 125 } 126 return msgBuilder; 127 } 128 }
三、将LogUtil与MVC衔接上,该MVC中的FilterAttribute、IExceptionFilter出场了。
$1、定义个ErrorFilterAttribute继承FilterAttribute、IExceptionFilter。
1 namespace NlogTest.FrameWork 2 { 3 public class ErrorFilterAttribute:FilterAttribute,IExceptionFilter 4 { 5 private const int commonError = 2000500; 6 7 public void OnException(ExceptionContext filterContext) 8 { 9 int errorCode = commonError; 10 Exception exception = filterContext.Exception; 11 12 if (exception is ErrorCodeException) 13 { 14 errorCode = ((ErrorCodeException)exception).ErrorCode; 15 } 16 string message = "Error"; 17 LogUtil.Log(errorCode,ex:exception,message:message); 18 } 19 } 20 }
$2、将ErrorFilterAttribute注册到App_Start底下的FilterConfig中,这样做的目的是利用MVC中过滤器对全局的controller进行处理。简而言之,比如任意一个controller中action抛出异常错误,这里都会检测到并作为日志记录的接口开始对这些异常错误进行记录。
1 public class FilterConfig 2 { 3 public static void RegisterGlobalFilters(GlobalFilterCollection filters) 4 { 5 //filters.Add(new HandleErrorAttribute()); 6 filters.Add(new ErrorFilterAttribute()); 7 } 8 }
2016-12-26
测试效果:
在HomeController中写一段会发生错误的代码:
到在输出目标位置中找对应log文件:
激动的时刻到来了
PS:至此整个Demo算是完成了,快过年了,公司也没啥事,自己捣鼓点东西,基础比较差,就当练手。经过这次,我明白了一件事,平时多积累点小知识点,可以汇集起来再实现一个小功能,新旧知识结合,挺好。
海的呐喊