asp.net MVC3 仿照博客園功能 異常處理


這幾天感覺我自己比較懶,除了偶爾的寫了一點博客以外,對於那個重要的仿照博客園功能的項目我竟然忘記更新了。失誤了,天天腦子里的事太多了,有點亂,程序員,傷不起啊。

還是不能不謙虛啊,今天繼續項目的開發,不做那些費時的工作了,那個等我星期休息的時候再做,今天來做一個異常處理的功能。
    
眾所周知,在asp.net世界中,對於異常的處理就是try catch,當然這個是在方法內部,還有Page_Error 頁面級別的錯誤,

application_error 應用程序級別的錯誤,這幾個地方可以用來處理異常信息。一般情況下,

我們對於已知的可能出現的錯誤會直接在try  catch中捕獲並且處理,但是對於那些我們沒有考慮到的異常信息,我們就要采取別的辦法了,

比如定義一個基類,用來處理子類拋出的異常,然后在可能出現異常信息的地方繼承該類,讓父類處理子類中不能確定的並且是拋出的未處理的異常信息。

這個和驗證用戶是否登陸的方式基本一樣,對於某些資源,需要有權限的用戶才能訪問,我們就會定義一個基類,用來驗證用戶是否登陸,

如果登陸才可以繼續執行,否則就要跳轉到登陸界面。

當然,前面說的處理異常的方式是在web form時代我們(起碼是我)常用的方式,但是在MVC 時代到臨的時候,這些處理是否更容易呢?

答案是肯定的,因為技術是在不斷進步的嘛。

在MVC中我們對於已知的異常信息仍然會采用try catch的方式,並且是很常用的方式,但是對於驗證用戶登陸或者catch未捕獲的異常信息

(當然我的意思是catch(exception ex)   在catch最后沒有這一條,或者說有這一句,但是把異常信息進行了拋出處理),我們有了更容易實現的方式。

下面讓我們一起走進如何使用MVC處理異常信息。

在軟件架構不斷發展的同時,設計模式也有了很多變種,AOP(面向切面編程或面向方面編程)就是一個變種的設計模式,對於設計模式的學習,

我個人不推薦死記硬背,我希望可以了解每種模式的意義,然后在項目中不要刻意的去使用它,而是在重構的時候進行,

這樣我們可以更加深入的了解設計模式背后包含的含義。舉個例子,單例模式是一個經典的設計模式,它可以保證類的實例只有一個,

但是如果我們不正確的使用這種方式,有時候會帶來負面效果,比如多線程同時訪問,只有在保證加鎖、解鎖的情況下可以保證,

但是在普通情況下就會出現意想不到的錯誤信息。

面向對象編程具有繼承性,這應該是面向對象三大特性之一,這是類的垂直方面的編程工作,有上下級或父子關系,AOP是水平方面的編程,

它可以保證在開始之前或結束之后進行,不會破壞里面的結構。個人粗淺理解。

在MVC 3中對AOP的支持就表現在filter  過濾器上,他可以保證在開始之前或結束之后進行。

對於異常的處理我們采用的是自定義異常處理信息繼承自IExceptionFilter,當然在MVC總內置了一個HandleErrorAttribute也可以用來捕獲異常,

但是我們自己來控制可能會更好一些。

 

首先我們在HomeController的Index方法中拋出一個異常信息

 1  public ActionResult Index(int? id, int pageSize = 20)  2  {  3             List<BlogInfo> blogList = BlogServices.GetAllBlogList().ToPagedList<BlogInfo>(id == null ? 1 : Convert.ToInt32(id), pageSize);  4             ViewBag.BlogList = blogList;  5             if (Request.IsAjaxRequest())  6  {  7 
 8  }  9             
10                 throw new HttpException(500, "");//拋出異常信息
11             
12 
13             return View(blogList); 14  } 15   //404Not Found
16         public ActionResult NotFound() 17  { 18             return View(); 19  } 20         //內部服務器錯誤 500
21         public ActionResult InternalError() 22  { 23             return View(); 24         }

2.設置自定義處理異常類

 1  public class CustomExceptionAttribute :FilterAttribute,IExceptionFilter   //HandleErrorAttribute
 2  {  3 
 4         public  void OnException(ExceptionContext filterContext)  5  {  6             if (filterContext.ExceptionHandled == true)  7  {  8                 HttpException httpExce = filterContext.Exception as HttpException;  9                 if (httpExce.GetHttpCode() != 500)//為什么要特別強調500 因為MVC處理HttpException的時候,如果為500 則會自動 10                     //將其ExceptionHandled設置為true,那么我們就無法捕獲異常
11  { 12                     return; 13  } 14  } 15             HttpException httpException = filterContext.Exception as HttpException; 16             if (httpException != null) 17  { 18                 filterContext.Controller.ViewBag.UrlRefer = filterContext.HttpContext.Request.UrlReferrer; 19                 if (httpException.GetHttpCode() == 404) 20  { 21                     filterContext.HttpContext.Response.Redirect("~/home/notfound"); 22  } 23                 else if (httpException.GetHttpCode() == 500) 24  { 25                     filterContext.HttpContext.Response.Redirect("~/home/internalError"); 26  } 27  } 28             //寫入日志 記錄
29             filterContext.ExceptionHandled = true;//設置異常已經處理
30  } 31     }
在這里我要多說一句,有些園友可能遇到這么一個問題,就是拋出了一個500的內部服務器異常,但是在自定義異常信息中就是無法捕獲到,是什么原因呢?

其實就是MVC對500 的特殊照顧,在HttpException的httpCode為500的時候,MVC框架會自動的處理,然后將其ExceptionHandled設置為true。

對於其他的異常狀態碼,比如404就沒有這樣的照顧,所以500我們要優先照顧呀。

3.在設置好了自定義異常處理以后,我們可以在每個Action或Controller中進行注入,但是在MVC 3 中提供了另外一種可以全局注入的方式,那就是全局Filter,我一般叫做全局篩選器。這樣就相當於我們在所有的Action上都進行了注入。

在global.asax中,進行全局注冊
1  public static void RegisterGlobalFilters(GlobalFilterCollection filters) 2  { 3             filters.Add(new CustomExceptionAttribute(),1);//自定義的驗證特性 4             filters.Add(new HandleErrorAttribute(),2); 5         }

 

4.我們在設置了自定義異常處理以后,會跳轉到對應的頁面,里面的信息相信大家都可以自己定制了

 

5.有圖有證據  先來一個404異常處理信息

我請求的頁面是home/index,然后自動跳轉到了notFound頁面
還有500錯誤,如果您不注意判斷一個這個錯誤,那么你是不可能的

總結一下,在MVC中處理異常有很多中方式,HandleErrorAttribute,自定義異常處理類(重寫IExceptionFilter或者是HandleErrorAttribute 的OnException方法),傳統的try catch方法,這些都可以,除去那個try catch,其實自定義異常處理就是Filter的體現,和登陸驗證沒有任何區別。
還有一點就是HttpException的HttpCode為500的情況,ExceptionHandled會被自動設置為true,需要特殊照顧一下。
在我們處理完了異常以后,一定要將其ExceptionHandled設置為true,這樣可以避免父類或者更高一級的異常處理捕獲處理該異常信息。
MVC處理異常就是這么簡單,Filter特性就是那么強大,讓我們擁抱MVC,擁抱filter。
我看到有位大牛的MVC 4 書籍已經可以預定了,先試讀一下,可以的話買一本,支持國產大牛,豐富一下自己。不是做廣告,是發牢騷,什么時候能輪到我出書呢。
 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM