This is the setting that I have. It will not redirect and processes both the application and some configured IIS errors in the same place. You can also pass on any information needed for your error controller.
In Web.config :
<system.web> <customErrors mode="Off" /> ... </system.web> <system.webServer> <httpErrors errorMode="Custom" existingResponse="Auto"> <remove statusCode="403" /> <remove statusCode="404" /> <remove statusCode="500" /> <error statusCode="403" responseMode="ExecuteURL" path="/Error/Display/403" /> <error statusCode="404" responseMode="ExecuteURL" path="/Error/Display/404" /> <error statusCode="500" responseMode="ExecuteURL" path="/Error/Display/500" /> </httpErrors> ... </system.webServer>
In ErrorController (showing method signatures for brevity only):
// This one gets called from Application_Error // You can add additional parameters to this action if needed public ActionResult Index(Exception exception) { ... } // This one gets called by IIS (see Web.config) public ActionResult Display([Bind(Prefix = "id")] HttpStatusCode statusCode) { ... }
In addition, I have an ErrorViewModel and Index ErrorViewModel .
In Application_Error :
protected void Application_Error(object sender, EventArgs e) { var exception = Server.GetLastError(); var httpContext = new HttpContextWrapper(Context); httpContext.ClearError(); var routeData = new RouteData(); routeData.Values["controller"] = "Error"; routeData.Values["action"] = "Index"; routeData.Values["exception"] = exception;
So far this is the basic setup that I have. This will not lead to redirection (the error controller action is executed from Application_Error), and it handles controller exceptions, as well as, for example, IIS 404 (for example, yourwebsite.com/blah.html).
From now on, everything that happens inside your ErrorController will be based on your needs.
As an example, I will add some additional information about my implementation. As I said, I have an ErrorViewModel .
My ErrorViewModel :
public class ErrorViewModel { public string Title { get; set; } public string Text { get; set; }
My ErrorController (relevant parts):
public ActionResult Index(Exception exception) { ErrorViewModel model; var statusCode = HttpStatusCode.InternalServerError; if (exception is HttpException) { statusCode = (HttpStatusCode)(exception as HttpException).GetHttpCode(); // More details on this below if (exception is DisplayableException) { model = CreateErrorModel(exception as DisplayableException); } else { model = CreateErrorModel(statusCode); model.Exception = exception; } } else { model = new ErrorViewModel { Exception = exception }; } return ErrorResult(model, statusCode); } public ActionResult Display([Bind(Prefix = "id")] HttpStatusCode statusCode) { var model = CreateErrorModel(statusCode); return ErrorResult(model, statusCode); } private ErrorViewModel CreateErrorModel(HttpStatusCode statusCode) { var model = new ErrorViewModel(); switch (statusCode) { case HttpStatusCode.NotFound: // Again, this is only relevant to my business logic. // You can do whatever you want here model.ContentResourceKey = "error-page-404"; break; case HttpStatusCode.Forbidden: model.Title = "Unauthorised."; model.Text = "Your are not authorised to access this resource."; break; // etc... } return model; } private ErrorViewModel CreateErrorModel(DisplayableException exception) { if (exception == null) { return new ErrorViewModel(); } return new ErrorViewModel { Title = exception.DisplayTitle, Text = exception.DisplayDescription, Exception = exception.InnerException }; } private ActionResult ErrorResult(ErrorViewModel model, HttpStatusCode statusCode) { HttpContext.Response.Clear(); HttpContext.Response.StatusCode = (int)statusCode; HttpContext.Response.TrySkipIisCustomErrors = true; return View("Index", model); }
In some cases, I need to display a custom message when an error occurs. I have a special exception for this purpose:
[Serializable] public class DisplayableException : HttpException { public string DisplayTitle { get; set; } public string DisplayDescription { get; set; } public DisplayableException(string title, string description) : this(title, description, HttpStatusCode.InternalServerError, null, null) { } public DisplayableException(string title, string description, Exception exception) : this(title, description, HttpStatusCode.InternalServerError, null, exception) { } public DisplayableException(string title, string description, string message, Exception exception) : this(title, description, HttpStatusCode.InternalServerError, message, exception) { } public DisplayableException(string title, string description, HttpStatusCode statusCode, string message, Exception inner) : base((int)statusCode, message, inner) { DisplayTitle = title; DisplayDescription = description; } }
Then I use it as follows:
catch(SomeException ex) { throw new DisplayableException("My Title", "My custom display message", "An error occurred and I must display something", ex) }
In my ErrorController I handle this exception separately, setting the ErrorViewModel Title and Text properties from this DisplayableException .