Can't handle SCIM Internal Server Errors
We need a way to handle Internal server errors (500) generated in SCIM APIs that allows to handle the request in a different way and possibly return different responses other than 500 in the case of a known issue that should not be 500 but for example 400 instead.
The problem is those controllers are wrapped inside a try {... } catch (Exception ex) {} that catches all exceptions of all types in the BulkController.cs and the BaseApiController.cs.
While I could write a middleware that checks if the response status code was 500, it is too late and the response was already sent to the client.
Possible solutions would be:
-
Re-throw the exception so it can be handled by the host application or some middleware.
-
Add a configuration event that is called when there is an internal server error, that receives the exception and the context with the request/response information, and returns whether the error was handled or not. So in the Startup service configuration a new option would be:
services.AddSIDScim(options =>
{
....
options.OnInternalServerError = MyOnInternalServerErrorHandler
});
function bool MyOnInternalServerErrorHandler(HttpContext context, Exception exception) {
bool isHandled = false;
if (IsKnownIssue(exception)) {
context.Response.StatusCode = (int)HttpStatusCode.BadRequest;
context.Response.ContentType = MediaTypeNames.Application.Json;
isHandled = true;
}
return isHandled ;
}
Then in SCIM BaseApiController.cs:
....
catch(Exception ex)
{
var isHandledError = _options.OnInternalServerError?.Invoke(HttpContext, ex) ?? false;
if (!isHandledError ) {
_logger.LogError(ex, ex.Message);
return this.BuildError(HttpStatusCode.InternalServerError, ex.Message, SCIMConstants.ErrorSCIMTypes.InternalServerError);
}
}
Hello,
First thank you for your proposal :)
We have made some changes in the release\4.0.4 branch to support your requirement.
You can easily subscribe to internal server errors like this and return a custom error message.
If NULL is returned, then the default result will be returned. The function takes the following parameters on entry:
- HttpContext
- Exception
- CancellationToken
services.AddSIDScim(_ =>
{
_.IgnoreUnsupportedCanonicalValues = false;
_.IsNoContentReturned = false;
_.SCIMEvents = new SCIMHostEvents
{
OnInternalServerError = async (ctx, e, c) =>
{
var contentResult = new ContentResult();
contentResult.StatusCode = 400;
contentResult.Content = JsonSerializer.Serialize(new
{
message = "hello"
});
contentResult.ContentType = "application/json";
return contentResult;
}
};
});
KR,
SID
Thanks a lot! that's exactly what we needed in our project. I could not test it though because we need to migrate first to the latest version, but once we do we will use this!