`HubException` message is always "wrapped", contrary to documentation
Is there an existing issue for this?
- [x] I have searched the existing issues
Is your feature request related to a problem? Please describe the problem.
According to the SignalR documentation, when throwing a HubException from a hub method, SignalR should "[send] the entire exception message to the client, unmodified." However, the actual behavior wraps the message:
// Server
throw new HubException("{\"code\":0}");
// Client receives
"An unexpected error occurred invoking 'MethodName' on the server. HubException: {\"code\":0}"
This is caused by ErrorMessageHelper.BuildErrorMessage() which - in the case of HubException - formats the message as:
https://github.com/dotnet/aspnetcore/blob/a9aaa320f1c4c771b2dee8c000409a5f04397339/src/SignalR/server/Core/src/Internal/ErrorMessageHelper.cs#L10-L13
This occurs when throwing the exception from a hub method and from a filter.
Describe the solution you'd like
The HubException.Message should be passed through unmodified to the client, as documented.
Alternatively, update the documentation to clarify this behaviour.
Additional context
Here is a sample use-case:
Passing JSON error payloads to clients:
// Server
throw new HubException("{\"code\":\"USER_NOT_FOUND\"}");
// Client receives
"An unexpected error occurred invoking 'GetUser' on the server. HubException: {\"code\":\"USER_NOT_FOUND\"}"
The client cannot directly deserialize this as JSON without first stripping the prefix.
This is similar to the following issues:
- #7722
- #12633
- #11891
However I feel it is different enough to warrant a separate report.
If this behaviour is not desired, what is the recommended method for handling/parsing errors on the client?
Sure, we could be a little clearer in the docs. A few lines up in the doc we give an example of a non-HubException error that's returned to the client, so we can probably include an example with a HubException.
If you want to parse the error then it should be easy to strip the prefix JSON.parse(error.split('HubException: ')[1])
Parsing out the string from SignalR feels like a fragile solution for dealing with errors. Is there a reason that explicit HubException exceptions thrown by user code need to be wrapped?
Having the ability to create an IHubFilter that catches known exceptions in hub methods and return well-formed error messages/codes is quite powerful (and follows a similar pattern to ASP .NET Core IExceptionFilter). If the appetite for changing the existing implementation is not there, introducing an IHubExceptionFilter interface to customize the error handling could also be a nice addition. This could be made backwards compatible (e.g. no exception filter = current behaviour).