Как сохранить Server.GetLastError после перенаправления ответа в MVC
В моем Global.asax я определил метод Application_error:
protected void Application_Error(object sender, EventArgs e)
{
// Code that runs when an unhandled error occurs
// Get the exception object.
var exc = Server.GetLastError();
//logics
Response.Redirect(String.Format("~/ControllerName/MethodName?errorType={0}", errorAsInteger));
}
И переменная exc сохраняет последнюю ошибку, но после перенаправления из ответа в отвечающем методе (MethodName) Server.GetLastError()
нулевой. Как я могу сохранить его или передать Response.Redirect(String.Format("~/ControllerName/MethodName?errorType={0}"
чтобы я мог иметь исключение в теле моего метода как объект?
2 ответа
Я хотел бы посоветовать вам не перенаправлять при возникновении ошибки, чтобы сохранить URL-адрес и установить правильный код состояния HTTP.
Вместо этого выполните свой контроллер внутри Application_Error
protected void Application_Error(object sender, EventArgs e)
{
var exception = Server.GetLastError();
var httpContext = ((HttpApplication)sender).Context;
httpContext.Response.Clear();
httpContext.ClearError();
ExecuteErrorController(httpContext, exception);
}
private void ExecuteErrorController(HttpContext httpContext, Exception exception)
{
var routeData = new RouteData();
routeData.Values["controller"] = "Error";
routeData.Values["action"] = "Index";
routeData.Values["errorType"] = 10; //this is your error code. Can this be retrieved from your error controller instead?
routeData.Values["exception"] = exception;
using (Controller controller = new ErrorController())
{
((IController)controller).Execute(new RequestContext(new HttpContextWrapper(httpContext), routeData));
}
}
Тогда ErrorController
public class ErrorController : Controller
{
public ActionResult Index(Exception exception, int errorType)
{
Response.TrySkipIisCustomErrors = true;
Response.StatusCode = GetStatusCode(exception);
return View();
}
private int GetStatusCode(Exception exception)
{
var httpException = exception as HttpException;
return httpException != null ? httpException.GetHttpCode() : (int)HttpStatusCode.InternalServerError;
}
}
Значение TempData сохраняется до тех пор, пока оно не будет прочитано или пока не истечет время ожидания сеанса. Сохранение TempData таким способом включает такие сценарии, как перенаправление, потому что значения в TempData доступны за пределами одного запроса.
Dictionary<string, object> tempDataDictionary = HttpContext.Current.Session["__ControllerTempData"] as Dictionary<string, object>;
if (tempDataDictionary == null)
{
tempDataDictionary = new Dictionary<string, object>();
HttpContext.Current.Session["__ControllerTempData"] = tempDataDictionary;
}
tempDataDictionary.Add("LastError", Server.GetLastError());
Тогда в вашем действии вы можете использовать
var error = TempData["LastError"];
Но вот другое решение, которое вы можете сделать без перенаправления
protected void Application_Error(object sender, EventArgs e)
{
Exception exception = Server.GetLastError();
Response.Clear();
var httpException = exception as HttpException;
var routeData = new RouteData();
routeData.Values.Add("controller", "Error");
if (httpException == null)
{
routeData.Values.Add("action", "HttpError500");
}
else
{
switch (httpException.GetHttpCode())
{
case 404:
routeData.Values.Add("action", "HttpError404");
break;
default:
routeData.Values.Add("action", "HttpError500");
break;
}
}
routeData.Values.Add("error", exception);
Server.ClearError();
IController errorController = DependencyResolver.Current.GetService<ErrorController>();
errorController.Execute(new RequestContext(new HttpContextWrapper(Context), routeData));
}
тогда в контроллере вы можете добавить действие
public ActionResult HttpError500(Exception error)
{
return View();
}