简体   繁体   中英

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:

  1. GetRecords() uses Execute instead of ExecuteAsync
  2. GetRecords() returns List<Record> instead of Task<List<Record>>
  3. TryGet() wraps GetRecordsAsync(request) in Task.FromResult() before returning it.

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

I must add that RestSharp's async requests were messy until the last version. You can have a quick look at how HttpWebRequest handles async calls, and what RestSharp did to manage them, it's hardcore. I know that it worked for some, but definitely, the issues are there.

If it's still relevant for you, I would advise moving to v107. Those interfaces you use are gone, not sure how big of an issue it would be for you. But also all sync methods are gone and it's fully async now, and it works.

I had the exact same problem and it turns out the reason was because I had a synchronous call hidden in my chain. So this line: return GetRecordsAsync(request); needs to have an await, which means TryAsync should be an asynchronous call as well. I have run into similar problems in the past where not having async from top to bottom causes issues. Easiest solution is make everything async, though there are other possible solutions as well

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM