Marventa.Framework 4.1.0

There is a newer version of this package available.
See the version list below for details.
dotnet add package Marventa.Framework --version 4.1.0
                    
NuGet\Install-Package Marventa.Framework -Version 4.1.0
                    
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="Marventa.Framework" Version="4.1.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Marventa.Framework" Version="4.1.0" />
                    
Directory.Packages.props
<PackageReference Include="Marventa.Framework" />
                    
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 Marventa.Framework --version 4.1.0
                    
#r "nuget: Marventa.Framework, 4.1.0"
                    
#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 Marventa.Framework@4.1.0
                    
#: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=Marventa.Framework&version=4.1.0
                    
Install as a Cake Addin
#tool nuget:?package=Marventa.Framework&version=4.1.0
                    
Install as a Cake Tool

Marventa.Framework v4.1.0

Enterprise .NET 8.0 & 9.0 framework - Convention over Configuration

NuGet License: MIT


📚 Table of Contents


📦 Installation

dotnet add package Marventa.Framework

🚀 Quick Start

1. Basic Setup (Auto-Configuration)

var builder = WebApplication.CreateBuilder(args);

// ✨ Auto-detects features from appsettings.json
builder.Services.AddMarventa(builder.Configuration);
builder.Services.AddControllers();

var app = builder.Build();

app.UseMarventa();  // ✨ Automatically configures middleware pipeline
app.MapControllers();
app.Run();

What UseMarventa() does automatically:

1. Exception Handling
2. HTTPS Redirection
3. Routing
4. Authentication & Authorization (if JWT configured)
5. Multi-Tenancy (if configured)
6. Rate Limiting (if configured)

2. Full Setup (with CQRS & Validation)

var builder = WebApplication.CreateBuilder(args);

// Infrastructure (auto-configured)
builder.Services.AddMarventa(builder.Configuration);

// CQRS + Validation (manual - requires your assembly)
builder.Services.AddMarventaMediatR(typeof(Program).Assembly);
builder.Services.AddMarventaValidation(typeof(Program).Assembly);

// Database (manual - requires your DbContext)
builder.Services.AddMarventaDbContext<AppDbContext>(options =>
    options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection")));

builder.Services.AddControllers();

var app = builder.Build();

app.UseMarventa();
app.MapControllers();
app.Run();

3. Minimal Configuration

{
  "Jwt": {
    "Secret": "your-super-secret-key-at-least-32-characters-long",
    "Issuer": "MyApp",
    "Audience": "MyApp",
    "ExpirationMinutes": 60
  }
}

4. Done! 🎉

  • ✅ JWT Authentication & Authorization
  • ✅ Cache (InMemory)
  • ✅ Exception Handling
  • ✅ Validation
  • ✅ API Responses

🎯 Features

✅ Auto-Configured (Convention over Configuration)

Security:

  • JWT Authentication - Token-based auth with permissions
  • Rate Limiting - IP/User/ApiKey based throttling
  • Password Hashing - BCrypt implementation
  • AES Encryption - Data encryption utilities

Data & Storage:

  • Caching - InMemory, Redis, Hybrid strategies
  • MongoDB - NoSQL database support
  • Elasticsearch - Full-text search
  • Local Storage - File system storage
  • Azure Blob Storage - Cloud file storage
  • AWS S3 - Cloud file storage

Event-Driven:

  • RabbitMQ - Message bus for events
  • Kafka - High-throughput event streaming
  • MassTransit - Advanced messaging with RabbitMQ

Infrastructure:

  • Multi-Tenancy - Header/Subdomain/Claim strategies
  • Exception Handling - Global error handling
  • Serilog - Structured logging
  • Health Checks - Database, Redis, RabbitMQ monitoring
  • API Responses - Standardized format

⚙️ Manual Configuration (Requires User Setup)

Application Patterns:

  • CQRS - Command/Query with MediatR
  • DDD - Entity, AggregateRoot, ValueObject, DomainEvent
  • Repository & UnitOfWork - Generic & custom repositories
  • FluentValidation - Request validation
  • Result Pattern - Type-safe error handling

Database:

  • EF Core - SQL Server, PostgreSQL support
  • Generic Repository - CRUD operations
  • Base DbContext - Multi-tenancy aware

Observability (Advanced):

  • OpenTelemetry - Distributed tracing (manual setup)
  • Resilience - Polly retry/circuit breaker utilities

💡 Usage Examples

Authentication & Authorization

Setup (auto-configured from appsettings.json):

{
  "Jwt": {
    "Secret": "your-super-secret-key-at-least-32-characters-long",
    "Issuer": "MyApp",
    "Audience": "MyApp",
    "ExpirationMinutes": 60
  }
}

Login:

[HttpPost("login")]
public async Task<IActionResult> Login(LoginRequest request)
{
    var user = await _userRepository.GetByEmailAsync(request.Email);
    if (user == null || !PasswordHasher.Verify(request.Password, user.PasswordHash))
        return Unauthorized();

    var token = _jwtTokenGenerator.GenerateToken(
        userId: user.Id.ToString(),
        email: user.Email,
        roles: user.Roles
    );

    return Ok(new { token });
}

Protected Endpoint:

[Authorize]
[RequirePermission("products.create")]
[HttpPost("products")]
public async Task<IActionResult> Create(CreateProductCommand command)
{
    var result = await _mediator.Send(command);
    return Ok(result);
}

CQRS & MediatR

Setup:

// In Program.cs
builder.Services.AddMarventa(builder.Configuration);
builder.Services.AddMarventaMediatR(typeof(Program).Assembly);
builder.Services.AddMarventaValidation(typeof(Program).Assembly);

Command:

public record CreateProductCommand : ICommand<Guid>
{
    public string Name { get; init; }
    public decimal Price { get; init; }
}

public class CreateProductCommandHandler : IRequestHandler<CreateProductCommand, Result<Guid>>
{
    private readonly IRepository<Product, Guid> _repository;
    private readonly IUnitOfWork _unitOfWork;

    public async Task<Result<Guid>> Handle(CreateProductCommand request, CancellationToken ct)
    {
        var product = new Product { Name = request.Name, Price = request.Price };
        await _repository.AddAsync(product, ct);
        await _unitOfWork.SaveChangesAsync(ct);

        return Result.Success(product.Id);
    }
}

Validation:

public class CreateProductCommandValidator : AbstractValidator<CreateProductCommand>
{
    public CreateProductCommandValidator()
    {
        RuleFor(x => x.Name).NotEmpty().MaximumLength(200);
        RuleFor(x => x.Price).GreaterThan(0);
    }
}

Controller:

[ApiController]
[Route("api/[controller]")]
public class ProductsController : ControllerBase
{
    private readonly IMediator _mediator;

    [HttpPost]
    public async Task<IActionResult> Create(CreateProductCommand command)
    {
        var result = await _mediator.Send(command);
        return result.IsSuccess ? Ok(result) : BadRequest(result);
    }
}

Database & Repository

Setup:

// In Program.cs
builder.Services.AddMarventaDbContext<AppDbContext>(options =>
    options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection")));

// Generic Repository
builder.Services.AddMarventaGenericRepository<Product, Guid>();

// Or Custom Repository
builder.Services.AddMarventaRepository<Product, Guid, ProductRepository>();

DbContext:

public class AppDbContext : BaseDbContext
{
    public DbSet<Product> Products { get; set; }

    public AppDbContext(DbContextOptions<AppDbContext> options) : base(options) { }
}

Entity (DDD):

public class Product : AuditableEntity<Guid>
{
    public string Name { get; set; }
    public decimal Price { get; set; }
    public Guid? TenantId { get; set; }  // For multi-tenancy

    // Domain Events
    public void UpdatePrice(decimal newPrice)
    {
        Price = newPrice;
        AddDomainEvent(new ProductPriceChangedEvent(Id, newPrice));
    }
}

Caching

InMemory (default):

public class ProductService
{
    private readonly ICacheService _cache;

    public async Task<Product> GetAsync(string id)
    {
        var cached = await _cache.GetAsync<Product>($"product:{id}");
        if (cached != null) return cached;

        var product = await _repository.GetByIdAsync(id);
        await _cache.SetAsync($"product:{id}", product,
            CacheOptions.WithAbsoluteExpiration(TimeSpan.FromMinutes(30)));

        return product;
    }
}

Redis:

{
  "Redis": {
    "ConnectionString": "localhost:6379"
  },
  "Caching": {
    "Type": "Redis"
  }
}

Event Bus (RabbitMQ & Kafka)

RabbitMQ:

{
  "RabbitMQ": {
    "Host": "localhost",
    "Username": "guest",
    "Password": "guest"
  }
}
// Publish
await _eventBus.PublishAsync(new OrderCreatedEvent
{
    OrderId = order.Id,
    Total = order.Total
});

// Subscribe
public class OrderCreatedEventHandler : IIntegrationEventHandler<OrderCreatedEvent>
{
    public async Task HandleAsync(OrderCreatedEvent @event, CancellationToken ct)
    {
        // Send confirmation email, update inventory, etc.
    }
}

Kafka (high-throughput):

{
  "Kafka": {
    "BootstrapServers": "localhost:9092",
    "GroupId": "myapp-group"
  }
}
// Producer
await _kafkaProducer.ProduceAsync("orders", new OrderCreatedEvent
{
    OrderId = order.Id,
    Total = order.Total
});

// Consumer
await _kafkaConsumer.SubscribeAsync("orders", async (message) =>
{
    var orderEvent = JsonSerializer.Deserialize<OrderCreatedEvent>(message);
    // Process event
});

MassTransit (advanced messaging):

{
  "MassTransit": {
    "Enabled": "true"
  },
  "RabbitMQ": {
    "Host": "localhost",
    "VirtualHost": "/",
    "Username": "guest",
    "Password": "guest"
  }
}
// Consumer
public class OrderCreatedConsumer : IConsumer<OrderCreatedEvent>
{
    public async Task Consume(ConsumeContext<OrderCreatedEvent> context)
    {
        var order = context.Message;
        // Process order
        await context.Publish(new OrderProcessedEvent { OrderId = order.OrderId });
    }
}

// Register consumer in Program.cs
builder.Services.AddMassTransit(x =>
{
    x.AddConsumer<OrderCreatedConsumer>();
    // UseMarventa() will configure RabbitMQ automatically
});

Multi-Tenancy

Config:

{
  "MultiTenancy": {
    "Strategy": "Header",
    "HeaderName": "X-Tenant-Id",
    "RequireTenant": true
  }
}

Usage:

public class ProductService
{
    private readonly ITenantContext _tenantContext;

    public async Task<List<Product>> GetAllAsync()
    {
        var tenantId = _tenantContext.TenantId;
        return await _repository.GetAllAsync(p => p.TenantId == tenantId);
    }
}

Rate Limiting

Config:

{
  "RateLimiting": {
    "RequestLimit": 100,
    "TimeWindowSeconds": 60,
    "Strategy": "IpAddress",
    "ReturnRateLimitHeaders": true
  }
}

Response Headers:

X-RateLimit-Limit: 100
X-RateLimit-Remaining: 45
X-RateLimit-Reset: 1234567890

Logging

Setup (auto-configured):

// In Program.cs
builder.Services.AddMarventa(builder.Configuration);

Usage:

public class ProductService
{
    private readonly ILogger<ProductService> _logger;

    public async Task<Product> GetAsync(Guid id)
    {
        _logger.LogInformation("Fetching product {ProductId}", id);

        var product = await _repository.GetByIdAsync(id);

        if (product == null)
            _logger.LogWarning("Product {ProductId} not found", id);

        return product;
    }
}

Configuration (appsettings.json):

{
  "Serilog": {
    "MinimumLevel": "Information",
    "WriteTo": [
      { "Name": "Console" },
      { "Name": "File", "Args": { "path": "logs/app.log", "rollingInterval": "Day" } }
    ]
  }
}

Storage (Local, Azure & AWS)

Local File System (default):

{
  "LocalStorage": {
    "BasePath": "D:/uploads",
    "BaseUrl": "https://myapp.com/files"  // Optional - for generating URLs
  }
}
// Upload
await _storage.UploadAsync(fileStream, "documents/file.pdf", "application/pdf");

// Download
var stream = await _storage.DownloadAsync("documents/file.pdf");

// Delete
await _storage.DeleteAsync("documents/file.pdf");

// Check if exists
var exists = await _storage.ExistsAsync("documents/file.pdf");

// Get URL
var url = await _storage.GetUrlAsync("documents/file.pdf");
// Returns: "https://myapp.com/files/documents/file.pdf" or local path

Azure Blob Storage:

{
  "Azure": {
    "Storage": {
      "ConnectionString": "your-connection-string",
      "ContainerName": "uploads"
    }
  }
}
// Upload
await _storage.UploadAsync(fileStream, "documents/file.pdf", "application/pdf");

// Download
var stream = await _storage.DownloadAsync("documents/file.pdf");

// Delete
await _storage.DeleteAsync("documents/file.pdf");

// List
var files = await _storage.ListAsync("documents/");

AWS S3:

{
  "AWS": {
    "AccessKey": "your-access-key",
    "SecretKey": "your-secret-key",
    "Region": "us-east-1",
    "BucketName": "my-bucket"
  }
}

Health Checks

Setup (auto-configured):

{
  "HealthChecks": {
    "Enabled": "true"
  },
  "ConnectionStrings": {
    "DefaultConnection": "Server=localhost;Database=MyApp;..."
  },
  "Redis": {
    "ConnectionString": "localhost:6379"
  },
  "RabbitMQ": {
    "Host": "localhost"
  }
}

Access:

GET /health

Response:
{
  "status": "Healthy",
  "entries": {
    "database": { "status": "Healthy" },
    "redis": { "status": "Healthy" },
    "rabbitmq": { "status": "Healthy" }
  }
}

Custom Health Check:

public class CustomHealthCheck : IHealthCheck
{
    public async Task<HealthCheckResult> CheckHealthAsync(
        HealthCheckContext context,
        CancellationToken cancellationToken = default)
    {
        // Custom logic
        var isHealthy = await CheckSomethingAsync();

        return isHealthy
            ? HealthCheckResult.Healthy("All systems operational")
            : HealthCheckResult.Unhealthy("System is down");
    }
}

// Register
builder.Services.AddHealthChecks()
    .AddCheck<CustomHealthCheck>("custom");

Search (Elasticsearch)

Setup:

{
  "Elasticsearch": {
    "Uri": "http://localhost:9200"
  }
}

Usage:

// Index a document
await _elasticsearchService.IndexDocumentAsync("products", product, product.Id);

// Search
var results = await _elasticsearchService.SearchAsync<Product>("products", "laptop gaming");

// Advanced search with filters
var searchResults = await _elasticsearchService.SearchAsync<Product>(
    "products",
    searchText: "laptop",
    filters: new Dictionary<string, object>
    {
        { "category", "electronics" },
        { "price", new { gte = 500, lte = 2000 } }
    }
);

⚙️ Configuration

Auto-Detection Table

Add these sections to appsettings.json to enable features:

Config Section Feature Example
Jwt Authentication "Secret": "your-key"
Redis + Caching Redis Cache "ConnectionString": "localhost:6379"
MultiTenancy Multi-Tenant "Strategy": "Header"
RateLimiting Rate Limiting "RequestLimit": 100
RabbitMQ Event Bus "Host": "localhost"
Kafka Event Streaming "BootstrapServers": "localhost:9092"
MassTransit Advanced Messaging "Enabled": "true"
Elasticsearch Search "Uri": "http://localhost:9200"
MongoDB NoSQL "ConnectionString": "mongodb://..."
HealthChecks Health Monitoring "Enabled": "true"
LocalStorage Local Files "BasePath": "D:/uploads"
Azure:Storage Azure Blob "ConnectionString": "..."
AWS AWS S3 "AccessKey": "...", "SecretKey": "..."

Manual Extensions

Features that need your code:

// CQRS + Validation
builder.Services.AddMarventaMediatR(typeof(Program).Assembly);
builder.Services.AddMarventaValidation(typeof(Program).Assembly);

// Database
builder.Services.AddMarventaDbContext<AppDbContext>(options =>
    options.UseSqlServer(connectionString));

// Repository (choose one)
builder.Services.AddMarventaGenericRepository<Product, Guid>();
builder.Services.AddMarventaRepository<Product, Guid, ProductRepository>();

// OpenTelemetry
builder.Services.AddMarventaOpenTelemetry(builder.Configuration, "MyService");

Custom Middleware

var app = builder.Build();

app.UseMarventa();        // Standard pipeline
app.UseCors("MyPolicy");  // Your custom middleware
app.UseStaticFiles();     // Your static files
app.MapControllers();
app.Run();

🔄 Migration Guide

v3.x → v4.0.2

Old:

builder.Services.AddMarventaFramework(builder.Configuration);
builder.Services.AddMarventaMediatR(typeof(Program).Assembly);
builder.Services.AddMarventaValidation(typeof(Program).Assembly);
builder.Services.AddMarventaJwtAuthentication(builder.Configuration);
builder.Services.AddMarventaCaching(builder.Configuration, CacheType.InMemory);

app.UseMarventaFramework(app.Environment);

New:

builder.Services.AddMarventa(builder.Configuration);
app.UseMarventa();

That's it! Everything else is automatic.


🎨 API Response Format

Success

{
  "success": true,
  "data": { "id": "123", "name": "Product" },
  "message": null,
  "errorCode": null
}

Error

{
  "success": false,
  "data": null,
  "message": "Product not found",
  "errorCode": "NOT_FOUND"
}

Validation Error

{
  "success": false,
  "message": "Validation failed",
  "errorCode": "VALIDATION_ERROR",
  "errors": {
    "Name": ["Product name is required"],
    "Price": ["Price must be greater than zero"]
  }
}

📝 What's New in v4.0.2

  • Convention over Configuration - Zero config by default
  • Auto-Detection - Framework scans appsettings.json automatically
  • One Line Setup - AddMarventa() + UseMarventa()
  • Simplified Documentation - Single README with everything
  • Advanced Rate Limiting - Multiple strategies
  • Enhanced Multi-Tenancy - Multiple resolution strategies

🤝 Contributing

Contributions welcome! Please submit a Pull Request.


📄 License

MIT License - see LICENSE


📧 Support

GitHub Issues


🌟 Show Your Support

⭐️ Star this repo if it helped you!


Built with ❤️ using .NET 8.0 & 9.0

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 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
5.2.0 230 10/13/2025 5.2.0 is deprecated because it is no longer maintained.
5.1.0 277 10/5/2025 5.1.0 is deprecated because it is no longer maintained.
5.0.0 184 10/4/2025 5.0.0 is deprecated because it is no longer maintained.
4.6.0 196 10/3/2025 4.6.0 is deprecated because it is no longer maintained.
4.5.5 216 10/2/2025 4.5.5 is deprecated because it is no longer maintained.
4.5.4 210 10/2/2025 4.5.4 is deprecated because it is no longer maintained.
4.5.3 208 10/2/2025 4.5.3 is deprecated because it is no longer maintained.
4.5.2 210 10/2/2025 4.5.2 is deprecated because it is no longer maintained.
4.5.1 211 10/2/2025 4.5.1 is deprecated because it is no longer maintained.
4.5.0 212 10/2/2025 4.5.0 is deprecated because it is no longer maintained.
4.4.0 218 10/1/2025 4.4.0 is deprecated because it is no longer maintained.
4.3.0 217 10/1/2025 4.3.0 is deprecated because it is no longer maintained.
4.2.0 218 10/1/2025 4.2.0 is deprecated because it is no longer maintained.
4.1.0 211 10/1/2025 4.1.0 is deprecated because it is no longer maintained.
4.0.2 218 10/1/2025 4.0.2 is deprecated because it is no longer maintained.
4.0.1 210 10/1/2025 4.0.1 is deprecated because it is no longer maintained.
4.0.0 286 9/30/2025 4.0.0 is deprecated because it is no longer maintained.
3.5.2 219 9/30/2025 3.5.2 is deprecated because it is no longer maintained.
3.5.1 250 9/30/2025 3.5.1 is deprecated because it is no longer maintained.
3.4.1 254 9/30/2025 3.4.1 is deprecated because it is no longer maintained.
3.4.0 249 9/30/2025 3.4.0 is deprecated because it is no longer maintained.
3.3.2 261 9/30/2025 3.3.2 is deprecated because it is no longer maintained.
3.2.0 253 9/30/2025 3.2.0 is deprecated because it is no longer maintained.
3.1.0 252 9/29/2025 3.1.0 is deprecated because it is no longer maintained.
3.0.1 251 9/29/2025 3.0.1 is deprecated because it is no longer maintained.
3.0.1-preview-20250929165802 246 9/29/2025 3.0.1-preview-20250929165802 is deprecated because it is no longer maintained.
3.0.0 248 9/29/2025 3.0.0 is deprecated because it is no longer maintained.
3.0.0-preview-20250929164242 251 9/29/2025 3.0.0-preview-20250929164242 is deprecated because it is no longer maintained.
3.0.0-preview-20250929162455 248 9/29/2025 3.0.0-preview-20250929162455 is deprecated because it is no longer maintained.
2.12.0-preview-20250929161039 242 9/29/2025 2.12.0-preview-20250929161039 is deprecated because it is no longer maintained.
2.11.0 253 9/29/2025 2.11.0 is deprecated because it is no longer maintained.
2.10.0 253 9/29/2025 2.10.0 is deprecated because it is no longer maintained.
2.9.0 247 9/29/2025 2.9.0 is deprecated because it is no longer maintained.
2.8.0 249 9/29/2025 2.8.0 is deprecated because it is no longer maintained.
2.7.0 260 9/29/2025 2.7.0 is deprecated because it is no longer maintained.
2.6.0 254 9/28/2025 2.6.0 is deprecated because it is no longer maintained.
2.5.0 260 9/28/2025 2.5.0 is deprecated because it is no longer maintained.
2.4.0 252 9/28/2025 2.4.0 is deprecated because it is no longer maintained.
2.3.0 253 9/28/2025 2.3.0 is deprecated because it is no longer maintained.
2.2.0 255 9/28/2025 2.2.0 is deprecated because it is no longer maintained.
2.1.0 253 9/26/2025 2.1.0 is deprecated because it is no longer maintained.
2.0.9 257 9/26/2025 2.0.9 is deprecated because it is no longer maintained.
2.0.5 250 9/25/2025 2.0.5 is deprecated because it is no longer maintained.
2.0.4 257 9/25/2025 2.0.4 is deprecated because it is no longer maintained.
2.0.3 261 9/25/2025 2.0.3 is deprecated because it is no longer maintained.
2.0.1 258 9/25/2025 2.0.1 is deprecated because it is no longer maintained.
2.0.0 258 9/25/2025 2.0.0 is deprecated because it is no longer maintained.
1.1.2 334 9/24/2025 1.1.2 is deprecated because it is no longer maintained.
1.1.1 335 9/24/2025 1.1.1 is deprecated because it is no longer maintained.
1.1.0 253 9/24/2025 1.1.0 is deprecated because it is no longer maintained.
1.0.0 258 9/24/2025 1.0.0 is deprecated because it is no longer maintained.