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
}
注:クッキーを設定し、読み込みは他のどこでも動作します。 問題はリダイレクトに関連していると思いますか?
レスポンスを消去した後は、完全に機能します。答えてくれてありがとう。 – musium