2016-12-15 3 views
0

MVC 5 응용 프로그램에서 전역 예외 처리를 구현하려고합니다. 이를 위해 Global.asax.cs의 Application_Error 이벤트에 처리기를 추가했습니다.ASP.Net MVC 5 - 쿠키가 저장되지 않았습니다

내 처리기에서 서버의 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

관련 문제