{"id":24750889,"url":"https://github.com/minhsangdotcom/clean-architecture","last_synced_at":"2026-02-14T10:10:03.950Z","repository":{"id":273340630,"uuid":"919371479","full_name":"minhsangdotcom/Clean-Architecture_The-Template","owner":"minhsangdotcom","description":"The ultimate .NET Core Clean Architecture Solution Template is here! 🚀 Designed for speed and scalability, it helps you deliver high-quality applications effortlessly.","archived":false,"fork":false,"pushed_at":"2025-01-28T06:27:00.000Z","size":1611,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-01-28T06:27:55.228Z","etag":null,"topics":["angular","clean-architecture","clean-code","csharp","dotnet","dotnet-core","dotnet-framework","reactjs"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/minhsangdotcom.png","metadata":{"files":{"readme":"README-VIETNAMESE.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2025-01-20T09:16:11.000Z","updated_at":"2025-01-28T06:27:03.000Z","dependencies_parsed_at":"2025-01-28T06:25:10.612Z","dependency_job_id":null,"html_url":"https://github.com/minhsangdotcom/Clean-Architecture_The-Template","commit_stats":null,"previous_names":["minhsangdotcom/clean-architecture_the-template"],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/minhsangdotcom%2FClean-Architecture_The-Template","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/minhsangdotcom%2FClean-Architecture_The-Template/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/minhsangdotcom%2FClean-Architecture_The-Template/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/minhsangdotcom%2FClean-Architecture_The-Template/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/minhsangdotcom","download_url":"https://codeload.github.com/minhsangdotcom/Clean-Architecture_The-Template/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":235996580,"owners_count":19078468,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["angular","clean-architecture","clean-code","csharp","dotnet","dotnet-core","dotnet-framework","reactjs"],"created_at":"2025-01-28T09:44:17.719Z","updated_at":"2025-10-10T21:31:53.297Z","avatar_url":"https://github.com/minhsangdotcom.png","language":"C#","readme":"# Clean Architecture The Template\n\n[English](README.md) | [Vietnamese](README-VIETNAMESE.md)\n\n#\n\n\n![Visual Studio Code](https://img.shields.io/badge/Visual%20Studio%20Code-0078d7.svg?logo=visual-studio-code\u0026logoColor=white)\n[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)\n![GitHub Release](https://img.shields.io/github/v/release/minhsangdotcom/clean-architecture?color=orange)\n![GitHub Org's stars](https://img.shields.io/github/stars/minhsangdotcom%2Fclean-architecture?color=pink)\n![GitHub forks](https://img.shields.io/github/forks/minhsangdotcom/clean-architecture?color=%23f61d9c)\n[![NuGet Version](https://img.shields.io/nuget/v/minhsangdotcom.TheTemplate.SharedKernel?label=SharedKernel\u0026color=red)](https://www.nuget.org/packages/minhsangdotcom.TheTemplate.SharedKernel)\n[![NuGet Version](https://img.shields.io/nuget/v/TranMinhSang.DynamicQueryExtension.EntityFrameworkCore?label=DynamicQueryExtension\u0026color=red)](https://www.nuget.org/packages/TranMinhSang.DynamicQueryExtension.EntityFrameworkCore)\n[![NuGet Version](https://img.shields.io/nuget/vpre/minhsangdotcom.TheTemplate.SpecificationPattern?style=flat\u0026label=SpecificationPattern\u0026color=red)](https://www.nuget.org/packages/minhsangdotcom.TheTemplate.SpecificationPattern/)\n[![NuGet Version](https://img.shields.io/nuget/vpre/minhsangdotcom.TheTemplate.ElasticsearchFluentConfig?style=flat\u0026label=ElasticsearchFluentConfig\u0026color=red)](https://www.nuget.org/packages/minhsangdotcom.TheTemplate.ElasticsearchFluentConfig/1.0.1-alpha)\n\n# Bảng nội dung \u003cdiv id= \"bang-noi-dung\"/\u003e\n\n- [Ngôn ngữ](#)\n- [Nhãn](#)\n- [Bảng nội dung](#bang-noi-dung)\n- [Giới thiệu](#gioi-thieu)\n- [Cho mình 1 ⭐ nhé](#cho-minh-sao-nhe)\n- [Định Nghĩa](#dinh-nghia)\n  - [Lợi ích](#lợi-ích)\n  - [Nhược điểm](#nhược-điểm)\n- [Tính năng :rocket:](#tinh-nang)\n- [Nhá hàng cho các tính năng :fire:](#nha-hang-cho-cac-tinh-nang)\n  - [Api](#api)\n  - [Truy vết](#truy-vet)\n  - [Lưu trử file media bằng Minio](#minio-storage)\n  - [Tự động dịch message](#message-translation)\n- [Sơ lượt về Cấu trúc :mag_right:](#so-luot-ve-cau-truc)\n- [Bắt đầu thôi nào](#bắt-đầu-thôi-nào)\n  - [Cách để chạy ứng dụng](#cách-để-chạy-ứng-dụng)\n  - [Hướng dẫn sử dụng](#hướng-dẫn-sử-dụng)\n    - [Authorize](#authorize)\n    - [Thêm một quyền mới vào ứng dụng](#thêm-một-quyền-mới-vào-ứng-dụng)\n    - [Bộ lọc](#bộ-lọc)\n    - [Phân trang](#phân-trang)\n- [Công nghệ](#công-nghệ)\n- [Hỗ trợ](#hỗ-trợ)\n- [Lời cảm ơn](#lời-cảm-ơn)\n- [Cấp phép](#cấp-phép)\n\u003cdiv id=\"gioi-thieu\" /\u003e\n\n# Giới thiệu \n\nTemplate này được thiết kế dành cho các bạn backend làm việc với ASP.NET Core. Nó cung cấp một cách hiệu quả để xây dựng các ứng dụng enterprise một cách đơn giản bằng cách tận dụng lợi thế từ kiến trúc Clean Architecture và .NET Core framework.\n\nVới template này, tất cả đã được thiết lập sẵn :smiley:.\n\u003cdiv id='cho-minh-sao-nhe'/\u003e\n\n# Cho mình 1 ⭐ nhé \n\nNếu bạn thấy template này hữu ích và học được điều gì đó từ nó, hãy cân nhắc cho mình một :star:.\n\nSự hỗ trợ của bạn là động lực giúp mình mang đến những tính năng mới và cải tiến tốt hơn trong các phiên bản sắp tới.\n\u003cdiv id =\"dinh-nghia\"/\u003e\n\n# Định Nghĩa\n\nKiến trúc Sạch (Clean Architecture) là một phương pháp thiết kế phần mềm do Robert C. Martin (Uncle Bob) giới thiệu, nhấn mạnh vào thuật ngữ \"Tách biệt các thành phần\",các tầng ngoài cùng sẽ phụ thuộc vào các tầng bên trong như hình minh họa. Tầng core sẽ không phụ thuộc vào các framework bên ngoài, cơ sở dữ liệu hay giao diện người dùng, từ đó giúp hệ thống dễ bảo trì, kiểm thử và phát triển theo thời gian.\n\n![Alt text](Screenshots/clean-architecture.png \"Cấu trúc chung của Clean Architecture\")\n\n### Lợi ích\n\n- **Các thành phần tách biệt**: Mỗi một tầng chịu trách nhiệm cho một khía cạnh của ứng dụng, giúp mã dễ hiểu và bảo trì.\n- **Dễ dàng kiểm thử**: Các business logic được tách biệt khỏi framework và UI, việc kiểm thử đơn vị trở nên đơn giản và đáng tin cậy hơn.\n- **Linh hoạt và Thích nghi**: Khi thay đổi framework, cơ sở dữ liệu hoặc các hệ thống bên ngoài ít ảnh hưởng đến logic của phần core.\n- **Tái sử dụng**: Các Business rules có thể được tái sử dụng trong các ứng dụng hoặc hệ thống khác mà không phải thay đổi quá nhiều code.\n- **Khả năng mở rộng**: Cấu trúc rõ ràng hỗ trợ việc phát triển và thêm tính năng mới mà không cần tái cơ cấu lại.\n- **Không phụ thuộc vào framework**: Không bị phụ thuộc nhiều vào framework, rất dễ dàng để thanh đổi công nghệ mới.\n\n### Nhược điểm\n\n- **_Phức tạp_**: Cấu trúc các tầng có thể tăng tính phức tạp, đặc biệt đối với các dự án nhỏ nơi các kiến trúc đơn giản hơn có thể phù hợp hơn\n- **_Chi phí khởi đầu cao_**: Thiết lập Kiến Trúc Sạch yêu cầu thêm nỗ lực để tổ chức các tầng và tuân theo các nguyên tắc thiết kế nghiêm ngặt.\n- **_Khó khăn khi học tập_**: Các developer không quen thuộc với nguyên tắc này có thể mất thời gian để hiểu rõ cấu trúc và lợi ích của nó.\n- **_Nguy cơ về cấu trúc quá phức tạp_**: Đối với các ứng dụng nhỏ, các tầng bổ sung có thể không cần thiết và dẫn đến sự phức tạp hóa.\n- **_Hiệu năng bị suy giảm_**: Sự trích dẫn và trừa tượng(interface) giữa các tầng có thể giảm hiệu năng, tuy nhiên thường là không đáng kể.\n\u003cdiv id='tinh-nang'/\u003e\n\n# Tính năng :rocket:\n\nCó gì đặc biệt khiến cho template này trở nên khác biệt so với những template khác có trên Github?\n\n### Tính năng cần thiết cho mọi dự án:\n\n- Đăng nhập :closed_lock_with_key:\n- Refresh token :arrows_counterclockwise:\n- Đổi mật khẩu :repeat:\n- Quên mật khẩu :unlock:\n- Xem và cập nhật profile người dùng :man_with_gua_pi_mao:\n- User CRUD :family:\n- Role CRUD 🛡️\n\n### Một số tính năng hữu ích khác:\n\n1. [DDD (Domain Driven Design)](/src/Domain/Aggregates/) :brain:\n1. [CQRS \u0026 Mediator](/src/Application/Features/) :twisted_rightwards_arrows:\n1. [Cross-cutting concern](/src/Application/Common/Behaviors/) :scissors:\n1. [Mail Sender](/src/Infrastructure/Services/Mail/) :mailbox:\n1. [Cached Repository](/src/Infrastructure/UnitOfWorks/CachedRepositories/) :computer:\n1. [Queue](/src/Infrastructure/Services/Queue/) [Example at feature/TicketSale](https://github.com/minhsangdotcom/clean-architecture/tree/feature/TicketSale) :walking:\n1. [Logging](/src/Api/Extensions/SerialogExtension.cs) :pencil:\n1. [Tracing](/src/Api/Extensions/OpenTelemetryExtensions.cs) :chart_with_upwards_trend:\n1. [Automatical translatable messages](https://github.com/minhsangdotcom/the-template_shared-kernel) :globe_with_meridians:\n1. [S3 AWS](/src/Infrastructure/Services/Aws/) :cloud:\n\u003cdiv id= 'nha-hang-cho-cac-tinh-nang'/\u003e\n\n# Nhá hàng cho các tính năng :fire:\n\n### API\n\n![User Apis](/Screenshots/user-api.png)\n\n![Role Apis](/Screenshots/role-api.png)\n\u003cdiv id='truy-vet'/\u003e\n\n### Truy Vết\n\n![Tracing](/Screenshots/trace.png)\n\u003cdiv id='minio-storage'/\u003e\n\n### Lưu trử file media bằng Minio\n\n![AWS s3 feature](Screenshots/AWS_S3_Feature.png)\n\u003cdiv id='message-translation'/\u003e\n\n### Tự động dịch message\n\n```json\n{\n  \"type\": \"BadRequestError\",\n  \"title\": \"Error has occured with password\",\n  \"status\": 400,\n  \"instance\": \"POST /api/v1/Users/Login\",\n  \"ErrorDetail\": {\n    \"message\": \"user_password_incorrect\",\n    \"en\": \"Password of user is incorrect\",\n    \"vi\": \"Mật khẩu của Người dùng không đúng\"\n  },\n  \"requestId\": \"0HNC1ERHD53E2:00000001\",\n  \"traceId\": \"fa7b365b49f1b554a9cfabd978d858c8\",\n  \"spanId\": \"8623dbe038a6dede\"\n}\n```\n\u003cdiv id='so-luot-ve-cau-truc'/\u003e\n\n# Sơ lượt về Cấu trúc :mag_right:\n\n```\n/Domain\n  ├── /Aggregates/           # Domain aggregates (entities with business rules)\n  └── /Common/               # Shared domain logic and base types\n       ├── AggregateRoot.cs       # Base class for aggregate roots\n       ├── BaseEntity.cs          # Base class for entities\n       └── UlidToStringConverter.cs  # Value converter for ULIDs\n```\n\n```\n/Application\n  ├── /Common\n  │     ├── /Auth/                   # custom authorization \u0026 policies in .NET Core\n  │     ├── /Behaviors/              # MediatR pipeline behaviors (CQRS cross‑cutting)\n  │     ├── /DomainEventHandlers/    # handlers for raising/domain events\n  │     ├── /Errors/                 # error types for Result‑pattern responses\n  │     ├── /Exceptions/             # domain/application exception definitions\n  │     ├── /Extensions/             # helper methods (pagination, LHS parsing, etc.)\n  │     ├── /Interfaces/             # application‑level contracts \u0026 abstractions\n  │     ├── /QueryStringProcessing/  # validation logic for query‑string params\n  │     └── /Security/               # security attributes (e.g. [Authorize], roles)\n  ├── /Features/                     # CQRS + MediatR pattern modules\n  │     ├── AuditLogs/               # commands \u0026 queries for audit‑trail\n  │     ├── Common/                  # shared feature utilities\n  │     ├── Permissions/             # manage app permissions\n  │     ├── QueueLogs/               # logging for background/queued jobs\n  │     ├── Regions/                 # region‑related commands \u0026 queries\n  │     ├── Roles/                   # role management (CRUD, assignments)\n  │     └── Users/                   # user‑centric commands \u0026 queries\n  └── DependencyInjection.cs         # Registration of all Application services into DI\n\n```\n\n```\n/Infrastructure\n  ├── /Constants/                    # application-wide constants \u0026 credential definitions\n  │     └── Credential.cs            # strongly-typed credentials (keys, secrets, etc.)\n  │\n  ├── /Data/                         # EF Core data layer: context, migrations, seeding, configs\n  │     ├── /Configurations/         # IEntityTypeConfiguration\u003c\u003e implementations\n  │     ├── /Interceptors/           # DbCommand/SaveChanges interceptors (logging, auditing)\n  │     ├── /Migrations/             # EF Core migration files\n  │     ├── /Seeds/                  # seed-data providers for initial data\n  │     ├── DatabaseSettings.cs      # POCO for database connection/settings\n  │     ├── DbInitializer.cs         # ensures DB is created \u0026 seeded on startup\n  │     ├── DesignTimeDbContextFactory.cs  # design-time factory for `dotnet ef` commands\n  │     ├── RegionDataSeeding.cs           # specific seed logic for Regions table\n  │     ├── TheDbContext.cs                # your `DbContext` implementation\n  │     └── ValidateDatabaseSetting.cs     # runtime validation of DB settings\n  │\n  ├── /Services/                     # external/infrastructure services \u0026 integrations\n  │     ├── /Aws/                    # AWS SDK wrappers (S3, SNS, etc.)\n  │     ├── /Cache/                  # caching implementations (Redis, MemoryCache)\n  │     ├── /ElasticSearch/          # Elasticsearch client \u0026 indexing/search logic\n  │     ├── /Hangfire/               # background-job scheduler configuration\n  │     ├── /Identity/               # identity provider integrations (JWT, OAuth)\n  │     ├── /Mail/                   # SMTP, SendGrid, or other mail-sending services\n  │     ├── /Queue/                  # Request queueing with Redis\n  │     ├── /Token/                  # token-related services and helpers\n  │     ├── ActionAccessorService.cs # grabs current `HttpContext` action info\n  │     └── CurrentUserService.cs    # resolves authenticated user details\n  │\n  ├── /UnitOfWorks/                  # Unit-of-Work \u0026 repository abstractions\n  │     ├── /CachedRepositories/     # repositories with built-in caching layers\n  │     ├── /Repositories/           # concrete repository implementations\n  │     ├── RepositoryExtension.cs   # extension methods for IRepository\u003cT\u003e\n  │     └── UnitOfWork.cs            # coordinates multiple repository commits\n  │\n  └── DependencyInjection.cs         # registration of all Infrastructure services into DI\n```\n\n```\n/Api\n  ├── /common/                         # shared helpers, configurations for API layer\n  │\n  ├── /Converters/                     # JSON/string converters for date types\n  │     ├── DateTimeConverter.cs           # custom converter for System.DateTime\n  │     └── DateTimeOffsetConverter.cs     # custom converter for System.DateTimeOffset\n  │\n  ├── /Endpoints/                      # minimal‑API endpoint definitions\n  │\n  ├── /Extensions/                     # extension methods (IServiceCollection, HttpContext, etc.)\n  │\n  ├── /Middlewares/                    # custom middleware (error handling, logging, auth, etc.)\n  │\n  ├── /Resources/                      # static resource files\n  │     └── /Translations/               # localization .resx files\n  │           ├── Message.en.resx           # English resource strings\n  │           └── Message.vi.resx           # Vietnamese resource strings\n  │\n  ├── /Settings/                       # POCOs bound to appsettings.json sections\n  │     ├── OpenApiSettings.cs             # swagger/OpenAPI configuration\n  │     ├── OpenTelemetrySettings.cs       # OTEL exporter/tracing settings\n  │     └── SerilogSettings.cs             # Serilog sink \u0026 logging configuration\n  │\n  └── /wwwroot/                        # publicly served static content\n        └── /Templates/                   # email/html templates, static assets\n```\n\n```\n            +-----------------------------------------------+\n            |                   Api                         |\n            +-----------------------------------------------+\n             |                     |                    |\n             |                     |                    |\n             ↓                     |                    |\n        +------------------+       |                    |\n        |  Infrastructure  |       |                    |\n        +------------------+       |                    |\n                        |          |                    |\n                        ↓          ↓                    ↓\n                    +--------------------+    +---------------------+\n                    |   Application      | -\u003e | Contracts           |\n                    +--------------------+    +---------------------+\n                             |\n                             ↓\n            +---------------------------+\n            |          Domain           |\n            +---------------------------+\n\n```\n\n# Bắt đầu thôi nào\n\n## Cách để chạy ứng dụng\n\nCác thứ cần để chạy ứng dụng:\n\n- [Net 8](https://dotnet.microsoft.com/en-us/download/dotnet/8.0)\n- [Docker](https://www.docker.com/)\n\nBước thứ 1 :point_up: :\n\nTạo 1 file tên appsettings.Development.json ở ngoài cùng của tầng Api, Sao chép nội dung của appsettings.example.json vào file mới tạo và sau đó điều chỉnh lại các cấu hình theo cách của bạn.\n\nChỉnh sửa connection string của PostgreSQL (Bởi vì template này đang sử dụng PostgreSQL).\n\n```json\n\"DatabaseSettings\": {\n    \"DatabaseConnection\": \"Host=localhost;Username=[your_username];Password=[your_password];Database=example\"\n},\n```\n\nCập nhật migration lên database\n\n```\ncd src/Infrastructure\n\ndotnet ef database update\n```\n\nBước tiếp theo nha :point_right::\n\n```\ncd Dockers/MinioS3\n\n```\n\nĐổi tên username và password ở file .env nếu cần thiết, lát nữa các bạn sẽ dùng nó để đăng nhập vào web manager đó.\n\n```\nMINIO_ROOT_USER=the_template_storage\nMINIO_ROOT_PASSWORD=storage@the_template1\n\n```\n\nDùng lệnh sau đây để chạy Amazon S3 service\n\n```\ndocker-compose up -d\n\n```\n\nTruy cập http://localhost:9001 và đăng nhập\n\n![S3 login](/Screenshots/S3-login.png)\n\nTạo ra cặp key\n\n![S3 keys](/Screenshots/create-key-s3.PNG)\n\nChỉnh lại setting ở your appsettings.json\n\n```json\n\"S3AwsSettings\": {\n      \"ServiceUrl\": \"http://localhost:9000\",\n      \"AccessKey\": \"\",\n      \"SecretKey\": \"\",\n      \"BucketName\": \"the-template-project\",\n      \"PublicUrl\": \"http://localhost:9000\",\n      \"PreSignedUrlExpirationInMinutes\": 1440,\n      \"Protocol\": 1\n    },\n```\n\nBước cuối nha\n\n```\ncd src/Api\ndotnet run\n\n```\n\nvào swagger ui ở http://localhost:8080/docs\n\nTài khoản admin mặc định là \u003cins\u003eusername:\u003c/ins\u003e \u003cb\u003echloe.kim\u003c/b\u003e, \u003cins\u003epassword\u003c/ins\u003e: \u003cb\u003eAdmin@123\u003c/b\u003e\n\nXong rồi đó :tada: :tada: :tada: :clap:\n\n## Hướng dẫn sử dụng\n\n### Authorize\n\nĐể phân quyền cho nó sử dụng RequireAuth vào minimal api,\ntham số permissions là kiểu string, các quyền được phân tách bởi dấu phẩy.\n\n```csharp\napp.MapPost(Router.UserRoute.Users, HandleAsync)\n    .WithOpenApi(operation =\u003e new OpenApiOperation(operation)\n    {\n        Summary = \"Create user 🧑\",\n        Description = \"Creates a new user and returns the created user details.\",\n        Tags = [new OpenApiTag() { Name = Router.UserRoute.Tags }],\n    })\n    .WithRequestValidation\u003cCreateUserCommand\u003e()\n    .RequireAuth(\n        permissions: Permission.Generate(PermissionAction.Create, PermissionResource.User)\n    )\n    .DisableAntiforgery();\n```\n\n**_Tạo ra role kèm theo permission_**\n\n```json\n{\n  \"description\": \"this is super admin role\",\n  \"name\": \"superAdmin\",\n  \"roleClaims\": [\n    {\n      \"claimType\": \"permission\",\n      \"claimValue\": \"create:customer\"\n    },\n    {\n      \"claimType\": \"permission\",\n      \"claimValue\": \"update:customer\"\n    }\n  ]\n}\n```\n\n### Thêm một quyền mới vào ứng dụng\n\nVào thư mục Constants trong Infrastructure mở file Credential.cs và chú ý tới permissions\n\n```csharp\npublic static readonly List\u003cDictionary\u003cstring, List\u003cstring\u003e\u003e\u003e permissions =\n    [\n        Permission.CreatebasicPermissions(PermissionResource.User),\n        Permission.CreatebasicPermissions(PermissionResource.Role),\n    ];\n```\n\nChú ý rằng, key là quyền chính còn value là danh sách quyền liên quan của nó\n\nPermission được gộp từ hành động và tên entity.\nVD:\n\n```\ncreate:user\n```\n\nĐây là nơi để tạo ra các PermissionAction từ lớp ActionPermission và PermissionResource.\n\n```csharp\npublic class PermissionAction\n{\n    public const string Create = nameof(Create);\n    public const string Update = nameof(Update);\n    public const string Delete = nameof(Delete);\n    public const string Detail = nameof(Detail);\n    public const string List = nameof(List);\n    public const string Test = nameof(Test);\n    public const string Testing = nameof(Testing);\n}\n\npublic class PermissionResource\n{\n    public const string User = nameof(User);\n    public const string Role = nameof(Role);\n}\n```\n\nTạo ra permission mới sau đó thêm nó vào list tên là permissions, tắt và chạy lại ứng dụng.\n\u003cdiv id='filtering'/\u003e\n\n### Bộ lọc\n\nĐể thực hiện tính năng filter, Chúng ta sẽ sử dụng cú pháp LHS Brackets.\n\nLHS là cách để sử dụng các phương thức trong dấu ngoặc vuông cho key\n\nVD:\n\n```\nGET api/v1/users?filter[dayOfBirth][$gt]=\"1990-10-01\"\n```\n\nVí dụ này nói rằng hãy lấy ra cho tôi tất cả những người có ngày sinh sau ngày 01 tháng 10 năm 1990\n\nTất cả các phương thức:\n\n| Operator      | Description                                |\n| ------------- | ------------------------------------------ |\n| $eq           | So sánh bằng                               |\n| $eqi          | So sánh bằng (Không phân biệt hoa thường)  |\n| $ne           | Không bằng                                 |\n| $nei          | Không bằng (Không phân biệt hoa thường)    |\n| $in           | Lọc ra các kết quả Có trong mảng này       |\n| $notin        | Lọc ra các kết quả không Có trong mảng này |\n| $lt           | Bé hơn                                     |\n| $lte          | Bé hơn bằng                                |\n| $gt           | Lớn hơn                                    |\n| $gte          | Lớn hơn hoặc bằng                          |\n| $between      | Kết quả nằm giữa 2 phần tử trong mảng      |\n| $notcontains  | không chứa                                 |\n| $notcontainsi | không chưa (Không phân biệt hoa thường)    |\n| $contains     | chứa                                       |\n| $containsi    | chứa (Không phân biệt hoa thường)          |\n| $startswith   | phần đầu khớp với                          |\n| $endswith     | phần cuối khớp với                         |\n\nVài VD:\n\n```\nGET /api/v1/user?filter[gender][$in][0]=1\u0026filter[gender][$in][1]=2\n```\n\n```\nGET /api/v1/user?filter[gender][$between][0]=1\u0026filter[gender][$between][1]=2\n```\n\n```\nGET /api/v1/user?filter[firstName][$contains]=abc\n```\n\nPhương thúc $and và $or:\n\n```\nGET /api/v1/users/filter[$and][0][firstName][$containsi]=\"sa\"\u0026filter[$and][1][lastName][$eq]=\"Tran\"\n```\n\n```JSON\n{\n  \"filter\": {\n    \"$and\": {\n      \"firstName\": \"sa\",\n      \"lastName\": \"Tran\"\n    }\n  }\n}\n```\n\n```\nGET /api/users/filter[$or][0][$and][0][claims][claimValue][$eq]=admin\u0026filter[$or][1][lastName][$eq]=Tran\n```\n\n```JSON\n{\n    \"filter\": {\n        \"$or\": {\n            \"$and\":{\n                \"claims\": {\n                    \"claimValue\": \"admin\"\n                }\n            },\n            \"lastName\": \"Tran\"\n        }\n    }\n}\n```\n\nCác bạn có thể tìm hiểu thêm ỏ một số link sau đây\n\n[https://docs.strapi.io/dev-docs/api/rest/filters-locale-publication#filtering](https://docs.strapi.io/dev-docs/api/rest/filters-locale-publication#filtering)\\\n[https://docs.strapi.io/dev-docs/api/rest/filters-locale-publication#complex-filtering](https://docs.strapi.io/dev-docs/api/rest/filters-locale-publication#complex-filtering)\\\n[https://docs.strapi.io/dev-docs/api/rest/filters-locale-publication#deep-filtering](https://docs.strapi.io/dev-docs/api/rest/filters-locale-publication#deep-filtering)\n\nMình thiết kế input đầu vào dựa trên [Strapi filter](https://docs.strapi.io/dev-docs/api/rest/filters-locale-publication)\n\nMình đã nhúng sẳn filter tự động vào tất cả các hàm lấy danh sách chỉ cần gọi\n\n```csharp\nunitOfWork.DynamicReadOnlyRepository\u003cUser\u003e()\n```\n\u003cdiv id='pagination'/\u003e\n\n### Phân trang\n\nOffset and cursor pagination được tích hợp sẳn trong template.\n\nĐể sử dựng offset pagination thêm dòng sau vào code\n\n```csharp\nvar response = await unitOfWork\n    .DynamicReadOnlyRepository\u003cUser\u003e(true)\n    .PagedListAsync(\n        new ListUserSpecification(),\n        query,\n        ListUserMapping.Selector(),\n        cancellationToken: cancellationToken\n    );\n```\n\nĐể sử dụng cursor pagination thêm dòng sau vào code\n\n```csharp\nvar response = await unitOfWork\n    .DynamicReadOnlyRepository\u003cUser\u003e(true)\n    .CursorPagedListAsync(\n        new ListUserSpecification(),\n        query,\n        ListUserMapping.Selector(),\n        cancellationToken: cancellationToken\n    );\n```\n\n```json\n{\n  \"results\": {\n    \"data\": [\n      {\n        \"firstName\": \"sang\",\n        \"lastName\": \"minh\",\n        \"username\": \"sang.minh123\",\n        \"email\": \"sang.minh123@gmail.com\",\n        \"phoneNumber\": \"0925123320\",\n        \"dayOfBirth\": \"1990-01-09T17:00:00Z\",\n        \"gender\": 2,\n        \"address\": \"abcdef,Xã Phước Vĩnh An,Huyện Củ Chi,Thành phố Hồ Chí Minh\",\n        \"avatar\": null,\n        \"status\": 1,\n        \"createdBy\": \"01JD936AXSDNMQ713P5XMVRQDV\",\n        \"updatedBy\": \"01JD936AXSDNMQ713P5XMVRQDV\",\n        \"updatedAt\": \"2025-04-16T14:26:01Z\",\n        \"id\": \"01JRZFDA1F7ZV4P7CFS5WSHW8A\",\n        \"createdAt\": \"2025-04-16T14:17:54Z\"\n      }\n    ],\n    \"paging\": {\n      \"pageSize\": 1,\n      \"totalPage\": 3,\n      \"hasNextPage\": true,\n      \"hasPreviousPage\": false,\n      \"before\": null,\n      \"after\": \"q+blUlBQci5KTSxJTXEsUbJSUDIyMDLVNTDRNTQLMTK0MjS3MjXRMzG3tDAx1DYwtzIwUNIB6/FMASk2MPQKinJzcTR0M48KMwkwd3YLNg0P9gi3cFTi5aoFAA==\"\n    }\n  },\n  \"status\": 200,\n  \"message\": \"Success\"\n}\n```\n\n# Công nghệ\n\n- .NET 8\n- EntityFramework core 8\n- AutoMapper\n- FluentValidation\n- Mediator\n- XUnit, FluentAssertion, Respawn\n- OpenTelemetry\n- PostgresSQL\n- Redis\n- ElasticSearch\n- Serilog\n- Docker\n- GitHub Workflow\n\n# Hỗ trợ\n\nNếu như có bất kì vấn đề nào thì cho mình biết qua [phần issue ](https://github.com/minhsangdotcom/clean-architecture/issues) nhé.\n\n# Lời cảm ơn\n\n:heart: Cảm ơn mọi người rất nhiều :heart: :pray:.\n\n- [Clean architecture by Jayson Taylor](https://github.com/jasontaylordev/CleanArchitecture)\n\n- [Clean architecture by amantinband](https://github.com/amantinband/clean-architecture)\n- [Clean architecture by Ardalis](https://github.com/ardalis/CleanArchitecture)\n- [Specification pattern](https://github.com/ardalis/Specification)\n- [REPR Pattern](https://github.com/ardalis/ApiEndpoints)\n- [Clean testing by Jayson Taylor](https://github.com/jasontaylordev/CleanArchitecture/tree/main/tests)\n\u003cdiv id=\"license\"/\u003e\n\n# Cấp phép\n\nDự án này sử dụng [MIT license](LICENSE)\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fminhsangdotcom%2Fclean-architecture","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fminhsangdotcom%2Fclean-architecture","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fminhsangdotcom%2Fclean-architecture/lists"}