Why does using using RestClient.ExecuteAsync with await fail silently when RestClient.Execute works?
I am currently working on an integration with Personio to fetch employee data.
Instead of waiting for a response, the solution below suddenly jumps out of the second method at the point commented in the code:
using Personio.Client.Configuration;
using Personio.Client.Exceptions;
using Personio.Client.Models.Data;
using LanguageExt;
using Newtonsoft.Json;
using RestSharp;
namespace Enpal.Personio.Client;
public class PersonioCompanyEmployeesClient
{
private readonly PersonioAuthorizationClient _authorizationClient;
private readonly PersonioConfig _personioConfig;
private readonly RestClient _restClient;
public PersonioCompanyEmployeesClient(PersonioAuthorizationClient authorizationClient, PersonioConfig personioConfig, RestClient restClient)
{
_authorizationClient = authorizationClient;
_personioConfig = personioConfig;
_restClient = restClient;
}
public TryAsync<List<Record>> TryGet(EmployeeRequestOptions options) =>
_authorizationClient.WithAuthorization<List<Record>>(token =>
{
_restClient.BaseUrl = new Uri(_personioConfig.BaseUrl, "/v1/company/employees");
_restClient.Timeout = -1;
IRestRequest request = new RestRequest(Method.GET)
.AddQueryParameter("limit", options.MaximumRecordCount.ToString())
.AddQueryParameter("offset", options.PageOffset.ToString())
.AddHeader("Accept", "application/json")
.AddHeader("Authorization", $"Bearer {token.Value}");
return GetRecordsAsync(request);
});
private async Task<List<Record>> GetRecordsAsync(IRestRequest request)
{
IRestResponse<RecordRequestResponse> requestResponse = await _restClient.ExecuteAsync<RecordRequestResponse>(request);
// Nothing below this line is ever executed!
if (requestResponse.IsSuccessful)
{
RecordRequestResponse? employeesResponse = JsonConvert.DeserializeObject<RecordRequestResponse>(requestResponse.Content);
return (employeesResponse != null && employeesResponse.WasSuccessful)
? employeesResponse.Records
.ToList()
: throw new PersonioRequestException("Connected to Personio, but could not get records.");
}
else
{
throw (requestResponse.ErrorException != null)
? new PersonioRequestException("Could not get records from Personio.", requestResponse.ErrorException)
: new PersonioRequestException("Could not get records from Personio. Reason unknown.");
}
}
}
However, I can make this solution work by using the synchronous method, like so:
public TryAsync<List<Record>> TryGet(EmployeeRequestOptions options) =>
_authorizationClient.WithAuthorization<List<Record>>(token =>
{
_restClient.BaseUrl = new Uri(_personioConfig.BaseUrl, "/v1/company/employees");
_restClient.Timeout = -1;
IRestRequest request = new RestRequest(Method.GET)
.AddQueryParameter("limit", options.MaximumRecordCount.ToString())
.AddQueryParameter("offset", options.PageOffset.ToString())
.AddHeader("Accept", "application/json")
.AddHeader("Authorization", $"Bearer {token.Value}");
return GetRecordsAsync(request);
});
private async Task<List<Record>> GetRecordsAsync(IRestRequest request)
{
IRestResponse<RecordRequestResponse> requestResponse = await _restClient.ExecuteAsync<RecordRequestResponse>(request);
if (requestResponse.IsSuccessful)
{
RecordRequestResponse? employeesResponse = JsonConvert.DeserializeObject<RecordRequestResponse>(requestResponse.Content);
return (employeesResponse != null && employeesResponse.WasSuccessful)
? employeesResponse.Records
.ToList()
: throw new PersonioRequestException("Connected to Personio, but could not get records.");
}
else
{
throw (requestResponse.ErrorException != null)
? new PersonioRequestException("Could not get records from Personio.", requestResponse.ErrorException)
: new PersonioRequestException("Could not get records from Personio. Reason unknown.");
}
}
The only changes:
-
GetRecords()
usesExecute
instead ofExecuteAsync
-
GetRecords()
returnsList<Record>
instead ofTask<List<Record>>
-
TryGet()
wrapsGetRecordsAsync(request)
inTask.FromResult()
before returning it.
Solution 1:
After looking at the restsharp's documentation, ExecuteAsync
does not throw an exception, but instead populates response.ErrorException
and response.ErrorMessage
if the response.IsSuccessful
equals to false so you should check first for the response.IsSuccessful
property value.
More details can be found here - https://restsharp.dev/intro.html#content-type