When an action (asp.net mvc 5) cannot find something in the database, the user must see a page with a short custom error message e.g. "Invoice 5 does not exist"
. Also, the response must have a 404
HTTP code.
Another example: when the action is improperly called, the user must see e.g. "Parameter 'invoiceId' is required"
. Also, the response must have a 400
HTTP code.
I tried to store the custom messages in the HTTP status description and to display them in custom error pages. There are two approaches (afaik):
A
mvc action:
return HttpNotFound("Invoice 5 does not exist"); OR
return new HttpStatusCodeResult(HttpStatusCode.BadRequest, "Parameter 'invoiceId' is required");
web.config:
<httpErrors errorMode="Custom">
<remove statusCode="404" />
<error statusCode="404" path="/Error/NotFound" responseMode="ExecuteURL" />
<remove statusCode="400" />
<error statusCode="400" path="/Error/BadRequest" responseMode="ExecuteURL" />
</httpErrors>
B
mvc action:
throw new HttpException(404, "Invoice 5 does not exist"); OR
throw new HttpException(400, "Parameter 'invoiceId' is required");
web.config:
<customErrors mode="On">
<error statusCode="404" redirect="~/Error/NotFound" />
<error statusCode="400" redirect="~/Error/BadRequest" />
</customErrors>
Either way, how can the HTTP status description be displayed in the custom page? How do I access it inside the NotFound/BadRequest action or view?
If this is impossible, how can a 4xx response contain a data-driven message, nicely presented to the user?
Update:
I was obsessed with using configuration but it seems impossible to push a custom string into an error page declared in web.config. Both @Carl and @V2Solutions answered only my fallback question (starting "If this is impossible..."). I would summarize their approaches like this:
C (@Carl)
Don't use web.config or HttpStatusCodeResult.
Throw exceptions, catch them in Application_Error and render custom error pages programmatically.
D (@V2Solutions)
Don't use web.config, exceptions, or HttpStatusCodeResult.
Set the status code/description directly in the Response and return whatever view you like.
BaseController :
To use in your action like this:
Create an ErrorController - this allows you to tailor your end-user error pages and status codes. Each action result accepts an exception which you can add to your route data in your application_error method in your global.asax. It doesn't have to be the exception object, it can be anything you like - just add it to the routedata in your application_error.
Your Error View:
Add a route to catch all urls to the end of your route config - this captures all 404's that are not already caught by matching existing routes:
In your global.asax:
Then when you throw
your message will be carried through and displayed to the user. You can specify at this point which status code you want to use, and extend the switch statement in the application_error.