-
Notifications
You must be signed in to change notification settings - Fork 4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
How to provide correct exception message to client #16
Comments
Could you add support for this type exceptions? something like:
or maybe there is better approach? |
Hi, First I have to apologize for such a long wait. Somehow I had muted notifications in this project and only by chance I'm responding at the moment. Hope, I got everything enabled again, so I'm more prepared next time. About exceptions and error handling:First thing to know, is that you should consider two types of exceptions: technical and non-technical errors. Technical errorsTechnical errors are usually mistakes in code or unhandled edge cases, which should be review-d and, if possible, fixed in application so that they couldn't happen again. In this library they appear as unhandled exceptions which bubble up to service request handler. The handler catches the exception and serializes it in the response as SOAP fault (as in your response sample). Usually these errors require development effort to fix. Non-technical errorsThese are errors, which are returned on purpose. Usually in return to invalid use input, some detected erroneous state in application or some other reason, when application has detected that it cannot continue with given input. Usually they are related to user input in given request and can be overcome by changing the request as required by the application. Customizing exceptional behaviorBy default, every exception is handled as technical error, but it's possible to handle the exception before serialization to get more appropriate behavior for certain system. For that you have to provide your own implementation of request handler by overriding the default one: public class CustomWebRequestHandler : WebServiceRequestHandler
{
public CustomWebRequestHandler(IServiceProvider serviceProvider, IServiceManager serviceManager)
: base(serviceProvider, serviceManager)
{ }
protected override Task OnInvocationErrorAsync(WebServiceContext context)
{
if (context.Exception is TargetInvocationException ex && ex.InnerException != null)
ExceptionDispatchInfo.Capture(ex.InnerException).Throw();
return Task.CompletedTask;
}
} To use this handler instead of default one, change the endpoints configuration in startup class: // endpoints.MapGet("/", c => c.ExecuteWsdlRequest<CalculatorServiceManager>());
endpoints.MapGet("/", c => c.ExecuteWsdlRequest<IServiceManager>());
// endpoints.MapPost("/", c => c.ExecuteWebServiceRequest<CalculatorServiceManager>());
endpoints.MapPost("/", c =>
{
using var handler = c.RequestServices.GetRequiredService<CustomWebRequestHandler>();
return XRoadLibMiddleware.Invoke(c, handler);
}); Also some dependencies need to be set up in startup class aswell: // services.AddSingleton<CalculatorServiceManager>();
services.AddSingleton<IServiceManager, CalculatorServiceManager>();
services.AddScoped<CustomWebRequestHandler>(); This should get your initial proposal working (by revealing innerexception to client) RecommendationsIn real application it might not be the best idea to display unexpected exceptions to clients (because their messages might reveal delicate info about application internals). For technical errors I would recommend instead to generate unique id for the exception, log it somewhere you can access it later, and display some generic message with error id to client. protected override Task OnInvocationErrorAsync(WebServiceContext context)
{
if (IsBusinessError(context.Exception))
{
context.Result = MapToClientError(context.Exception);
return Task.CompletedTask;
}
Guid internalErrorId = Guid.NewGuid();
// log message with internalErrorId
// ...
throw new Exception($"Internal server error (ID: {internalErrorId})")
} Also, you can provide generic implementation for non-technical errors in the same class ClientError : IXRoadFault
{
public string FaultCode { get; set; }
public string FaultString { get; set; }
} and custom behaviour (using the same example, but as another type of error result): protected override Task OnInvocationErrorAsync(WebServiceContext context)
{
// TODO : Use domain-specific exception types or some other filter to avoid exposing internal details in exceptions.
if (context.Exception is TargetInvocationException ex && ex.InnerException != null)
context.Result = new ClientError
{
FaultCode = "CODE-1234",
FaultString = ex.InnerException.Message
};
return Task.CompletedTask;
} |
@janno-p Hi, I implemented CustomWebRequestHandler and now my input validations are working. |
Hi,
What is the best way to provide exception message to the client?
Example:
Request:
Response:
Question:
You can see that the server return message Exception has been thrown by the target of an invocation.
How can I provide client with message: Attempted to divide by zero?
Thank you.
Update:
Adding stack trace.
On screen below in method
SoapMessageFormatter.CreateFault(Exception exception)
you can see that DivideByZeroException inside InnerExceptionProperty.The text was updated successfully, but these errors were encountered: