2016-03-15 36 views
1

我試圖實現自定義的錯誤在我的asp.net mvc的5應用程序處理,使用相同的技術,我一直使用:MVC 5自定義錯誤頁中使用Autofac

protected void Application_Error(object sender, EventArgs e) 
    { 
     try 
     { 

      HandleApplicationErrors(); 
      Response.TrySkipIisCustomErrors = true; 
     } 
     catch(Exception ex) 
     { 
      Response.Write(ex.ToString()); 
      Response.StatusCode = 500;   
     } 
    } 

private void HandleApplicationErrors(int? statusCode = null) 
    { 
     try 
     { 
      Exception ex = Server.GetLastError(); 
      Response.Clear(); 

      HttpException httpEx = ex as HttpException; 
      if (statusCode == null && httpEx != null) statusCode = httpEx.GetHttpCode(); 

      RouteData routeData = new RouteData(); 
      routeData.Values.Add("controller", "Error"); 

      switch (statusCode) 
      { 
       case 404: 
        routeData.Values.Add("action", "NotFound"); 
        break; 
       case 403: 
        routeData.Values.Add("action", "Forbidden"); 
        break; 
       default: 
        routeData.Values.Add("action", "ServerError"); 
        break; 
      } 

      routeData.Values.Add("exception", ex); 

      Server.ClearError(); 
      this.Server.ClearError(); 
      this.Response.TrySkipIisCustomErrors = true; 
      IController controller = new ErrorController(); 
      controller.Execute(new RequestContext(new HttpContextWrapper(this.Context), routeData)); 
     } 
     catch(Exception ex) 
     { 
      Response.Write(ex.ToString()); 
      Response.StatusCode = 500; 
     } 
    } 

這工作就好了在過去,但是在這個應用程序中,我使用的是Autofac,而且它正在拋出「實例無法解析,並且嵌套的生命週期無法在此LifetimeScope中創建,因爲它已經處理完畢。」在controller.Execute線上。我已經嘗試從autofac註冊中排除ErrorController(它不具有和構造函數參數)並直接構造它。

控制器代碼非常簡單:

 private CustomErrorModel GetModel(Exception ex) 
    { 

     var model = new CustomErrorModel(); 
     model.RequestedUrl = Request.Url.OriginalString; 
     model.ReferrerUrl = (Request.UrlReferrer == null || model.RequestedUrl == Request.UrlReferrer.OriginalString) ? null : Request.UrlReferrer.OriginalString; 
     model.Exception = ex; 
     return model; 

    } 

    public ActionResult ServerError(Exception ex) 
    { 
     var model = GetModel(ex); 

     Response.StatusCode = (int)HttpStatusCode.InternalServerError; 
     Response.Status = "500 Internal Server Error"; 
     return View(model); 
    } 

任何人有使這項工作任何想法?

+0

錯誤控制器的構造函數呢?有一個嗎?我正在做與你完全一樣的事情(包括使用Autofac)並且沒有任何問題。 –

+0

錯誤控制器沒有構造函數。這一切在不使用autofac時都有效。順便說一句,我也嘗試了一個空的默認構造函數。 –

+1

實際上,我認爲你的問題是你的控制器中的'ServerError'動作將參數定義爲'ex',但是在'HandleApplicationErrors'中,你將它的路由參數設置爲'exception'。更改以使它們匹配,並且它會按預期工作。 –

回答

1

我做我的應用程序非常類似的事情,包括使用Autofac依賴注入,並沒有和你一樣看到同樣的問題。

仔細查看您的HandleApplicationErrors方法,我注意到您的路線數據與您的ServerError操作期望的參數不匹配。

HandleApplicationErrors,你傳遞一個名爲exception

參數ServerError,你期待一個名爲ex

參數更新路由數據的設定以符合像這樣:

routeData.Values.Add("ex", ex); 

將解決該問題。

0

「請求壽命本身設置在EndRequest事件。你 可以在引用了MVC整合其被自動添加 到您的管道RequestLifetimeHttpModule看到這一點。 很可能是一個競爭條件,其中Autofac事件處理程序 正在您自己的EndRequest事件處理程序之前觸發,這可能是現在最可能出現的 ,這是因爲最近的Autofac集成 嘗試進行模塊註冊等,因此開發人員無法更改到 ,所以我們註冊了模塊在預申請開始。我們 訂閱ev首先,所以我們先打電話。

不幸的是,從 Autofac側真的沒有太多的事要做 - EndRequest是管道中的最後一個事件,我們必須處置生命週期範圍,所以這就是它發生的地方。

如果您在EndRequest中處理需要解決的問題,則可能爲時已晚。即使在以前的集成中,EndRequest也會有風險。例如,如果您解決了一個對象 實現了IDisposable,則在 EndRequest上釋放的生命週期範圍將處理該對象,並且您將與 對象處於不良狀態。

我建議在EndRequest之前嘗試將您的操作執行移至 。或者,如果您100%確定鏈中的對象不是IDisposable,則可以在早期事件中解析對象 ,將其存儲在HttpContext.Items中,然後從那裏檢索它 以用於EndRequest處理程序」

字體:https://github.com/autofac/Autofac/issues/570

+0

我有點困惑於此,我沒有使用容器或試圖解決Application_Error處理程序中的任何事情。 –

+0

那麼,當使用autofac時,推薦的處理錯誤的方法是什麼,因爲我讀的所有內容都指向了使用我正在使用的技術..似乎我必須選擇autofac或自定義錯誤頁面? –

1

好吧,這裏回答我的問題,我看了一下堆棧跟蹤,似乎異常是由MVC試圖用容器找到模型綁定引起的。 ..所以我讓我的動作方法無參數並且解決了它!

參考發帖代碼在這裏:

protected void Application_Error(object sender, EventArgs e) 
{ 
    try 
    { 

     HandleApplicationErrors(); 
     Response.TrySkipIisCustomErrors = true; 
    } 
    catch(Exception ex) 
    { 
     Response.Write(ex.ToString()); 
     Response.StatusCode = 500;   
    } 
} 

private void HandleApplicationErrors(int? statusCode = null) 
{ 
    try 
    { 
     Exception ex = Server.GetLastError(); 
     Response.Clear(); 

     HttpException httpEx = ex as HttpException; 
     if (statusCode == null && httpEx != null) statusCode = httpEx.GetHttpCode(); 

     RouteData routeData = new RouteData(); 
     routeData.Values.Add("controller", "Error"); 

     switch (statusCode) 
     { 
      case 404: 
       routeData.Values.Add("action", "NotFound"); 
       break; 
      case 403: 
       routeData.Values.Add("action", "Forbidden"); 
       break; 
      default: 
       routeData.Values.Add("action", "ServerError"); 
       break; 
     } 

     //routeData.Values.Add("exception", ex); 

     Server.ClearError(); 
     this.Server.ClearError(); 
     this.Response.TrySkipIisCustomErrors = true; 
     IController controller = new ErrorController(); 
     controller.Execute(new RequestContext(new  HttpContextWrapper(this.Context), routeData)); 
    } 
    catch(Exception ex) 
    { 
     Response.Write(ex.ToString()); 
     Response.StatusCode = 500; 
    } 
} 

和我的控制器方法:

public ActionResult ServerError() 
{ 
    HttpException ex = Server.GetLastError() as HttpException; 
    var model = GetModel(ex); 
    Response.StatusCode = (int)HttpStatusCode.InternalServerError; 
    Response.Status = "500 Internal Server Error"; 
    return View(model); 
}