Repository files navigation

Foundatio.CommandQuery

NuGetBuild Status

A powerful Command Query Responsibility Segregation (CQRS) framework built on the mediator pattern. This library provides core abstractions and implementations for building scalable, maintainable applications using CQRS principles.

Features

  • Clean CQRS Implementation - Separate read and write operations with clear command/query patterns
  • Mediator Pattern - Built on Foundatio.Mediator for decoupled messaging
  • Multiple Data Stores - Support for Entity Framework Core and MongoDB out of the box
  • ASP.NET Core Integration - Minimal API endpoints for exposing commands and queries via HTTP
  • Caching Support - Built-in caching abstractions for query optimization
  • Dynamic Queries - Powerful filtering, sorting, and pagination with LINQ support
  • Multi-Targeting - Supports .NET 8, .NET 9, and .NET 10

Packages

PackageDescriptionNuGet
Foundatio.CommandQueryCore abstractions and base classes for implementing CQRS patterns using the mediator patternNuGet
Foundatio.CommandQuery.DispatcherDispatcher implementation providing centralized command and query handling with caching supportNuGet
Foundatio.CommandQuery.EndpointsASP.NET Core Minimal API endpoints for HTTP-based command and query executionNuGet
Foundatio.CommandQuery.EntityFrameworkEntity Framework Core integration providing database query and persistence handlers with dynamic LINQ supportNuGet
Foundatio.CommandQuery.MongoDBMongoDB integration providing NoSQL database query and persistence handlers with dynamic LINQ supportNuGet

Installation

Using .NET CLI

# Core package
dotnet add package Foundatio.CommandQuery
# Entity Framework integration
dotnet add package Foundatio.CommandQuery.EntityFramework
# MongoDB integration
dotnet add package Foundatio.CommandQuery.MongoDB
# ASP.NET Core endpoints
dotnet add package Foundatio.CommandQuery.Endpoints
# Dispatcher for Blazor 
dotnet add package Foundatio.CommandQuery.Dispatcher

Using Package Manager Console

Install-Package Foundatio.CommandQuery
Install-Package Foundatio.CommandQuery.EntityFramework
Install-Package Foundatio.CommandQuery.MongoDB
Install-Package Foundatio.CommandQuery.Endpoints
Install-Package Foundatio.CommandQuery.Dispatcher

Quick Start

1. Define Your Models

// Entity modelpublicclassTask:IHaveIdentifier<int>{publicintId{get;set;}publicstringTitle{get;set;}publicstringDescription{get;set;}publicDateTimeCreated{get;set;}publicstringCreatedBy{get;set;}}// Read modelpublicclassTaskReadModel:EntityReadModel<int>{publicstringTitle{get;set;}publicstringDescription{get;set;}}// Create modelpublicclassTaskCreateModel:EntityCreateModel<int>{publicstringTitle{get;set;}publicstringDescription{get;set;}}// Update modelpublicclassTaskUpdateModel:EntityUpdateModel{publicstringTitle{get;set;}publicstringDescription{get;set;}}

2. Create Command and Query Handlers

usingFoundatio.CommandQuery.EntityFramework;publicclassTaskCommandHandler:EntityCommandHandler<AppDbContext,Task,int,TaskReadModel,TaskCreateModel,TaskUpdateModel>{publicTaskCommandHandler(AppDbContextcontext,IMappermapper):base(context,mapper){}}publicclassTaskQueryHandler:EntityQueryHandler<AppDbContext,Task,int,TaskReadModel>{publicTaskQueryHandler(AppDbContextcontext,IMappermapper):base(context,mapper){}}

3. Register Services

varbuilder=WebApplication.CreateBuilder(args);// Add mediator with assemblies containing handlersbuilder.Services.AddMediator(options =>options.AddAssembly(typeof(Program).Assembly));// Add your DbContextbuilder.Services.AddDbContext<AppDbContext>(options =>options.UseSqlServer(builder.Configuration.GetConnectionString("Default")));// Add endpoint routesbuilder.Services.AddEndpointRoutes();

4. Configure Minimal API Endpoints

publicclassTaskEndpoint:EntityCommandEndpointBase<int,TaskListModel,TaskReadModel,TaskCreateModel,TaskUpdateModel>{publicTaskEndpoint(ILoggerFactoryloggerFactory):base(loggerFactory,"tasks","api/tasks"){}}varapp=builder.Build();// Map endpoint routesapp.MapEndpointRoutes();app.Run();

This automatically creates the following endpoints:

  • GET /api/tasks/{id} - Get a task by ID
  • GET /api/tasks - Query tasks with pagination and sorting
  • POST /api/tasks/query - Query tasks with advanced filtering
  • GET /api/tasks/{id}/update - Get task update model
  • POST /api/tasks - Create a new task
  • PUT /api/tasks/{id} - Update a task
  • DELETE /api/tasks/{id} - Delete a task

Advanced Usage

Using Commands Directly

publicclassTaskService{privatereadonlyIMediator_mediator;publicTaskService(IMediatormediator){_mediator=mediator;}publicasyncTask<Result<TaskReadModel>>CreateTaskAsync(TaskCreateModelmodel,ClaimsPrincipaluser){varcommand=newCreateEntity<TaskCreateModel,TaskReadModel>(user,model);returnawait_mediator.InvokeAsync<Result<TaskReadModel>>(command);}publicasyncTask<Result<TaskReadModel>>GetTaskAsync(intid,ClaimsPrincipaluser){varquery=newGetEntity<int,TaskReadModel>(user,id);returnawait_mediator.InvokeAsync<Result<TaskReadModel>>(query);}publicasyncTask<Result<QueryResult<TaskReadModel>>>QueryTasksAsync(QueryDefinitionquery,ClaimsPrincipaluser){varcommand=newQueryEntities<TaskReadModel>(user,query);returnawait_mediator.InvokeAsync<Result<QueryResult<TaskReadModel>>>(command);}}

Advanced Querying

// Query with filtering, sorting, and paginationvarqueryDefinition=newQueryDefinition{Filter=newQueryFilter{Logic=FilterLogic.And,Filters=newList<QueryFilter>{new(){Field="Status",Operator=FilterOperator.Equal,Value="Active"},new(){Field="Priority",Operator=FilterOperator.GreaterThan,Value=3}}},Sorts=newList<QuerySort>{new(){Name="Priority",Descending=true},new(){Name="Created",Descending=false}},Page=1,PageSize=20};varquery=newQueryEntities<TaskReadModel>(user,queryDefinition);varresult=await_mediator.InvokeAsync<Result<QueryResult<TaskReadModel>>>(query);

MongoDB Usage

usingFoundatio.CommandQuery.MongoDB;publicclassTaskCommandHandler:EntityCommandHandler<Task,int,TaskReadModel,TaskCreateModel,TaskUpdateModel>{publicTaskCommandHandler(IMongoDatabasedatabase,IMappermapper):base(database,mapper){}}publicclassTaskQueryHandler:EntityQueryHandler<Task,int,TaskReadModel>{publicTaskQueryHandler(IMongoDatabasedatabase,IMappermapper):base(database,mapper){}}

Custom Command Handlers

publicrecordProcessTaskCommand:PrincipalCommand<CompleteModel>{publicProcessTaskCommand(ClaimsPrincipal?principal,stringaction):base(principal){Action=action;}publicstringAction{get;}}publicclassProcessTaskHandler:IRequestHandler<ProcessTaskCommand,CompleteModel>{publicasyncValueTask<CompleteModel>HandleAsync(ProcessTaskCommandrequest,CancellationTokencancellationToken=default){// Custom processing logicreturnCompleteModel.Success($"Processed: {request.Action}");}}

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

License

This project is licensed under the Apache License 2.0 - see the LICENSE file for details.

About

No description, website, or topics provided.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Sponsor this project

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Repository files navigation

Foundatio.CommandQuery

NuGetBuild Status

A powerful Command Query Responsibility Segregation (CQRS) framework built on the mediator pattern. This library provides core abstractions and implementations for building scalable, maintainable applications using CQRS principles.

Features

  • Clean CQRS Implementation - Separate read and write operations with clear command/query patterns
  • Mediator Pattern - Built on Foundatio.Mediator for decoupled messaging
  • Multiple Data Stores - Support for Entity Framework Core and MongoDB out of the box
  • ASP.NET Core Integration - Minimal API endpoints for exposing commands and queries via HTTP
  • Caching Support - Built-in caching abstractions for query optimization
  • Dynamic Queries - Powerful filtering, sorting, and pagination with LINQ support
  • Multi-Targeting - Supports .NET 8, .NET 9, and .NET 10

Packages

PackageDescriptionNuGet
Foundatio.CommandQueryCore abstractions and base classes for implementing CQRS patterns using the mediator patternNuGet
Foundatio.CommandQuery.DispatcherDispatcher implementation providing centralized command and query handling with caching supportNuGet
Foundatio.CommandQuery.EndpointsASP.NET Core Minimal API endpoints for HTTP-based command and query executionNuGet
Foundatio.CommandQuery.EntityFrameworkEntity Framework Core integration providing database query and persistence handlers with dynamic LINQ supportNuGet
Foundatio.CommandQuery.MongoDBMongoDB integration providing NoSQL database query and persistence handlers with dynamic LINQ supportNuGet

Installation

Using .NET CLI

# Core package
dotnet add package Foundatio.CommandQuery
# Entity Framework integration
dotnet add package Foundatio.CommandQuery.EntityFramework
# MongoDB integration
dotnet add package Foundatio.CommandQuery.MongoDB
# ASP.NET Core endpoints
dotnet add package Foundatio.CommandQuery.Endpoints
# Dispatcher for Blazor 
dotnet add package Foundatio.CommandQuery.Dispatcher

Using Package Manager Console

Install-Package Foundatio.CommandQuery
Install-Package Foundatio.CommandQuery.EntityFramework
Install-Package Foundatio.CommandQuery.MongoDB
Install-Package Foundatio.CommandQuery.Endpoints
Install-Package Foundatio.CommandQuery.Dispatcher

Quick Start

1. Define Your Models

// Entity modelpublicclassTask:IHaveIdentifier<int>{publicintId{get;set;}publicstringTitle{get;set;}publicstringDescription{get;set;}publicDateTimeCreated{get;set;}publicstringCreatedBy{get;set;}}// Read modelpublicclassTaskReadModel:EntityReadModel<int>{publicstringTitle{get;set;}publicstringDescription{get;set;}}// Create modelpublicclassTaskCreateModel:EntityCreateModel<int>{publicstringTitle{get;set;}publicstringDescription{get;set;}}// Update modelpublicclassTaskUpdateModel:EntityUpdateModel{publicstringTitle{get;set;}publicstringDescription{get;set;}}

2. Create Command and Query Handlers

usingFoundatio.CommandQuery.EntityFramework;publicclassTaskCommandHandler:EntityCommandHandler<AppDbContext,Task,int,TaskReadModel,TaskCreateModel,TaskUpdateModel>{publicTaskCommandHandler(AppDbContextcontext,IMappermapper):base(context,mapper){}}publicclassTaskQueryHandler:EntityQueryHandler<AppDbContext,Task,int,TaskReadModel>{publicTaskQueryHandler(AppDbContextcontext,IMappermapper):base(context,mapper){}}

3. Register Services

varbuilder=WebApplication.CreateBuilder(args);// Add mediator with assemblies containing handlersbuilder.Services.AddMediator(options =>options.AddAssembly(typeof(Program).Assembly));// Add your DbContextbuilder.Services.AddDbContext<AppDbContext>(options =>options.UseSqlServer(builder.Configuration.GetConnectionString("Default")));// Add endpoint routesbuilder.Services.AddEndpointRoutes();

4. Configure Minimal API Endpoints

publicclassTaskEndpoint:EntityCommandEndpointBase<int,TaskListModel,TaskReadModel,TaskCreateModel,TaskUpdateModel>{publicTaskEndpoint(ILoggerFactoryloggerFactory):base(loggerFactory,"tasks","api/tasks"){}}varapp=builder.Build();// Map endpoint routesapp.MapEndpointRoutes();app.Run();

This automatically creates the following endpoints:

  • GET /api/tasks/{id} - Get a task by ID
  • GET /api/tasks - Query tasks with pagination and sorting
  • POST /api/tasks/query - Query tasks with advanced filtering
  • GET /api/tasks/{id}/update - Get task update model
  • POST /api/tasks - Create a new task
  • PUT /api/tasks/{id} - Update a task
  • DELETE /api/tasks/{id} - Delete a task

Advanced Usage

Using Commands Directly

publicclassTaskService{privatereadonlyIMediator_mediator;publicTaskService(IMediatormediator){_mediator=mediator;}publicasyncTask<Result<TaskReadModel>>CreateTaskAsync(TaskCreateModelmodel,ClaimsPrincipaluser){varcommand=newCreateEntity<TaskCreateModel,TaskReadModel>(user,model);returnawait_mediator.InvokeAsync<Result<TaskReadModel>>(command);}publicasyncTask<Result<TaskReadModel>>GetTaskAsync(intid,ClaimsPrincipaluser){varquery=newGetEntity<int,TaskReadModel>(user,id);returnawait_mediator.InvokeAsync<Result<TaskReadModel>>(query);}publicasyncTask<Result<QueryResult<TaskReadModel>>>QueryTasksAsync(QueryDefinitionquery,ClaimsPrincipaluser){varcommand=newQueryEntities<TaskReadModel>(user,query);returnawait_mediator.InvokeAsync<Result<QueryResult<TaskReadModel>>>(command);}}

Advanced Querying

// Query with filtering, sorting, and paginationvarqueryDefinition=newQueryDefinition{Filter=newQueryFilter{Logic=FilterLogic.And,Filters=newList<QueryFilter>{new(){Field="Status",Operator=FilterOperator.Equal,Value="Active"},new(){Field="Priority",Operator=FilterOperator.GreaterThan,Value=3}}},Sorts=newList<QuerySort>{new(){Name="Priority",Descending=true},new(){Name="Created",Descending=false}},Page=1,PageSize=20};varquery=newQueryEntities<TaskReadModel>(user,queryDefinition);varresult=await_mediator.InvokeAsync<Result<QueryResult<TaskReadModel>>>(query);

MongoDB Usage

usingFoundatio.CommandQuery.MongoDB;publicclassTaskCommandHandler:EntityCommandHandler<Task,int,TaskReadModel,TaskCreateModel,TaskUpdateModel>{publicTaskCommandHandler(IMongoDatabasedatabase,IMappermapper):base(database,mapper){}}publicclassTaskQueryHandler:EntityQueryHandler<Task,int,TaskReadModel>{publicTaskQueryHandler(IMongoDatabasedatabase,IMappermapper):base(database,mapper){}}

Custom Command Handlers

publicrecordProcessTaskCommand:PrincipalCommand<CompleteModel>{publicProcessTaskCommand(ClaimsPrincipal?principal,stringaction):base(principal){Action=action;}publicstringAction{get;}}publicclassProcessTaskHandler:IRequestHandler<ProcessTaskCommand,CompleteModel>{publicasyncValueTask<CompleteModel>HandleAsync(ProcessTaskCommandrequest,CancellationTokencancellationToken=default){// Custom processing logicreturnCompleteModel.Success($"Processed: {request.Action}");}}

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

License

This project is licensed under the Apache License 2.0 - see the LICENSE file for details.

About

No description, website, or topics provided.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Sponsor this project

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

Foundatio.CommandQuery

NuGetBuild Status

A powerful Command Query Responsibility Segregation (CQRS) framework built on the mediator pattern. This library provides core abstractions and implementations for building scalable, maintainable applications using CQRS principles.

Features

  • Clean CQRS Implementation - Separate read and write operations with clear command/query patterns
  • Mediator Pattern - Built on Foundatio.Mediator for decoupled messaging
  • Multiple Data Stores - Support for Entity Framework Core and MongoDB out of the box
  • ASP.NET Core Integration - Minimal API endpoints for exposing commands and queries via HTTP
  • Caching Support - Built-in caching abstractions for query optimization
  • Dynamic Queries - Powerful filtering, sorting, and pagination with LINQ support
  • Multi-Targeting - Supports .NET 8, .NET 9, and .NET 10

Packages

PackageDescriptionNuGet
Foundatio.CommandQueryCore abstractions and base classes for implementing CQRS patterns using the mediator patternNuGet
Foundatio.CommandQuery.DispatcherDispatcher implementation providing centralized command and query handling with caching supportNuGet
Foundatio.CommandQuery.EndpointsASP.NET Core Minimal API endpoints for HTTP-based command and query executionNuGet
Foundatio.CommandQuery.EntityFrameworkEntity Framework Core integration providing database query and persistence handlers with dynamic LINQ supportNuGet
Foundatio.CommandQuery.MongoDBMongoDB integration providing NoSQL database query and persistence handlers with dynamic LINQ supportNuGet

Installation

Using .NET CLI

# Core package
dotnet add package Foundatio.CommandQuery
# Entity Framework integration
dotnet add package Foundatio.CommandQuery.EntityFramework
# MongoDB integration
dotnet add package Foundatio.CommandQuery.MongoDB
# ASP.NET Core endpoints
dotnet add package Foundatio.CommandQuery.Endpoints
# Dispatcher for Blazor 
dotnet add package Foundatio.CommandQuery.Dispatcher

Using Package Manager Console

Install-Package Foundatio.CommandQuery
Install-Package Foundatio.CommandQuery.EntityFramework
Install-Package Foundatio.CommandQuery.MongoDB
Install-Package Foundatio.CommandQuery.Endpoints
Install-Package Foundatio.CommandQuery.Dispatcher

Quick Start

1. Define Your Models

// Entity modelpublicclassTask:IHaveIdentifier<int>{publicintId{get;set;}publicstringTitle{get;set;}publicstringDescription{get;set;}publicDateTimeCreated{get;set;}publicstringCreatedBy{get;set;}}// Read modelpublicclassTaskReadModel:EntityReadModel<int>{publicstringTitle{get;set;}publicstringDescription{get;set;}}// Create modelpublicclassTaskCreateModel:EntityCreateModel<int>{publicstringTitle{get;set;}publicstringDescription{get;set;}}// Update modelpublicclassTaskUpdateModel:EntityUpdateModel{publicstringTitle{get;set;}publicstringDescription{get;set;}}

2. Create Command and Query Handlers

usingFoundatio.CommandQuery.EntityFramework;publicclassTaskCommandHandler:EntityCommandHandler<AppDbContext,Task,int,TaskReadModel,TaskCreateModel,TaskUpdateModel>{publicTaskCommandHandler(AppDbContextcontext,IMappermapper):base(context,mapper){}}publicclassTaskQueryHandler:EntityQueryHandler<AppDbContext,Task,int,TaskReadModel>{publicTaskQueryHandler(AppDbContextcontext,IMappermapper):base(context,mapper){}}

3. Register Services

varbuilder=WebApplication.CreateBuilder(args);// Add mediator with assemblies containing handlersbuilder.Services.AddMediator(options =>options.AddAssembly(typeof(Program).Assembly));// Add your DbContextbuilder.Services.AddDbContext<AppDbContext>(options =>options.UseSqlServer(builder.Configuration.GetConnectionString("Default")));// Add endpoint routesbuilder.Services.AddEndpointRoutes();

4. Configure Minimal API Endpoints

publicclassTaskEndpoint:EntityCommandEndpointBase<int,TaskListModel,TaskReadModel,TaskCreateModel,TaskUpdateModel>{publicTaskEndpoint(ILoggerFactoryloggerFactory):base(loggerFactory,"tasks","api/tasks"){}}varapp=builder.Build();// Map endpoint routesapp.MapEndpointRoutes();app.Run();

This automatically creates the following endpoints:

  • GET /api/tasks/{id} - Get a task by ID
  • GET /api/tasks - Query tasks with pagination and sorting
  • POST /api/tasks/query - Query tasks with advanced filtering
  • GET /api/tasks/{id}/update - Get task update model
  • POST /api/tasks - Create a new task
  • PUT /api/tasks/{id} - Update a task
  • DELETE /api/tasks/{id} - Delete a task

Advanced Usage

Using Commands Directly

publicclassTaskService{privatereadonlyIMediator_mediator;publicTaskService(IMediatormediator){_mediator=mediator;}publicasyncTask<Result<TaskReadModel>>CreateTaskAsync(TaskCreateModelmodel,ClaimsPrincipaluser){varcommand=newCreateEntity<TaskCreateModel,TaskReadModel>(user,model);returnawait_mediator.InvokeAsync<Result<TaskReadModel>>(command);}publicasyncTask<Result<TaskReadModel>>GetTaskAsync(intid,ClaimsPrincipaluser){varquery=newGetEntity<int,TaskReadModel>(user,id);returnawait_mediator.InvokeAsync<Result<TaskReadModel>>(query);}publicasyncTask<Result<QueryResult<TaskReadModel>>>QueryTasksAsync(QueryDefinitionquery,ClaimsPrincipaluser){varcommand=newQueryEntities<TaskReadModel>(user,query);returnawait_mediator.InvokeAsync<Result<QueryResult<TaskReadModel>>>(command);}}

Advanced Querying

// Query with filtering, sorting, and paginationvarqueryDefinition=newQueryDefinition{Filter=newQueryFilter{Logic=FilterLogic.And,Filters=newList<QueryFilter>{new(){Field="Status",Operator=FilterOperator.Equal,Value="Active"},new(){Field="Priority",Operator=FilterOperator.GreaterThan,Value=3}}},Sorts=newList<QuerySort>{new(){Name="Priority",Descending=true},new(){Name="Created",Descending=false}},Page=1,PageSize=20};varquery=newQueryEntities<TaskReadModel>(user,queryDefinition);varresult=await_mediator.InvokeAsync<Result<QueryResult<TaskReadModel>>>(query);

MongoDB Usage

usingFoundatio.CommandQuery.MongoDB;publicclassTaskCommandHandler:EntityCommandHandler<Task,int,TaskReadModel,TaskCreateModel,TaskUpdateModel>{publicTaskCommandHandler(IMongoDatabasedatabase,IMappermapper):base(database,mapper){}}publicclassTaskQueryHandler:EntityQueryHandler<Task,int,TaskReadModel>{publicTaskQueryHandler(IMongoDatabasedatabase,IMappermapper):base(database,mapper){}}

Custom Command Handlers

publicrecordProcessTaskCommand:PrincipalCommand<CompleteModel>{publicProcessTaskCommand(ClaimsPrincipal?principal,stringaction):base(principal){Action=action;}publicstringAction{get;}}publicclassProcessTaskHandler:IRequestHandler<ProcessTaskCommand,CompleteModel>{publicasyncValueTask<CompleteModel>HandleAsync(ProcessTaskCommandrequest,CancellationTokencancellationToken=default){// Custom processing logicreturnCompleteModel.Success($"Processed: {request.Action}");}}

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

License

This project is licensed under the Apache License 2.0 - see the LICENSE file for details.

About

No description, website, or topics provided.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Sponsor this project

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

Foundatio.CommandQuery

NuGetBuild Status

A powerful Command Query Responsibility Segregation (CQRS) framework built on the mediator pattern. This library provides core abstractions and implementations for building scalable, maintainable applications using CQRS principles.

Features

  • Clean CQRS Implementation - Separate read and write operations with clear command/query patterns
  • Mediator Pattern - Built on Foundatio.Mediator for decoupled messaging
  • Multiple Data Stores - Support for Entity Framework Core and MongoDB out of the box
  • ASP.NET Core Integration - Minimal API endpoints for exposing commands and queries via HTTP
  • Caching Support - Built-in caching abstractions for query optimization
  • Dynamic Queries - Powerful filtering, sorting, and pagination with LINQ support
  • Multi-Targeting - Supports .NET 8, .NET 9, and .NET 10

Packages

PackageDescriptionNuGet
Foundatio.CommandQueryCore abstractions and base classes for implementing CQRS patterns using the mediator patternNuGet
Foundatio.CommandQuery.DispatcherDispatcher implementation providing centralized command and query handling with caching supportNuGet
Foundatio.CommandQuery.EndpointsASP.NET Core Minimal API endpoints for HTTP-based command and query executionNuGet
Foundatio.CommandQuery.EntityFrameworkEntity Framework Core integration providing database query and persistence handlers with dynamic LINQ supportNuGet
Foundatio.CommandQuery.MongoDBMongoDB integration providing NoSQL database query and persistence handlers with dynamic LINQ supportNuGet

Installation

Using .NET CLI

# Core package
dotnet add package Foundatio.CommandQuery
# Entity Framework integration
dotnet add package Foundatio.CommandQuery.EntityFramework
# MongoDB integration
dotnet add package Foundatio.CommandQuery.MongoDB
# ASP.NET Core endpoints
dotnet add package Foundatio.CommandQuery.Endpoints
# Dispatcher for Blazor 
dotnet add package Foundatio.CommandQuery.Dispatcher

Using Package Manager Console

Install-Package Foundatio.CommandQuery
Install-Package Foundatio.CommandQuery.EntityFramework
Install-Package Foundatio.CommandQuery.MongoDB
Install-Package Foundatio.CommandQuery.Endpoints
Install-Package Foundatio.CommandQuery.Dispatcher

Quick Start

1. Define Your Models

// Entity modelpublicclassTask:IHaveIdentifier<int>{publicintId{get;set;}publicstringTitle{get;set;}publicstringDescription{get;set;}publicDateTimeCreated{get;set;}publicstringCreatedBy{get;set;}}// Read modelpublicclassTaskReadModel:EntityReadModel<int>{publicstringTitle{get;set;}publicstringDescription{get;set;}}// Create modelpublicclassTaskCreateModel:EntityCreateModel<int>{publicstringTitle{get;set;}publicstringDescription{get;set;}}// Update modelpublicclassTaskUpdateModel:EntityUpdateModel{publicstringTitle{get;set;}publicstringDescription{get;set;}}

2. Create Command and Query Handlers

usingFoundatio.CommandQuery.EntityFramework;publicclassTaskCommandHandler:EntityCommandHandler<AppDbContext,Task,int,TaskReadModel,TaskCreateModel,TaskUpdateModel>{publicTaskCommandHandler(AppDbContextcontext,IMappermapper):base(context,mapper){}}publicclassTaskQueryHandler:EntityQueryHandler<AppDbContext,Task,int,TaskReadModel>{publicTaskQueryHandler(AppDbContextcontext,IMappermapper):base(context,mapper){}}

3. Register Services

varbuilder=WebApplication.CreateBuilder(args);// Add mediator with assemblies containing handlersbuilder.Services.AddMediator(options =>options.AddAssembly(typeof(Program).Assembly));// Add your DbContextbuilder.Services.AddDbContext<AppDbContext>(options =>options.UseSqlServer(builder.Configuration.GetConnectionString("Default")));// Add endpoint routesbuilder.Services.AddEndpointRoutes();

4. Configure Minimal API Endpoints

publicclassTaskEndpoint:EntityCommandEndpointBase<int,TaskListModel,TaskReadModel,TaskCreateModel,TaskUpdateModel>{publicTaskEndpoint(ILoggerFactoryloggerFactory):base(loggerFactory,"tasks","api/tasks"){}}varapp=builder.Build();// Map endpoint routesapp.MapEndpointRoutes();app.Run();

This automatically creates the following endpoints:

  • GET /api/tasks/{id} - Get a task by ID
  • GET /api/tasks - Query tasks with pagination and sorting
  • POST /api/tasks/query - Query tasks with advanced filtering
  • GET /api/tasks/{id}/update - Get task update model
  • POST /api/tasks - Create a new task
  • PUT /api/tasks/{id} - Update a task
  • DELETE /api/tasks/{id} - Delete a task

Advanced Usage

Using Commands Directly

publicclassTaskService{privatereadonlyIMediator_mediator;publicTaskService(IMediatormediator){_mediator=mediator;}publicasyncTask<Result<TaskReadModel>>CreateTaskAsync(TaskCreateModelmodel,ClaimsPrincipaluser){varcommand=newCreateEntity<TaskCreateModel,TaskReadModel>(user,model);returnawait_mediator.InvokeAsync<Result<TaskReadModel>>(command);}publicasyncTask<Result<TaskReadModel>>GetTaskAsync(intid,ClaimsPrincipaluser){varquery=newGetEntity<int,TaskReadModel>(user,id);returnawait_mediator.InvokeAsync<Result<TaskReadModel>>(query);}publicasyncTask<Result<QueryResult<TaskReadModel>>>QueryTasksAsync(QueryDefinitionquery,ClaimsPrincipaluser){varcommand=newQueryEntities<TaskReadModel>(user,query);returnawait_mediator.InvokeAsync<Result<QueryResult<TaskReadModel>>>(command);}}

Advanced Querying

// Query with filtering, sorting, and paginationvarqueryDefinition=newQueryDefinition{Filter=newQueryFilter{Logic=FilterLogic.And,Filters=newList<QueryFilter>{new(){Field="Status",Operator=FilterOperator.Equal,Value="Active"},new(){Field="Priority",Operator=FilterOperator.GreaterThan,Value=3}}},Sorts=newList<QuerySort>{new(){Name="Priority",Descending=true},new(){Name="Created",Descending=false}},Page=1,PageSize=20};varquery=newQueryEntities<TaskReadModel>(user,queryDefinition);varresult=await_mediator.InvokeAsync<Result<QueryResult<TaskReadModel>>>(query);

MongoDB Usage

usingFoundatio.CommandQuery.MongoDB;publicclassTaskCommandHandler:EntityCommandHandler<Task,int,TaskReadModel,TaskCreateModel,TaskUpdateModel>{publicTaskCommandHandler(IMongoDatabasedatabase,IMappermapper):base(database,mapper){}}publicclassTaskQueryHandler:EntityQueryHandler<Task,int,TaskReadModel>{publicTaskQueryHandler(IMongoDatabasedatabase,IMappermapper):base(database,mapper){}}

Custom Command Handlers

publicrecordProcessTaskCommand:PrincipalCommand<CompleteModel>{publicProcessTaskCommand(ClaimsPrincipal?principal,stringaction):base(principal){Action=action;}publicstringAction{get;}}publicclassProcessTaskHandler:IRequestHandler<ProcessTaskCommand,CompleteModel>{publicasyncValueTask<CompleteModel>HandleAsync(ProcessTaskCommandrequest,CancellationTokencancellationToken=default){// Custom processing logicreturnCompleteModel.Success($"Processed: {request.Action}");}}

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

License

This project is licensed under the Apache License 2.0 - see the LICENSE file for details.

About

No description, website, or topics provided.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Sponsor this project

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Repository files navigation

Foundatio.CommandQuery

NuGetBuild Status

A powerful Command Query Responsibility Segregation (CQRS) framework built on the mediator pattern. This library provides core abstractions and implementations for building scalable, maintainable applications using CQRS principles.

Features

  • Clean CQRS Implementation - Separate read and write operations with clear command/query patterns
  • Mediator Pattern - Built on Foundatio.Mediator for decoupled messaging
  • Multiple Data Stores - Support for Entity Framework Core and MongoDB out of the box
  • ASP.NET Core Integration - Minimal API endpoints for exposing commands and queries via HTTP
  • Caching Support - Built-in caching abstractions for query optimization
  • Dynamic Queries - Powerful filtering, sorting, and pagination with LINQ support
  • Multi-Targeting - Supports .NET 8, .NET 9, and .NET 10

Packages

PackageDescriptionNuGet
Foundatio.CommandQueryCore abstractions and base classes for implementing CQRS patterns using the mediator patternNuGet
Foundatio.CommandQuery.DispatcherDispatcher implementation providing centralized command and query handling with caching supportNuGet
Foundatio.CommandQuery.EndpointsASP.NET Core Minimal API endpoints for HTTP-based command and query executionNuGet
Foundatio.CommandQuery.EntityFrameworkEntity Framework Core integration providing database query and persistence handlers with dynamic LINQ supportNuGet
Foundatio.CommandQuery.MongoDBMongoDB integration providing NoSQL database query and persistence handlers with dynamic LINQ supportNuGet

Installation

Using .NET CLI

# Core package
dotnet add package Foundatio.CommandQuery
# Entity Framework integration
dotnet add package Foundatio.CommandQuery.EntityFramework
# MongoDB integration
dotnet add package Foundatio.CommandQuery.MongoDB
# ASP.NET Core endpoints
dotnet add package Foundatio.CommandQuery.Endpoints
# Dispatcher for Blazor 
dotnet add package Foundatio.CommandQuery.Dispatcher

Using Package Manager Console

Install-Package Foundatio.CommandQuery
Install-Package Foundatio.CommandQuery.EntityFramework
Install-Package Foundatio.CommandQuery.MongoDB
Install-Package Foundatio.CommandQuery.Endpoints
Install-Package Foundatio.CommandQuery.Dispatcher

Quick Start

1. Define Your Models

// Entity modelpublicclassTask:IHaveIdentifier<int>{publicintId{get;set;}publicstringTitle{get;set;}publicstringDescription{get;set;}publicDateTimeCreated{get;set;}publicstringCreatedBy{get;set;}}// Read modelpublicclassTaskReadModel:EntityReadModel<int>{publicstringTitle{get;set;}publicstringDescription{get;set;}}// Create modelpublicclassTaskCreateModel:EntityCreateModel<int>{publicstringTitle{get;set;}publicstringDescription{get;set;}}// Update modelpublicclassTaskUpdateModel:EntityUpdateModel{publicstringTitle{get;set;}publicstringDescription{get;set;}}

2. Create Command and Query Handlers

usingFoundatio.CommandQuery.EntityFramework;publicclassTaskCommandHandler:EntityCommandHandler<AppDbContext,Task,int,TaskReadModel,TaskCreateModel,TaskUpdateModel>{publicTaskCommandHandler(AppDbContextcontext,IMappermapper):base(context,mapper){}}publicclassTaskQueryHandler:EntityQueryHandler<AppDbContext,Task,int,TaskReadModel>{publicTaskQueryHandler(AppDbContextcontext,IMappermapper):base(context,mapper){}}

3. Register Services

varbuilder=WebApplication.CreateBuilder(args);// Add mediator with assemblies containing handlersbuilder.Services.AddMediator(options =>options.AddAssembly(typeof(Program).Assembly));// Add your DbContextbuilder.Services.AddDbContext<AppDbContext>(options =>options.UseSqlServer(builder.Configuration.GetConnectionString("Default")));// Add endpoint routesbuilder.Services.AddEndpointRoutes();

4. Configure Minimal API Endpoints

publicclassTaskEndpoint:EntityCommandEndpointBase<int,TaskListModel,TaskReadModel,TaskCreateModel,TaskUpdateModel>{publicTaskEndpoint(ILoggerFactoryloggerFactory):base(loggerFactory,"tasks","api/tasks"){}}varapp=builder.Build();// Map endpoint routesapp.MapEndpointRoutes();app.Run();

This automatically creates the following endpoints:

  • GET /api/tasks/{id} - Get a task by ID
  • GET /api/tasks - Query tasks with pagination and sorting
  • POST /api/tasks/query - Query tasks with advanced filtering
  • GET /api/tasks/{id}/update - Get task update model
  • POST /api/tasks - Create a new task
  • PUT /api/tasks/{id} - Update a task
  • DELETE /api/tasks/{id} - Delete a task

Advanced Usage

Using Commands Directly

publicclassTaskService{privatereadonlyIMediator_mediator;publicTaskService(IMediatormediator){_mediator=mediator;}publicasyncTask<Result<TaskReadModel>>CreateTaskAsync(TaskCreateModelmodel,ClaimsPrincipaluser){varcommand=newCreateEntity<TaskCreateModel,TaskReadModel>(user,model);returnawait_mediator.InvokeAsync<Result<TaskReadModel>>(command);}publicasyncTask<Result<TaskReadModel>>GetTaskAsync(intid,ClaimsPrincipaluser){varquery=newGetEntity<int,TaskReadModel>(user,id);returnawait_mediator.InvokeAsync<Result<TaskReadModel>>(query);}publicasyncTask<Result<QueryResult<TaskReadModel>>>QueryTasksAsync(QueryDefinitionquery,ClaimsPrincipaluser){varcommand=newQueryEntities<TaskReadModel>(user,query);returnawait_mediator.InvokeAsync<Result<QueryResult<TaskReadModel>>>(command);}}

Advanced Querying

// Query with filtering, sorting, and paginationvarqueryDefinition=newQueryDefinition{Filter=newQueryFilter{Logic=FilterLogic.And,Filters=newList<QueryFilter>{new(){Field="Status",Operator=FilterOperator.Equal,Value="Active"},new(){Field="Priority",Operator=FilterOperator.GreaterThan,Value=3}}},Sorts=newList<QuerySort>{new(){Name="Priority",Descending=true},new(){Name="Created",Descending=false}},Page=1,PageSize=20};varquery=newQueryEntities<TaskReadModel>(user,queryDefinition);varresult=await_mediator.InvokeAsync<Result<QueryResult<TaskReadModel>>>(query);

MongoDB Usage

usingFoundatio.CommandQuery.MongoDB;publicclassTaskCommandHandler:EntityCommandHandler<Task,int,TaskReadModel,TaskCreateModel,TaskUpdateModel>{publicTaskCommandHandler(IMongoDatabasedatabase,IMappermapper):base(database,mapper){}}publicclassTaskQueryHandler:EntityQueryHandler<Task,int,TaskReadModel>{publicTaskQueryHandler(IMongoDatabasedatabase,IMappermapper):base(database,mapper){}}

Custom Command Handlers

publicrecordProcessTaskCommand:PrincipalCommand<CompleteModel>{publicProcessTaskCommand(ClaimsPrincipal?principal,stringaction):base(principal){Action=action;}publicstringAction{get;}}publicclassProcessTaskHandler:IRequestHandler<ProcessTaskCommand,CompleteModel>{publicasyncValueTask<CompleteModel>HandleAsync(ProcessTaskCommandrequest,CancellationTokencancellationToken=default){// Custom processing logicreturnCompleteModel.Success($"Processed: {request.Action}");}}

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

License

This project is licensed under the Apache License 2.0 - see the LICENSE file for details.

About

No description, website, or topics provided.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Sponsor this project

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

Foundatio.CommandQuery

NuGetBuild Status

A powerful Command Query Responsibility Segregation (CQRS) framework built on the mediator pattern. This library provides core abstractions and implementations for building scalable, maintainable applications using CQRS principles.

Features

  • Clean CQRS Implementation - Separate read and write operations with clear command/query patterns
  • Mediator Pattern - Built on Foundatio.Mediator for decoupled messaging
  • Multiple Data Stores - Support for Entity Framework Core and MongoDB out of the box
  • ASP.NET Core Integration - Minimal API endpoints for exposing commands and queries via HTTP
  • Caching Support - Built-in caching abstractions for query optimization
  • Dynamic Queries - Powerful filtering, sorting, and pagination with LINQ support
  • Multi-Targeting - Supports .NET 8, .NET 9, and .NET 10

Packages

PackageDescriptionNuGet
Foundatio.CommandQueryCore abstractions and base classes for implementing CQRS patterns using the mediator patternNuGet
Foundatio.CommandQuery.DispatcherDispatcher implementation providing centralized command and query handling with caching supportNuGet
Foundatio.CommandQuery.EndpointsASP.NET Core Minimal API endpoints for HTTP-based command and query executionNuGet
Foundatio.CommandQuery.EntityFrameworkEntity Framework Core integration providing database query and persistence handlers with dynamic LINQ supportNuGet
Foundatio.CommandQuery.MongoDBMongoDB integration providing NoSQL database query and persistence handlers with dynamic LINQ supportNuGet

Installation

Using .NET CLI

# Core package
dotnet add package Foundatio.CommandQuery
# Entity Framework integration
dotnet add package Foundatio.CommandQuery.EntityFramework
# MongoDB integration
dotnet add package Foundatio.CommandQuery.MongoDB
# ASP.NET Core endpoints
dotnet add package Foundatio.CommandQuery.Endpoints
# Dispatcher for Blazor 
dotnet add package Foundatio.CommandQuery.Dispatcher

Using Package Manager Console

Install-Package Foundatio.CommandQuery
Install-Package Foundatio.CommandQuery.EntityFramework
Install-Package Foundatio.CommandQuery.MongoDB
Install-Package Foundatio.CommandQuery.Endpoints
Install-Package Foundatio.CommandQuery.Dispatcher

Quick Start

1. Define Your Models

// Entity modelpublicclassTask:IHaveIdentifier<int>{publicintId{get;set;}publicstringTitle{get;set;}publicstringDescription{get;set;}publicDateTimeCreated{get;set;}publicstringCreatedBy{get;set;}}// Read modelpublicclassTaskReadModel:EntityReadModel<int>{publicstringTitle{get;set;}publicstringDescription{get;set;}}// Create modelpublicclassTaskCreateModel:EntityCreateModel<int>{publicstringTitle{get;set;}publicstringDescription{get;set;}}// Update modelpublicclassTaskUpdateModel:EntityUpdateModel{publicstringTitle{get;set;}publicstringDescription{get;set;}}

2. Create Command and Query Handlers

usingFoundatio.CommandQuery.EntityFramework;publicclassTaskCommandHandler:EntityCommandHandler<AppDbContext,Task,int,TaskReadModel,TaskCreateModel,TaskUpdateModel>{publicTaskCommandHandler(AppDbContextcontext,IMappermapper):base(context,mapper){}}publicclassTaskQueryHandler:EntityQueryHandler<AppDbContext,Task,int,TaskReadModel>{publicTaskQueryHandler(AppDbContextcontext,IMappermapper):base(context,mapper){}}

3. Register Services

varbuilder=WebApplication.CreateBuilder(args);// Add mediator with assemblies containing handlersbuilder.Services.AddMediator(options =>options.AddAssembly(typeof(Program).Assembly));// Add your DbContextbuilder.Services.AddDbContext<AppDbContext>(options =>options.UseSqlServer(builder.Configuration.GetConnectionString("Default")));// Add endpoint routesbuilder.Services.AddEndpointRoutes();

4. Configure Minimal API Endpoints

publicclassTaskEndpoint:EntityCommandEndpointBase<int,TaskListModel,TaskReadModel,TaskCreateModel,TaskUpdateModel>{publicTaskEndpoint(ILoggerFactoryloggerFactory):base(loggerFactory,"tasks","api/tasks"){}}varapp=builder.Build();// Map endpoint routesapp.MapEndpointRoutes();app.Run();

This automatically creates the following endpoints:

  • GET /api/tasks/{id} - Get a task by ID
  • GET /api/tasks - Query tasks with pagination and sorting
  • POST /api/tasks/query - Query tasks with advanced filtering
  • GET /api/tasks/{id}/update - Get task update model
  • POST /api/tasks - Create a new task
  • PUT /api/tasks/{id} - Update a task
  • DELETE /api/tasks/{id} - Delete a task

Advanced Usage

Using Commands Directly

publicclassTaskService{privatereadonlyIMediator_mediator;publicTaskService(IMediatormediator){_mediator=mediator;}publicasyncTask<Result<TaskReadModel>>CreateTaskAsync(TaskCreateModelmodel,ClaimsPrincipaluser){varcommand=newCreateEntity<TaskCreateModel,TaskReadModel>(user,model);returnawait_mediator.InvokeAsync<Result<TaskReadModel>>(command);}publicasyncTask<Result<TaskReadModel>>GetTaskAsync(intid,ClaimsPrincipaluser){varquery=newGetEntity<int,TaskReadModel>(user,id);returnawait_mediator.InvokeAsync<Result<TaskReadModel>>(query);}publicasyncTask<Result<QueryResult<TaskReadModel>>>QueryTasksAsync(QueryDefinitionquery,ClaimsPrincipaluser){varcommand=newQueryEntities<TaskReadModel>(user,query);returnawait_mediator.InvokeAsync<Result<QueryResult<TaskReadModel>>>(command);}}

Advanced Querying

// Query with filtering, sorting, and paginationvarqueryDefinition=newQueryDefinition{Filter=newQueryFilter{Logic=FilterLogic.And,Filters=newList<QueryFilter>{new(){Field="Status",Operator=FilterOperator.Equal,Value="Active"},new(){Field="Priority",Operator=FilterOperator.GreaterThan,Value=3}}},Sorts=newList<QuerySort>{new(){Name="Priority",Descending=true},new(){Name="Created",Descending=false}},Page=1,PageSize=20};varquery=newQueryEntities<TaskReadModel>(user,queryDefinition);varresult=await_mediator.InvokeAsync<Result<QueryResult<TaskReadModel>>>(query);

MongoDB Usage

usingFoundatio.CommandQuery.MongoDB;publicclassTaskCommandHandler:EntityCommandHandler<Task,int,TaskReadModel,TaskCreateModel,TaskUpdateModel>{publicTaskCommandHandler(IMongoDatabasedatabase,IMappermapper):base(database,mapper){}}publicclassTaskQueryHandler:EntityQueryHandler<Task,int,TaskReadModel>{publicTaskQueryHandler(IMongoDatabasedatabase,IMappermapper):base(database,mapper){}}

Custom Command Handlers

publicrecordProcessTaskCommand:PrincipalCommand<CompleteModel>{publicProcessTaskCommand(ClaimsPrincipal?principal,stringaction):base(principal){Action=action;}publicstringAction{get;}}publicclassProcessTaskHandler:IRequestHandler<ProcessTaskCommand,CompleteModel>{publicasyncValueTask<CompleteModel>HandleAsync(ProcessTaskCommandrequest,CancellationTokencancellationToken=default){// Custom processing logicreturnCompleteModel.Success($"Processed: {request.Action}");}}

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

License

This project is licensed under the Apache License 2.0 - see the LICENSE file for details.

About

No description, website, or topics provided.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Sponsor this project

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

Foundatio.CommandQuery

NuGetBuild Status

A powerful Command Query Responsibility Segregation (CQRS) framework built on the mediator pattern. This library provides core abstractions and implementations for building scalable, maintainable applications using CQRS principles.

Features

  • Clean CQRS Implementation - Separate read and write operations with clear command/query patterns
  • Mediator Pattern - Built on Foundatio.Mediator for decoupled messaging
  • Multiple Data Stores - Support for Entity Framework Core and MongoDB out of the box
  • ASP.NET Core Integration - Minimal API endpoints for exposing commands and queries via HTTP
  • Caching Support - Built-in caching abstractions for query optimization
  • Dynamic Queries - Powerful filtering, sorting, and pagination with LINQ support
  • Multi-Targeting - Supports .NET 8, .NET 9, and .NET 10

Packages

PackageDescriptionNuGet
Foundatio.CommandQueryCore abstractions and base classes for implementing CQRS patterns using the mediator patternNuGet
Foundatio.CommandQuery.DispatcherDispatcher implementation providing centralized command and query handling with caching supportNuGet
Foundatio.CommandQuery.EndpointsASP.NET Core Minimal API endpoints for HTTP-based command and query executionNuGet
Foundatio.CommandQuery.EntityFrameworkEntity Framework Core integration providing database query and persistence handlers with dynamic LINQ supportNuGet
Foundatio.CommandQuery.MongoDBMongoDB integration providing NoSQL database query and persistence handlers with dynamic LINQ supportNuGet

Installation

Using .NET CLI

# Core package
dotnet add package Foundatio.CommandQuery
# Entity Framework integration
dotnet add package Foundatio.CommandQuery.EntityFramework
# MongoDB integration
dotnet add package Foundatio.CommandQuery.MongoDB
# ASP.NET Core endpoints
dotnet add package Foundatio.CommandQuery.Endpoints
# Dispatcher for Blazor 
dotnet add package Foundatio.CommandQuery.Dispatcher

Using Package Manager Console

Install-Package Foundatio.CommandQuery
Install-Package Foundatio.CommandQuery.EntityFramework
Install-Package Foundatio.CommandQuery.MongoDB
Install-Package Foundatio.CommandQuery.Endpoints
Install-Package Foundatio.CommandQuery.Dispatcher

Quick Start

1. Define Your Models

// Entity modelpublicclassTask:IHaveIdentifier<int>{publicintId{get;set;}publicstringTitle{get;set;}publicstringDescription{get;set;}publicDateTimeCreated{get;set;}publicstringCreatedBy{get;set;}}// Read modelpublicclassTaskReadModel:EntityReadModel<int>{publicstringTitle{get;set;}publicstringDescription{get;set;}}// Create modelpublicclassTaskCreateModel:EntityCreateModel<int>{publicstringTitle{get;set;}publicstringDescription{get;set;}}// Update modelpublicclassTaskUpdateModel:EntityUpdateModel{publicstringTitle{get;set;}publicstringDescription{get;set;}}

2. Create Command and Query Handlers

usingFoundatio.CommandQuery.EntityFramework;publicclassTaskCommandHandler:EntityCommandHandler<AppDbContext,Task,int,TaskReadModel,TaskCreateModel,TaskUpdateModel>{publicTaskCommandHandler(AppDbContextcontext,IMappermapper):base(context,mapper){}}publicclassTaskQueryHandler:EntityQueryHandler<AppDbContext,Task,int,TaskReadModel>{publicTaskQueryHandler(AppDbContextcontext,IMappermapper):base(context,mapper){}}

3. Register Services

varbuilder=WebApplication.CreateBuilder(args);// Add mediator with assemblies containing handlersbuilder.Services.AddMediator(options =>options.AddAssembly(typeof(Program).Assembly));// Add your DbContextbuilder.Services.AddDbContext<AppDbContext>(options =>options.UseSqlServer(builder.Configuration.GetConnectionString("Default")));// Add endpoint routesbuilder.Services.AddEndpointRoutes();

4. Configure Minimal API Endpoints

publicclassTaskEndpoint:EntityCommandEndpointBase<int,TaskListModel,TaskReadModel,TaskCreateModel,TaskUpdateModel>{publicTaskEndpoint(ILoggerFactoryloggerFactory):base(loggerFactory,"tasks","api/tasks"){}}varapp=builder.Build();// Map endpoint routesapp.MapEndpointRoutes();app.Run();

This automatically creates the following endpoints:

  • GET /api/tasks/{id} - Get a task by ID
  • GET /api/tasks - Query tasks with pagination and sorting
  • POST /api/tasks/query - Query tasks with advanced filtering
  • GET /api/tasks/{id}/update - Get task update model
  • POST /api/tasks - Create a new task
  • PUT /api/tasks/{id} - Update a task
  • DELETE /api/tasks/{id} - Delete a task

Advanced Usage

Using Commands Directly

publicclassTaskService{privatereadonlyIMediator_mediator;publicTaskService(IMediatormediator){_mediator=mediator;}publicasyncTask<Result<TaskReadModel>>CreateTaskAsync(TaskCreateModelmodel,ClaimsPrincipaluser){varcommand=newCreateEntity<TaskCreateModel,TaskReadModel>(user,model);returnawait_mediator.InvokeAsync<Result<TaskReadModel>>(command);}publicasyncTask<Result<TaskReadModel>>GetTaskAsync(intid,ClaimsPrincipaluser){varquery=newGetEntity<int,TaskReadModel>(user,id);returnawait_mediator.InvokeAsync<Result<TaskReadModel>>(query);}publicasyncTask<Result<QueryResult<TaskReadModel>>>QueryTasksAsync(QueryDefinitionquery,ClaimsPrincipaluser){varcommand=newQueryEntities<TaskReadModel>(user,query);returnawait_mediator.InvokeAsync<Result<QueryResult<TaskReadModel>>>(command);}}

Advanced Querying

// Query with filtering, sorting, and paginationvarqueryDefinition=newQueryDefinition{Filter=newQueryFilter{Logic=FilterLogic.And,Filters=newList<QueryFilter>{new(){Field="Status",Operator=FilterOperator.Equal,Value="Active"},new(){Field="Priority",Operator=FilterOperator.GreaterThan,Value=3}}},Sorts=newList<QuerySort>{new(){Name="Priority",Descending=true},new(){Name="Created",Descending=false}},Page=1,PageSize=20};varquery=newQueryEntities<TaskReadModel>(user,queryDefinition);varresult=await_mediator.InvokeAsync<Result<QueryResult<TaskReadModel>>>(query);

MongoDB Usage

usingFoundatio.CommandQuery.MongoDB;publicclassTaskCommandHandler:EntityCommandHandler<Task,int,TaskReadModel,TaskCreateModel,TaskUpdateModel>{publicTaskCommandHandler(IMongoDatabasedatabase,IMappermapper):base(database,mapper){}}publicclassTaskQueryHandler:EntityQueryHandler<Task,int,TaskReadModel>{publicTaskQueryHandler(IMongoDatabasedatabase,IMappermapper):base(database,mapper){}}

Custom Command Handlers

publicrecordProcessTaskCommand:PrincipalCommand<CompleteModel>{publicProcessTaskCommand(ClaimsPrincipal?principal,stringaction):base(principal){Action=action;}publicstringAction{get;}}publicclassProcessTaskHandler:IRequestHandler<ProcessTaskCommand,CompleteModel>{publicasyncValueTask<CompleteModel>HandleAsync(ProcessTaskCommandrequest,CancellationTokencancellationToken=default){// Custom processing logicreturnCompleteModel.Success($"Processed: {request.Action}");}}

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

License

This project is licensed under the Apache License 2.0 - see the LICENSE file for details.

About

No description, website, or topics provided.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Sponsor this project

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Repository files navigation

Foundatio.CommandQuery

NuGetBuild Status

A powerful Command Query Responsibility Segregation (CQRS) framework built on the mediator pattern. This library provides core abstractions and implementations for building scalable, maintainable applications using CQRS principles.

Features

  • Clean CQRS Implementation - Separate read and write operations with clear command/query patterns
  • Mediator Pattern - Built on Foundatio.Mediator for decoupled messaging
  • Multiple Data Stores - Support for Entity Framework Core and MongoDB out of the box
  • ASP.NET Core Integration - Minimal API endpoints for exposing commands and queries via HTTP
  • Caching Support - Built-in caching abstractions for query optimization
  • Dynamic Queries - Powerful filtering, sorting, and pagination with LINQ support
  • Multi-Targeting - Supports .NET 8, .NET 9, and .NET 10

Packages

PackageDescriptionNuGet
Foundatio.CommandQueryCore abstractions and base classes for implementing CQRS patterns using the mediator patternNuGet
Foundatio.CommandQuery.DispatcherDispatcher implementation providing centralized command and query handling with caching supportNuGet
Foundatio.CommandQuery.EndpointsASP.NET Core Minimal API endpoints for HTTP-based command and query executionNuGet
Foundatio.CommandQuery.EntityFrameworkEntity Framework Core integration providing database query and persistence handlers with dynamic LINQ supportNuGet
Foundatio.CommandQuery.MongoDBMongoDB integration providing NoSQL database query and persistence handlers with dynamic LINQ supportNuGet

Installation

Using .NET CLI

# Core package
dotnet add package Foundatio.CommandQuery
# Entity Framework integration
dotnet add package Foundatio.CommandQuery.EntityFramework
# MongoDB integration
dotnet add package Foundatio.CommandQuery.MongoDB
# ASP.NET Core endpoints
dotnet add package Foundatio.CommandQuery.Endpoints
# Dispatcher for Blazor 
dotnet add package Foundatio.CommandQuery.Dispatcher

Using Package Manager Console

Install-Package Foundatio.CommandQuery
Install-Package Foundatio.CommandQuery.EntityFramework
Install-Package Foundatio.CommandQuery.MongoDB
Install-Package Foundatio.CommandQuery.Endpoints
Install-Package Foundatio.CommandQuery.Dispatcher

Quick Start

1. Define Your Models

// Entity modelpublicclassTask:IHaveIdentifier<int>{publicintId{get;set;}publicstringTitle{get;set;}publicstringDescription{get;set;}publicDateTimeCreated{get;set;}publicstringCreatedBy{get;set;}}// Read modelpublicclassTaskReadModel:EntityReadModel<int>{publicstringTitle{get;set;}publicstringDescription{get;set;}}// Create modelpublicclassTaskCreateModel:EntityCreateModel<int>{publicstringTitle{get;set;}publicstringDescription{get;set;}}// Update modelpublicclassTaskUpdateModel:EntityUpdateModel{publicstringTitle{get;set;}publicstringDescription{get;set;}}

2. Create Command and Query Handlers

usingFoundatio.CommandQuery.EntityFramework;publicclassTaskCommandHandler:EntityCommandHandler<AppDbContext,Task,int,TaskReadModel,TaskCreateModel,TaskUpdateModel>{publicTaskCommandHandler(AppDbContextcontext,IMappermapper):base(context,mapper){}}publicclassTaskQueryHandler:EntityQueryHandler<AppDbContext,Task,int,TaskReadModel>{publicTaskQueryHandler(AppDbContextcontext,IMappermapper):base(context,mapper){}}

3. Register Services

varbuilder=WebApplication.CreateBuilder(args);// Add mediator with assemblies containing handlersbuilder.Services.AddMediator(options =>options.AddAssembly(typeof(Program).Assembly));// Add your DbContextbuilder.Services.AddDbContext<AppDbContext>(options =>options.UseSqlServer(builder.Configuration.GetConnectionString("Default")));// Add endpoint routesbuilder.Services.AddEndpointRoutes();

4. Configure Minimal API Endpoints

publicclassTaskEndpoint:EntityCommandEndpointBase<int,TaskListModel,TaskReadModel,TaskCreateModel,TaskUpdateModel>{publicTaskEndpoint(ILoggerFactoryloggerFactory):base(loggerFactory,"tasks","api/tasks"){}}varapp=builder.Build();// Map endpoint routesapp.MapEndpointRoutes();app.Run();

This automatically creates the following endpoints:

  • GET /api/tasks/{id} - Get a task by ID
  • GET /api/tasks - Query tasks with pagination and sorting
  • POST /api/tasks/query - Query tasks with advanced filtering
  • GET /api/tasks/{id}/update - Get task update model
  • POST /api/tasks - Create a new task
  • PUT /api/tasks/{id} - Update a task
  • DELETE /api/tasks/{id} - Delete a task

Advanced Usage

Using Commands Directly

publicclassTaskService{privatereadonlyIMediator_mediator;publicTaskService(IMediatormediator){_mediator=mediator;}publicasyncTask<Result<TaskReadModel>>CreateTaskAsync(TaskCreateModelmodel,ClaimsPrincipaluser){varcommand=newCreateEntity<TaskCreateModel,TaskReadModel>(user,model);returnawait_mediator.InvokeAsync<Result<TaskReadModel>>(command);}publicasyncTask<Result<TaskReadModel>>GetTaskAsync(intid,ClaimsPrincipaluser){varquery=newGetEntity<int,TaskReadModel>(user,id);returnawait_mediator.InvokeAsync<Result<TaskReadModel>>(query);}publicasyncTask<Result<QueryResult<TaskReadModel>>>QueryTasksAsync(QueryDefinitionquery,ClaimsPrincipaluser){varcommand=newQueryEntities<TaskReadModel>(user,query);returnawait_mediator.InvokeAsync<Result<QueryResult<TaskReadModel>>>(command);}}

Advanced Querying

// Query with filtering, sorting, and paginationvarqueryDefinition=newQueryDefinition{Filter=newQueryFilter{Logic=FilterLogic.And,Filters=newList<QueryFilter>{new(){Field="Status",Operator=FilterOperator.Equal,Value="Active"},new(){Field="Priority",Operator=FilterOperator.GreaterThan,Value=3}}},Sorts=newList<QuerySort>{new(){Name="Priority",Descending=true},new(){Name="Created",Descending=false}},Page=1,PageSize=20};varquery=newQueryEntities<TaskReadModel>(user,queryDefinition);varresult=await_mediator.InvokeAsync<Result<QueryResult<TaskReadModel>>>(query);

MongoDB Usage

usingFoundatio.CommandQuery.MongoDB;publicclassTaskCommandHandler:EntityCommandHandler<Task,int,TaskReadModel,TaskCreateModel,TaskUpdateModel>{publicTaskCommandHandler(IMongoDatabasedatabase,IMappermapper):base(database,mapper){}}publicclassTaskQueryHandler:EntityQueryHandler<Task,int,TaskReadModel>{publicTaskQueryHandler(IMongoDatabasedatabase,IMappermapper):base(database,mapper){}}

Custom Command Handlers

publicrecordProcessTaskCommand:PrincipalCommand<CompleteModel>{publicProcessTaskCommand(ClaimsPrincipal?principal,stringaction):base(principal){Action=action;}publicstringAction{get;}}publicclassProcessTaskHandler:IRequestHandler<ProcessTaskCommand,CompleteModel>{publicasyncValueTask<CompleteModel>HandleAsync(ProcessTaskCommandrequest,CancellationTokencancellationToken=default){// Custom processing logicreturnCompleteModel.Success($"Processed: {request.Action}");}}

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

License

This project is licensed under the Apache License 2.0 - see the LICENSE file for details.

About

No description, website, or topics provided.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Sponsor this project

Packages

Contributors

Languages