This work is heavily influenced by Paul Stovell's excellent Consistent error handling with Nancy article.
- Simple setup of custom views for error pages, 404 pages and authorization/authentication failure pages
- Supports any Nancy view engine
- Will send JSON serialized representation of errors if client has requested JSON
- Easily add support for custom error handling logic or for mapping application specific exception types to appropriate error responses
Use Nuget!
Install-Package Nancy.CustomErrors
Custom error handling is set up in the ApplicationStartup method of your Nancy Bootstrapper. In its simplest form, your simply call Nancy.CustomErrors.Enable, passing an IPipelines instance.
protectedoverridevoidApplicationStartup(TinyIoCContainercontainer,IPipelinespipelines){base.ApplicationStartup(container,pipelines);// ...CustomErrors.Enable(pipelines);}In this form, default configuration options will be assumed. The default configuration assumes the following
- Any and all unhandled exceptions will generate a response with a 500 HTTP status code
- Any request with an Accept header containing a recognised json type will be served with a JSON representation of the error, rather than a rendered view
Note that if you are using the Nancy.Elmah package, ElmahLogging.Enable() should be called before CustomErrors.Enable()
Setting up custom configuration is a simple case of implementing an configuration class that extends Nancy.CustomErrors.CustomErrorsConfiguration, and passing an instance of the class along in the call to CustomErrors.Enable()
publicclassMyErrorConfiguration:Nancy.CustomErrors.CustomErrorsConfiguration{publicMyErrorConfiguration():base(){// Map error status codes to custom view namesErrorViews[HttpStatusCode.NotFound]="CustomNotFoundView";ErrorViews[HttpStatusCode.InternalServerError]="CustomErrorView";ErrorViews[HttpStatusCode.Forbidden]="Forbidden";}// Custom redirection handler for an unauthorised request// Returning an empty string will result in the response being sent with HttpStatusCode.Forbidden// Otherwise, return the url to redirect the client to. publicoverridestringGetAuthorizationUrl(NancyContextcontext){if(context.CurrentUser==null){return"/accounts/login"}returnString.Empty;}// Custom mapping of a thrown exception to an ErrorResponse with status code// The implementation in this example is the default implementation used in// Nancy.CustomErrors.CustomErrorConfiguration. Override this if you need to// Map custom exception types to different status codes, or error objects.// An example might be to map a custom security exception to HttpForbidden status// code, rather than the default InternalServerError status codepublicoverrideErrorResponseHandleError(NancyContextcontext,Exceptionex,ISerializerserializer){varerror=newError{FullException=ex.ToString(),Message=ex.Message};returnnewErrorResponse(error,serializer).WithStatusCode(HttpStatusCode.InternalServerError)asErrorResponse;}}Once you've implemented a custom error handling configuration, just pass it along in the CustomErrors.Enable call in your bootstrapper
protectedoverridevoidApplicationStartup(TinyIoCContainercontainer,IPipelinespipelines){base.ApplicationStartup(container,pipelines);// ...CustomErrors.Enable(pipelines,newMyErrorConfiguration());}Your error views will be rendered with a simple object model, containing a Title, Summary and optional Details field. All fields are c# string type.
We use whatever view engine is presently configured in your project. By default you will need to create a single view resolved by the name "Error" to handle all error types. If you would like to use different views for different status codes, just set up a custom configuration as shown above.
Here is a simple example using the Razor view engine
@inherits Nancy.ViewEngines.Razor.NancyRazorViewBase<dynamic><h1>Ouch!</h1><h2>@Model.Title</h2><p>@Model.Summary</p><p>@Model.Details</p>