6 <h2>NotFound</h2>
7 一般人看不出来,这是一个美化了的NotFound页面。
8 </div>
2.6 Error.cshtml改得更友好一些
1 <div style=" margin:0px auto; width:500px; margin:20px;">
2 <h2>默认异常页面</h2>
3 你好,这是系统默认异常界面,已经美化过了,请放心使用。
4 </div>
2.7 在Home控制器中手动触发异常
1 public ActionResult ThrowHttp500()
2 {
3 throw new HttpException(500, "服务器错误");
4 }
5
6 public ActionResult ThrowHttp404()
7 {
8 throw new HttpException(404, "页面未找到");
9 }
10
11 [HandleError(ExceptionType = typeof(NullReferenceException))]
12 public ActionResult ThrowNullReferenceException()
13 {
14 throw new NullReferenceException();
15 }
16
17 public ActionResult ThrowFormatException()
18 {
19 string str = "";
20 int count = Convert.ToInt32(str);
21 return View("Index");
22 }
2.8 运行以下几种异常会跳到之前的默认异常页面
http://localhost:5572/Home/ThrowHttp500
http://localhost:5572/Home/ThrowNullReferenceException
http://localhost:5572/Home/ThrowFormatException
2.9 页面未找到会转至:http://localhost:5572/Home/ThrowHttp404
2.10 当然了,别忘了在2.2 中我们还在中记录了日志功能(LjrExecptionAttribute),我们去看看
堆栈信息都有了,这就很好定位BUG位置了,通过分析其日志,大概可以知道问题原因
上边已经解决了WEB中的异常信息,但是一个项目不可能只有WEB,还有很多类库,WebService等
3、类库异常处理
3.1 看看捕捉异常的一般做法
1 public bool CommonMethod(LoginUserCURequest entity)
2 {
3 try
4 {
5 this.repository.Add(new LoginUser()
6 {
7 Id = entity.Id,
8 LoginName = entity.LoginName,
9 Password = entity.Password,
10 IsEnabled = entity.IsEnabled,
11 CreateTime = DateTime.Now
12 });
13
14 foreach (var Id in entity.Roles)
15 {
16 this.roleUserMappingRepository.Add(new RoleUserMapping()
17 {
18 Id = Guid.NewGuid(),
19 RoleId = Id,
20 LoginUserId = entity.Id,
21 CreateTime = DateTime.Now
22 });
23 }
24
25 this.unitOfWork.Commit();
26
27 return true;
28 }
29 catch (Exception ex)
30 {
31 Logger.Error(ex.Message, ex);
32 return false;
33 }
34 }
大部分人应该都是像上边一样处理异常,这本身没有问题
但是仔细想想,还是有点问题的,我们来看看
1、每个方法都要写try{}catch{},到最后整个类库都是try catch,这很丑。。,颜值太低了,就提不起多少兴趣了。
2、处理异常这本身就不应该属于业务逻辑的一部分,得把他弄走,因为他污染了业务逻辑
3、只记录了异常堆栈,输入参数没有,如果要记录参数值,还得写一堆日志代码,那就更丑了。
3.2 有困难,拦截器来帮忙;对于这种现象,于是一些聪明的开发者就搞出了AOP编程
AOP是基于特性(Attribute)的,不过自己搞的话貌似还挺复杂的,简单的还行,复杂的我也不会
于是我就盯上了PostSharp,版本1.5以上是收费的,这点要注意。我们先来搞一个简单的异常拦截器
1 [Serializable]
2 [AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true)]
3 public class ExceptionAttribute : PostSharp.Aspects.OnExceptionAspect
4 {
5 public override void OnException(MethodExecutionArgs args)
6 {
7 StringBuilder sb = new StringBuilder();
8 sb.AppendLine(args.Exception.Message);
9 sb.AppendFormat("位置:{0}.{1}", args.Method.ReflectedType, args.Method).AppendLine();
10
11 sb.AppendLine("参数:");
12 foreach(var item in args.Arguments)
13 {
14 sb.AppendFormat(item.ToString()).AppendLine();
15 }
16
17 Logger.Error(sb.ToString(), args.Exception);
18
19 args.FlowBehavior = FlowBehavior.ThrowException;
20 }
21 }
标红的得注意了,必须要写清楚的,不然没有效果
还有一个小坑就是PostSharp不支持实体参数的,传普通类型的string、int之类的在OnException中是可以拿到值的
如果是实体,比如这种
1 public class LoginUserCURequest
2 {
3 /// <summary>Id</summary>
4 public Guid Id { get; set; }
5
6 /// <summary>登录账户名&