> This project was originally initiated by [Powered Software Inc.](https://poweredsoft.com/) and was forked from the [PoweredSoft.CQRS](https://github.com/PoweredSoft/CQRS) Repository # CQRS Our implementation of query and command responsibility segregation (CQRS). ## Getting Started > Install nuget package to your awesome project. | Package Name | NuGet | NuGet Install | |-----------------------------------------| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |-----------------------------------------------------------------------:| | Svrnty.CQRS | [![NuGet](https://img.shields.io/nuget/v/Svrnty.CQRS.svg?style=flat-square&label=nuget)](https://www.nuget.org/packages/Svrnty.CQRS/) | ```dotnet add package Svrnty.CQRS ``` | | Svrnty.CQRS.MinimalApi | [![NuGet](https://img.shields.io/nuget/v/Svrnty.CQRS.MinimalApi.svg?style=flat-square&label=nuget)](https://www.nuget.org/packages/Svrnty.CQRS.MinimalApi/) | ```dotnet add package Svrnty.CQRS.MinimalApi ``` | | Svrnty.CQRS.AspNetCore | [![NuGet](https://img.shields.io/nuget/v/Svrnty.CQRS.AspNetCore.svg?style=flat-square&label=nuget)](https://www.nuget.org/packages/Svrnty.CQRS.AspNetCore/) | ```dotnet add package Svrnty.CQRS.AspNetCore ``` | | Svrnty.CQRS.FluentValidation | [![NuGet](https://img.shields.io/nuget/v/Svrnty.CQRS.FluentValidation.svg?style=flat-square&label=nuget)](https://www.nuget.org/packages/Svrnty.CQRS.FluentValidation/) | ```dotnet add package Svrnty.CQRS.FluentValidation ``` | | Svrnty.CQRS.DynamicQuery | [![NuGet](https://img.shields.io/nuget/v/Svrnty.CQRS.DynamicQuery.svg?style=flat-square&label=nuget)](https://www.nuget.org/packages/Svrnty.CQRS.DynamicQuery/) | ```dotnet add package Svrnty.CQRS.DynamicQuery ``` | | Svrnty.CQRS.DynamicQuery.AspNetCore | [![NuGet](https://img.shields.io/nuget/v/Svrnty.CQRS.DynamicQuery.AspNetCore.svg?style=flat-square&label=nuget)](https://www.nuget.org/packages/Svrnty.CQRS.DynamicQuery.AspNetCore/) | ```dotnet add package Svrnty.CQRS.DynamicQuery.AspNetCore ``` | | Svrnty.CQRS.Grpc | [![NuGet](https://img.shields.io/nuget/v/Svrnty.CQRS.Grpc.svg?style=flat-square&label=nuget)](https://www.nuget.org/packages/Svrnty.CQRS.Grpc/) | ```dotnet add package Svrnty.CQRS.Grpc ``` | > Abstractions Packages. | Package Name | NuGet | NuGet Install | | ---------------------------- |----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -----------------------------------------------------: | | Svrnty.CQRS.Abstractions | [![NuGet](https://img.shields.io/nuget/v/Svrnty.CQRS.Abstractions.svg?style=flat-square&label=nuget)](https://www.nuget.org/packages/Svrnty.CQRS.Abstractions/) | ```dotnet add package Svrnty.CQRS.Abstractions ``` | | Svrnty.CQRS.AspNetCore.Abstractions | [![NuGet](https://img.shields.io/nuget/v/Svrnty.CQRS.AspNetCore.Abstractions.svg?style=flat-square&label=nuget)](https://www.nuget.org/packages/Svrnty.CQRS.AspNetCore.Abstractions/) | ```dotnet add package Svrnty.CQRS.AspNetCore.Abstractions ``` | | Svrnty.CQRS.DynamicQuery.Abstractions | [![NuGet](https://img.shields.io/nuget/v/Svrnty.CQRS.DynamicQuery.Abstractions.svg?style=flat-square&label=nuget)](https://www.nuget.org/packages/Svrnty.CQRS.DynamicQuery.Abstractions/) | ```dotnet add package Svrnty.CQRS.AspNetCore.Abstractions ``` | ## Sample of startup code for Minimal API (Recommended) ```csharp var builder = WebApplication.CreateBuilder(args); // Register CQRS core services builder.Services.AddSvrntyCQRS(); builder.Services.AddDefaultCommandDiscovery(); builder.Services.AddDefaultQueryDiscovery(); // Add your commands and queries AddQueries(builder.Services); AddCommands(builder.Services); // Add Swagger (optional) builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); var app = builder.Build(); if (app.Environment.IsDevelopment()) { app.UseSwagger(); app.UseSwaggerUI(); } // Map CQRS endpoints - automatically creates routes for all commands and queries app.MapSvrntyCommands(); // Creates POST /api/command/{commandName} endpoints app.MapSvrntyQueries(); // Creates POST/GET /api/query/{queryName} endpoints app.Run(); ``` ## Sample of startup code for ASP.NET Core MVC (Legacy) ```csharp public void ConfigureServices(IServiceCollection services) { // make sure to add your queries and commands before configuring MvcBuilder with .AddSvrntyCommands and .AddSvrntyQueries AddQueries(services); AddCommands(services); // adds the non related to aspnet core features. services.AddSvrntyCQRS(); services .AddControllers() .AddSvrntyQueries() // adds queries to aspnetcore mvc.(you can make it configurable to load balance only commands on a instance) .AddSvrntyCommands() // adds commands to aspnetcore mvc. (you can make it configurable to load balance only commands on a instance) .AddFluentValidation(); services.AddSwaggerGen(); } ``` ## Sample of startup code for gRPC ```csharp var builder = WebApplication.CreateBuilder(args); // Register CQRS core services builder.Services.AddSvrntyCQRS(); builder.Services.AddDefaultCommandDiscovery(); builder.Services.AddDefaultQueryDiscovery(); // Add your commands and queries AddQueries(builder.Services); AddCommands(builder.Services); // Add gRPC support builder.Services.AddSvrntyCqrsGrpc(); var app = builder.Build(); // Map gRPC endpoints app.MapSvrntyGrpcCommands(); app.MapSvrntyGrpcQueries(); app.Run(); ``` ### Important: protobuf-net Requirements for gRPC To use gRPC, your commands and queries must be annotated with protobuf-net attributes: ```csharp using ProtoBuf; [ProtoContract] public class CreatePersonCommand { [ProtoMember(1)] public string FirstName { get; set; } = string.Empty; [ProtoMember(2)] public string LastName { get; set; } = string.Empty; [ProtoMember(3)] public int Age { get; set; } } [ProtoContract] public class Person { [ProtoMember(1)] public int Id { get; set; } [ProtoMember(2)] public string FullName { get; set; } = string.Empty; } ``` **Notes:** - Add `[ProtoContract]` to each command/query/result class - Add `[ProtoMember(n)]` to each property with sequential numbers starting from 1 - These attributes don't interfere with JSON serialization or FluentValidation - You can use both HTTP REST (MinimalApi/MVC) and gRPC simultaneously > Example how to add your queries and commands. ```csharp private void AddCommands(IServiceCollection services) { services.AddCommand(); services.AddTransient, CreatePersonCommandValidator>(); services.AddCommand(); services.AddTransient, EchoCommandValidator>(); } private void AddQueries(IServiceCollection services) { services.AddQuery, PersonQueryHandler>(); } ``` # Fluent Validation We use fluent validation in all of our projects, but we don't want it to be enforced. If you install ```Svrnty.CQRS.FluentValidation``` you can use this way of registrating your commands. ```csharp public void ConfigureServices(IServiceCollection services) { // without Package. services.AddCommand(); services.AddTransient, EchoCommandValidator>(); } public void ConfigureServices(IServiceCollection services) { // with Svrnty.CQRS.FluentValidation package. services.AddCommand(); } ``` # 2024-2025 Roadmap | Task | Description | Status | |----------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------|--------| | Support .NET 8 | Ensure compatibility with .NET 8. | ✅ | | Support .NET 10 | Upgrade to .NET 10 with C# 14 language support. | ✅ | | Update FluentValidation | Upgrade FluentValidation to version 11.x for .NET 10 compatibility. | ✅ | | Add gRPC Support with protobuf-net | Implement gRPC endpoints with binary protobuf serialization for high-performance scenarios. | ✅ | | Create a new demo project as an example | Develop a new demo project to serve as an example for users. | ⬜️ | | New Independent Module for MVC | Develop a standalone module, independent of MVC, to enhance framework flexibility. | ⬜️ | | Implement .NET Native Compilation (AOT) | Enable full Ahead-of-Time (AOT) compilation support (blocked by third-party dependencies). | ⬜️ | | Create a website for the Framework | Develop a website to host comprehensive documentation for the framework. | ⬜️ | | Re-add support for GraphQL | Re-integrate support for GraphQL, exploring lightweight solutions. | ⬜️ |