在MVC的Global.asax Application_Error 中處理全局錯誤。
如果在未到創建請求對象時報錯,此時 Context.Handler == null 。
判斷為Ajax請求時,我們返回Json對象字符串。不是Ajax請求時,轉到錯誤顯示頁面。
/// <summary> /// 全局錯誤 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> protected void Application_Error(object sender, EventArgs e) { Exception ex = Server.GetLastError(); LogHelper.Error(ex); // 記錄錯誤日志(NLog 挺好用的(* ̄︶ ̄)) if (Context.Handler == null) { return; } if (new HttpRequestWrapper(Request).IsAjaxRequest()) { Response.Clear(); Response.ContentType = "application/json; charset=utf-8"; Response.Write("{\"state\":\"0\",\"msg\":\"" + ex.Message + "\"}"); Response.Flush(); Response.End(); } else { // 方案一 重定向到錯誤頁面,帶上簡單的錯誤信息 //string errurl = "/Error/Error?msg=" + ex.Message; //Response.Redirect(errurl, true); // 方案二 帶上錯誤對象,轉到錯誤頁 Response.Clear();
RouteData routeData = new RouteData();
routeData.Values.Add("Controller", "Shared"); // 已有的錯誤控制器
routeData.Values.Add("Action", "Error"); // 自定義的錯誤頁面
Server.ClearError();
SharedController controller = new SharedController(); // 自定義錯誤頁面控制器
string errController = Request.RequestContext.RouteData.Values["Controller"].ToString();
string errAction = Request.RequestContext.RouteData.Values["Action"].ToString();
HandleErrorInfo handleErrorInfo = new HandleErrorInfo(ex, errController, errAction);
controller.ViewData.Model = handleErrorInfo; //傳錯誤信息
RequestContext requestContext = new RequestContext(new HttpContextWrapper(Context), routeData); // 封裝與已定義路由匹配的HTTP請求的信息
((IController)controller).Execute(requestContext); //執行上下文請求
Response.End(); } }
其中方案二的對象用法,與默認的錯誤頁(即 /Shared/Error.cshtml)一樣。當我們不對錯誤進行任何處理時,在web.config中可配置錯誤頁到 /Shared/Error.cshtml。
Error.cshtml的代碼:
@model System.Web.Mvc.HandleErrorInfo @{ ViewBag.Title = "系統錯誤"; Layout = "~/Views/Shared/_Layout.cshtml"; } <h3 class="text-danger">系統錯誤</h3> @if (Model != null) { <span class="text-warning">@(Model.Exception.Message)</span> } else { <span class="text-warning">處理請求時出錯。</span> }
方案二的Action的代碼:
public ActionResult Error() { return View(); }
相關配置影響:
<!--開啟會導致異常不走Application_Error,直接尋Error--> <!--<customErrors mode="On" defaultRedirect="~/Error.cshtml" />-->