FxResult 1.1.3

dotnet add package FxResult --version 1.1.3
                    
NuGet\Install-Package FxResult -Version 1.1.3
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="FxResult" Version="1.1.3" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="FxResult" Version="1.1.3" />
                    
Directory.Packages.props
<PackageReference Include="FxResult" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add FxResult --version 1.1.3
                    
#r "nuget: FxResult, 1.1.3"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package FxResult@1.1.3
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=FxResult&version=1.1.3
                    
Install as a Cake Addin
#tool nuget:?package=FxResult&version=1.1.3
                    
Install as a Cake Tool

FxResult

FxResult

A fluent, exception-safe Result<T> for .NET — clean success/failure pipelines without throwing exceptions in business logic.

dotnet add package FxResult

✨ Features

  • Result<T> / Result<RUnit> — struct-based success/failure wrapper with IResult for non-generic handling
  • Exception-safe.Try(), .TryAsync(), .ThenTry() capture exceptions as Error with caller location
  • Validation.Ensure(), .FailIf(), .FailIfNull() + async variants with CancellationToken
  • Chaining.Then(), .ThenAsync() with out var capture and Result<RUnit> overloads
  • Conditional.If() / .ElseIf() / .Else() branching with type-safe ResultBranch (sync + async)
  • Side-effects.Tap(), .TapFailure(), .OnSuccess(), .OnFailure(), .OnFinally() (sync/async)
  • MetadataMetaInfo with CorrelationId, Additional, Trace, pagination, BuildLogScope()
  • API responses.ToResponseDto()ResultResponse<T> with PublicErrorResponse
  • Error modelrecord Error with Code, Message, Source, Caller, Exception, Location, implicit conversions

🌐 GitHub Repository


🔁 How the Pipeline Works

Every step returns a Result<T>. On success the value flows forward. On failure the chain short-circuits — remaining steps are skipped and the error propagates unchanged until a hook handles it.

flowchart TD
    A["Try / Then"] -->|ok| B["Ensure / FailIf"]
    B -->|ok| C["If / ElseIf / Else"]
    C -->|ok| D["Tap"]
    D -->|ok| E["Then"]

    B -->|FAIL| ERR["Error propagates\n(all steps skipped)"]
    C -->|FAIL| ERR
    D -->|skip| ERR
    E -->|skip| ERR

    ERR --> F[".OnFailure()\nrecover / log"]
    E --> G[".OnSuccess()\ncommit / log"]

    F --> H[".OnFinally()\nalways runs"]
    G --> H

🧩 Usage Examples

Full pipeline

var result = await Result<string>
    .Try(() => GetUserInput())                                        // capture or wrap exception
    .Ensure(x => !string.IsNullOrWhiteSpace(x), "EMPTY", "Required") // validate: must pass
    .FailIf(x => x.Length < 3, "SHORT", "Too short")                 // validate: must not match
    .ThenAsync(x => FindInCacheAsync(x))                              // async transform
    .FailIfNullAsync("NOT_FOUND", "Not found")                       // null-safe unwrap
    .Tap(out var captured)                                            // capture intermediate value
    .Then(Save)                                                       // transform
    .OnFailure(res => { Log(res.Error); return res; })                // failure hook
    .OnSuccess(res => { Commit(res.Value); return res; })             // success hook
    .OnFinally(res => { Console.WriteLine("Done"); return res; });    // always runs

Conditional branching

// Route values through different processing paths
var result = Result<int>.Success(75)
    .If(x => x > 100, x => ApplyPremiumRate(x))
    .ElseIf(x => x > 50, x => ApplyStandardRate(x))
    .Else(x => ApplyBaseRate(x))
    .Then(FormatReceipt);   // ← continues the chain after branching

// Async branching
var result = await Result<int>.Success(75)
    .IfAsync(x => x > 100, LookupPremiumAsync)
    .ElseIfAsync(x => x > 50, LookupStandardAsync)
    .ElseAsync(LookupDefaultAsync);

// Fail if no branch matches
var result = Result<int>.Success(10)
    .If(x => x > 100, x => ProcessHighValue(x))
    .Else(x => Result<int>.Fail(new Error("OUT_OF_RANGE", "Value too low")));

📖 Quick Reference

Category Methods
Create Result<T>.Success(), .Fail(), .Try(), .TryAsync(), implicit from T / Error
Chain .Then(), .ThenAsync(), .ThenTry(), .ThenTryAsync() — with out var capture
Validate .Ensure(), .EnsureAsync(), .FailIf(), .FailIfAsync(), .FailIfNull(), .FailIfNullAsync()
Conditional .If() / .ElseIf() / .Else() + async: .IfAsync(), .ElseIfAsync(), .ElseAsync()
Side-effects .Tap(), .TapAsync(), .TapFailure(), .TapFailureAsync(), .Tap(out var)
Hooks .OnSuccess(), .OnFailure(), .OnFinally() + async + CancellationToken variants
Metadata .WithMeta(), .WithMetaData(), .WithTrace(), .BuildLogScope()
Pagination .ToPagedResult(page, pageSize) on IEnumerable<T> / IQueryable<T>
API .ToResponseDto()ResultResponse<T>

For source, docs, and advanced usage, visit: 👉 https://github.com/M-Meydan/FxResult

Product 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 was computed.  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 was computed.  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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • net8.0

    • No dependencies.

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.1.3 116 3/17/2026
1.1.2 110 3/12/2026
1.1.1 195 7/1/2025
1.0.8 193 6/30/2025
1.0.7 191 6/30/2025
1.0.5 188 6/30/2025
1.0.4 133 6/28/2025
1.0.0 148 6/28/2025