MisterMoret.Try
1.0.0-beta.3
dotnet add package MisterMoret.Try --version 1.0.0-beta.3
NuGet\Install-Package MisterMoret.Try -Version 1.0.0-beta.3
<PackageReference Include="MisterMoret.Try" Version="1.0.0-beta.3" />
<PackageVersion Include="MisterMoret.Try" Version="1.0.0-beta.3" />
<PackageReference Include="MisterMoret.Try" />
paket add MisterMoret.Try --version 1.0.0-beta.3
#r "nuget: MisterMoret.Try, 1.0.0-beta.3"
#:package MisterMoret.Try@1.0.0-beta.3
#addin nuget:?package=MisterMoret.Try&version=1.0.0-beta.3&prerelease
#tool nuget:?package=MisterMoret.Try&version=1.0.0-beta.3&prerelease
MisterMoret.Try
A lightweight try/catch wrapper that converts unhandled exceptions into failed Result or HttpResult objects, eliminating boilerplate exception handling in .NET applications.
This package is currently in beta and available via NuGet.org.
β¨ Features
- Exception-Safe Execution: Wrap any synchronous or asynchronous delegate and receive a failed result instead of a thrown exception.
- Result Integration: Works seamlessly with
MisterMoret.Resultsβ returnsResult<T>,Result,HttpResult<T>, andHttpResult. - HTTP-Aware: Maps HTTP-related exceptions to meaningful
HttpStatusCodevalues automatically. - Auto-Wrapping: Pass a plain
Func<Task<T>>and let the library wrap the return value in a result for you. - Custom Error Messages: Supply an optional
exceptionMapperdelegate to control the error message on failure instead of usingException.Message. - Zero Boilerplate: Import the namespace once and call methods directly via the class name.
- Modern .NET Support: Targets .NET 8.0, 9.0, and 10.0.
π Installation
Install the package via the NuGet CLI:
dotnet add package MisterMoret.Try --version 1.0.0-beta.3
π‘ Usage
Add a using directive to bring the classes into scope:
using MisterMoret.Try;
TryOperation β Result Overloads
Use when you want a Result or Result<T> back. Both synchronous and asynchronous delegates are supported.
Asynchronous (ExecuteAsync)
Auto-wrapping β pass a plain delegate and the result is created for you:
// Returns Result<User>
var result = await TryOperation.ExecuteAsync(() => _repository.GetUserAsync(id));
if (result.IsSuccess)
{
Console.WriteLine(result.Value.Name);
}
else
{
foreach (var error in result.Errors)
{
Console.WriteLine($"Error: {error}");
}
}
Manual result β use when you need to return a failure or perform validation inside the delegate:
var result = await TryOperation.ExecuteAsync(async () =>
{
var user = await _repository.GetUserAsync(id);
if (user == null)
return Result<User>.Failure("User not found.");
return Result<User>.Success(user);
});
Synchronous (Execute)
Use the same patterns with synchronous delegates when async is not needed:
Auto-wrapping β wraps the return value in Result<T>.Success:
// Returns Result<User>
var result = TryOperation.Execute(() => _repository.GetUser(id));
if (result.IsSuccess)
{
Console.WriteLine(result.Value.Name);
}
else
{
foreach (var error in result.Errors)
{
Console.WriteLine($"Error: {error}");
}
}
Manual result β use when you need to return a failure or perform validation inside the delegate:
var result = TryOperation.Execute(() =>
{
var user = _repository.GetUser(id);
if (user == null)
return Result<User>.Failure("User not found.");
return Result<User>.Success(user);
});
Void action β wraps a side-effecting operation in Result.Success:
var result = TryOperation.Execute(() => _repository.DeleteUser(id));
if (!result.IsSuccess)
{
Console.WriteLine(string.Join(", ", result.Errors));
}
Custom Error Messages (exceptionMapper)
All TryOperation overloads accept an optional Func<Exception, string>? exceptionMapper parameter. When supplied, the delegate produces the error message on failure instead of Exception.Message. The parameter is positional, so pass it after the operation delegate:
var result = await TryOperation.ExecuteAsync(
() => _repository.GetUserAsync(id),
ex => $"Failed to load user {id}: {ex.GetType().Name}");
if (!result.IsSuccess)
{
Console.WriteLine(result.Errors[0]); // "Failed to load user 42: InvalidOperationException"
}
When exceptionMapper is omitted or null, the behaviour is unchanged β Exception.Message is used.
TryHttpOperation.ExecuteAsync β HttpResult Overloads
Use when you want an HttpResult or HttpResult<T> back. HTTP-related exceptions are mapped to appropriate status codes automatically.
Auto-wrapping β success defaults to 200 OK:
// Returns HttpResult<User>
var result = await TryHttpOperation.ExecuteAsync(() => _repository.GetUserAsync(id));
if (result.IsSuccess)
{
Console.WriteLine(result.Value.Name);
}
else if (result.Code == HttpStatusCode.RequestTimeout)
{
Console.WriteLine("The request timed out.");
}
Manual result β use when you need control over the success status code:
var result = await TryHttpOperation.ExecuteAsync(() => _apiClient.GetAsync<User>("users/1"));
Exception Mapping
Applies to all TryHttpOperation.ExecuteAsync overloads:
| Exception | Status Code |
|---|---|
TaskCanceledException (timeout) |
408 Request Timeout |
HttpRequestException (with embedded code) |
Embedded HttpStatusCode |
HttpRequestException (no embedded code) |
503 Service Unavailable |
Any other Exception |
500 Internal Server Error |
Custom Error Messages (exceptionMapper)
All TryHttpOperation.ExecuteAsync overloads accept the same optional Func<Exception, string>? exceptionMapper parameter. It controls only the error message β the HTTP status code mapping above is unaffected:
var result = await TryHttpOperation.ExecuteAsync(
() => _apiClient.GetAsync<User>("users/1"),
ex => "Upstream service is unavailable. Please try again later.");
βοΈ License
This project is licensed under the MIT License - see the LICENSE file for details.
π€ Author
FrΓ©dΓ©ric Goetinck-Moret
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- MisterMoret.Results (>= 1.0.0-beta.5)
-
net8.0
- MisterMoret.Results (>= 1.0.0-beta.5)
-
net9.0
- MisterMoret.Results (>= 1.0.0-beta.5)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 1.0.0-beta.3 | 84 | 5/25/2026 |
See the full changelog at https://github.com/fgoetinck/mister-moret/blob/main/src/MisterMoret.Try/CHANGELOG.md