Http Client β REslava.Result.Http
REslava.Result.Http wraps
HttpClientcalls so every HTTP response and network failure becomes a typedResult<T>. The client-side complement toToIResult()β completes the full round-trip.
Install: dotnet add package REslava.Result.Http
10.6.1. GetResult<T> β Type-safe GET
Sends a GET request and deserializes the body on 2xx; maps 4xx/5xx to typed domain errors automatically. Accepts both string and Uri overloads.
using REslava.Result.Http;
// string overload
Result<User> user = await httpClient.GetResult<User>("/api/users/42");
user.Match(
onSuccess: u => Console.WriteLine($"Got {u.Name}"),
onFailure: errors => Console.WriteLine(errors[0].Message));
// 404 β NotFoundError, 401 β UnauthorizedError, network failure β ExceptionError
// Uri overload
Result<User> user2 = await httpClient.GetResult<User>(new Uri("https://api.example.com/users/42"));
10.6.2. PostResult<TBody, TResponse> β Type-safe POST
Sends a POST request with a JSON-serialized body and returns Result<TResponse>.
Result<User> created = await httpClient.PostResult<CreateUserRequest, User>(
"/api/users",
new CreateUserRequest("Alice", "alice@example.com"));
if (created.IsSuccess)
Console.WriteLine($"Created user {created.Value.Id}");
10.6.3. PutResult<TBody, TResponse> β Type-safe PUT
Sends a PUT request with a JSON-serialized body and returns Result<TResponse>.
Result<User> updated = await httpClient.PutResult<UpdateUserRequest, User>(
"/api/users/42",
new UpdateUserRequest("Alice Updated"));
updated.Match(
onSuccess: u => Console.WriteLine($"Updated: {u.Name}"),
onFailure: errors => Console.WriteLine(errors[0].Message));
10.6.4. DeleteResult β Type-safe DELETE (no body)
Sends a DELETE request and returns a non-generic Result β use when the API returns no body on success (204 No Content pattern).
Result deleted = await httpClient.DeleteResult("/api/users/42");
if (deleted.IsSuccess)
Console.WriteLine("Resource deleted");
10.6.5. DeleteResult<T> β Type-safe DELETE (with response body)
Sends a DELETE request and deserializes the response body into Result<T> β use when the API returns the deleted resource or a confirmation object.
Result<DeletedUserDto> result = await httpClient.DeleteResult<DeletedUserDto>("/api/users/42");
if (result.IsSuccess)
Console.WriteLine($"Archived at: {result.Value.ArchivedAt}");
10.6.6. HttpResultOptions β Custom JSON & Error Mapping
Configures JSON deserialization options and/or replaces the entire status-code-to-error mapping with a custom delegate. Pass as the last parameter to any extension method.
var options = new HttpResultOptions
{
// Custom JSON serialization (default: JsonSerializerDefaults.Web)
JsonOptions = new JsonSerializerOptions
{
PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower
},
// Complete override of the status-code β IError mapping
StatusCodeMapper = (statusCode, reasonPhrase) => statusCode switch
{
(HttpStatusCode)429 => new RateLimitError("Too many requests β back off and retry"),
_ => new Error($"HTTP {(int)statusCode}: {reasonPhrase}")
}
};
Result<User> user = await httpClient.GetResult<User>("/api/users/42", options);
10.6.7. Status Code β Error Mapping (defaults)
| HTTP Status | Domain Error | Default Message |
|---|---|---|
| 404 Not Found | NotFoundError |
"Resource not found" |
| 401 Unauthorized | UnauthorizedError |
"Authentication required" |
| 403 Forbidden | ForbiddenError |
"Access denied" |
| 409 Conflict | ConflictError |
"A conflict occurred" |
| 422 Unprocessable Entity | ValidationError |
"Validation failed" |
| Other 4xx / 5xx | Error |
"HTTP {code}: {reasonPhrase}" |
| Network / timeout | ExceptionError |
ex.Message |
Override any or all mappings via HttpResultOptions.StatusCodeMapper.
See REslava.Result.Http README for the full API reference.