Jonathan Wood Jonathan Wood - 1 month ago 14
ASP.NET (C#) Question

Passing a view model with Server.TransferRequest()

I'm trying to fine-tune the error handling in my MVC application.

I've enabled custom errors in my web.config, and I added the following code to

Application_Error
.

Global.asax

protected void Application_Error(object sender, EventArgs e)
{
Exception exception = Server.GetLastError() as Exception;
if (exception != null)
{
Context.ClearError();
Context.Response.TrySkipIisCustomErrors = true;

string path = (exception is HttpException && (exception as HttpException).GetHttpCode() == 404) ?
"~/Error/NotFound" :
"~/Error/Index";
Context.Server.TransferRequest(path, false);
}
}


ErrorController.cs

[AllowAnonymous]
public ActionResult Index()
{
Response.Clear();
Response.StatusCode = 503;
Response.TrySkipIisCustomErrors = true;
return View();
}

[AllowAnonymous]
public ActionResult NotFound()
{
Response.Clear();
Response.StatusCode = 404;
Response.TrySkipIisCustomErrors = true;
return View();
}


Web.config

<system.web>
<customErrors mode="RemoteOnly" defaultRedirect="~/Error">
<error statusCode="404" redirect="~/Error/NotFound"/>
<error statusCode="500" redirect="~/Error" />
</customErrors>
</system.web>


This seems to be working fairly well. But how can I pass some error details along to my Error controller?

Also, extra points for tips on getting exception details to my Error controller for exceptions that occur within a controller.

Note: I do not want to use a redirect here. Doing so would tell crawlers like Google incorrect information about the URL.

Answer

If you want to get error details within error controller than do not clear error details (Context.ClearError()) inside Application_Error function.

Once you are in ErrorController Action fetch the last error again and then clear it.

HttpContext.Server.GetLastError()

If you want to get the the controller and action name under which exception occurred you can use below code to fetch detail

Request.RequestContext.RouteData.Values["controller"]
Request.RequestContext.RouteData.Values["action"]

Also if you want to run ErrorController and Specific Action from Application_Error function you can do something like below

   protected void Application_Error()
   {

Exception exception = Server.GetLastError();
var httpException = exception as HttpException;
Response.Clear();
Server.ClearError();
var routeData = new RouteData();
routeData.Values["controller"] = "Errors";
routeData.Values["action"] = "Common";
routeData.Values["exception"] = exception;
Response.StatusCode = 500;
if (httpException != null)
{
  Response.StatusCode = httpException.GetHttpCode();
  switch (Response.StatusCode)
{
  case 403:
    routeData.Values["action"] = "Http403";
    break;
  case 404:
    routeData.Values["action"] = "Http404";
    break;
  case 400:
    routeData.Values["action"] = "Http400";
    break;
  }
}

Response.TrySkipIisCustomErrors = true;
IController errorsController = new ErrorsController();
var rc = new RequestContext(new HttpContextWrapper(Context), routeData);

/* This will run specific action without redirecting */
errorsController.Execute(rc);

}

If you want to pass error as an object to error controller then you can add extra route data like below

routeData.Values["errorDetail"] = httpException;

Comments