Nedo.AspNet.Infrastructure 1.0.9

dotnet add package Nedo.AspNet.Infrastructure --version 1.0.9
                    
NuGet\Install-Package Nedo.AspNet.Infrastructure -Version 1.0.9
                    
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="Nedo.AspNet.Infrastructure" Version="1.0.9" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Nedo.AspNet.Infrastructure" Version="1.0.9" />
                    
Directory.Packages.props
<PackageReference Include="Nedo.AspNet.Infrastructure" />
                    
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 Nedo.AspNet.Infrastructure --version 1.0.9
                    
#r "nuget: Nedo.AspNet.Infrastructure, 1.0.9"
                    
#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 Nedo.AspNet.Infrastructure@1.0.9
                    
#: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=Nedo.AspNet.Infrastructure&version=1.0.9
                    
Install as a Cake Addin
#tool nuget:?package=Nedo.AspNet.Infrastructure&version=1.0.9
                    
Install as a Cake Tool

Nedo.AspNet.Infrastructure

A modular, production-ready infrastructure library for .NET 9 that standardizes integration with databases, message brokers, caches, and background services.

Features

  • ๐Ÿ”Œ Unified Connectivity โ€” Standardized patterns for database, messaging, and caching
  • ๐Ÿ—„๏ธ Multi-Database โ€” PostgreSQL, Oracle, MySQL, MariaDB, SQLite, InfluxDB, Qdrant
  • ๐Ÿ“จ Multi-Broker Messaging โ€” RabbitMQ, NATS JetStream, MQTT, Redis Streams
  • ๐Ÿ’พ Distributed Caching โ€” In-Memory, Redis, Valkey
  • ๐Ÿ’“ Health Checks โ€” Fail-fast startup + HTTP liveness/readiness probes
  • โš™๏ธ Background Processing โ€” Work queues and scheduled jobs
  • ๐Ÿ“Š Observability โ€” ActivitySource tracing + System.Diagnostics.Metrics
  • ๐Ÿ—๏ธ Config Validation โ€” Catch configuration errors at startup, not at 3 AM
  • โœ… Testable โ€” Interface-driven, easy to mock

Quick Start

dotnet add package Nedo.AspNet.Infrastructure
var builder = WebApplication.CreateBuilder(args);

builder.Services.AddNedoInfrastructure(builder.Configuration, infra =>
{
    // Database
    infra.AddPostgreSQL();

    // Messaging (pick one)
    infra.AddRabbitMQ(msg =>
    {
        msg.AddConsumer<OrderCreated, OrderCreatedHandler>("orders.created");
    });

    // Caching (pick one)
    infra.AddRedisCache();
});

var app = builder.Build();

await app.RunStartupHealthChecksAsync();   // fail-fast if services unreachable
app.MapInfrastructureHealthChecks();       // HTTP health endpoints

app.Run();

Database

Providers

Provider Extension EF Core Package
PostgreSQL AddPostgreSQL() AddPostgreSqlDbContext<T>() Npgsql
Oracle AddOracle() AddOracleDbContext<T>() Oracle.ManagedDataAccess
MySQL AddMySQL() AddMySqlDbContext<T>() MySqlConnector
MariaDB AddMariaDb() AddMariaDbDbContext<T>() MySqlConnector
SQLite AddSQLite() AddSqliteDbContext<T>() Microsoft.Data.Sqlite
InfluxDB AddInfluxDb() โ€” (time-series) InfluxDB.Client
Qdrant AddQdrant() โ€” (vector DB) Qdrant.Client

Configuration

{
  "Infrastructure": {
    "Database": {
      "Provider": "PostgreSQL",
      "Connection": {
        "Host": "localhost",
        "Port": 5432,
        "Database": "mydb",
        "Username": "user",
        "Password": "pass"
      },
      "CommandTimeout": 30
    }
  }
}

If both ConnectionString and Connection.* are set, ConnectionString takes priority.

Qdrant (Vector Database)

infra.AddQdrant(opts =>
{
    opts.Host = "localhost";
    opts.Port = 6334;
});
public class EmbeddingService(IQdrantVectorClient qdrant)
{
    public async Task IndexAsync(string id, float[] embedding)
    {
        var point = new PointStruct
        {
            Id = new PointId { Uuid = id },
            Vectors = embedding,
            Payload = { ["indexed_at"] = DateTimeOffset.UtcNow.ToString("O") }
        };

        await qdrant.UpsertAsync("documents", [point]);
    }

    public async Task<IReadOnlyList<ScoredPoint>> SearchAsync(float[] query)
    {
        return await qdrant.SearchAsync("documents", query, limit: 5);
    }
}

<details> <summary>Qdrant Configuration</summary>

{
  "Infrastructure": {
    "Database": {
      "Qdrant": {
        "Host": "localhost",
        "Port": 6334,
        "Https": false,
        "ApiKey": "",
        "DefaultCollection": "",
        "Timeout": "00:00:10"
      }
    }
  }
}

</details>

Messaging

Providers

Provider Extension Package Best For
RabbitMQ AddRabbitMQ() RabbitMQ.Client Enterprise messaging, task queues
NATS JetStream AddNatsJetStream() NATS.Net High-throughput streaming
MQTT AddMqtt() MQTTnet IoT, lightweight pub/sub
Redis Streams AddRedisStream() StackExchange.Redis Persistent log, consumer groups

Usage

Publish messages:

public class OrderService(IMessagePublisher publisher)
{
    public async Task CreateOrderAsync(Order order)
    {
        await _repo.SaveAsync(order);

        await publisher.PublishAsync(
            new OrderCreated(order.Id, order.Total),
            topic: "orders.created",
            properties: new MessageProperties
            {
                CorrelationId = Activity.Current?.Id,
                DeliveryMode = DeliveryMode.Persistent
            });
    }
}

Consume messages:

public record OrderCreated(Guid OrderId, decimal Total);

public class OrderCreatedHandler(ILogger<OrderCreatedHandler> logger)
    : IMessageConsumer<OrderCreated>
{
    public async Task<bool> HandleAsync(
        ConsumeContext<OrderCreated> context, CancellationToken ct = default)
    {
        logger.LogInformation("Order {Id}: ${Total}",
            context.Message.OrderId, context.Message.Total);

        // Process the order...

        return true;   // ack
        // return false; โ†’ nack / requeue
    }
}

Register consumers:

infra.AddRabbitMQ(msg =>
{
    msg.AddConsumer<OrderCreated, OrderCreatedHandler>("orders.created");
    msg.AddConsumer<PaymentReceived, PaymentHandler>("payments.received");
});

// Or with NATS JetStream:
infra.AddNatsJetStream(msg =>
{
    msg.AddConsumer<OrderCreated, OrderCreatedHandler>("APP.orders.created");
});

// Or with MQTT:
infra.AddMqtt(msg =>
{
    msg.AddConsumer<SensorReading, SensorHandler>("sensors/temperature");
});

// Or with Redis Streams:
infra.AddRedisStream(msg =>
{
    msg.AddConsumer<OrderCreated, OrderCreatedHandler>("orders.created");
});

Configuration

<details> <summary>RabbitMQ</summary>

{
  "Infrastructure": {
    "Messaging": {
      "Enabled": true,
      "Provider": "RabbitMQ",
      "HostName": "localhost",
      "Port": 5672,
      "Username": "guest",
      "Password": "guest",
      "Exchange": { "Name": "app.events", "Type": "topic", "Durable": true },
      "Consumer": { "PrefetchCount": 10, "RetryCount": 3 },
      "DeadLetter": { "Enabled": true, "Exchange": "app.deadletter", "MaxRetries": 5 }
    }
  }
}

</details>

<details> <summary>NATS JetStream</summary>

{
  "Infrastructure": {
    "Messaging": {
      "Enabled": true,
      "Provider": "NatsJetStream",
      "Nats": {
        "Url": "nats://localhost:4222",
        "StreamName": "APP",
        "DurableName": "app-worker",
        "AckWait": "00:00:30",
        "MaxDeliver": 5
      }
    }
  }
}

</details>

<details> <summary>MQTT</summary>

{
  "Infrastructure": {
    "Messaging": {
      "Enabled": true,
      "Provider": "MQTT",
      "Mqtt": {
        "BrokerHost": "localhost",
        "BrokerPort": 1883,
        "ClientId": "myapp-worker",
        "CleanSession": true,
        "DefaultQoS": 1,
        "UseTls": false
      }
    }
  }
}

</details>

<details> <summary>Redis Streams</summary>

{
  "Infrastructure": {
    "Messaging": {
      "Enabled": true,
      "Provider": "RedisStream",
      "RedisStream": {
        "ConnectionString": "localhost:6379",
        "StreamPrefix": "messaging",
        "ConsumerGroup": "app-workers",
        "ConsumerName": "worker-1",
        "ReadBatchSize": 10,
        "MaxStreamLength": 0
      }
    }
  }
}

</details>

Caching

Providers

Provider Extension Package
In-Memory AddInMemoryCache() (built-in)
Redis AddRedisCache() StackExchange.Redis
Valkey AddValkeyCache() StackExchange.Redis
Hybrid AddHybridCache() L1 in-memory + L2 distributed

Usage

public class ProductService(ICacheProvider cache, IProductRepo repo)
{
    public async Task<Product?> GetAsync(int id, CancellationToken ct)
    {
        return await cache.GetOrCreateAsync(
            key: $"products:{id}",
            factory: async ct => await repo.FindByIdAsync(id, ct),
            options: new CacheEntryOptions
            {
                AbsoluteExpiration = TimeSpan.FromMinutes(30),
                Tags = ["products"]
            },
            ct: ct);
    }

    public async Task InvalidateCategoryAsync(CancellationToken ct)
    {
        await cache.RemoveByTagAsync("products", ct);
    }
}

Configuration

{
  "Infrastructure": {
    "Cache": {
      "Enabled": true,
      "ConnectionString": "localhost:6379",
      "KeyPrefix": "myapp:",
      "DefaultExpiration": "01:00:00"
    }
  }
}

Health Checks

var app = builder.Build();

await app.RunStartupHealthChecksAsync();  // fail-fast if DB/cache/broker unreachable
app.MapInfrastructureHealthChecks();      // HTTP endpoints
Endpoint Tag Purpose
GET /health/live Liveness Is the process alive?
GET /health/ready Readiness Can it handle traffic?
GET /health/startup Startup Has initial setup completed?

All registered providers (database, messaging, caching) automatically contribute health checks.

Observability

Every module emits structured tracing and metrics:

Module Trace Span Metrics
Database db.query, db.connection infra.db.queries.*
Messaging messaging.publish, messaging.consume infra.messaging.*
Cache cache.get, cache.set, cache.remove infra.cache.*

Documentation

Full documentation in docs/:

# Section Documents
00 ๐Ÿ“– Getting Started
01 ๐Ÿ—„๏ธ Database Overview ยท Connection Strings ยท PostgreSQL ยท Oracle ยท MySQL ยท MariaDB ยท SQLite ยท InfluxDB ยท Qdrant ยท EF Core
02 ๐Ÿ“จ Messaging Overview ยท RabbitMQ ยท NATS JetStream ยท MQTT ยท Redis Streams
03 ๐Ÿ’พ Cache Overview ยท Usage Patterns ยท Redis ยท Valkey ยท In-Memory ยท Hybrid ยท Configuration
04 ๐Ÿ’“ Health Overview
05 ๐Ÿ“Š Observability Overview
06 โš™๏ธ Background Overview ยท Work Queues ยท Scheduled Jobs ยท Managed Services
07 ๐Ÿ”ง Core Configuration ยท Connection Lifecycle ยท Resilience ยท Extensibility

Project Structure

โ”œโ”€โ”€ docs/                           # Documentation (by topic)
โ”œโ”€โ”€ sample/                         # Sample projects
โ”œโ”€โ”€ src/Nedo.AspNet.Infrastructure/
โ”‚   โ”œโ”€โ”€ Builder/                    # DI builder & extensions
โ”‚   โ”œโ”€โ”€ Configuration/              # Strongly-typed options
โ”‚   โ”œโ”€โ”€ Core/                       # Connection factory & pooling
โ”‚   โ”œโ”€โ”€ Database/                   # PostgreSQL, Oracle, MySQL, MariaDB, SQLite
โ”‚   โ”‚   โ”œโ”€โ”€ InfluxDb/              # Time-series database
โ”‚   โ”‚   โ””โ”€โ”€ Qdrant/                # Vector database
โ”‚   โ”œโ”€โ”€ Messaging/
โ”‚   โ”‚   โ”œโ”€โ”€ RabbitMQ/              # AMQP provider
โ”‚   โ”‚   โ”œโ”€โ”€ NatsJetStream/         # NATS provider
โ”‚   โ”‚   โ”œโ”€โ”€ Mqtt/                  # MQTT provider
โ”‚   โ”‚   โ””โ”€โ”€ RedisStream/           # Redis Streams provider
โ”‚   โ”œโ”€โ”€ Caching/
โ”‚   โ”‚   โ””โ”€โ”€ Redis/                 # Redis/Valkey provider
โ”‚   โ”œโ”€โ”€ HealthChecks/
โ”‚   โ”œโ”€โ”€ Observability/
โ”‚   โ””โ”€โ”€ BackgroundProcessing/
โ”œโ”€โ”€ test/                           # Unit tests (102 passing)
โ”œโ”€โ”€ .gitlab-ci.yml
โ””โ”€โ”€ README.md

Build & Test

dotnet build
dotnet test    # 102 tests

Releasing

  1. Tag: git tag v1.0.0
  2. Push: git push origin v1.0.0
  3. GitLab CI builds, packs, and publishes to NuGet.

Requires: NUGET_API_KEY CI/CD variable.

License

MIT License

Product Compatible and additional computed target framework versions.
.NET 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 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.

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.9 84 3/25/2026
1.0.3 94 3/3/2026
1.0.2 84 3/3/2026
1.0.1 84 3/3/2026
1.0.0 80 3/3/2026