I'm currently refactoring a microservice which uses RestSharp's RestClient
to call out to Personio, in order to use the latest version of RestSharp (v107), as well as to use ExecuteAsync
instead of Execute
.
I have the following method:
[SuppressMessage("Style", "IDE0053:Use expression body for lambda expressions", Justification = "lambda leave Match ambiguous.")]
public TryAsync<T> WithAuthorization<T>(Func<Token, Task<T>> doSomething, CancellationToken cancellationToken) =>
TryAsync(async () =>
{
T? result = default;
Exception? resultException = null;
TryAsync<Token> authorizationAttempt = TryAuthorize(cancellationToken);
_ = await apply(token => doSomething(token), authorizationAttempt)
.Match(
Succ: async dataTask =>
{
result = await dataTask;
},
Fail: exception =>
{
resultException = exception;
}
)
.ConfigureAwait(false);
// FIXME: Does not wait!!!!
return result
?? ((resultException == null)
? throw new PersonioRequestException("Could not get data from Personio: Reason unknown.")
: throw new PersonioRequestException($"Could not get data from Personio: {resultException.Message}", resultException)
);
});
As indicated in the code above, the method does not wait before returning the result, or as the case happens to be throwing an exception with reason unknown.
With the debugger, I've been able to determine authorizationAttempt
gets a value and doSomething()
is invoked, but while waiting for a response, the error is thrown.
The code which consumes the above method, providing the function for doSomething()
is this:
public TryAsync<RequestResponse<T>> TryGet<T>(RequestOptions options, CancellationToken cancellationToken) =>
_authorizationClient.WithAuthorization<RequestResponse<T>>(
async token =>
{
UriBuilder urlBuilder = new(_personioConfig.BaseUrl.AppendPathSegment(options.Endpoint))
{
// This is used to add parameters which are used for filtering and may be unique for the record type, such as "updated_from".
Query = options.QueryParameters.ToString()
};
RestRequest request = new(urlBuilder.Uri, Method.Get);
request.Timeout = -1;
if (options.Pagination.IsActive)
{
request = request.AddQueryParameters(options.Pagination);
}
request = request
.AddHeader("Accept", "application/json")
.AddHeader("Authorization", $"Bearer {token.Value}");
return await GetRecords<T>(request, cancellationToken);
},
cancellationToken
);
private async Task<RequestResponse<T>> GetRecords<T>(RestRequest request, CancellationToken cancellationToken)
{
RestResponse<RequestResponse<T>> requestResponse = await _restClient.ExecuteAsync<RequestResponse<T>>(request, cancellationToken);
// FIXME: The next line is never executed.
RequestResponse<T>? dataResponse = JsonConvert.DeserializeObject<RequestResponse<T>>(requestResponse?.Content ?? "");
return (requestResponse?.IsSuccessful ?? false)
? (dataResponse != null && dataResponse.WasSuccessful)
? dataResponse
: throw new PersonioRequestException("Connected to Personio, but could not get records.")
: throw (
(requestResponse?.ErrorException != null)
? new("Could not get records from Personio.", requestResponse.ErrorException)
: new($"Could not get records from Personio. {dataResponse?.Error?.Message ?? UnknownProblem}."));
}
As indicated in the code above, the method GetRecords()
is invoked, but the system throws an error from result
(back in the first method above) being unpopulated before ExecuteAsync()
has any sort of result.
An earlier form of the code, with an earlier version of RestSharp(v106) and synchronous execution worked fine. At that time, the TryGet
looked like:
public TryAsync<RequestResponse<T>> TryGet<T>(RequestOptions options) =>
_authorizationClient.WithAuthorization<RequestResponse<T>>(token =>
{
UriBuilder urlBuilder = new(_personioConfig.BaseUrl.AppendPathSegment(options.Endpoint))
{
// This is used to add parameters which are used for filtering and may be unique for the record type, such as "updated_from".
Query = options.QueryParameters.ToString()
};
_restClient.BaseUrl = urlBuilder.Uri;
_restClient.Timeout = -1;
IRestRequest request = new RestRequest(Method.GET);
if (options.Pagination.IsActive)
{
request = request.AddQueryParameters(options.Pagination);
}
request = request
.AddHeader("Accept", "application/json")
.AddHeader("Authorization", $"Bearer {token.Value}");
return Task.FromResult(GetRecords<T>(request));
});
private RequestResponse<T> GetRecords<T>(IRestRequest request)
{
IRestResponse<RequestResponse<T>> requestResponse = _restClient.Execute<RequestResponse<T>>(request);
RequestResponse<T>? dataResponse = JsonConvert.DeserializeObject<RequestResponse<T>>(requestResponse.Content);
return requestResponse.IsSuccessful
? (dataResponse != null && dataResponse.WasSuccessful)
? dataResponse
: throw new PersonioRequestException("Connected to Personio, but could not get records.")
: throw (
(requestResponse.ErrorException != null)
? new("Could not get records from Personio.", requestResponse.ErrorException)
: new($"Could not get records from Personio. {dataResponse?.Error?.Message ?? UnknownProblem}."));
}
What am I doing wrong or missing?
How can I make this work using RestSharp 107.x and ExecuteAsync()
?