Custom error handling #318
-
Hi, Is there a way to configure custom error handling / error provider? E.g. I would like to setup error provider for my json API to only output json equivalent of the error message as a payload. That will provide more information to the API consumer, compared to the unstructured HTML that is outputted by default. I've noticed that it is probably just hardcoded to the server core - or am I misinterpreting this? I would like to inject my own error handler implementation for specific layouts in my server. Or at least my own implementation server-wide or instruct the default error provider to output the error model as json. Thank you. |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 5 replies
-
The To respond with JSON, you would currently need to clone the
Just created #319 for this. |
Beta Was this translation helpful? Give feedback.
-
So I tried this, the server responds with correct HTTP error code, but it keeps the connection open until it times out. Not sure what I might be doing wrong. internal class JsonErrorHandlerBuilder : IConcernBuilder
{
public IConcern Build(IHandler parent, Func<IHandler, IHandler> contentFactory)
{
return new JsonErrorHandler(parent, contentFactory);
}
}
internal class JsonErrorHandler : IConcern
{
public IHandler Content { get; }
public IHandler Parent { get; }
public JsonErrorHandler(IHandler parent, Func<IHandler, IHandler> contentFactory)
{
Parent = parent;
Content = contentFactory(this);
}
public ValueTask PrepareAsync() => Content.PrepareAsync();
public IEnumerable<ContentElement> GetContent(IRequest request) => Content.GetContent(request);
public async ValueTask<IResponse> HandleAsync(IRequest request)
{
try
{
var response = await Content.HandleAsync(request)
.ConfigureAwait(false);
if (response is null)
{
return Content.GetNotFound(request).Build();
}
return response;
}
catch (ProviderException e)
{
var model = new ErrorModel((int)e.Status, e.Message, e);
return request.Respond()
.Content(new JsonContent(model, JsonOptions.Default))
.Status(e.Status)
.Build();
}
catch (Exception e)
{
var model = new ErrorModel((int)ResponseStatus.InternalServerError, e.Message, e);
return request.Respond()
.Content(new JsonContent(model, JsonOptions.Default))
.Status(ResponseStatus.InternalServerError)
.Build();
}
}
private record ErrorModel(int ErrorCode, string Message, Exception Exception);
} Setup: var api = Layout
.Create()
.Authentication(apiAuth)
.Add(new JsonErrorHandlerBuilder())
.AddService("auth", new AuthService(authController))
.AddService("exchanges", new ExchangeService(exchanges))
...
.AddService("utility", new UtilityService(strategies))
;
var httpContent = Layout
.Create()
.Add("api", api)
.Add(CorsPolicy.Permissive())
.Fallback(SinglePageApplication.From(ResourceTree.FromDirectory("www")))
;
var server = Host
.Create()
.Handler(httpContent)
.Defaults()
.Port(Settings.Default.Port)
#if DEBUG
.Development()
#endif
.Start(); |
Beta Was this translation helpful? Give feedback.
The
ErrorHandlingProvider
on root level will look for anIErrorHandler
instance in the routing chain to actually render an error to HTML. This allows, for example, theWebsiteRouter
to render error messages in the style of the chosen theme. Nevertheless, this approach can only be used to render HTML error pages because the result of the renderer is embedded into the current template.To respond with JSON, you would currently need to clone the
ErrorHandlingProvider
and add it as a concern to your webservice router. Something like: