refit
refit copied to clipboard
feature: Ability to catch all exceptions, throw no exception and return a result
There are already several issues (now all closed unfortunately) related to Refit not being able to catch exceptions which are not a result of server response or due to the serialization or deserialization:
https://github.com/reactiveui/refit/issues/719 https://github.com/reactiveui/refit/issues/273
Here's an example of exceptions not currently caught by Refit:
- System.Net.Http.HttpRequestException (for example, when host is not reachable for example)
- System.Net.WebException (for example, Error: ConnectFailure (Connection refused))
- Exception due to cancelling the operation when CancellationToken was provided
These exceptions are NOT caught by the newer ExceptionFactory mechanism: https://github.com/reactiveui/refit#providing-a-custom-exceptionfactory
In a real app, as a developer, you cannot just ignore/swallow these exceptions. Many times you need to actually even show a message to the user so the user is aware. Therefore, instead of having to catch and handle these errors correctly in every app, I think it would be really very useful if correctly catching and handling all the exceptions is implemented right in the Refit library.
From an API change point of view, I'm not sure exactly how is the best to do this. @clairernovotny suggested here to have a new ApiRequestException
which will ensure the new way will be completely backward compatible and doesn't break any of the existing apps. Which sounds good.
Hi,
I found a possible issue in the class TaskToObservable
, if you create a Task which will throw an exception and you dispose the subscription before the error is thrown AND if a garbage collection is done, than you'll get an UnobservedTaskException.
I made an WPF application to reproduce this problem, If you run the application and click on the button 'Click me' you'll see an exception in red, if you click on the 'switch button', and test again you'll see that the problem is fixed.
I have the same issue
Same issue too: any news on this subject please?
I have the same issue too
same issue
Exactly same pb for me
Sorry @clairernovotny, can we have some feedback on this issue please ?
I have the same issue
I have the same issue. At some point of my code, I get entities from 3 different sources: one is directly on my database (ok) and the other two are by APIs. If getting those entities from the APIs doesn't work as expected (for example "connection refused"), I can't just show an error to my client, I must just show some alerts. I made it work using try catch, but it seems to be kind of "Go Horse", would be awesome if we could kind of "map exceptions to httpResponses" on Refit.
I am also having this issue on Android + iOS Xamarin.MAUI apps. If we use refit, the above exceptions are triggered when there is no connection. We can work around this, but it's annoying when it could be handled by refit.
Hello,
I would like to give my solution to solve this issue.
- Create a new class called
HttpRequestExceptionHandler
and inherit from theHttpClientHandler
class. - Override the
SendAsync
andSend
methods ofHttpClientHandler
. The code is as follows. -
HttpRequestExceptionHandler
as a parameter of the constructor of theHttpClient
. - Use
HttpClient
as parameter ofFor
ofRestService
.
Putting things together
-
HttpRequestExceptionHandler.cs
public class HttpRequestExceptionHandler : HttpClientHandler
{
protected override async Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request, CancellationToken cancellationToken)
{
try
{
return await base.SendAsync(request, cancellationToken);
}
catch (HttpRequestException exception)
{
// You can use other status codes, such as HttpStatusCode.GatewayTimeout etc.
return new HttpResponseMessage(HttpStatusCode.ServiceUnavailable)
{
Content = new StringContent(exception.Message),
RequestMessage = request,
};
}
}
protected override HttpResponseMessage Send(HttpRequestMessage request, CancellationToken cancellationToken)
{
try
{
return base.Send(request, cancellationToken);
}
catch (HttpRequestException exception)
{
return new HttpResponseMessage(HttpStatusCode.ServiceUnavailable)
{
Content = new StringContent(exception.Message),
RequestMessage = request,
};
}
}
}
-
App.cs
public partial class Program
{
private static readonly HttpClient _http;
static Program()
{
var handler = new HttpRequestExceptionHandler();
_http = new HttpClient(handler) { BaseAddress = new Uri("https://api.github.com") };
}
private static async Task Main()
{
var gitHubApi = RestService.For<IGitHubApi>(_http);
var octocat = await gitHubApi.GetUser("octocat");
}
}
Same issue. Any news?