2016-12-15 12 views
0

MVC 5アプリケーションでグローバル例外処理を実装しようとしています。 これを達成するために、Global.asax.csのApplication_Errorイベントにハンドラを追加しました。ASP.Net MVC 5 - Cookieが保存されていない

私のハンドラーでは、サーバーのGetLastErrorからエラーの詳細を読みました。 エラーの詳細をクッキーに保存し、エラーコントローラにリダイレクトしてクッキーを読み取り、エラーの詳細をユーザーに表示します。

クッキーは正しく設定されますが、エラーコントローラでそのクッキーを読み取ろうとするとクッキーは存在しません。

これは私のコードです:

protected void Application_Error(Object sender, EventArgs e) 
{ 
    const String route = "Default"; 
    const String controller = "Errors"; 
    const String area = ""; 
    var action = "InternalServerError"; 
    var errorCode = 500; 

    try 
    { 
     // Get the previous exception. 
     var exception = Server.GetLastError() ?? new HttpException((Int32) HttpStatusCode.InternalServerError, "Unknown internal server error occurred."); 
     // Clear the exception 
     Server.ClearError(); 
     // Bypass IIS custom errors 
     Response.TrySkipIisCustomErrors = true; 

     // Check for HTTP code 
     var httpException = exception as HttpException; 
     if (httpException != null) 
      errorCode = httpException.GetHttpCode(); 

     // ReSharper disable once SwitchStatementMissingSomeCases 
     switch (errorCode) 
     { 
      case 401: 
      case 403: 
       action = "Forbidden"; 
       break; 
      case 404: 
       action = "NotFound"; 
       break; 
     } 

     // Try to collect some error details 
     try 
     { 
      var details = new WebErrorDetails 
      { 
       Exception = exception, 
       ErrorSource = HttpContext.Current.Request.Url.ToString() 
      }; 

      HttpContext.Current.Response.Cookies.Set(new HttpCookie(CommonConstants.ErrorDetails, JsonConvert.SerializeObject(details)) 
      { 
       Expires = DateTime.Now.Add(2.ToMinutes()), 
       HttpOnly = true 
      }); 
     } 
     catch 
     { 
      // ignore 
     } 

     Response.RedirectToRoute(route, new RouteValueDictionary(new { area, controller, action })); 
    } 
    catch 
    { 
     Response.RedirectToRoute(route, new RouteValueDictionary(new { area, controller, action = "InternalServerError" })); 
    } 
} 


public class ErrorsController : ControllerBase 
{ 
    #region Ctor 

    /// <summary> 
    ///  Initialize a new instance of the <see cref="ErrorsController" /> class. 
    /// </summary> 
    /// <param name="loggerFactory">A <see cref="ILoggerFactory" />.</param> 
    public ErrorsController(ILoggerFactory loggerFactory) 
     : base(loggerFactory.CreateLogger(typeof(ErrorsController))) 
    { 
     Logger.Trace("Enter."); 
    } 

    #endregion 

    #region Private Members 

    [NotNull] 
    private WebErrorDetails PopErrorDetails() 
    { 
     try 
     { 
      // GetRequestCookie looks like this => HttpContext.Current.Request.Cookies[cookieName]; 
      var cookie = HttpContextService.GetRequestCookie(CommonConstants.ErrorDetails); 
      if (cookie != null) 
      { 
       var errorDetails = JsonConvert.DeserializeObject<WebErrorDetails>(cookie.Value); 
       if (errorDetails != null) 
        return errorDetails; 
      } 
     } 
     catch (Exception ex) 
     { 
      Logger.Warn(ex, "Failed to pop error details."); 
     } 

     // Fall-back value 
     return new WebErrorDetails 
     { 
      Exception = new Exception("Exception details missing."), 
      ErrorSource = "-" 
     }; 
    } 

    private void StoreErrorDetails(WebErrorDetails errorDetails) 
    { 
     try 
     { 
      HttpContextService.AddCookieToResponse(new HttpCookie(CommonConstants.ErrorDetails, JsonConvert.SerializeObject(errorDetails)) 
                { 
                 Expires = DateTime.Now.Add(2.ToMinutes()), 
                 HttpOnly = true 
                }); 
     } 
     catch (Exception ex) 
     { 
      Logger.Warn(ex, "Failed to store error details."); 
     } 
    } 

    #endregion 

    #region Action Methods 

    /// <summary> 
    ///  Returns a error view for 500 internal server errors. 
    /// </summary> 
    /// <returns>Returns a error view for 500 internal server errors.</returns> 
    public async Task<ActionResult> InternalServerError() 
    { 
     Logger.Info("Enter error action method."); 
     WebErrorDetails errorDetails = null; 
     try 
     { 
      errorDetails = PopErrorDetails(); 

      // Get the layout view model 
      var layoutVm = await PrepareLayoutViewModel(); 

      // Build the view model 
      var vm = new LayoutApplicationErrorViewModel 
      { 
       Exception = errorDetails.Exception, 
       ErrorSource = errorDetails.ErrorSource, 
       ViewTitle = CommonResources.Common_Static_InternalServerError 
      }; 
      HttpContextService.StatusCode = (Int32) HttpStatusCode.InternalServerError; 

      // Set the layout view model 
      SetLayoutData(layoutVm, vm); 

      return View("Error", vm); 
     } 
     catch (Exception ex) 
     { 
      try 
      { 
       Logger.Error(ex, "Unexpected exception occurred."); 
       if (errorDetails != null) 
        StoreErrorDetails(errorDetails); 
       else 
        StoreErrorDetails(new WebErrorDetails 
             { 
              ErrorSource = HttpContextService.RequestUrl.ToString(), 
              Exception = ex 
             }); 
      } 
      catch 
      { 
       // ignore 
      } 
      return RedirectToAction("GeneralError", "Errors"); 
     } 
    } 

    /// <summary> 
    ///  Returns a general error view without any layout. 
    /// </summary> 
    /// <returns>Returns a general error view without any layout.</returns> 
    public ActionResult GeneralError() 
    { 
     Logger.Info("Enter general error action method."); 

     try 
     { 
      // Build the view model 
      var errorDetails = PopErrorDetails(); 
      var vm = new LayoutApplicationErrorViewModel 
      { 
       Exception = errorDetails.Exception, 
       ErrorSource = errorDetails.ErrorSource, 
       ViewTitle = "Error" 
      }; 
      HttpContextService.StatusCode = (Int32) HttpStatusCode.InternalServerError; 

      return View(vm); 
     } 
     catch (Exception ex) 
     { 
      Logger.Fatal(ex, "Could not display basic error view."); 
     } 
    } 

    #endregion 
} 

注:クッキーを設定し、読み込みは他のどこでも動作します。 問題はリダイレクトに関連していると思いますか?

答えて

1

//応答をクリアします。

Response.Clear(); 
+0

レスポンスを消去した後は、完全に機能します。答えてくれてありがとう。 – musium

関連する問題