You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Create ApiRequestException for wrapping SendAsync exceptions (#2052)
* Create ApiRequestException for wrapping SendAsync exceptions
* Remove commented line, fix spelling errors
* chore: Update readme for V11 breaking change, update verified API approval tests, fix TargetFramework of Stub Generators
- V10 has been released, so next major release is V11
- API Approval tests were failing due to the breaking changes
- The .NET 10 SDK has issues parsing `TargetFrameworks` with just a single entry. Changed to `TargetFramework` (singular)
* test: Update .NET 10 verified API approval tests
* test: Update ApiApprovalTests
---------
Co-authored-by: Chris Pulman <chris.pulman@yahoo.com>
@@ -112,6 +113,24 @@ Refit 6.3 splits out the XML serialization via `XmlContentSerializer` into a sep
112
113
is to reduce the dependency size when using Refit with Web Assembly (WASM) applications. If you require XML, add a reference
113
114
to `Refit.Xml`.
114
115
116
+
### V11.x.x
117
+
118
+
#### Breaking changes in 11.x
119
+
120
+
Refit 10 introduces `ApiRequestException` to represent requests that fail before receiving a response from the server.
121
+
This exception will now wrap previous exceptions such as `HttpRequestException` and `TaskCanceledException` when they occur during request execution.
122
+
123
+
* If you were not wrapping responses with `IApiResponse` and were catching these exceptions directly, you will need to update your code to catch `ApiRequestException` instead.
124
+
* If you were wrapping responses with `IApiResponse`, these exceptions will no longer be thrown and will instead be captured in the `IApiResponse.Error` property.
125
+
You can use the new `IApiResponse.HasRequestError(out var apiRequestException)` method to safely check and retrieve the `ApiRequestException` instance.
126
+
127
+
The `IApiResponse.Error` property's type has also changed to `ApiExceptionBase`, which is the new base class for `ApiException` and `ApiRequestException`.
128
+
If your code accessed members specific to `ApiException` (i.e. anything related to the response from the server), you can use the new `IApiResponse.HasResponseError(out var apiException)` method to safely check and retrieve the `ApiException` instance.
129
+
130
+
All response-related properties of `IApiResponse` are now nullable.
131
+
The new `IApiResponse.IsReceived` property can be used to check if a response was received from the server, and will mark those properties as non-null.
132
+
The original `IApiResponse.IsSuccessful` and `IApiResponse.IsSuccessStatusCode` properties can still be used to check if the response was received and is successful.
133
+
115
134
### API Attributes
116
135
117
136
Every method must have an HTTP attribute that provides the request method and
//Finally, retrieving the content in the response body as a strongly-typed object
1137
-
varuser=response.Content;
1150
+
//Looping through all the headers
1151
+
foreach(varheaderinresponse.Headers)
1152
+
{
1153
+
varheaderName=header.Key;
1154
+
varheaderValue=string.Join(',', header.Value);
1155
+
}
1156
+
1157
+
//Finally, retrieving the content in the response body as a strongly-typed object
1158
+
varuser=response.Content;
1159
+
}
1138
1160
```
1139
1161
1140
1162
### Using generic interfaces
@@ -1402,7 +1424,9 @@ Refit also ships analyzers for newer Roslyn toolchains, including a Roslyn 5.0 b
1402
1424
Refit has different exception handling behavior depending on if your Refit interface methods return `Task<T>` or if they return `Task<IApiResponse>`, `Task<IApiResponse<T>>`, or `Task<ApiResponse<T>>`.
1403
1425
1404
1426
#### <aid="when-returning-taskapiresponset"></a>When returning `Task<IApiResponse>`, `Task<IApiResponse<T>>`, or `Task<ApiResponse<T>>`
1405
-
Refit traps any `ApiException` raised by the `ExceptionFactory` when processing the response, and any errors that occur when attempting to deserialize the response to `ApiResponse<T>`, and populates the exception into the `Error` property on `ApiResponse<T>` without throwing the exception.
1427
+
Refit traps any `HttpRequestException` or `TaskCanceledException` raised by the `HttpClient` in an `ApiRequestException`.
1428
+
Refit also traps any `ApiException` raised by the `ExceptionFactory` when processing the response, and any errors that occur when attempting to deserialize the response to `ApiResponse<T>`.
1429
+
In both cases, it will populate the exception into the `Error` property on `ApiResponse<T>` without throwing the exception.
_logger.LogError(response.Error, "An error occurred while calling the API.");
1418
1449
}
1419
1450
```
1420
1451
1421
1452
> [!NOTE]
1422
1453
> The `IsSuccessful` property checks whether the response status code is in the range 200-299 and there wasn't any other error (for example, during content deserialization). If you just want to check the HTTP response status code, you can use the `IsSuccessStatusCode` property.
1423
1454
1424
1455
#### When returning `Task<T>`
1425
-
Refit throws any `ApiException` raised by the `ExceptionFactory` when processing the response and any errors that occur when attempting to deserialize the response to `Task<T>`.
1456
+
Refit throws any exception raised by the `HttpClient` and wraps it in an `ApiRequestException`.
1457
+
It also throws any `ApiException` raised by the `ExceptionFactory` when processing the response and any errors that occur when attempting to deserialize the response to `Task<T>`.
1426
1458
1427
1459
```csharp
1428
1460
// ...
1429
1461
try
1430
1462
{
1431
1463
varresult=awaitawesomeApi.GetFooAsync("bar");
1432
1464
}
1465
+
catch (ApiRequestExceptionexception)
1466
+
{
1467
+
//exception handling for when a response was not received from the server
1468
+
}
1433
1469
catch (ApiExceptionexception)
1434
1470
{
1435
-
//exception handling
1471
+
//exception handling for when a response was received from the server
1472
+
}
1473
+
// Or to not distinguish between request/response exceptions
1474
+
catch (ApiExceptionBaseexception)
1475
+
{
1476
+
//exception handling for when an error occurs during the request/response
You can also override default exceptions behavior that are raised by the `ExceptionFactory` when processing the result by providing a custom exception factory in `RefitSettings`. For example, you can suppress all exceptions with the following:
1508
+
You can also override default exceptions behavior that are raised by the `ExceptionFactory` when processing the result by providing a custom exception factory in `RefitSettings`. For example, you can suppress all `ApiException`s with the following:
0 commit comments