Skip to content

Instantly share code, notes, and snippets.

@jchannon
Last active August 31, 2017 01:11
This will handle Nancy content negotiation on errors so the client receives JSON, XML or HTML based on the client Accept headers
public class CustomBootstrapper : DefaultNancyBootstrapper
{
protected override void ApplicationStartup(TinyIoCContainer container, IPipelines pipelines)
{
pipelines.OnError += (ctx, exception) =>
{
ctx.Items.Add("OnErrorException", exception);
return null;
};
}
}
public class Error
{
public string ErrorMessage { get; set; }
public string FullException { get; set; }
}
public class ErrorStatusCodeHandler : IStatusCodeHandler
{
private readonly IResponseNegotiator responseNegotiator;
public ErrorStatusCodeHandler(IResponseNegotiator responseNegotiator)
{
this.responseNegotiator = responseNegotiator;
}
public bool HandlesStatusCode(HttpStatusCode statusCode, NancyContext context)
{
return statusCode == HttpStatusCode.InternalServerError;
}
public void Handle(HttpStatusCode statusCode, NancyContext context)
{
var response = new Negotiator(context);
Error error = null;
if (context.Items.ContainsKey("OnErrorException"))
{
var exception = context.Items["OnErrorException"] as Exception;
error = new Error { ErrorMessage = exception.Message, FullException = exception.ToString() };
}
response.WithModel(new ErrorPageViewModel
{
Title = "Sorry, something went wrong",
Summary = error == null ? "An unexpected error occurred." : error.ErrorMessage,
Details = error == null ? null : error.FullException
})
.WithStatusCode(statusCode)
.WithView("Error");
var errorresponse = responseNegotiator.NegotiateResponse(response, context);
context.Response = errorresponse;
}
}
@JeanTerblanche
Copy link

Thanks, this is really great but it doesn't seem to work with Hosting.AspNet - any ideas?

@MacsDickinson
Copy link

@JeanTerblanche It may not be the same issue as you are seeing but I needed to call errorresponse.PreExecute(context); to prevent a null reference exception within Nancy.Responses.MaterialisingResponse.

L35 of errorstatuscodehandler.cs becomes

var errorresponse = responseNegotiator.NegotiateResponse(response, context);
errorresponse.PreExecute(context);
context.Response = errorresponse;

@liddellj
Copy link

@MacsDickinson thank you very much - I was encountering the same issue and this fixed it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment