一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - ASP.NET教程 - ASP.NET MVC中異常Exception攔截的深入理解

ASP.NET MVC中異常Exception攔截的深入理解

2020-05-28 14:57沉淀的風 ASP.NET教程

異常信息的處理在程序中非常重要, 在asp.net mvc中提供異常屬性攔截器進行對異常信息的處理,下面這篇文章主要給大家介紹了關于ASP.NET MVC中異常Exception攔截的相關資料,需要的朋友可以參考下

一、前言

由于客戶端的環境不一致,有可能會造成我們預計不到的異常錯誤,所以在項目中,友好的異常信息提示,是非常重要的。在asp.net mvc中實現異常屬性攔截也非常簡單,只需要繼承另一個類(System.Web.Mvc.FilterAttribute)和一個接口(System.Web.Mvc.IExceptionFilter),實現接口里面OnException方法,或者直接繼承Mvc 提供的類System.Web.Mvc.HandleErrorAttribute。

下面話不多說了,來一起看看詳細的介紹吧

二、實現關鍵邏輯

繼承System.Web.Mvc.HandleErrorAttribute,重寫了OnException方法,主要實現邏輯代碼如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
public class HandlerErrorAttribute : HandleErrorAttribute
{
 /// <summary>
 /// 控制器方法中出現異常,會調用該方法捕獲異常
 /// </summary>
 /// <param name="context">提供使用</param>
 public override void OnException(ExceptionContext context)
 {
 WriteLog(context);
 base.OnException(context);
 context.ExceptionHandled = true;
 if (context.Exception is UserFriendlyException)
 {
 context.HttpContext.Response.StatusCode = (int)HttpStatusCode.OK;
 context.Result = new ContentResult { Content = new AjaxResult { type = ResultType.error, message = context.Exception.Message }.ToJson() };
 }
 else if (context.Exception is NoAuthorizeException)
 {
 context.HttpContext.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
 if (!context.HttpContext.Request.IsAjaxRequest())
 {
 context.HttpContext.Response.RedirectToRoute("Default", new { controller = "Error", action = "Error401", errorUrl = context.HttpContext.Request.RawUrl });
 }
 else
 {
 context.Result = new ContentResult { Content = context.HttpContext.Request.RawUrl };
 }
 }
 else
 {
 context.HttpContext.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
 ExceptionMessage error = new ExceptionMessage(context.Exception);
 var s = error.ToJson();
 if (!context.HttpContext.Request.IsAjaxRequest())
 {
  context.HttpContext.Response.RedirectToRoute("Default", new { controller = "Error", action = "Error500", data = WebHelper.UrlEncode(s) });
 }
 else
 {
  context.Result = new ContentResult { Content = WebHelper.UrlEncode(s) };
 }
 }
 }
 
 /// <summary>
 /// 寫入日志(log4net)
 /// </summary>
 /// <param name="context">提供使用</param>
 private void WriteLog(ExceptionContext context)
 {
 if (context == null)
 return;
 if (context.Exception is NoAuthorizeException || context.Exception is UserFriendlyException)
 {
 //友好錯誤提示,未授權錯誤提示,記錄警告日志
 LogHelper.Warn(context.Exception.Message);
 }
 else
 {
 //異常錯誤,
 LogHelper.Error(context.Exception);
 
 ////TODO :寫入錯誤日志到數據庫
 }
 }
}

MVC 過濾器全局注冊異常攔截:

?
1
2
3
4
5
6
7
public class FilterConfig
 {
 public static void RegisterGlobalFilters(GlobalFilterCollection filters)
 {
 filters.Add(new HandlerErrorAttribute());
 }
 }

我們看到,context.Exception 分為3種:UserFriendlyException,NoAuthorizeException 或 Exception;UserFriendlyException 是指友好異常,前端友好提示錯誤信息。NoAuthorizeException 為401未授權異常,當頁面未被授權訪問時,返回該異常,并攜帶有未授權的路徑地址。其他異常統一返回500錯誤,并攜帶異常信息。

三、異常處理 

1.401 未授權錯誤

異常定義代碼:

?
1
2
3
4
5
6
7
8
9
10
/// <summary>
/// 沒有被授權的異常
/// </summary>
public class NoAuthorizeException : Exception
{
 public NoAuthorizeException(string message)
 : base(message)
 {
 }
}

拋出異常代碼:

?
1
throw new NoAuthorizeException("未授權");

前端UI效果:

ASP.NET MVC中異常Exception攔截的深入理解

2.404 未找到頁面錯誤

MVC的404異常處理,有幾種方式,我們采用了在Global.asax全局請求函數中處理, 請查看以下代碼

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
protected void Application_EndRequest()
 {
 if (Context.Response.StatusCode == 404)
 {
 bool isAjax = new HttpRequestWrapper(Context.Request).IsAjaxRequest();
 if (isAjax)
 {
  Response.Clear();
  Response.Write(Context.Request.RawUrl);
 }
 else
 {
  Response.RedirectToRoute("Default", new { controller = "Error", action = "Error404", errorUrl = Context.Request.RawUrl });
 }
 }
 }

前端UI效果:

ASP.NET MVC中異常Exception攔截的深入理解

3.500服務器內部錯誤

500異常錯誤拋出的異常信息對象定義:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
/// <summary>
/// 異常錯誤信息
/// </summary>
[Serializable]
public class ExceptionMessage
{
 public ExceptionMessage()
 {
 }
 
 /// <summary>
 /// 構造函數
 /// 默認顯示異常頁面
 /// </summary>
 /// <param name="ex">異常對象</param>
 public ExceptionMessage(Exception ex)
 :this(ex, true)
 {
 
 }
 /// <summary>
 /// 構造函數
 /// </summary>
 /// <param name="ex">異常對象</param>
 /// <param name="isShowException">是否顯示異常頁面</param>
 public ExceptionMessage(Exception ex, bool isShowException)
 {
 MsgType = ex.GetType().Name;
 Message = ex.InnerException != null ? ex.InnerException.Message : ex.Message;
 StackTrace = ex.StackTrace.Length > 300 ? ex.StackTrace.Substring(0, 300) : ex.StackTrace;
 Source = ex.Source;
 Time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
 Assembly = ex.TargetSite.Module.Assembly.FullName;
 Method = ex.TargetSite.Name;
 
 ShowException = isShowException;
 var request = HttpContext.Current.Request;
 IP = Net.Ip;
 UserAgent = request.UserAgent;
 Path = request.Path;
 HttpMethod = request.HttpMethod;
 }
 /// <summary>
 /// 消息類型
 /// </summary>
 public string MsgType { get; set; }
 
 /// <summary>
 /// 消息內容
 /// </summary>
 public string Message { get; set; }
 
 /// <summary>
 /// 請求路徑
 /// </summary>
 public string Path { get; set; }
 
 /// <summary>
 /// 程序集名稱
 /// </summary>
 public string Assembly { get; set; }
 
 /// <summary>
 /// 異常參數
 /// </summary>
 public string ActionArguments { get; set; }
 
 /// <summary>
 /// 請求類型
 /// </summary>
 public string HttpMethod { get; set; }
 
 /// <summary>
 /// 異常堆棧
 /// </summary>
 public string StackTrace { get; set; }
 
 /// <summary>
 /// 異常源
 /// </summary>
 public string Source { get; set; }
 
 /// <summary>
 /// 服務器IP 端口
 /// </summary>
 public string IP { get; set; }
 
 /// <summary>
 /// 客戶端瀏覽器標識
 /// </summary>
 public string UserAgent { get; set; }
 
 
 /// <summary>
 /// 是否顯示異常界面
 /// </summary>
 public bool ShowException { get; set; }
 
 /// <summary>
 /// 異常發生時間
 /// </summary>
 public string Time { get; set; }
 
 /// <summary>
 /// 異常發生方法
 /// </summary>
 public string Method { get; set; }
}

拋出異常代碼:

?
1
throw new Exception("出錯了");

前端UI效果:

ASP.NET MVC中異常Exception攔截的深入理解

4. UserFriendlyException 友好異常

異常定義代碼:

?
1
2
3
4
5
6
7
8
9
10
/// <summary>
/// 用戶友好異常
/// </summary>
public class UserFriendlyException : Exception
{
 public UserFriendlyException(string message)
 : base(message)
 {
 }
}

在異常攔截關鍵代碼中,我們發現友好異常(UserFriendlyException)其實是返回了一個結果對象AjaxResult,

ASP.NET MVC中異常Exception攔截的深入理解

AjaxResult對象的定義:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
/// <summary>
 /// 表示Ajax操作結果
 /// </summary>
 public class AjaxResult
 {
 /// <summary>
 /// 獲取 Ajax操作結果類型
 /// </summary>
 public ResultType type { get; set; }
 
 /// <summary>
 /// 獲取 Ajax操作結果編碼
 /// </summary>
 public int errorcode { get; set; }
 
 /// <summary>
 /// 獲取 消息內容
 /// </summary>
 public string message { get; set; }
 
 /// <summary>
 /// 獲取 返回數據
 /// </summary>
 public object resultdata { get; set; }
 }
 /// <summary>
 /// 表示 ajax 操作結果類型的枚舉
 /// </summary>
 public enum ResultType
 {
 /// <summary>
 /// 消息結果類型
 /// </summary>
 info = 0,
 
 /// <summary>
 /// 成功結果類型
 /// </summary>
 success = 1,
 
 /// <summary>
 /// 警告結果類型
 /// </summary>
 warning = 2,
 
 /// <summary>
 /// 異常結果類型
 /// </summary>
 error = 3
 }

四、Ajax請求異常時處理

在異常攔截的關鍵代碼中,我們有看到,如果是ajax請求時,是執行不同的邏輯,這是因為ajax的請求,不能直接通過MVC的路由跳轉,在請求時必須返回結果內容

ASP.NET MVC中異常Exception攔截的深入理解

然后在前端ajax的方法中,統一處理返回的錯誤,以下是我們項目中用到的ajax封裝,對異常錯誤,進行了統一處理。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
(function ($) {
 "use strict";
 
 $.httpCode = {
 success: "1",
 fail: "3",
 };
 // http 通信異常的時候調用此方法
 $.httpErrorLog = function (msg) {
 console.log('=====>' + new Date().getTime() + '<=====');
 console.log(msg);
 };
 
 // ajax請求錯誤處理
 $.httpError = function (xhr, textStatus, errorThrown) {
 
 if (xhr.status == 401) {
  location.href = "/Error/Error401?errorUrl=" + xhr.responseText;
 }
 
 if (xhr.status == 404) {
  location.href = "/Error/Error404?errorUrl=" + xhr.responseText;
 }
 
 if (xhr.status == 500) {
  location.href = "/Error/Error500?data=" + xhr.responseText;
 }
 };
 
 /* get請求方法(異步):
 * url地址, param參數, callback回調函數 beforeSend 請求之前回調函數, complete 請求完成之后回調函數
 * 考慮到get請求一般將參數與url拼接一起傳遞,所以將param參數放置最后
 * 返回AjaxResult結果對象
 */
 $.httpAsyncGet = function (url, callback, beforeSend, complete, param) {
 $.ajax({
  url: url,
  data: param,
  type: "GET",
  dataType: "json",
  async: true,
  cache: false,
  success: function (data) {
  if ($.isFunction(callback)) callback(data);
  },
  error: function (XMLHttpRequest, textStatus, errorThrown) {
  $.httpError(XMLHttpRequest, textStatus, errorThrown);
  },
  beforeSend: function () {
  if (!!beforeSend) beforeSend();
  },
  complete: function () {
  if (!!complete) complete();
  }
 });
 };
 
 /* get請求方法(同步):
 * url地址,param參數
 * 返回實體數據對象
 */
 $.httpGet = function (url, param) {
 var res = {};
 $.ajax({
  url: url,
  data: param,
  type: "GET",
  dataType: "json",
  async: false,
  cache: false,
  success: function (data) {
  res = data;
  },
  error: function (XMLHttpRequest, textStatus, errorThrown) {
  $.httpError(XMLHttpRequest, textStatus, errorThrown);
  },
 });
 return res;
 };
 
 /* post請求方法(異步):
 * url地址, param參數, callback回調函數 beforeSend 請求之前回調函數, complete 請求完成之后回調函數
 * 返回AjaxResult結果對象
 */
 $.httpAsyncPost = function (url, param, callback, beforeSend, complete) {
 $.ajax({
  url: url,
  data: param,
  type: "POST",
  dataType: "json",
  async: true,
  cache: false,
  success: function (data) {
  if ($.isFunction(callback)) callback(data);
  },
  error: function (XMLHttpRequest, textStatus, errorThrown) {
  $.httpError(XMLHttpRequest, textStatus, errorThrown);
  },
  beforeSend: function () {
  if (!!beforeSend) beforeSend();
  },
  complete: function () {
  if (!!complete) complete();
  }
 });
 };
 
 /* post請求方法(同步):
 * url地址,param參數, callback回調函數
 * 返回實體數據對象
 */
 $.httpPost = function (url, param, callback) {
 $.ajax({
  url: url,
  data: param,
  type: "POST",
  dataType: "json",
  async: false,
  cache: false,
  success: function (data) {
  if ($.isFunction(callback)) callback(data);
  },
  error: function (XMLHttpRequest, textStatus, errorThrown) {
  $.httpError(XMLHttpRequest, textStatus, errorThrown);
  },
 });
 },
 
 /* ajax異步封裝:
 * type 請求類型, url地址, param參數, callback回調函數
 * 返回實體數據對象
 */
 $.httpAsync = function (type, url, param, callback) {
 $.ajax({
  url: url,
  data: param,
  type: type,
  dataType: "json",
  async: true,
  cache: false,
  success: function (data) {
  if ($.isFunction(callback)) callback(data);
  },
  error: function (XMLHttpRequest, textStatus, errorThrown) {
  $.httpError(XMLHttpRequest, textStatus, errorThrown);
  },
 });
 };
})(jQuery);

五、總結

至此,我們發現其實MVC的異常處理,真的很簡單,只需要在過濾器中全局注冊之后,然后重寫OnException的方法,實現邏輯即可。關鍵是在于項目中Ajax請求,需要用統一的封裝方法。

好了,以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對服務器之家的支持。

原文鏈接:https://www.cnblogs.com/xyb0226/p/9250334.html

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: aⅴ视频在线免播放观看 | 卫生间被教官做好爽HH视频 | yy6080久久国产伦理 | 久久一本岛在免费线观看2020 | 亚洲精品视频一区 | 非洲一级毛片又粗又长aaaa | 国产123区 | 午夜在线播放免费人成无 | 婷射吧| 黑人巨鞭大战白妞10级 | 91真人毛片一级在线播放 | 午夜精品久久久久久 | 免费观看国产大片资源视频 | 污文啊好棒棒啊好了 | 午夜福利合集1000在线 | 午夜国产福利视频一区 | 国产rpg迷雾之风冷狐破解 | 国产成人免费a在线资源 | 国产悠悠视频在线播放 | 动漫美女人物被黄漫在线看 | 欧美一级特黄刺激大片视频 | 岛国在线播放v片免费 | 亚洲免费色 | 香蕉eeww99国产精选播放 | 亚洲国产在线观看免费视频 | 欧美国产视频 | 日本十大顶级绝伦推理片 | 果冻传媒九一制片厂 | 欧美日韩免费一区二区在线观看 | 精品一区heyzo在线播放 | 无人区免费一二三四乱码 | 性派对videos18party | 色老板在线视频 | 久久精品视在线观看2 | 亚洲视频在线看 | 欧美调教打屁股spank视频 | 五月天色综合 | 国产aaaaa一级毛片 | 97综合 | 亚久久伊人精品青青草原2020 | 日韩国产欧美一区二区三区 |