Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ApiException: add synchronous [Try]GetContentAs #1591

Open
jods4 opened this issue Nov 6, 2023 · 0 comments
Open

ApiException: add synchronous [Try]GetContentAs #1591

jods4 opened this issue Nov 6, 2023 · 0 comments

Comments

@jods4
Copy link

jods4 commented Nov 6, 2023

Problem statement
When catching an ApiException, you may want to look at the response body as it could be a well known Error format.
Of course this peeking might fail: no body or not the right format.

ApiException offers T? GetContentAsAsync<T>() to deserialize the error contents.
At first glance it looks good, but in practice it falls short.

The problem is that this method can throw, or return null.
When it happens you want to fallback to a more generic catch handler, which isn't easily doable (no goto!).
The obvious solution would be to put GetContentAsAsync() in an exception filter (aka catch .. when ..).
That does not work because you can't await inside an exception filter, CLR requires synchronous filters.

Using only plain Refit API, you end up with code like this...

try
{
  try
  {
    // call a Refit API
    var response = await client.DoStuff();
  }
  catch (ApiException ex)
  {
    var error = await ex.GetContentAsAsync<Error>();
    if (error is null) throw;
    // Do Error-specific stuff
    return;
  }
}
catch (Exception ex)
{
  // Do generic exception stuff
}

Suggested solution
As the response is already buffered in a string, GetContentAs may well be sync.
(This implies one new sync method on IHttpContentSerializer).
It would also be nice if the result is non-nullable and it wouldn't throw on errors, maybe bool TryGetContentAs<T>(out T result).
(Those two requirements are not hard-requirements: 1. an exception filter that throws is equivalent to false; 2. one could do when (ex.GetContentAs<T>() is T error) to filter out nulls.)

With this, plain Refit code becomes a lot more intuitive and readable:

try
{
}
catch (ApiException ex) when (ex.TryGetContentAs<Error>(out var error))
{
  // Do something with `error`
}
catch (Exception ex)
{
  // Non-specific error handling
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant