Nexus.Pipeline.Sample.MvcApp 1.0.3

The owner has unlisted this package. This could mean that the package is deprecated, has security vulnerabilities or shouldn't be used anymore.
dotnet add package Nexus.Pipeline.Sample.MvcApp --version 1.0.3
                    
NuGet\Install-Package Nexus.Pipeline.Sample.MvcApp -Version 1.0.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="Nexus.Pipeline.Sample.MvcApp" Version="1.0.3" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Nexus.Pipeline.Sample.MvcApp" Version="1.0.3" />
                    
Directory.Packages.props
<PackageReference Include="Nexus.Pipeline.Sample.MvcApp" />
                    
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 Nexus.Pipeline.Sample.MvcApp --version 1.0.3
                    
#r "nuget: Nexus.Pipeline.Sample.MvcApp, 1.0.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 Nexus.Pipeline.Sample.MvcApp@1.0.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=Nexus.Pipeline.Sample.MvcApp&version=1.0.3
                    
Install as a Cake Addin
#tool nuget:?package=Nexus.Pipeline.Sample.MvcApp&version=1.0.3
                    
Install as a Cake Tool

Nexus.Pipeline

Build NuGet License: MIT .NET

Typed steps. Structured results. Full execution history.

Nexus.Pipeline is a typed, in-process execution pipeline library for .NET. You register an ordered sequence of steps on a fluent builder, attach cross-cutting behaviors (logging, retry, timeout, transactions, OpenTelemetry metrics), and execute against a shared IExecutionContext that carries the request, the evolving response, and a per-step execution history. Every execution returns a PipelineResult<TResponse> — structured errors, no exception-based control flow. Supports inline lambda steps and DI-resolved class-based steps interchangeably. Targets .NET 4.6.2 through .NET 10, with AOT and trim compatibility on .NET 8+.

graph TB
    subgraph APP["Application Layer"]
        API["ASP.NET Core / Worker"]
        LEGACY["net462 Console / WCF / MVC 5"]
    end

    subgraph CORE["Core Engine"]
        BUILDER["PipelineBuilder / PipelineDefinitionBuilder"]
        EXEC["PipelineExecutor"]
        CTX["ExecutionContext + ContextScope"]
        COMP["CompensationEngine"]
    end

    subgraph BEH["Behaviors (middleware chain)"]
        LOG["LoggingBehavior (−1000)"]
        RETRY["RetryBehavior (−800)"]
        TIMEOUT["TimeoutBehavior (−600)"]
        EXC["ExceptionHandlingBehavior (MaxValue)"]
    end

    subgraph DI["DI / Hosting"]
        SVC["AddNexusPipeline()"]
        RES["IStepResolver (DI-backed)"]
    end

    APP --> DI
    DI --> CORE
    CORE --> BEH
    CORE --> COMP

Feature Highlights

Feature Description
Multi-TFM net462 · netstandard2.0 · net6.0 · net8.0 · net9.0 · net10.0
Fluent builder Pipeline.For<>() — build-and-execute in one chain
Reusable definitions Pipeline.Define<>().Build() — immutable, thread-safe, build once
Validation phase IValidationStep runs before execute; short-circuits on failure
Middleware behaviors Ordered IPipelineBehavior chain wraps all step execution
Retry + Timeout WithPolicy(p => p.Retry(3).Timeout(10s)) — shortcut wiring
Saga compensation WithCompensation<T>() — reverse-order rollback on failure
Conditional routing .If() / .Else() — runtime context-driven branching
Parallel branches .Parallel() — concurrent fan-out with Task.WhenAll
DAG dependencies .DependsOn<T>() — topological sort guarantees order
Structured errors ErrorInfo with Code, Category, Severity, Source
Execution history Per-step StepExecutionRecord with status and duration
OpenTelemetry MetricsBehavior emits System.Diagnostics.Activity spans
Visualization result.Metadata.ToMermaid() / ToPlantUml() diagram export

Packages

Package NuGet TFMs Description
Nexus.Pipeline NuGet net462 · ns2.0 · net6–10 Execution engine, behaviors, DI integration, and visualization

Diagram export (Mermaid, PlantUML, JSON) targets netstandard2.0 and .NET 6+ (not net462).


Installation

dotnet add package Nexus.Pipeline
# Package Manager Console
Install-Package Nexus.Pipeline

Quick Start

Pattern 1 — Pipeline.For<>(): Build-and-Execute

The fastest way to run a pipeline. Each call to .ExecuteAsync() is a fresh execution.

using Nexus.Pipeline;
using Nexus.Pipeline.Behaviors;
using Nexus.Pipeline.DependencyInjection.Extensions;

// DI wiring (once at startup)
services.AddNexusPipeline();
services.AddPipelineStep<ValidatePaymentStep>();
services.AddPipelineStep<CheckBalanceStep>();
services.AddPipelineStep<CreateTransactionStep>();
services.AddTransient(typeof(LoggingBehavior<,>));
services.AddTransient(typeof(ExceptionHandlingBehavior<,>));

// Execution (per-request)
var result = await Pipeline
    .For<PaymentRequest, PaymentResponse>(resolver)
    .WithName("PaymentPipeline")
    .AddBehavior<LoggingBehavior<PaymentRequest, PaymentResponse>>()
    .AddBehavior<ExceptionHandlingBehavior<PaymentRequest, PaymentResponse>>()
    .Validation<ValidatePaymentStep>()
    .Step<CheckBalanceStep>()
    .Step<CreateTransactionStep>()
    .ExecuteAsync(request, cancellationToken);

// Result
result.IsSuccess          // bool
result.Response           // PaymentResponse?
result.Errors             // IReadOnlyList<ErrorInfo>
result.ExecutionHistory   // per-step records
result.Metadata.Duration  // TimeSpan?

Pattern 2 — Pipeline.Define<>(): Reusable Definition

Build once at startup; call ExecuteAsync many times. Each call gets its own CorrelationId and ExecutionContext — fully thread-safe.

// Built ONCE (e.g. in a singleton or static field)
IPipelineDefinition<PaymentRequest, PaymentResponse> _pipeline =
    Pipeline.Define<PaymentRequest, PaymentResponse>(resolver)
        .WithName("PaymentPipeline")
        .WithVersion("2.0")
        .WithLoggerFactory(loggerFactory)
        .WithCorrelationIdFactory(() => "PAY-" + Guid.NewGuid().ToString("N")[..8])
        .AddBehavior<LoggingBehavior<PaymentRequest, PaymentResponse>>()
        .WithPolicy(p => p.Retry(3).Timeout(TimeSpan.FromSeconds(30)))
        .Validation<ValidatePaymentStep>()
        .Step<CheckBalanceStep>()
        .Step<CreateTransactionStep>()
        .Build();

// Executed MANY times (concurrent-safe)
var result = await _pipeline.ExecuteAsync(request, cancellationToken);

Pattern 3 — Implementing a Step

public sealed class CheckBalanceStep : IPipelineStep<PaymentRequest, PaymentResponse>
{
    private readonly IAccountRepository _accounts;

    public CheckBalanceStep(IAccountRepository accounts) => _accounts = accounts;

    public string StepName => "CheckBalance";
    public int Order => 2;

    public async Task<StepOutcome> ExecuteAsync(
        IExecutionContext<PaymentRequest, PaymentResponse> context,
        CancellationToken cancellationToken = default)
    {
        var balance = await _accounts.GetBalanceAsync(context.Request.CustomerId, cancellationToken);

        if (context.Request.Amount > balance)
            return StepOutcome.Fail;

        context.Items.Set("available_balance", balance);
        return StepOutcome.Continue;
    }
}

Advanced Patterns

Saga Compensation (Rollback)

Compensation steps are registered per-step and run in reverse order on pipeline failure.

await Pipeline
    .For<TransferRequest, TransferResponse>(resolver)
    .Validation<ValidateTransferStep>()
    .Step<ReserveAmountStep>()
    .WithCompensation<ReleaseReservationStep>()   // runs if pipeline fails AFTER this step
    .Step<ExecuteTransferStep>()
    .WithCompensation<ReverseTransferStep>()       // runs first (reverse order)
    .Step<AuditTransferStep>()
    .ExecuteAsync(request, ct);

If AuditTransferStep fails → ReverseTransferStep runs, then ReleaseReservationStep.

Conditional Routing

Pipeline.Define<ApprovalRequest, ApprovalResponse>(resolver)
    .Step<CheckAutoApprovalStep>()   // sets ctx.Scope["auto_approved"] = true/false
    .If(ctx => ctx.Items.TryGet<bool>("auto_approved", out var v) && v,
        b => b.Step<AutoApproveStep>())
    .If(ctx => ctx.Items.TryGet<bool>("manager_required", out var v) && v,
        b => b.Step<RequestManagerApprovalStep>())
    .Build();

Parallel Branches

pipeline
    .Step<ProcessOrderStep>()
    .Parallel(
        b => b.Step<NotifyApplicantStep>(),     // concurrent
        b => b.Step<NotifySlackChannelStep>())   // concurrent
    .Step<FinalizeStep>()

DAG (Dependency Graph)

pipeline
    .Step<StepA>()
    .Step<StepB>().DependsOn<StepA>()    // B runs after A
    .Step<StepC>().DependsOn<StepA>()    // C runs after A (parallel with B)
    .Step<StepD>().DependsOn<StepB>().DependsOn<StepC>()  // D waits for B and C

Validation Step

public sealed class ValidatePaymentStep : IValidationStep<PaymentRequest, PaymentResponse>
{
    public string StepName => "ValidatePayment";
    public int Order => 0;

    public Task<ValidationResult> ValidateAsync(
        IExecutionContext<PaymentRequest, PaymentResponse> context,
        CancellationToken cancellationToken = default)
    {
        var errors = new List<ErrorInfo>();

        if (context.Request.Amount <= 0)
            errors.Add(ErrorInfo.Validation("PAY-VAL-001", "Amount must be positive", nameof(PaymentRequest.Amount)));
        if (string.IsNullOrEmpty(context.Request.CustomerId))
            errors.Add(ErrorInfo.Validation("PAY-VAL-002", "CustomerId is required", nameof(PaymentRequest.CustomerId)));

        return Task.FromResult(
            errors.Count == 0 ? ValidationResult.Valid() : ValidationResult.Invalid(errors.ToArray()));
    }

    public Task<StepOutcome> ExecuteAsync(
        IExecutionContext<PaymentRequest, PaymentResponse> context,
        CancellationToken cancellationToken = default)
        => Task.FromResult(StepOutcome.Continue);
}

Pipeline Visualization

// After execution, export a Mermaid diagram of what ran
var mermaid = result.Metadata.ToMermaid();
Console.WriteLine(mermaid);

// Output:
// graph TD
//   ValidatePayment["ValidatePayment ✓ 2ms"]
//   CheckBalance["CheckBalance ✓ 5ms"]
//   CreateTransaction["CreateTransaction ✓ 12ms"]
//   ValidatePayment --> CheckBalance --> CreateTransaction

Step Outcomes

Outcome Effect
StepOutcome.Continue Proceed to next step
StepOutcome.Stop Stop execution, return success with current response
StepOutcome.Fail Stop execution, return failure; triggers compensation

Built-in Behaviors

Behavior Order Description
LoggingBehavior<,> −1000 Structured logs for start/end/duration/errors
MetricsBehavior<,> −900 System.Diagnostics.Activity spans for OpenTelemetry
RetryBehavior<,> −800 Exponential back-off retry with configurable predicate
TimeoutBehavior<,> −600 Pipeline-level deadline via CancellationToken
TransactionBehavior<,> −400 Ambient TransactionScope (commit on success)
ExceptionHandlingBehavior<,> int.MaxValue Catches all unhandled exceptions → structured failure

Lower Order = outermost (wraps everything inside it). ExceptionHandlingBehavior should always be outermost in practice, so register it last or use int.MaxValue.

WithPolicy() Shortcut

pipeline.WithPolicy(p => p
    .Retry(3, delay: TimeSpan.FromMilliseconds(200), backoffMultiplier: 2.0)
    .Timeout(TimeSpan.FromSeconds(30)));

Execution Context API

Every step receives IExecutionContext<TRequest, TResponse>:

ctx.Request              // TRequest — read-only
ctx.Response             // TResponse? — set by steps
ctx.CorrelationId        // string — unique per pipeline run
ctx.CancellationToken    // propagated cancellation

// Cross-step state bag (typed, dictionary-backed)
ctx.Items.Set("key", value);
ctx.Items.TryGet<T>("key", out var v);
ctx.Items.Remove("key");

// Execution metadata
ctx.ExecutionHistory     // IReadOnlyList<StepExecutionRecord>
ctx.PipelineMetadata     // name, version, tags

Error Model

result.Errors  // IReadOnlyList<ErrorInfo>

// ErrorInfo properties:
error.Code          // "PAY-001"
error.Message       // human-readable
error.PropertyName  // field that caused the error (validation)
error.ErrorType     // Business | Technical | Unknown
error.Category      // Validation | Authorization | NotFound | ...
error.Severity      // Error | Warning | Critical | Info
error.Exception     // Exception? (if from ExceptionHandlingBehavior)

// Pattern matching on result:
var msg = result.Match(
    onSuccess:   r  => $"OK: {r.TransactionId}",
    onFailure:   e  => $"Fail: {e[0].Code}",
    onException: ex => $"Ex: {ex.Message}");

// Fluent callbacks:
result
    .OnSuccess(r => log.LogInformation("Done: {TxnId}", r.TransactionId))
    .OnFailure(errors => log.LogWarning("Failed: {Code}", errors[0].Code))
    .OnException(ex => log.LogError(ex, "Unhandled exception"));

.NET Framework 4.6 Compatibility

All packages ship a net462 target. Add these binding redirects to app.config:

<runtime>
  <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
    <dependentAssembly>
      <assemblyIdentity name="Microsoft.Extensions.DependencyInjection.Abstractions"
                        publicKeyToken="adb9793829ddae60" culture="neutral" />
      <bindingRedirect oldVersion="0.0.0.0-8.0.0.0" newVersion="8.0.0.0" />
    </dependentAssembly>
    <dependentAssembly>
      <assemblyIdentity name="Microsoft.Extensions.Logging.Abstractions"
                        publicKeyToken="adb9793829ddae60" culture="neutral" />
      <bindingRedirect oldVersion="0.0.0.0-8.0.0.0" newVersion="8.0.0.0" />
    </dependentAssembly>
    
  </assemblyBinding>
</runtime>

Entry point on net462 (no top-level statements):

static void Main(string[] args)
{
    RunAsync().GetAwaiter().GetResult();
}

static async Task RunAsync()
{
    var result = await Pipeline
        .For<OrderRequest, OrderResponse>(resolver)
        .Validation<ValidateOrderStep>()
        .Step<CheckInventoryStep>()
        .Step<ReserveInventoryStep>()
        .WithCompensation<CancelReservationStep>()
        .Step<CreateOrderStep>()
        .ExecuteAsync(request);
}

See docs/samples/net-framework-46.md for ASP.NET MVC 5, WCF, and Autofac integration patterns.


Samples

Sample TFM What it demonstrates
Nexus.Pipeline.Sample.Console net9.0 Basic step, validation, behaviors, result handling
Nexus.Pipeline.Sample.WebApi net9.0 ASP.NET Core Minimal API integration
Nexus.Pipeline.Sample.Net9 net9.0 .NET 9-specific demo
Nexus.Pipeline.Sample.Net10 net10.0 .NET 10-specific demo
Nexus.Pipeline.BankingWorkflow net9.0 Full saga: reserve → transfer → audit + compensation rollback, retry
Nexus.Pipeline.ApprovalWorkflow net9.0 Conditional routing, parallel notifications, Pipeline.Define<>() reuse
Nexus.Pipeline.NetFramework46 net462 All patterns on .NET 4.6.2: static Main, binding redirects
Nexus.Pipeline.ManualWiring net462 No DI container — manual LoggerFactory + Options wiring
Nexus.Pipeline.Sample.MvcApp net462 ASP.NET MVC 5 integration
Nexus.Pipeline.Sample.WcfService net462 WCF service integration

Documentation

Doc Description
docs/architecture/overview.md Architecture narrative, design principles, entry points
docs/architecture/solution-structure.md Project layout, TFM matrix, dependency graph
docs/execution-flow/pipeline-execution.md Step loop, behavior chain, compensation contract
docs/behaviors/built-in-behaviors.md All 6 behaviors with order, configuration, examples
docs/compensation/saga-pattern.md Saga pattern, rollback design, WithCompensation guide
docs/best-practices/index.md Step design, error codes, DI patterns, testing
docs/performance/index.md Benchmarks, caching, behavior selection
docs/troubleshooting/index.md Common errors, circular deps, compensation debugging
docs/migration/from-mediator.md Migrating from MediatR with concept mapping table
docs/samples/net-framework-46.md Full .NET 4.6 guide: MVC 5, WCF, Autofac, binding redirects
docs/diagnostics/index.md Execution history, logging, OpenTelemetry, health checks
docs/persistence/index.md Persistence patterns, outbox, integration guidance
docs/pipeline-engine/index.md Internal architecture of the execution runtime
docs/plugins/index.md Extension points, custom resolvers, visualization plugins

Architecture Diagrams

Mermaid (.mmd) and PlantUML (.puml) diagrams in docs/diagrams/:

Diagram Description
01-high-level-architecture Component overview
02-solution-structure Package dependency graph
03-pipeline-execution-flow Full execution flowchart with compensation
04-sequence-success Happy path sequence diagram
05-sequence-validation-failure Short-circuit on invalid input
06-sequence-retry RetryBehavior exponential backoff
07-sequence-compensation Saga rollback sequence
08-sequence-parallel Parallel branch fan-out/fan-in
09-class-abstractions Core interface hierarchy
10-class-result-hierarchy Result and error model classes
12-dag-execution DAG topological sort example
13-deployment Production deployment topology
15-state-pipeline Pipeline lifecycle state machine

License

MIT — see LICENSE for details.

Product Compatible and additional computed target framework versions.
.NET Framework net462 is compatible.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

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