女友不是想拋就拋,但異常卻能夠,不信請往下看。html
今天在MVC Controller中寫代碼時,糾結了一下:ajax
public async Task<ActionResult> Save(int? postId) { if(!IsOwner(postId.Value, userId)) { //拋不拋異常呢? } }
在這個地方要不要拋異常呢?json
若是不拋異常,就得這麼寫:app
public async Task<ActionResult> Save(int? postId) { if(!IsOwner(postId.Value, userId)) { return Json(new { isSuccess = false, message = "嘗試執行未經受權的操做" }); } }
並且一般在這樣的狀況下,還須要記錄日誌,因而代碼變成:async
if(!IsOwner(postId.Value, userId)) { Logger.Default.Info("UnauthorizedSave", "..."); return Json(new { isSuccess = false, message = "嘗試執行未經受權的操做" }); }
若是拋異常呢,代碼就能夠這麼寫:post
if(IsOwner(postId.Value, userId)) { throw new UnauthorizedAccessException(); }
代碼顯得更簡潔,更具表達力,並且記錄錯誤日誌能夠在Application_Error中統一處理:url
protected void Application_Error(Object sender, EventArgs e) { var lastError = Server.GetLastError(); if (lastError != null) { Logger.Default.Error("Application_Error", lastError); Response.StatusCode = 500; Server.ClearError(); } }
但這會帶來一個問題,客戶端收到的將是自定義500錯誤頁面的html代碼,不只沒有具體的錯誤信息,並且在ajax回調時還要額外處理,而一般咱們最期待的是一個json格式的返回結果。spa
因而要想實現「想拋就拋」,就必須解決:如何在Application_Error中統一處理ajax請求處理過程當中產生的異常,並將之轉換成json格式的響應內容返回給客戶端。日誌
分解一下,就變成了2個問題:code
1)如何在Application_Error中判斷一個請求是不是ajax請求?
今天上午經過MVC的擴展方法IsAjaxRequest解決了,詳見如何在Global.asax中判斷是不是ajax請求:
if ((new HttpRequestWrapper(Request)).IsAjaxRequest()) { }
2)如何生成json格式的響應內容並返回給客戶端?
這個能夠經過Json.NET+Response.Write來解決,代碼以下:
Response.Clear(); Response.ContentType = "application/json; charset=utf-8"; Response.Write(Newtonsoft.Json.JsonConvert.SerializeObject( new { isSuccess = false, message = lastError.Message })); Response.Flush();
最終實現「想拋就拋」的代碼以下:
protected void Application_Error(Object sender, EventArgs e) { var lastError = Server.GetLastError(); if (lastError != null) { CNBlogs.Infrastructure.Logging.Logger.Default.Error("Application_Error", lastError); if(Request != null && (new HttpRequestWrapper(Request)).IsAjaxRequest()) { Response.Clear(); Response.ContentType = "application/json; charset=utf-8"; Response.Write(Newtonsoft.Json.JsonConvert.SerializeObject( new { isSuccess = false, message = lastError.Message })); Response.Flush(); Server.ClearError(); return; } Response.StatusCode = 500; Server.ClearError(); } }
ajax客戶端收到的結果以下:
今後,能夠盡情地拋異常了。