3

在我的Global.asax我已经定义Application_Error事件:如何保持Server.GetLastError响应重定向后MVC

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

的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(); 
     } 
+0

但tempDataDictionary是一个局部变量在这里。我该如何在使用Response.RidirectoTo – mathinvalidnik

+0

重定向的方法中使用它以及字典是引用类型。所以你不是指定到局部变量,但指向内存,也有更新文件关于第二个可能的解决方案 –

+0

在这种情况下,URL不会改变。我试过了。另外,这样我可以在控制器方法中执行Server.GetLastError(),并返回正确的值。 – mathinvalidnik

8

我想t o建议您在出现错误时重定向而不是,以便保留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; 
    } 
} 
+0

优秀的答案MVC 5使用!我想补充说,对于任何有问题的请求输出被发送并显示为纯文本的情况下,使用'httpContext.Response.ContentType =“text/html”;'在'routeData.Values [“exception” ] =异常;'并且应该修复它。 – petersmm

+0

有人可以解释一行“routeData.Values [”errorType“] = 10; //这是您的错误代码,可以从错误控制器中检索吗?”我不明白errorType = 10代表什么或它背后的评论的含义。 – Tomislav3008