How to keep the Server.GetLastError after Response redirecting in MVC

mathinvalidnik picture mathinvalidnik · Jan 14, 2014 · Viewed 8.9k times · Source

In my Global.asax I have defined the Application_error method :

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));
}

And the exc variable does keep the last error but After being redirected from the response in the responding method(MethodName) the Server.GetLastError() is null. How can I keep it or pass it to the Response.Redirect(String.Format("~/ControllerName/MethodName?errorType={0}" so I can have the exception in my method body as an object ?

Answer

LostInComputer picture LostInComputer · Jan 14, 2014

I would like to advise you to not redirect when there is an error so that the URL is preserved and the correct HTTP status code is set.

Instead, execute your controller inside 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));
    }
}

Then ErrorController is

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;
    }
}