原文:
系统需要越来越自动化,我们需要引入日志记录和异常捕获
管理员的操作记录需要被记录,看出哪些模块是频繁操作,分析哪些是不必要的功能,哪些是需要被优化的。系统的异常需要被捕获,而不是将系统出错显示出来给用户就不了了知。我们需要异常日志不断改进系统。我们老说用户,我们还没有用户权限的表,所以我们在Home中先加入一个虚拟用户吧!首先我们创建一个用户类AccountModel放在App.Models下的Sys文件夹下
using System;using System.Collections.Generic;using System.Linq;using System.Text;namespace App.Models.Sys{ public class AccountModel { public string Id { get; set; } public string TrueName { get; set; } }}
在HomeController或者AccountController插入代码
AccountModel account = new AccountModel();account.Id = "admin";account.TrueName = "admin";Session["Account"] = account;
下面将带来系统日志的记录,主要记录管理员的增、删、改等操作的成功与失败的异常记录
日志插件有著名的log4net,可以输出多种格式,如文本,xml,数据库等,我们没有必要做到这么强大,我们只做符合系统的就可以了,记录到数据库,方便做统计等操 作,我们何时何地记录日志?- 在Controller层做记录;
- 当用户的操作成功时记录;
- 当用户的操作失败时记录;
首先创建数据库存放表:SysLog
USE DBGO/****** Object: Table [dbo].[SysLog] Script Date: 11/20/2013 21:13:38 ******/SET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOSET ANSI_PADDING ONGOCREATE TABLE [dbo].[SysLog]( [Id] [varchar](50) NOT NULL, --GUID [Operator] [varchar](50) NULL,--操作人 [Message] [varchar](500) NULL,--操作信息 [Result] [varchar](20) NULL,--结果 [Type] [varchar](20) NULL,--操作类型 [Module] [varchar](20) NULL,--操作模块 [CreateTime] [datetime] NULL,--操作事件 CONSTRAINT [PK_SysLog] PRIMARY KEY CLUSTERED ( [Id] ASC)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]) ON [PRIMARY]GOSET ANSI_PADDING OFFGO
EF更新模型,创建SysLogModel类放在App.Models下的Sys文件夹下
using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.ComponentModel.DataAnnotations;namespace App.Models.Sys{ public class SysLogModel { [Display(Name = "ID")] public string Id { get; set; } [Display(Name = "操作人")] public string Operator { get; set; } [Display(Name = "信息")] public string Message { get; set; } [Display(Name = "结果")] public string Result { get; set; } [Display(Name = "类型")] public string Type { get; set; } [Display(Name = "模块")] public string Module { get; set; } [Display(Name = "创建时间")] public DateTime? CreateTime { get; set; } }}
创建SysLog的BLL层和DAL层
using System;using App.Models;using System.Linq;namespace App.IDAL{ public interface ISysLogRepository { int Create(SysLog entity); void Delete(DBContainer db, string[] deleteCollection); IQueryableGetList(DBContainer db); SysLog GetById(string id); }}
using System;using System.Collections.Generic;using System.Linq;using System.Text;using App.Models;using App.IDAL;namespace App.DAL{ public class SysLogRepository:IDisposable, ISysLogRepository { ////// 获取集合 /// /// 数据库 ///集合 public IQueryableGetList(DBContainer db) { IQueryable list = db.SysLog.AsQueryable(); return list; } /// /// 创建一个对象 /// /// 数据库 /// 实体 public int Create(SysLog entity) { using (DBContainer db = new DBContainer()) { db.SysLog.AddObject(entity); return db.SaveChanges(); } } ////// 删除对象集合 /// /// 数据库 /// 集合 public void Delete(DBContainer db, string[] deleteCollection) { IQueryablecollection = from f in db.SysLog where deleteCollection.Contains(f.Id) select f; foreach (var deleteItem in collection) { db.SysLog.DeleteObject(deleteItem); } } /// /// 根据ID获取一个实体 /// /// ///public SysLog GetById(string id) { using (DBContainer db = new DBContainer()) { return db.SysLog.SingleOrDefault(a => a.Id == id); } } public void Dispose() { } }}
using System;using System.Collections.Generic;using App.Common;using App.Models;namespace App.IBLL{ public interface ISysLogBLL { ListGetList(ref GridPager pager,string queryStr); SysLog GetById(string id); }}
using System;using System.Collections.Generic;using System.Linq;using System.Text;using Microsoft.Practices.Unity;using App.IDAL;using App.Common;using App.Models.Sys;using App.Models;using App.IBLL;namespace App.BLL{ public class SysLogBLL: ISysLogBLL { [Dependency] public ISysLogRepository logRepository { get; set; } public ListGetList(ref GridPager pager, string queryStr) { DBContainer db = new DBContainer(); List query = null; IQueryable list = logRepository.GetList(db); if (!string.IsNullOrWhiteSpace(queryStr)) { list = list.Where(a => a.Message.Contains(queryStr) || a.Module.Contains(queryStr)); pager.totalRows = list.Count(); } else { pager.totalRows = list.Count(); } if (pager.order == "desc") { query = list.OrderByDescending(c => c.CreateTime).Skip((pager.page - 1) * pager.rows).Take(pager.rows).ToList(); } else { query = list.OrderBy(c => c.CreateTime).Skip((pager.page - 1) * pager.rows).Take(pager.rows).ToList(); } return query; } public SysLog GetById(string id) { return logRepository.GetById(id); } }}
创建SysLog的Controller
using System;using System.Collections.Generic;using System.Linq;using System.Web;using System.Web.Mvc;using App.Common;using App.Models;using Microsoft.Practices.Unity;using App.IBLL;using App.Models.Sys;namespace App.Admin.Controllers{ public class SysLogController : Controller { // // GET: /SysLog/ [Dependency] public ISysLogBLL logBLL { get; set; } public ActionResult Index() { return View(); } public JsonResult GetList(GridPager pager, string queryStr) { Listlist = logBLL.GetList(ref pager, queryStr); var json = new { total = pager.totalRows, rows = (from r in list select new SysLogModel() { Id= r.Id, Operator= r.Operator, Message= r.Message, Result= r.Result, Type= r.Type, Module= r.Module, CreateTime= r.CreateTime }).ToArray() }; return Json(json); } #region 详细 public ActionResult Details(string id) { SysLog entity = logBLL.GetById(id); SysLogModel info = new SysLogModel() { Id = entity.Id, Operator = entity.Operator, Message = entity.Message, Result = entity.Result, Type = entity.Type, Module = entity.Module, CreateTime = entity.CreateTime, }; return View(info); } #endregion }}
创建SysLog的Index视图和Details视图,我们暂时提示Index和Details,删除功能童鞋们自己扩展,我们有样例程序SysSample嘛,什么都是必然的了
@using App.Admin;@using App.Common;@using App.Models.Sys;@{ ViewBag.Title = "Index"; Layout = "~/Views/Shared/_Index_Layout.cshtml";}
@model App.Models.Sys.SysLogModel@using App.Common;@using App.Admin;@using App.Models.Sys;@{ ViewBag.Title = "Details"; Layout = "~/Views/Shared/_Index_LayoutEdit.cshtml";} @using (Html.BeginForm()){
@Html.LabelFor(model => model.Operator) | @Html.EditorFor(model => model.Operator) |
---|---|
@Html.LabelFor(model => model.Message) | @Html.TextAreaFor(model => model.Message, new { @style="height:100px;"}) |
@Html.LabelFor(model => model.Result) | @Html.EditorFor(model => model.Result) |
@Html.LabelFor(model => model.Type) | @Html.EditorFor(model => model.Type) |
@Html.LabelFor(model => model.Module) | @Html.EditorFor(model => model.Module) |
@Html.LabelFor(model => model.CreateTime) | @Html.TextBoxFor(model => model.CreateTime) |
有看过前面的童鞋,应该很熟悉这一步很机械化的创建了
- 创建数据表
- 更新到EF
- 创建BLL和DAL层
- 创建Model
- 创建爱你Controller
- 创建View
- 注入到容器
- 运行
你看了不累我都觉得累了,我们以后会讲用T4,我们自动生成
预览下效果,你会发现我们的左边的菜单栏可以点出来了。oh yeh...(别忘记注入)
分页和详细都没有问题了。
接下来是是异常的捕获,我们在何时处理异常?我们没有处理的异常该怎么办?我们处理异常时出现异常怎么又怎么办?反正我是要捕获到这异常了...、
我们一般先对数据进行判断避免捕获异常,因为try catch会降低程序的性能,我们一般在业务层捕获异常,处理逻辑容易导致异常- 处理异常出错,我们将输出文本格式,来记录异常
- 我们将写全局异常捕获来拦截异常
- 你觉得我们的系统后盾还不够强大吗?
创建异常存放数据表SysException
USE DBGO/****** Object: Table [dbo].[SysException] Script Date: 11/20/2013 21:17:44 ******/SET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOSET ANSI_PADDING ONGOCREATE TABLE [dbo].[SysException]( [Id] [varchar](50) NOT NULL, --GUID [HelpLink] [varchar](500) NULL,--帮助链接 [Message] [varchar](500) NULL,--异常信息 [Source] [varchar](500) NULL,--来源 [StackTrace] [text] NULL,--堆栈 [TargetSite] [varchar](500) NULL,--目标页 [Data] [varchar](500) NULL,--程序集 [CreateTime] [datetime] NULL,--发生时间 CONSTRAINT [PK_SysException] PRIMARY KEY CLUSTERED ( [Id] ASC)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]GOSET ANSI_PADDING OFFGO
EF更新模型,创建SysExceptionModel类放在App.Models下的Sys文件夹下
using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.ComponentModel.DataAnnotations;namespace App.Models.Sys{ ////// 异常处理类 /// public class SysExceptionModel { [Display(Name = "ID")] public string Id { get; set; } [Display(Name = "帮助链接")] public string HelpLink { get; set; } [Display(Name = "错误信息")] public string Message { get; set; } [Display(Name = "来源")] public string Source { get; set; } [Display(Name = "堆栈")] public string StackTrace { get; set; } [Display(Name = "目标页")] public string TargetSite { get; set; } [Display(Name = "程序集")] public string Data { get; set; } [Display(Name = "发生时间")] public DateTime? CreateTime { get; set; } }}
创建SysException的BLL层和DAL层
using System;using App.Models;using System.Linq;namespace App.IDAL{ public interface ISysExceptionRepository { int Create(SysException entity); IQueryableGetList(DBContainer db); SysException GetById(string id); }}
using System;using System.Collections.Generic;using System.Linq;using System.Text;using App.Models;using App.IDAL;namespace App.DAL{ public class SysExceptionRepository:IDisposable, ISysExceptionRepository { ////// 获取集合 /// /// 数据库 ///集合 public IQueryableGetList(DBContainer db) { IQueryable list = db.SysException.AsQueryable(); return list; } /// /// 创建一个对象 /// /// 数据库 /// 实体 public int Create( SysException entity) { using (DBContainer db = new DBContainer()) { db.SysException.AddObject(entity); return db.SaveChanges(); } } ////// 根据ID获取一个实体 /// /// ///public SysException GetById(string id) { using (DBContainer db = new DBContainer()) { return db.SysException.SingleOrDefault(a => a.Id == id); } } public void Dispose() { } }}
using System;using System.Collections.Generic;using App.Common;using App.Models;namespace App.IBLL{ public interface ISysExceptionBLL { ListGetList(ref GridPager pager,string queryStr); SysException GetById(string id); }}
using System;using System.Collections.Generic;using System.Linq;using System.Text;using Microsoft.Practices.Unity;using App.IDAL;using App.Common;using App.Models.Sys;using App.Models;using App.IBLL;namespace App.BLL{ public class SysExceptionBLL: ISysExceptionBLL { [Dependency] public ISysExceptionRepository exceptionRepository { get; set; } public ListGetList(ref GridPager pager, string queryStr) { DBContainer db = new DBContainer(); List query = null; IQueryable list = exceptionRepository.GetList(db); if (!string.IsNullOrWhiteSpace(queryStr)) { list = list.Where(a => a.Message.Contains(queryStr)); pager.totalRows = list.Count(); } else { pager.totalRows = list.Count(); } if (pager.order == "desc") { query = list.OrderByDescending(c => c.CreateTime).Skip((pager.page - 1) * pager.rows).Take(pager.rows).ToList(); } else { query = list.OrderBy(c => c.CreateTime).Skip((pager.page - 1) * pager.rows).Take(pager.rows).ToList(); } return query; } public SysException GetById(string id) { return exceptionRepository.GetById(id); } }}
创建SysException的Controller
using System;using System.Collections.Generic;using System.Linq;using System.Web;using System.Web.Mvc;using System.Reflection;using System.Text;using App.Common;using App.Models;using App.IBLL;using App.Models.Sys;using Microsoft.Practices.Unity;namespace App.Admin.Controllers{ public class SysExceptionController : Controller { // // GET: /SysException/ [Dependency] public ISysExceptionBLL exceptionBLL { get; set; } public ActionResult Index() { return View(); } public JsonResult GetList(GridPager pager, string queryStr) { Listlist = exceptionBLL.GetList(ref pager, queryStr); var json = new { total = pager.totalRows, rows = (from r in list select new SysException() { Id = r.Id, HelpLink =r.HelpLink, Message = r.Message, Source = r.Source, StackTrace = r.StackTrace, TargetSite = r.TargetSite, Data = r.Data, CreateTime = r.CreateTime }).ToArray() }; return Json(json); } #region 详细 public ActionResult Details(string id) { SysException entity = exceptionBLL.GetById(id); SysExceptionModel info = new SysExceptionModel() { Id = entity.Id, HelpLink = entity.HelpLink, Message = entity.Message, Source = entity.Source, StackTrace = entity.StackTrace, TargetSite = entity.TargetSite, Data = entity.Data, CreateTime = entity.CreateTime, }; return View(info); } #endregion } }
创建SysException的Index视图和Details视图
@using App.Admin;@using App.Common;@using App.Models.Sys;@{ ViewBag.Title = "Index"; Layout = "~/Views/Shared/_Index_Layout.cshtml";}
@model App.Models.Sys.SysExceptionModel@using App.Admin;@using App.Common;@using App.Models.Sys;@{ ViewBag.Title = "Details"; Layout = "~/Views/Shared/_Index_LayoutEdit.cshtml";} @using (Html.BeginForm()){@Html.ValidationSummary(false)
@Html.LabelFor(model => model.HelpLink) | @Html.EditorFor(model => model.HelpLink) |
---|---|
@Html.LabelFor(model => model.Message) | @Html.TextAreaFor(model => model.Message, new { @style = "height:100px;width:550px" }) |
@Html.LabelFor(model => model.Source) | @Html.EditorFor(model => model.Source) |
@Html.LabelFor(model => model.StackTrace) | @Html.TextAreaFor(model => model.StackTrace, new { @style = "height:100px;width:550px" }) |
@Html.LabelFor(model => model.TargetSite) | @Html.TextAreaFor(model => model.TargetSite, new { @style = "height:100px;width:550px" }) |
@Html.LabelFor(model => model.Data) | @Html.EditorFor(model => model.Data) |
@Html.LabelFor(model => model.CreateTime) | @Html.TextBoxFor(model => model.CreateTime) |
被忘记注入到容器。预览一下
由于时间关系,把异常和日志的应用放到一下讲吧。
然后我认为无目的的提供源码对园友的帮助是不大的,只能说你拥有一套源码,无论多漂亮都好,你自己不思考不动手,东西永远还是别人做出来的,真正遇到问题,是难解决,或者解决不了的,然而系统,我并没有完完全全把所有代码放出来,但是复杂的逻辑或者重点我都放出来了,正如上面,日志和异常的删除功能我没有放出源代码,就希望大家一起来完善这个强大的系统。
我希望大家如果有时间跟着来做,你肯定会受益匪浅