Browse Source

Merge branch 'rel-9.3' into auto-merge/rel-9-2/3933

pull/23510/head
maliming 6 months ago
committed by GitHub
parent
commit
f70d03d8ab
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 2
      .github/ISSUE_TEMPLATE/config.yml
  2. 22
      .github/workflows/auto-pr.yml
  3. 2
      .github/workflows/build-and-test.yml
  4. 140
      Directory.Packages.props
  5. 2
      README.md
  6. 33
      abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json
  7. 9
      abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/en.json
  8. 3
      common.props
  9. 2
      docs/en/Blog-Posts/2022-03-08 v5_2_Preview/POST.md
  10. 2
      docs/en/Blog-Posts/2024-02-16 v8_1_Preview/POST.md
  11. 2
      docs/en/Blog-Posts/2024-05-21 v8_2_Release/POST.md
  12. 2
      docs/en/Blog-Posts/2024-07-31 v8_3_Preview/post.md
  13. 2
      docs/en/Blog-Posts/2024-09-06 v8_3_Release_Stable/POST.md
  14. 2
      docs/en/Blog-Posts/2024-10-23 v9_0_Preview/POST.md
  15. 2
      docs/en/Blog-Posts/2024-11-19 v9_0_Release_Stable/post.md
  16. 2
      docs/en/Blog-Posts/2025-01-21 v9_1_Preview/POST.md
  17. 2
      docs/en/Blog-Posts/2025-03-07 v9_1_Release_Stable/POST.md
  18. 195
      docs/en/Blog-Posts/2025-03-27 v9_2_Preview/POST.md
  19. BIN
      docs/en/Blog-Posts/2025-03-27 v9_2_Preview/after.png
  20. BIN
      docs/en/Blog-Posts/2025-03-27 v9_2_Preview/before.png
  21. BIN
      docs/en/Blog-Posts/2025-03-27 v9_2_Preview/configure-timezone.png
  22. BIN
      docs/en/Blog-Posts/2025-03-27 v9_2_Preview/cover-image.png
  23. BIN
      docs/en/Blog-Posts/2025-03-27 v9_2_Preview/require-email-verification-for-register.png
  24. BIN
      docs/en/Blog-Posts/2025-03-27 v9_2_Preview/select-account.png
  25. BIN
      docs/en/Blog-Posts/2025-03-27 v9_2_Preview/studio-switch-to-preview.png
  26. 86
      docs/en/Blog-Posts/2025-06-02 v9_2_Release_Stable/POST.md
  27. BIN
      docs/en/Blog-Posts/2025-06-02 v9_2_Release_Stable/cover-image.png
  28. BIN
      docs/en/Blog-Posts/2025-06-02 v9_2_Release_Stable/upgrade-abp-packages.png
  29. 97
      docs/en/Blog-Posts/2025-06-10-Announcing-ABP-Studio-1.0-Stable-Release/POST.md
  30. BIN
      docs/en/Blog-Posts/2025-06-10-Announcing-ABP-Studio-1.0-Stable-Release/abp-studio-check-for-updates.png
  31. BIN
      docs/en/Blog-Posts/2025-06-10-Announcing-ABP-Studio-1.0-Stable-Release/abp-studio-download.png
  32. BIN
      docs/en/Blog-Posts/2025-06-10-Announcing-ABP-Studio-1.0-Stable-Release/containers-type.png
  33. BIN
      docs/en/Blog-Posts/2025-06-10-Announcing-ABP-Studio-1.0-Stable-Release/cover-image.png
  34. BIN
      docs/en/Blog-Posts/2025-06-10-Announcing-ABP-Studio-1.0-Stable-Release/health-checks.png
  35. BIN
      docs/en/Blog-Posts/2025-06-10-Announcing-ABP-Studio-1.0-Stable-Release/new-migration-added.gif
  36. BIN
      docs/en/Blog-Posts/2025-06-10-Announcing-ABP-Studio-1.0-Stable-Release/saas-health-check.png
  37. BIN
      docs/en/Blog-Posts/2025-06-10-Announcing-ABP-Studio-1.0-Stable-Release/theme-style-selection-leptonx.png
  38. 6
      docs/en/Community-Articles/2020-09-09-Replacing-Email-Template-and-Sending-Emails/POST.md
  39. 12
      docs/en/Community-Articles/2020-12-10-How-to-Integrate-the-Telerik-Blazor-Component/POST.md
  40. 16
      docs/en/Community-Articles/2021-06-17-Using-Elsa-Workflow-with-ABP-Framework/POST.md
  41. 12
      docs/en/Community-Articles/2021-10-31-Many-to-Many-Relationship-with-ABP-and-EF-Core/POST.md
  42. 12
      docs/en/Community-Articles/2021-12-13-Integrating-the-Syncfusion-MVC-Components-to-the-ABP-MVC-UI/POST.md
  43. 10
      docs/en/Community-Articles/2022-02-06-How-to-Hide-ABP-Related-Endpoints-on-Swagger-UI/POST.md
  44. 2
      docs/en/Community-Articles/2022-03-09-abpio-platform-52-rc-has-been-published/post.md
  45. 12
      docs/en/Community-Articles/2022-04-06-Concurrency-Check-in-ABP-Based-Applications/POST.md
  46. 12
      docs/en/Community-Articles/2022-11-22-gRPC-JSON-Transcoding/POST.md
  47. 12
      docs/en/Community-Articles/2022-18-11-whats-new-with-net7/POST.md
  48. 12
      docs/en/Community-Articles/2023-07-03-Image-Compression-And-Resize/POST.md
  49. 12
      docs/en/Community-Articles/2023-08-12-ABP-Commercial-GDPR-Module-Overview/POST.md
  50. 12
      docs/en/Community-Articles/2023-10-30-NET-8-ASP-NET-Core-Metrics/POST.md
  51. 12
      docs/en/Community-Articles/2023-11-16-Upgrading-Your-Existing-Projects-to-NET8/POST.md
  52. 12
      docs/en/Community-Articles/2024-01-18-ABP-Now-Supports-Keyed-Services/POST.md
  53. 2
      docs/en/Community-Articles/2024-02-19-abpio-platform-81-rc-has-been-published/post.md
  54. 6
      docs/en/Community-Articles/2024-04-19-Performing-Case-Insensitive-Search-In-Postgresql/POST.md
  55. 12
      docs/en/Community-Articles/2024-05-10-Sentiment-Analysis-within-ABP-Based-Application/POST.md
  56. 2
      docs/en/Community-Articles/2024-05-24-abpio-platform-82-rc-has-been-published/post.md
  57. 2
      docs/en/Community-Articles/2024-08-01-abpio-platform-83-rc-has-been-published/post.md
  58. 2
      docs/en/Community-Articles/2024-09-12-abpio-platform-83-final-has-been-released/post.md
  59. 2
      docs/en/Community-Articles/2024-10-23-abpio-platform-90-rc-has-been-published/post.md
  60. 12
      docs/en/Community-Articles/2024-11-01-Hybrid-Cache-Net-9/POST.md
  61. 2
      docs/en/Community-Articles/2024-11-21-abpio-platform-90-has-been-released-based-on-net-90/post.md
  62. 2
      docs/en/Community-Articles/2025-01-21-abp-platform-91-rc-has-been-released/post.md
  63. 12
      docs/en/Community-Articles/2025-02-04-OpenIddict-Custom-Logic/POST.md
  64. 2
      docs/en/Community-Articles/2025-03-11-Developing-A-Multi-Timezone-Application-Using-The-ABP-Framework/post.md
  65. 2
      docs/en/Community-Articles/2025-03-18-Using-Vue-Components/post.md
  66. 4
      docs/en/Community-Articles/2025-03-23-Understanding-the-Embedded-Files-in-ABP-Framework/post.md
  67. 12
      docs/en/Community-Articles/2025-03-24-How-to-Change-the-CurrentUser-in-ABP/POST.md
  68. 38
      docs/en/Community-Articles/2025-03-27-Announcing-the-ABP-Contributor-Program/post.md
  69. 170
      docs/en/Community-Articles/2025-04-20-IDX10204/POST.md
  70. BIN
      docs/en/Community-Articles/2025-04-20-IDX10204/header.png
  71. BIN
      docs/en/Community-Articles/2025-04-20-IDX10204/payload.png
  72. 262
      docs/en/Community-Articles/2025-04-25-AI-Comment-Summarization/POST.md
  73. BIN
      docs/en/Community-Articles/2025-04-25-AI-Comment-Summarization/comment-example.png
  74. BIN
      docs/en/Community-Articles/2025-04-25-AI-Comment-Summarization/summary-card.png
  75. 134
      docs/en/Community-Articles/2025-05-11-AI-Chat/POST.md
  76. BIN
      docs/en/Community-Articles/2025-05-11-AI-Chat/ai-chat.png
  77. BIN
      docs/en/Community-Articles/2025-05-11-AI-Chat/cover.png
  78. 268
      docs/en/Community-Articles/2025-05-19-RouteTenantResolveContributor/POST.md
  79. BIN
      docs/en/Community-Articles/2025-05-19-RouteTenantResolveContributor/cover.png
  80. BIN
      docs/en/Community-Articles/2025-05-19-RouteTenantResolveContributor/swagger-ui.png
  81. BIN
      docs/en/Community-Articles/2025-05-19-RouteTenantResolveContributor/ui.png
  82. 38
      docs/en/Community-Articles/2025-06-10-bootcamp/post.md
  83. BIN
      docs/en/Community-Articles/2025-06-12-fix-mongodb-guid-abp-v9.2.0-upgrade/mongo-db.jpg
  84. 93
      docs/en/Community-Articles/2025-06-12-fix-mongodb-guid-abp-v9.2.0-upgrade/post.md
  85. 113
      docs/en/Community-Articles/2025-06-13-modular-docker-container-management/modular-docker-container-management.md
  86. BIN
      docs/en/Community-Articles/2025-06-13-modular-docker-container-management/solution-runner-containers.png
  87. 1
      docs/en/cli/index.md
  88. 66
      docs/en/docs-nav.json
  89. 2
      docs/en/framework/api-development/static-csharp-clients.md
  90. 2
      docs/en/framework/api-development/swagger.md
  91. 12
      docs/en/framework/data/entity-framework-core/mysql.md
  92. 2
      docs/en/framework/fundamentals/fluent-validation.md
  93. 2
      docs/en/framework/infrastructure/background-jobs/hangfire.md
  94. 19
      docs/en/framework/infrastructure/background-jobs/index.md
  95. 2
      docs/en/framework/infrastructure/background-jobs/quartz.md
  96. 2
      docs/en/framework/infrastructure/background-workers/hangfire.md
  97. 3
      docs/en/framework/infrastructure/background-workers/index.md
  98. 2
      docs/en/framework/infrastructure/background-workers/quartz.md
  99. 8
      docs/en/framework/infrastructure/image-manipulation.md
  100. 2
      docs/en/framework/infrastructure/sms-sending.md

2
.github/ISSUE_TEMPLATE/config.yml

@ -1,4 +1,4 @@
blank_issues_enabled: true
blank_issues_enabled: false
contact_links:
- name: Issue with ABP Commercial
url: https://abp.io/support/questions

22
.github/workflows/auto-pr.yml

@ -1,13 +1,13 @@
name: Merge branch rel-9.3 with rel-9.2
name: Merge branch dev with rel-9.3
on:
push:
branches:
- rel-9.2
- rel-9.3
permissions:
contents: read
jobs:
merge-rel-9-3-with-rel-9-2:
merge-dev-with-rel-9-3:
permissions:
contents: write # for peter-evans/create-pull-request to create branch
pull-requests: write # for peter-evans/create-pull-request to create a PR
@ -15,17 +15,17 @@ jobs:
steps:
- uses: actions/checkout@v2
with:
ref: rel-9.3
ref: dev
- name: Reset promotion branch
run: |
git fetch origin rel-9.2:rel-9.2
git reset --hard rel-9.2
git fetch origin rel-9.3:rel-9.3
git reset --hard rel-9.3
- name: Create Pull Request
uses: peter-evans/create-pull-request@v3
with:
branch: auto-merge/rel-9-2/${{github.run_number}}
title: Merge branch rel-9.3 with rel-9.2
body: This PR generated automatically to merge rel-9.3 with rel-9.2. Please review the changed files before merging to prevent any errors that may occur.
branch: auto-merge/rel-9-3/${{github.run_number}}
title: Merge branch dev with rel-9.3
body: This PR generated automatically to merge dev with rel-9.3. Please review the changed files before merging to prevent any errors that may occur.
reviewers: maliming
draft: true
token: ${{ github.token }}
@ -34,5 +34,5 @@ jobs:
GH_TOKEN: ${{ secrets.BOT_SECRET }}
run: |
gh pr ready
gh pr review auto-merge/rel-9-2/${{github.run_number}} --approve
gh pr merge auto-merge/rel-9-2/${{github.run_number}} --merge --auto --delete-branch
gh pr review auto-merge/rel-9-3/${{github.run_number}} --approve
gh pr merge auto-merge/rel-9-3/${{github.run_number}} --merge --auto --delete-branch

2
.github/workflows/build-and-test.yml

@ -48,7 +48,7 @@ permissions:
jobs:
build-test:
runs-on: ubuntu-22.04
timeout-minutes: 40
timeout-minutes: 50
if: ${{ !github.event.pull_request.draft }}
steps:
- uses: actions/checkout@v2

140
Directory.Packages.props

@ -18,10 +18,10 @@
<PackageVersion Include="BunnyCDN.Net.Storage" Version="1.0.4" />
<PackageVersion Include="Azure.Messaging.ServiceBus" Version="7.19.0" />
<PackageVersion Include="Azure.Storage.Blobs" Version="12.24.0" />
<PackageVersion Include="Blazorise" Version="1.7.6" />
<PackageVersion Include="Blazorise.Components" Version="1.7.6" />
<PackageVersion Include="Blazorise.DataGrid" Version="1.7.6" />
<PackageVersion Include="Blazorise.Snackbar" Version="1.7.6" />
<PackageVersion Include="Blazorise" Version="1.8.0" />
<PackageVersion Include="Blazorise.Components" Version="1.8.0" />
<PackageVersion Include="Blazorise.DataGrid" Version="1.8.0" />
<PackageVersion Include="Blazorise.Snackbar" Version="1.8.0" />
<PackageVersion Include="Castle.Core" Version="5.1.1" />
<PackageVersion Include="Castle.Core.AsyncInterceptor" Version="2.1.0" />
<PackageVersion Include="CommonMark.NET" Version="0.15.1" />
@ -34,6 +34,9 @@
<PackageVersion Include="DistributedLock.Core" Version="1.0.8" />
<PackageVersion Include="DistributedLock.Redis" Version="1.0.3" />
<PackageVersion Include="DeepL.net" Version="1.15.0" />
<PackageVersion Include="itext.bouncy-castle-adapter" Version="9.2.0" />
<PackageVersion Include="itext7" Version="9.2.0" />
<PackageVersion Include="itext7.pdfhtml" Version="6.2.0" />
<PackageVersion Include="MongoSandbox.Core" Version="2.0.0" />
<PackageVersion Include="MongoSandbox8.runtime.linux-x64" Version="2.0.0" />
<PackageVersion Include="MongoSandbox8.runtime.osx-arm64" Version="2.0.0" />
@ -52,68 +55,68 @@
<PackageVersion Include="Magick.NET-Q16-AnyCPU" Version="13.4.0" />
<PackageVersion Include="MailKit" Version="4.12.0" />
<PackageVersion Include="Markdig.Signed" Version="0.41.1" />
<PackageVersion Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="9.0.4" />
<PackageVersion Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="9.0.4" />
<PackageVersion Include="Microsoft.AspNetCore.Authorization" Version="9.0.4" />
<PackageVersion Include="Microsoft.AspNetCore.Components" Version="9.0.4" />
<PackageVersion Include="Microsoft.AspNetCore.Components.Authorization" Version="9.0.4" />
<PackageVersion Include="Microsoft.AspNetCore.Components.Web" Version="9.0.4" />
<PackageVersion Include="Microsoft.AspNetCore.Components.WebAssembly" Version="9.0.4" />
<PackageVersion Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="9.0.4" />
<PackageVersion Include="Microsoft.AspNetCore.Components.WebAssembly.Authentication" Version="9.0.4" />
<PackageVersion Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="9.0.4" />
<PackageVersion Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="9.0.5" />
<PackageVersion Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="9.0.5" />
<PackageVersion Include="Microsoft.AspNetCore.Authorization" Version="9.0.5" />
<PackageVersion Include="Microsoft.AspNetCore.Components" Version="9.0.5" />
<PackageVersion Include="Microsoft.AspNetCore.Components.Authorization" Version="9.0.5" />
<PackageVersion Include="Microsoft.AspNetCore.Components.Web" Version="9.0.5" />
<PackageVersion Include="Microsoft.AspNetCore.Components.WebAssembly" Version="9.0.5" />
<PackageVersion Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="9.0.5" />
<PackageVersion Include="Microsoft.AspNetCore.Components.WebAssembly.Authentication" Version="9.0.5" />
<PackageVersion Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="9.0.5" />
<PackageVersion Include="Microsoft.AspNetCore.Components.WebView.Maui" Version="9.0.60" />
<PackageVersion Include="Microsoft.Maui.Controls" Version="9.0.60" />
<PackageVersion Include="Microsoft.AspNetCore.DataProtection.StackExchangeRedis" Version="9.0.4" />
<PackageVersion Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="9.0.4" />
<PackageVersion Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="9.0.4" />
<PackageVersion Include="Microsoft.AspNetCore.Mvc.Testing" Version="9.0.4" />
<PackageVersion Include="Microsoft.AspNetCore.DataProtection.StackExchangeRedis" Version="9.0.5" />
<PackageVersion Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="9.0.5" />
<PackageVersion Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="9.0.5" />
<PackageVersion Include="Microsoft.AspNetCore.Mvc.Testing" Version="9.0.5" />
<PackageVersion Include="Microsoft.AspNetCore.Razor.Language" Version="6.0.36" />
<PackageVersion Include="Microsoft.AspNetCore.TestHost" Version="9.0.4" />
<PackageVersion Include="Microsoft.AspNetCore.WebUtilities" Version="9.0.4" />
<PackageVersion Include="Microsoft.Bcl.AsyncInterfaces" Version="9.0.4" />
<PackageVersion Include="Microsoft.AspNetCore.TestHost" Version="9.0.5" />
<PackageVersion Include="Microsoft.AspNetCore.WebUtilities" Version="9.0.5" />
<PackageVersion Include="Microsoft.Bcl.AsyncInterfaces" Version="9.0.5" />
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="4.5.0" />
<PackageVersion Include="Microsoft.CSharp" Version="4.7.0" />
<PackageVersion Include="Microsoft.Data.Sqlite" Version="9.0.4" />
<PackageVersion Include="Microsoft.Data.Sqlite" Version="9.0.5" />
<PackageVersion Include="Microsoft.Data.SqlClient" Version="6.0.2" />
<PackageVersion Include="Microsoft.EntityFrameworkCore" Version="9.0.4" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Design" Version="9.0.4" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.InMemory" Version="9.0.4" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Proxies" Version="9.0.4" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Relational" Version="9.0.4" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Sqlite" Version="9.0.4" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.SqlServer" Version="9.0.4" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Tools" Version="9.0.4" />
<PackageVersion Include="Microsoft.EntityFrameworkCore" Version="9.0.5" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Design" Version="9.0.5" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.InMemory" Version="9.0.5" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Proxies" Version="9.0.5" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Relational" Version="9.0.5" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Sqlite" Version="9.0.5" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.SqlServer" Version="9.0.5" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Tools" Version="9.0.5" />
<PackageVersion Include="Microsoft.Extensions.Caching.Hybrid" Version="9.4.0" />
<PackageVersion Include="Microsoft.Extensions.Caching.Memory" Version="9.0.4" />
<PackageVersion Include="Microsoft.Extensions.Caching.StackExchangeRedis" Version="9.0.4" />
<PackageVersion Include="Microsoft.Extensions.Configuration.Binder" Version="9.0.4" />
<PackageVersion Include="Microsoft.Extensions.Configuration.CommandLine" Version="9.0.4" />
<PackageVersion Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="9.0.4" />
<PackageVersion Include="Microsoft.Extensions.Configuration.UserSecrets" Version="9.0.4" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="9.0.4" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="9.0.4" />
<PackageVersion Include="Microsoft.Extensions.FileProviders.Composite" Version="9.0.4" />
<PackageVersion Include="Microsoft.Extensions.FileProviders.Embedded" Version="9.0.4" />
<PackageVersion Include="Microsoft.Extensions.FileProviders.Physical" Version="9.0.4" />
<PackageVersion Include="Microsoft.Extensions.FileSystemGlobbing" Version="9.0.4" />
<PackageVersion Include="Microsoft.Extensions.Hosting" Version="9.0.4" />
<PackageVersion Include="Microsoft.Extensions.Hosting.Abstractions" Version="9.0.4" />
<PackageVersion Include="Microsoft.Extensions.Http" Version="9.0.4" />
<PackageVersion Include="Microsoft.Extensions.Identity.Core" Version="9.0.4" />
<PackageVersion Include="Microsoft.Extensions.Localization" Version="9.0.4" />
<PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="9.0.4" />
<PackageVersion Include="Microsoft.Extensions.Logging" Version="9.0.4" />
<PackageVersion Include="Microsoft.Extensions.Logging.Console" Version="9.0.4" />
<PackageVersion Include="Microsoft.Extensions.Options" Version="9.0.4" />
<PackageVersion Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="9.0.4" />
<PackageVersion Include="Microsoft.Extensions.Caching.Memory" Version="9.0.5" />
<PackageVersion Include="Microsoft.Extensions.Caching.StackExchangeRedis" Version="9.0.5" />
<PackageVersion Include="Microsoft.Extensions.Configuration.Binder" Version="9.0.5" />
<PackageVersion Include="Microsoft.Extensions.Configuration.CommandLine" Version="9.0.5" />
<PackageVersion Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="9.0.5" />
<PackageVersion Include="Microsoft.Extensions.Configuration.UserSecrets" Version="9.0.5" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="9.0.5" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="9.0.5" />
<PackageVersion Include="Microsoft.Extensions.FileProviders.Composite" Version="9.0.5" />
<PackageVersion Include="Microsoft.Extensions.FileProviders.Embedded" Version="9.0.5" />
<PackageVersion Include="Microsoft.Extensions.FileProviders.Physical" Version="9.0.5" />
<PackageVersion Include="Microsoft.Extensions.FileSystemGlobbing" Version="9.0.5" />
<PackageVersion Include="Microsoft.Extensions.Hosting" Version="9.0.5" />
<PackageVersion Include="Microsoft.Extensions.Hosting.Abstractions" Version="9.0.5" />
<PackageVersion Include="Microsoft.Extensions.Http" Version="9.0.5" />
<PackageVersion Include="Microsoft.Extensions.Identity.Core" Version="9.0.5" />
<PackageVersion Include="Microsoft.Extensions.Localization" Version="9.0.5" />
<PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="9.0.5" />
<PackageVersion Include="Microsoft.Extensions.Logging" Version="9.0.5" />
<PackageVersion Include="Microsoft.Extensions.Logging.Console" Version="9.0.5" />
<PackageVersion Include="Microsoft.Extensions.Options" Version="9.0.5" />
<PackageVersion Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="9.0.5" />
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.13.0" />
<PackageVersion Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="9.0.0" />
<PackageVersion Include="Microsoft.SourceLink.GitHub" Version="8.0.0" />
<PackageVersion Include="System.IdentityModel.Tokens.Jwt" Version="8.9.0" />
<PackageVersion Include="Microsoft.IdentityModel.Protocols.OpenIdConnect" Version="8.9.0" />
<PackageVersion Include="Microsoft.IdentityModel.Tokens" Version="8.9.0" />
<PackageVersion Include="Microsoft.IdentityModel.JsonWebTokens" Version="8.9.0" />
<PackageVersion Include="System.IdentityModel.Tokens.Jwt" Version="8.12.0" />
<PackageVersion Include="Microsoft.IdentityModel.Protocols.OpenIdConnect" Version="8.12.0" />
<PackageVersion Include="Microsoft.IdentityModel.Tokens" Version="8.12.0" />
<PackageVersion Include="Microsoft.IdentityModel.JsonWebTokens" Version="8.12.0" />
<PackageVersion Include="Minio" Version="6.0.4" />
<PackageVersion Include="MongoDB.Driver" Version="3.3.0" />
<PackageVersion Include="NEST" Version="7.17.5" />
@ -125,20 +128,21 @@
<PackageVersion Include="NUglify" Version="1.21.15" />
<PackageVersion Include="Nullable" Version="1.3.1" />
<PackageVersion Include="Octokit" Version="14.0.0" />
<PackageVersion Include="OpenIddict.Abstractions" Version="6.2.1" />
<PackageVersion Include="OpenIddict.Core" Version="6.2.1" />
<PackageVersion Include="OpenIddict.Server.AspNetCore" Version="6.2.1" />
<PackageVersion Include="OpenIddict.Validation.AspNetCore" Version="6.2.1" />
<PackageVersion Include="OpenIddict.Validation.ServerIntegration" Version="6.2.1" />
<PackageVersion Include="OpenIddict.Abstractions" Version="6.4.0" />
<PackageVersion Include="OpenIddict.Core" Version="6.4.0" />
<PackageVersion Include="OpenIddict.Server.AspNetCore" Version="6.4.0" />
<PackageVersion Include="OpenIddict.Validation.AspNetCore" Version="6.4.0" />
<PackageVersion Include="OpenIddict.Validation.ServerIntegration" Version="6.4.0" />
<PackageVersion Include="Oracle.EntityFrameworkCore" Version="9.23.80" />
<PackageVersion Include="Polly" Version="8.5.2" />
<PackageVersion Include="Polly.Extensions.Http" Version="3.0.0" />
<PackageVersion Include="Pomelo.EntityFrameworkCore.MySql" Version="9.0.0-preview.3.efcore.9.0.0" />
<PackageVersion Include="Pomelo.EntityFrameworkCore.MySql" Version="9.0.0-rc.1.efcore.9.0.0" />
<PackageVersion Include="MySql.EntityFrameworkCore" Version="9.0.6" />
<PackageVersion Include="Quartz" Version="3.14.0" />
<PackageVersion Include="Quartz.Extensions.DependencyInjection" Version="3.14.0" />
<PackageVersion Include="Quartz.Plugins.TimeZoneConverter" Version="3.14.0" />
<PackageVersion Include="Quartz.Serialization.Json" Version="3.14.0" />
<PackageVersion Include="RabbitMQ.Client" Version="6.8.1" />
<PackageVersion Include="RabbitMQ.Client" Version="7.1.2" />
<PackageVersion Include="Rebus" Version="8.8.0" />
<PackageVersion Include="Rebus.ServiceProvider" Version="10.3.0" />
<PackageVersion Include="Scriban" Version="6.2.1" />
@ -160,17 +164,17 @@
<PackageVersion Include="Spectre.Console" Version="0.50.0" />
<PackageVersion Include="StackExchange.Redis" Version="2.8.31" />
<PackageVersion Include="Swashbuckle.AspNetCore" Version="8.1.1" />
<PackageVersion Include="System.Collections.Immutable" Version="9.0.4" />
<PackageVersion Include="System.Collections.Immutable" Version="9.0.5" />
<PackageVersion Include="System.ComponentModel.Annotations" Version="5.0.0" />
<PackageVersion Include="System.Linq.Async" Version="6.0.1" />
<PackageVersion Include="System.Linq.Dynamic.Core" Version="1.6.2" />
<PackageVersion Include="System.Linq.Queryable" Version="4.3.0" />
<PackageVersion Include="System.Runtime.Loader" Version="4.3.0" />
<PackageVersion Include="System.Security.Permissions" Version="9.0.4" />
<PackageVersion Include="System.Security.Permissions" Version="9.0.5" />
<PackageVersion Include="System.Security.Principal.Windows" Version="5.0.0" />
<PackageVersion Include="System.Text.Encoding.CodePages" Version="9.0.4" />
<PackageVersion Include="System.Text.Encodings.Web" Version="9.0.4" />
<PackageVersion Include="System.Text.Json" Version="9.0.4" />
<PackageVersion Include="System.Text.Encoding.CodePages" Version="9.0.5" />
<PackageVersion Include="System.Text.Encodings.Web" Version="9.0.5" />
<PackageVersion Include="System.Text.Json" Version="9.0.5" />
<PackageVersion Include="System.Threading.Tasks.Extensions" Version="4.6.3" />
<PackageVersion Include="TencentCloudSDK.Sms" Version="3.0.1231" />
<PackageVersion Include="TimeZoneConverter" Version="7.0.0" />

2
README.md

@ -27,7 +27,7 @@ The following diagram contains the core components of the **ABP Platform** and s
ABP offers a complete architectural model to build modern enterprise software solutions. Here, the fundamental architectural structures offered and first-class supported by ABP:
* [Domain Driven Design](https://abp.io/docs/latest/framework/architecture/domain-driven-design)
* [Domain Driven Design (DDD)](https://abp.io/docs/latest/framework/architecture/domain-driven-design)
* [Microservices](https://abp.io/docs/latest/framework/architecture/microservices)
* [Modularity](https://abp.io/docs/latest/framework/architecture/modularity/basics)
* [Multi-Tenancy](https://abp.io/docs/latest/framework/architecture/multi-tenancy)

33
abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json

@ -690,6 +690,37 @@
"Permission:Campaigns": "Campaigns",
"Permission:Licenses": "License Settings",
"BlockUserPolicy": "User Block Policies",
"Permission:BlockUserPolicy": "User Block Policy"
"Permission:BlockUserPolicy": "User Block Policy",
"ManageImages" : "Manage Image",
"ModuleMainImage": "Module Main Image",
"ModuleImageInfo1": "Accepted file types : <strong> JPEG, JPG, PNG, SVG </strong>",
"ModuleImageInfo2": "Max file size : <strong> 1 MB </strong>",
"ModuleImageInfo3": "Image Proportion : <strong> 1:1 </strong>",
"ModuleImageInfo4": "<a href='/images/example-module-img.png' download> Download a sample cover image </a>",
"AreYouSureToDeleteImage": "Are you sure you want to delete this image?",
"CompactPercentage": "Compact Percentage",
"CompactPercentageDescription": "Percentage of cache entries to remove during compaction (1-100)",
"Settings": "Settings",
"MaxSizeOfInMemoryCache": "Max Size Of In Memory Cache",
"MaxSizeOfInMemoryCacheInfo": "Gets or sets the maximum size of the memory cache.",
"SizeOfTriggerAutoCompact": "Size Of Trigger Auto Compact",
"SizeOfTriggerAutoCompactInfo": "Gets or sets the size threshold that triggers auto-compaction. When the cache size exceeds this value, auto-compaction will be performed",
"AutoCompactPercentage": "Auto Compact Percentage",
"AutoCompactPercentageInfo": "Gets or sets the percentage of items to remove when auto-compaction is triggered (1-100)",
"ClearCaches": "This clears all NuGet content cache",
"CacheLatestVersions": "Cache Latest Versions",
"VersionCount": "Version Count",
"VersionCountInfo": "Gets or sets the number of versions to cache",
"IncludeLeptonX": "Include LeptonX",
"IncludeLeptonXInfo": "Gets or sets whether to include LeptonX in the cache",
"IncludePrerelease": "Include Prerelease",
"IncludePrereleaseInfo": "Gets or sets whether to include prerelease versions in the cache",
"CacheVersionCount": "Cache Version Count",
"CacheVersionCountInfo": "Gets or sets the number of versions to cache",
"CacheLatestVersionsInfo": "This caches the latest versions of the NuGet packages",
"NuGetApiKey": "NuGet API key",
"QuestionCount": "Question Count",
"MakeAnnouncement": "Make Announcement",
"MakeAnnouncementInfo": "Check it if you want to make an announcement for this post"
}
}

9
abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/en.json

@ -66,7 +66,7 @@
"AuditLogging": "Audit Logging",
"Caching": "Caching",
"Multitenancy": "Multitenancy",
"DataFiltering": "Data filtering",
"DataFiltering": "Data Filtering",
"ConventionOverConfiguration": "Convention Over Configuration",
"ConventionOverConfigurationExplanation": "ABP implements common application conventions by default with minimal or zero configuration.",
"ConventionOverConfigurationExplanationList1": "Auto registers known services to dependency injection.",
@ -1886,6 +1886,11 @@
"FaqIyzicoPaymentIssuesExplanation5": "<strong>Credit/Debit Cards</strong>: Visa, MasterCard, American Express, Discover, Diners Club, JCB",
"FaqIyzicoPaymentIssuesExplanation6": "<strong>Digital Wallets</strong>: PayPal, AliPay, WebMoney",
"FaqIyzicoPaymentIssuesExplanation7": "Alternatively, you can send the license amount directly via bank wire transfer. For our bank account details, please visit: <a href='https://volosoft.com/bank-account'>Bank Account Information</a> (use USD currency).",
"FaqIyzicoPaymentIssuesExplanation8": "ABP website doesn't save or process your credit card. We use payment gateways for this and the entire transaction is handled by payment gateways. We have no authority to interfere with the payment process or fix the payment steps. If you have further questions or need additional support, feel free to contact us at <a href='https://abp.io/contact'>abp.io/contact</a>."
"FaqIyzicoPaymentIssuesExplanation8": "ABP website doesn't save or process your credit card. We use payment gateways for this and the entire transaction is handled by payment gateways. We have no authority to interfere with the payment process or fix the payment steps. If you have further questions or need additional support, feel free to contact us at <a href='https://abp.io/contact'>abp.io/contact</a>.",
"BiographyContainsUrlValidationMessage": "Biography cannot contain URL.",
"CreatePostSEOTitleInfo": "SEO URL is a clean, readable, keyword-rich URL that helps both users and search engines understand what this post is about. Keep it short with 60 characters. SEO titles over 60 characters will be truncated. Use hyphens (-) to separate words (not underscores). Include target keywords near the start. Lowercase only. No stop words unless needed (e.g: \"and\", \"or\", \"the\").",
"SEOTitle": "SEO URL",
"InvalidYouTubeUrl": "The URL you entered is not a valid YouTube video link. Please make sure it points to a specific video and try again.",
"SelectAnOption": "Select an option"
}
}

3
common.props

@ -1,8 +1,7 @@
<Project>
<PropertyGroup>
<LangVersion>latest</LangVersion>
<Version>9.2.4</Version>
<LeptonXVersion>4.2.4</LeptonXVersion>
<LeptonXVersion>4.3.1</LeptonXVersion>
<NoWarn>$(NoWarn);CS1591;CS0436</NoWarn>
<PackageIconUrl>https://abp.io/assets/abp_nupkg.png</PackageIconUrl>
<PackageProjectUrl>https://abp.io/</PackageProjectUrl>

2
docs/en/Blog-Posts/2022-03-08 v5_2_Preview/POST.md

@ -187,7 +187,7 @@ We organized the 3rd live [ABP Community Talks](https://community.abp.io/events)
* [Enis Necipoğlu](https://twitter.com/EnisNecipoglu) has also created [an article](https://community.abp.io/posts/using-autofilterer-with-abp-framework-uuqv81jm) to demonstrate how to use his own open source [AutoFilterer](https://github.com/enisn/AutoFilterer) library with the ABP Framework.
* [Jonathan Potts](https://github.com/jonathanpotts) has created his first ABP Community article that shows how to use Bootswatch themes with the ABP Framework. [See it here](https://community.abp.io/posts/customizing-the-abp-basic-theme-with-bootswatch-4luoqzr0).
Thanks to all the contributors. It is appreciated if you want to submit your post and share your knowledge with the ABP community: https://community.abp.io/posts/submit
Thanks to all the contributors. It is appreciated if you want to submit your post and share your knowledge with the ABP community: https://community.abp.io/posts/create
## Conclusion

2
docs/en/Blog-Posts/2024-02-16 v8_1_Preview/POST.md

@ -230,7 +230,7 @@ There are exciting articles contributed by the ABP community as always. I will h
* [A Best Practice for Designing Interfaces in .NET C#](https://community.abp.io/posts/a-best-practice-for-designing-interfaces-in-.net-c-9xqc4h8d)
* [Invariance, Covariance, and Contravariance in .NET C#](https://community.abp.io/posts/invariance-covariance-and-contravariance-in-.net-c-9blmuhme)
Thanks to the ABP Community for all the content they have published. You can also [post your ABP-related (text or video) content](https://community.abp.io/posts/submit) to the ABP Community.
Thanks to the ABP Community for all the content they have published. You can also [post your ABP-related (text or video) content](https://community.abp.io/posts/create) to the ABP Community.
## Conclusion

2
docs/en/Blog-Posts/2024-05-21 v8_2_Release/POST.md

@ -260,7 +260,7 @@ There are exciting articles contributed by the ABP community as always. I will h
* [Using FluentValidation with ABP Framework](https://community.abp.io/posts/using-fluentvalidation-with-abp-framework-2cxuwl70) by [Enes Döner](https://community.abp.io/members/Enes)
* [Using Blob Storage with ABP](https://community.abp.io/posts/using-blob-storage-with-abp-framework-jygtmhn4) by [Emre Kendirli](https://community.abp.io/members/emrekenderli)
Thanks to the ABP Community for all the content they have published. You can also [post your ABP-related (text or video) content](https://community.abp.io/posts/submit) to the ABP Community.
Thanks to the ABP Community for all the content they have published. You can also [post your ABP-related (text or video) content](https://community.abp.io/posts/create) to the ABP Community.
## Conclusion

2
docs/en/Blog-Posts/2024-07-31 v8_3_Preview/post.md

@ -168,7 +168,7 @@ There are exciting articles contributed by the ABP community as always. I will h
* [How to use .NET Aspire with ABP framework](https://abp.io/community/articles/how-to-use-.net-aspire-with-abp-framework-h29km4kk) by [Berkan Şaşmaz](https://twitter.com/berkansasmazz)
* [Exciting New Feature in ABP.IO CMS Kit: Marked Item System](https://abp.io/community/articles/exciting-new-feature-in-abp.io-cms-kit-marked-item-system.-2hvpq0me) by [Suhaib Mousa](https://abp.io/community/members/suhaibmousa032@gmail.com)
Thanks to the ABP Community for all the content they have published. You can also [post your ABP-related (text or video) content](https://abp.io/community/posts/submit) to the ABP Community.
Thanks to the ABP Community for all the content they have published. You can also [post your ABP-related (text or video) content](https://abp.io/community/posts/create) to the ABP Community.
## Conclusion

2
docs/en/Blog-Posts/2024-09-06 v8_3_Release_Stable/POST.md

@ -70,7 +70,7 @@ As always, exciting articles have been contributed by the ABP community. I will
* [Introducing the Google Cloud Storage BLOB Provider](https://abp.io/community/articles/introducing-the-google-cloud-storage-blob-provider-yrt6azc0) by [Engincan Veske](https://twitter.com/EngincanVeske)
* [Switching Between Organization Units](https://abp.io/community/articles/switching-between-organization-units-i5tokpzt) by [Liming Ma](https://github.com/maliming)
Thanks to the ABP Community for all the content they have published. You can also [post your ABP-related (text or video) content](https://abp.io/community/posts/submit) to the ABP Community.
Thanks to the ABP Community for all the content they have published. You can also [post your ABP-related (text or video) content](https://abp.io/community/posts/create) to the ABP Community.
## About the Next Version

2
docs/en/Blog-Posts/2024-10-23 v9_0_Preview/POST.md

@ -214,7 +214,7 @@ There are exciting articles contributed by the ABP community as always. I will h
* [ABP-Powered Web App with Inertia.js, React, and Vite](https://abp.io/community/articles/abppowered-web-app-with-inertia.js-react-and-vite-j7cccvad) by [Anto Subash](https://antosubash.com/)
* [Multi-Tenancy Support in Angular Apps with ABP.IO](https://abp.io/community/articles/multitenancy-support-in-angular-apps-with-abp.io-lw9l36c5) by [HeadChannel Team](https://headchannel.co.uk/)
Thanks to the ABP Community for all the content they have published. You can also [post your ABP-related (text or video) content](https://abp.io/community/posts/submit) to the ABP Community.
Thanks to the ABP Community for all the content they have published. You can also [post your ABP-related (text or video) content](https://abp.io/community/posts/create) to the ABP Community.
## Conclusion

2
docs/en/Blog-Posts/2024-11-19 v9_0_Release_Stable/post.md

@ -78,7 +78,7 @@ In addition to [the articles to highlight .NET 9.0 features written by our team]
* [How to create your Own AI Bot on WhatsApp Using an ABP.io Template](https://abp.io/community/articles/how-to-create-your-own-ai-bot-on-whatsapp-using-the-abp-framework-c6jgvt9c) by [Michael Kokula](https://abp.io/community/members/Michal_Kokula)
* [ABP Now Supports .NET 9](https://abp.io/community/articles/abp-now-supports-.net-9-zpkznc4f) by [Alper Ebiçoğlu](https://x.com/alperebicoglu)
Thanks to the ABP Community for all the content they have published. You can also [post your ABP related (text or video) content](https://abp.io/community/posts/submit) to the ABP Community.
Thanks to the ABP Community for all the content they have published. You can also [post your ABP related (text or video) content](https://abp.io/community/posts/create) to the ABP Community.
### ABP Community Talks 2024.7: What’s New with .NET 9 & ABP 9?

2
docs/en/Blog-Posts/2025-01-21 v9_1_Preview/POST.md

@ -138,7 +138,7 @@ There are exciting articles contributed by the ABP community as always. I will h
* [The new Unit Test structure in ABP application](https://abp.io/community/articles/the-new-unit-test-structure-in-abp-application-4vvvp2oy) by [Liming Ma](https://github.com/maliming)
* [How to Use OpenAI API with ABP Framework](https://abp.io/community/articles/how-to-use-openai-api-with-abp-framework-rsfvihla) by [Berkan Şaşmaz](https://github.com/berkansasmaz)
Thanks to the ABP Community for all the content they have published. You can also [post your ABP-related (text or video) content](https://abp.io/community/posts/submit) to the ABP Community.
Thanks to the ABP Community for all the content they have published. You can also [post your ABP-related (text or video) content](https://abp.io/community/posts/create) to the ABP Community.
## Conclusion

2
docs/en/Blog-Posts/2025-03-07 v9_1_Release_Stable/POST.md

@ -67,7 +67,7 @@ As always, exciting articles have been contributed by the ABP community. I will
* [Containerization: Blazor WASM + JWT Web API => Docker](https://abp.io/community/articles/containerization-blazor-wasm-jwt-web-api-docker-i3eirlsf) by [Bart Van Hoey](https://abp.io/community/members/bartvanhoey)
* [Configuring Post-Logout Redirect URI in ABP Based Blazor Applications with OpenIddict](https://abp.io/community/articles/configuring-postlogout-redirect-uri-in-abp-based-blazor-applications-with-openiddict-1t84suxg) by [Engincan Veske](https://github.com/EngincanV)
Thanks to the ABP Community for all the content they have published. You can also [post your ABP related (text or video) content](https://abp.io/community/posts/submit) to the ABP Community.
Thanks to the ABP Community for all the content they have published. You can also [post your ABP related (text or video) content](https://abp.io/community/posts/create) to the ABP Community.
### ABP Community Talks 2025.2: Real World Problems and Solutions with AI

195
docs/en/Blog-Posts/2025-03-27 v9_2_Preview/POST.md

@ -0,0 +1,195 @@
# ABP Platform 9.2 RC Has Been Released
We are happy to release [ABP](https://abp.io) version **9.2 RC** (Release Candidate). This blog post introduces the new features and important changes in this new version.
Try this version and provide feedback for a more stable version of ABP v9.2! Thanks to you in advance.
## Get Started with the 9.2 RC
You can check the [Get Started page](https://abp.io/get-started) to see how to get started with ABP. You can either download [ABP Studio](https://abp.io/get-started#abp-studio-tab) (**recommended**, if you prefer a user-friendly GUI application - desktop application) or use the [ABP CLI](https://abp.io/docs/latest/cli).
By default, ABP Studio uses stable versions to create solutions. Therefore, if you want to create a solution with a preview version, first you need to create a solution and then switch your solution to the preview version from the ABP Studio UI:
![studio-switch-to-preview.png](studio-switch-to-preview.png)
## Migration Guide
There are a few breaking changes in this version that may affect your application. Please read the migration guide carefully, if you are upgrading from v9.x or earlier: [ABP Version 9.2 Migration Guide](https://abp.io/docs/9.2/release-info/migration-guides/abp-9-2)
## What's New with ABP v9.2?
In this section, I will introduce some major features released in this version.
Here is a brief list of titles explained in the next sections:
* Added `ApplicationName` Property to Isolate Background Jobs & Background Workers
* Docs Module: Added "Alternative Words" to Filter Items
* Introducing the Bunny BLOB Storage Provider
* Upgraded `MongoDB.Driver` to v3.1.0
* Using Timezone Settings to Display Datetime
* Identity Pro Module: Require Email Verification to Register
* Switching users during OAuth login
### Added ApplicationName Property to Isolate Background Jobs & Background Workers
ABP's [Background Jobs Module](https://abp.io/docs/latest/modules/background-jobs) has been enhanced with a new `ApplicationName` property that helps isolate jobs and workers across multiple applications sharing the same database.
Previously, when different applications used the BackgroundJobs module and shared a database, an application might encounter jobs that didn't belong to it. This would lead to failed processing attempts and marking jobs as `IsAbandoned = true` with a "Undefined background job for the job name" error, preventing these jobs from ever being executed.
With the new `ApplicationName` property, applications now properly filter jobs at the repository level, ensuring each application only processes job types it recognizes. This prevents the incorrect abandonment of jobs and ensures consistent behavior in multi-application scenarios.
You can set `ApplicationName` of `AbpBackgroundJobWorkerOptions` to your application name to isolate jobs and workers across multiple applications sharing the same database:
```csharp
public override void PreConfigureServices(ServiceConfigurationContext context)
{
PreConfigure<AbpBackgroundJobWorkerOptions>(options =>
{
options.ApplicationName = context.Services.GetApplicationName()!;
});
}
```
> For more information, please refer to the [Background Jobs Module](https://abp.io/docs/latest/modules/background-jobs) documentation and the [PR](https://github.com/abpframework/abp/pull/22169) that added this feature.
### Docs Module: Added "Alternative Words" to Filter Items
[ABP's Docs Module](https://abp.io/docs/9.2/modules/docs) now supports "alternative words" to enhance the search functionality when filtering documentation items. This feature addresses a common user experience issue where users might search using terminology different from what appears in the documentation.
For example, when a user searches for "Error" in the documentation, they may actually be looking for content related to "Exception Handling." With this new feature, documentation items can now be configured with alternative keywords that are considered during filtering.
The implementation allows defining optional "keywords" for items in the navigation tree. For example:
```json
{
"text": "Exception Handling",
"path": "framework/fundamentals/exception-handling.md",
"keywords": ["Error", "Another Value"]
}
```
When users search or filter content, the system now considers both the original text and these alternative keywords, improving discoverability of relevant documentation sections. This enhancement makes the documentation more accessible and user-friendly, especially for newcomers who might not be familiar with the exact terminology used in the ABP documentation.
### Introducing the Bunny BLOB Storage Provider
ABP v9.2 RC introduces a new BLOB storage provider for [Bunny Storage](https://bunny.net/storage/), a global edge storage solution. This addition expands ABP's BLOB Storage options beyond the existing providers like Azure, AWS, and others.
The [Bunny BLOB Storage Provider](https://abp.io/docs/9.2/framework/infrastructure/blob-storing/bunny) allows ABP applications to seamlessly integrate with Bunny's CDN-backed storage service, which offers high-performance content delivery through its global network.
To use this new provider, you'll need to:
* Run `abp add-package Volo.Abp.BlobStoring.Bunny` command.
* And then configure the provider in your module's `ConfigureServices` method:
```csharp
Configure<AbpBlobStoringOptions>(options =>
{
options.Containers.ConfigureDefault(container =>
{
container.UseBunny(bunny =>
{
bunny.StorageZoneName = "your-storage-zone";
bunny.ApiKey = "your-api-key";
bunny.Region = "your-region"; // de, ny, la, sg, or sy
});
});
});
```
This integration provides ABP applications with an efficient and globally distributed storage solution, particularly beneficial for applications requiring fast content delivery across different geographical regions. To use this new provider and make the related configurations, you can refer to the [Bunny Storage Provider](https://abp.io/docs/9.2/framework/infrastructure/blob-storing/bunny) documentation always.
> This new BLOB Storage provider is contributed by [@suhaib-mousa](https://github.com/suhaib-mousa). Thanks to him for his contribution!
> We are always happy to see the community contributing to the ABP Framework and encouraging them to contribute more.
### Upgraded `MongoDB.Driver` to `v3.1.0`
ABP v9.2 RC includes an upgrade to `MongoDB.Driver` version `3.1.0`. This significant version bump from previous releases brings several improvements and new features that benefit ABP applications using MongoDB as their database.
The upgrade provides:
* Async/Await Support: Write non-blocking, asynchronous code easily.
* Fluent API: Build queries and updates intuitively with Builders.
* LINQ Support: Use LINQ for querying MongoDB collections.
* and more ...
> For more information, please refer to the [MongoDB.Driver release notes](https://github.com/mongodb/mongo-csharp-driver/releases/tag/v3.1.0).
We have prepared a [migration guide](https://abp.io/docs/9.2/release-info/migration-guides/MongoDB-Driver-2-to-3) for this upgrade. Please refer to it to learn more about the changes and how to migrate your application.
### Using Timezone Settings to Display Datetime
A significant enhancement in ABP v9.2 is the ability to use timezone settings to display `DateTime` values according to the user's or application's configured timezone. Introduced in `v9.2.0-rc.2`, this feature addresses the common challenge of ensuring users see accurate time information, regardless of their geographical location.
Previously, `DateTime` values were often shown in the server's timezone or in UTC, which could cause confusion for users in different timezones. With this new feature, ABP applications can now respect the configured timezone and automatically convert and display datetime values accordingly.
**Before setting the timezone:**
Consider a scenario where you have a list of books, and the `CreationTime` property is displayed without any timezone consideration. It may appear in the server's default timezone:
![before.png](before.png)
*(Screenshot of a Books page showing the CreationTime in a default timezone.)*
**Setting the timezone:**
To set the timezone, start by configuring the `AbpClockOptions` in your module's `ConfigureServices` method:
```csharp
Configure<AbpClockOptions>(options =>
{
options.Kind = DateTimeKind.Utc;
});
```
> By setting the `Kind` property of `AbpClockOptions` to `DateTimeKind.Utc`, ABP will normalize all datetime values. Times stored in the database and returned to the frontend will be in UTC. Additionally, the `SupportsMultipleTimezone` property of the `IClock` service will be **true**, and you’ll be able to configure the timezone from the UI under the _Settings_ page.
After setting the `Kind` property, you can run your application and configure the timezone from the UI under the _Settings_ page. For example, set the timezone to "Asia/Tokyo (+09:00)":
![configure-timezone.png](configure-timezone.png)
*(Screenshot showing the configuration setting for Abp.Timing.TimeZone, set to "Asia/Tokyo (+09:00)".)*
> ABP provides the `Abp.Timing.TimeZone` setting, which allows you to configure the desired timezone at the application, tenant, or user level and this setting can be configured in the UI under the _Settings_ page, inside of the _Time Zone_ tab.
**After setting the timezone:**
Once the timezone is configured, ABP automatically handles the conversion and display of `DateTime` values. The `CreationTime` on the _Books_ page will now be shown in the **"Asia/Tokyo"** timezone.
![after.png](after.png)
*(Screenshot of the _Books_ page after setting the timezone, showing the `CreationTime` adjusted to the "Asia/Tokyo" timezone.)*
This feature utilizes the `IClock` service, which provides methods like `ConvertToUserTime` and `ConvertToUtc` to facilitate timezone conversions. By configuring the `Abp.Timing.TimeZone` setting, developers can ensure a consistent and user-friendly experience across applications with a global user base.
> For a more detailed guide on implementing and using this feature, refer to the article: [Developing a Multi-Timezone Application Using the ABP Framework](https://abp.io/community/articles/developing-a-multitimezone-application-using-the-abp-framework-zk7fnrdq). It offers step-by-step instructions and examples for handling multi-timezone scenarios in ABP applications.
### Identity Pro Module: Require Email Verification to Register
[ABP Identity Pro module](https://abp.io/docs/9.2/modules/identity-pro) has been enhanced with a new feature that allows administrators to require email verification during the registration process. This security improvement ensures that users must verify their email addresses before their registration is considered complete. Enabling this feature is especially important for applications that want to prevent spam registrations.
Administrators can enable or disable this feature through the **Identity management -> Identity Verification (tab)** settings page (by checking the `Enforce email verification to register` checkbox):
![require-email-verification.png](./require-email-verification-for-register.png)
### Switching users during OAuth login
If you have an OAuth/Auth Server application using the [ABP Account Pro module](https://abp.io/docs/9.2/modules/account-pro) , you can pass the `prompt=select_account` parameter to force the user to select an account.
![select-account.png](./select-account.png)
For more information, please refer to the [Switching users during OAuth login](https://abp.io/docs/9.2/modules/account-pro#switching-users-during-oauth-login) documentation.
### New ABP Community Articles
There are exciting articles contributed by the ABP community as always. I will highlight some of them here:
* [Implementing CQRS with MediatR in ABP](https://abp.io/community/articles/implementing-cqrs-with-mediatr-in-abp-xiqz2iio) by [Engincan Veske](https://github.com/EngincanV)
* [Using Vue Components in a Razor Pages ABP Application](https://abp.io/community/articles/using-vue-components-in-a-razor-pages-abp-application-z3jr07tv) by [Enis Necipoglu](https://github.com/enisn)
* [Using ABP's AWS Blob Storing Provider with DigitalOcean Spaces](https://abp.io/community/articles/using-abps-aws-blob-storing-provider-with-digitalocean-spaces-7hlyb25g) by [Suhaib Mousa](https://abp.io/community/members/suhaib-mousa)
* [Video Post: Using Vue Components in a Razor Pages ABP Application](https://abp.io/community/articles/using-vue-components-in-a-razor-pages-abp-application-z3jr07tv) by [Enis Necipoglu](https://github.com/enisn)
* [Understanding the Embedded Files in ABP Framework](https://abp.io/community/articles/understanding-the-embedded-files-in-abp-framework-nsrp8aa9) by [Liming Ma](https://github.com/maliming)
* [How to Change the CurrentUser in ABP?](https://abp.io/community/articles/how-to-change-the-currentuser-in-abp-i3uu1m7g) by [Engincan Veske](https://github.com/EngincanV)
Thanks to the ABP Community for all the content they have published. You can also [post your ABP-related (text or video) content](https://abp.io/community/posts/create) to the ABP Community.
## Conclusion
This version comes with some new features and a lot of enhancements to the existing features. You can see the [Road Map](https://abp.io/docs/9.2/release-info/road-map) documentation to learn about the release schedule and planned features for the next releases. Please try ABP v9.2 RC and provide feedback to help us release a more stable version.
Thanks for being a part of this community!

BIN
docs/en/Blog-Posts/2025-03-27 v9_2_Preview/after.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

BIN
docs/en/Blog-Posts/2025-03-27 v9_2_Preview/before.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

BIN
docs/en/Blog-Posts/2025-03-27 v9_2_Preview/configure-timezone.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

BIN
docs/en/Blog-Posts/2025-03-27 v9_2_Preview/cover-image.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 492 KiB

BIN
docs/en/Blog-Posts/2025-03-27 v9_2_Preview/require-email-verification-for-register.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 170 KiB

BIN
docs/en/Blog-Posts/2025-03-27 v9_2_Preview/select-account.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 727 KiB

BIN
docs/en/Blog-Posts/2025-03-27 v9_2_Preview/studio-switch-to-preview.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

86
docs/en/Blog-Posts/2025-06-02 v9_2_Release_Stable/POST.md

@ -0,0 +1,86 @@
# ABP.IO Platform 9.2 Final Has Been Released!
We are glad to announce that [ABP](https://abp.io/) 9.2 stable version has been released today.
## What's New With Version 9.2?
All the new features were explained in detail in the [9.2 RC Announcement Post](https://abp.io/community/articles/abp-platform-9.2-rc-has-been-released-jpq072nh), so there is no need to review them again. You can check it out for more details.
## Getting Started with 9.2
### Creating New Solutions
You can check the [Get Started page](https://abp.io/get-started) to see how to get started with ABP. You can either download [ABP Studio](https://abp.io/get-started#abp-studio-tab) (**recommended**, if you prefer a user-friendly GUI application - desktop application) or use the [ABP CLI](https://abp.io/docs/latest/cli) to create new solutions.
### How to Upgrade an Existing Solution
You can upgrade your existing solutions with either ABP Studio or ABP CLI. In the following sections, both approaches are explained:
### Upgrading via ABP Studio
If you are already using the ABP Studio, you can upgrade it to the latest version. ABP Studio periodically checks for updates in the background, and when a new version of ABP Studio is available, you will be notified through a modal. Then, you can update it by confirming the opened modal. See [the documentation](https://abp.io/docs/latest/studio/installation#upgrading) for more info.
After upgrading the ABP Studio, then you can open your solution in the application, and simply click the **Upgrade ABP Packages** action button to instantly upgrade your solution:
![](upgrade-abp-packages.png)
### Upgrading via ABP CLI
Alternatively, you can upgrade your existing solution via ABP CLI. First, you need to install the ABP CLI or upgrade it to the latest version.
If you haven't installed it yet, you can run the following command:
```bash
dotnet tool install -g Volo.Abp.Studio.Cli
```
Or to update the existing CLI, you can run the following command:
```bash
dotnet tool update -g Volo.Abp.Studio.Cli
```
After installing/updating the ABP CLI, you can use the [`update` command](https://abp.io/docs/latest/CLI#update) to update all the ABP related NuGet and NPM packages in your solution as follows:
```bash
abp update
```
You can run this command in the root folder of your solution to update all ABP related packages.
## Migration Guides
There are a few breaking changes in this version that may affect your application. Please read the migration guide carefully, if you are upgrading from v9.x: [ABP Version 9.2 Migration Guide](https://abp.io/docs/9.2/release-info/migration-guides/abp-9-2)
## Community News
### New ABP Community Articles
As always, exciting articles have been contributed by the ABP community. I will highlight some of them here:
* [Liming Ma](https://github.com/maliming) has published 3 new articles:
* [Integrating .NET AI Chat Template with ABP Framework](https://abp.io/community/articles/integrating-.net-ai-chat-template-with-abp-framework-qavb5p2j)
* [Resolving Tenant from Route in ABP Framework](https://abp.io/community/articles/resolving-tenant-from-route-in-abp-framework-ah7oru97)
* [Common Errors in JWT Bearer Authentication](https://abp.io/community/articles/common-errors-in-jwt-bearer-authentication-4u3wrbs5)
* [Engincan Veske](https://engincanveske.substack.com/) has published 3 new articles:
* [Understanding HttpApi.Client Project & Remote Services in an ABP Based Application](https://abp.io/community/articles/http-api-client-and-remote-services-in-abp-based-application-xkknsp6m)
* [Using Elsa 3 with the ABP Framework: A Comprehensive Guide](https://abp.io/community/articles/using-elsa-3-workflow-with-abp-framework-usqk8afg)
* [Implementing Custom Tenant Logo Feature in ABP Framework: A Step-by-Step Guide](https://abp.io/community/articles/implementing-custom-tenant-logo-feature-in-abp-framework-a-stepbystep-guide-sba96ac9)
* [Berkan Şaşmaz](https://berkansasmaz.com/) has published 2 new articles:
* [Understanding the Domain and Application Layers in ABP Framework](https://abp.io/community/articles/understanding-the-domain-and-application-layers-in-abp-1fipc4x4)
* [How Do We Maintain Code Quality and Technical Debt in Our .NET Codebase?](https://abp.io/community/articles/how-do-we-maintain-code-quality-and-technical-debt-in-our-.net-codebase-z7glpya1)
* [Enis Necipoğlu](https://github.com/enisn) has published 2 new articles:
* [White Labeling in ABP Framework](https://abp.io/community/articles/white-labeling-in-abp-framework-5trwmrfm) by [Enis Necipoğlu](https://github.com/enisn)
* [You do it wrong! Customizing ABP Login Page Correctly](https://abp.io/community/articles/you-do-it-wrong-customizing-abp-login-page-correctly-bna7wzt5)
* [Ariful Islam](https://abp.io/community/members/arif) has published 2 new articles:
* [Multi-Workspace Management for ABP Applications](https://abp.io/community/articles/multiworkspace-management-for-abp-applications-eghgty3j)
* [Using Semantic Kernel in the ABP Framework](https://abp.io/community/articles/using-semantic-kernel-in-the-abp-framework-qo5cnuzs)
* [Guide to Add Custom Modules in ABP.IO App](https://abp.io/community/articles/guide-to-add-custom-modules-in-abp.io-app-sttetffa) by [Harsh Gupta](https://abp.io/community/members/harshgupta)
* [Debugging NuGet Packages in ABP.IO: A Complete Guide](https://abp.io/community/articles/debugging-nuget-packages-in-abp.io-a-complete-guide-h13y2033) by [Suhaib Mousa](https://suhaibmousa.com/)
* [Using Microsoft AI Extensions Library and OpenAI to Summarize User Comments](https://abp.io/community/articles/using-microsoft-ai-extensions-library-and-openai-to-summarize-user-comments-gj1lusg7) by [Halil Ibrahim Kalkan](https://twitter.com/hibrahimkalkan)
Thanks to the ABP Community for all the content they have published. You can also [post your ABP related (text or video) content](https://abp.io/community/posts/create) to the ABP Community.
## About the Next Version
The next feature version will be 9.3. You can follow the [release planning here](https://github.com/abpframework/abp/milestones). Please [submit an issue](https://github.com/abpframework/abp/issues/new) if you have any problems with this version.

BIN
docs/en/Blog-Posts/2025-06-02 v9_2_Release_Stable/cover-image.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 492 KiB

BIN
docs/en/Blog-Posts/2025-06-02 v9_2_Release_Stable/upgrade-abp-packages.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

97
docs/en/Blog-Posts/2025-06-10-Announcing-ABP-Studio-1.0-Stable-Release/POST.md

@ -0,0 +1,97 @@
# Announcing ABP Studio 1.0 General Availability 🚀
It's the moment you've been waiting for! We are thrilled to announce the stable release of ABP Studio v1.0. This milestone marks a significant step forward in our mission to provide a first-class, integrated development environment for ABP developers. Paired with the recently released [ABP v9.2](https://abp.io/community/articles/announcing-abp-9-2-stable-release-061qmtzb), ABP Studio v1.0 brings new features and improvements that will make your development work faster and more efficient.
For the past several months, our core ABP team has been hard at work, focusing on the features that matter most to you, our community of developers. This release is the peak of that effort, bringing a host of improvements and new capabilities to the forefront. Let's dive in and explore what's new in ABP Studio v1.0.
## What's New with ABP Studio v1.0?
ABP Studio v1.0 is all about enhancing your development experience, from project creation to deployment. Here, we'll walk you through some of the latest features we've implemented, along with other key enhancements that make this release truly special.
### ❤️ Solution Runner with Ready/Health Checks
ABP Studio's Solution Runner now provides visual health monitoring that makes tracking your applications' status easily. When you start an application, a spinner indicates it's "starting", then in the *Overall* tab, you can see the application's health (✅ for healthy, ⚠️ for unhealthy) that displays real-time health status:
![Health Checks](health-checks.png)
With [pre-configured health checks](https://abp.io/docs/9.2/solution-templates/layered-web-application/health-check-configuration) in ABP solution templates including database connectivity tests, you get instant feedback on your applications' health.
When health check UI is configured, you can access comprehensive health dashboards with a dedicated "Browse Health UI" command or see the last health response from the "Show Latest Health Check Response" command:
![SaaS Health Check](saas-health-check.png)
When you restart applications that are open in your browser, ABP Studio automatically refreshes the pages for you.
### 🎨 Theme Style Selection on Project Creation
When creating a new solution, you can now choose your theme, theme style, and layout right from the project creation wizard instead of having to configure these settings later. ABP Studio lets you pick from [ABP's officially provided themes including Basic, LeptonX Lite, and LeptonX](https://abp.io/docs/latest/ui-themes).
![Theme Style Selection LeptonX](theme-style-selection-leptonx.png)
If you select Basic or LeptonX Lite themes, only the theme will be changed. However, if you select the LeptonX theme, you'll get additional options to fine-tune your setup:
- **Theme Style Configuration** - Pick from **System, Light, Dim, or Dark** styles to match how you like your development environment
- **Layout Options** - **Sidebar menu** / **Top menu**
### 📦 "Container" Application Type for Solution Runner
ABP Studio v1.0 introduces a dedicated "Container" application type that gives you better control over your Docker containers directly from the Solution Runner. Instead of managing all your containers through PowerShell scripts or running them all together, you can now see and control each container individually in the Solution Runner panel.
![Container Application Type](containers-type.png)
This new feature replaces the previous _Infrastructure_ folder approach with a cleaner, more intuitive container section. You can now:
- **Start and stop containers individually** - No more starting all containers at once when you only need specific services
- **Monitor container status** - See which containers are running, stopped, or have issues directly in the UI
- **Manage container dependencies** - Control the order and timing of container startup based on your application needs
Whether you're working with databases, message brokers, or other containerized services, the new Container application type makes it much easier to manage your development environment. This is especially useful for microservice architectures where you might want to run only specific services during development or testing.
### ⚙️ Handle Multiple DbContexts When Adding/Removing/Applying Migrations
When working with ABP solutions that have multiple DbContexts (such as when using the separate tenant database option), ABP Studio now intelligently prompts you to select the appropriate DbContext for migration operations. This enhancement ensures you're always working with the correct database context and helps prevent common mistakes when managing multiple databases.
![EF Core Migration Context Selection](new-migration-added.gif)
The context selection dialog appears automatically when you perform any of these Entity Framework operations:
- **Adding a new migration** - Choose which DbContext the new migration should target
- **Removing an existing migration** - Select the DbContext from which to remove the migration
- **Updating the database** - Specify which database context should be updated
## Get Started with ABP Studio v1.0 Today!
ABP Studio v1.0 is built on the solid foundation of the [latest version of ABP Framework, which is v9.2](https://abp.io/community/articles/announcing-abp-9-2-stable-release-061qmtzb). This means that when you create a new project with ABP Studio, you're getting all the latest features, performance improvements, and bug fixes that come with v9.2. This includes updates to dependencies, enhancements to the core framework, and improvements to application modules.
We are incredibly excited for you to get your hands on ABP Studio v1.0. We believe these new features will make a real difference in your day-to-day development workflow.
### ⬇️ Download ABP Studio 1.0
Ready to get started? You can download the stable v1.0 release right now from the official ABP Studio website: **[https://abp.io/studio](https://abp.io/studio)**
![ABP Studio 1.0 Download](abp-studio-download.png)
If you are an existing ABP Studio user, it's even easier. You don't need to download the installer again. Simply launch ABP Studio, and it will prompt you to update to the latest version directly from the UI.
> Alternatively, you can click to the *Help -> Check for Updates* context menu item to check for updates and install the latest version:
>
> ![ABP Studio 1.0 Check for Updates](abp-studio-check-for-updates.png)
### 🔮 What's Next?
ABP Studio v1.0 represents just the beginning of our journey. We're committed to continuously evolving the platform, adding features that directly address real-world development challenges and enhance your workflow. Our goal is to make ABP Studio the go-to development environment for .NET and ABP Framework developers.
We will keep releasing new versions with exciting features based on our roadmap and your valuable feedback. To give you a sneak peek into what's planned for future releases, you can expect to see:
- **Environment Variable Management:** A dedicated UI to easily manage environment variables for your solutions.
- **OpenTelemetry Integration:** We'll be integrating OpenTelemetry support directly into the startup templates, making distributed tracing and observability a seamless part of your application from day one.
- **LeptonX Theme Builder**: Allowing users to determine styling, colour palette and easily override their project's theme styles.
- **Monitor dashboards of the tools used in the solution (e.g. Kubernetes, Redis, Grafana, etc...)**
- **Pre-configured .NET Aspire for the Microservice Startup Template**
- **and more...**
We are incredibly excited about the future of ABP Studio and can't wait to share the next set of features with you. Your comments and suggestions are invaluable to us. If you have any feedback, please drop a comment below.
Thank you for being part of our community and happy coding!
**The Volosoft Team**

BIN
docs/en/Blog-Posts/2025-06-10-Announcing-ABP-Studio-1.0-Stable-Release/abp-studio-check-for-updates.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

BIN
docs/en/Blog-Posts/2025-06-10-Announcing-ABP-Studio-1.0-Stable-Release/abp-studio-download.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 282 KiB

BIN
docs/en/Blog-Posts/2025-06-10-Announcing-ABP-Studio-1.0-Stable-Release/containers-type.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

BIN
docs/en/Blog-Posts/2025-06-10-Announcing-ABP-Studio-1.0-Stable-Release/cover-image.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 455 KiB

BIN
docs/en/Blog-Posts/2025-06-10-Announcing-ABP-Studio-1.0-Stable-Release/health-checks.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 207 KiB

BIN
docs/en/Blog-Posts/2025-06-10-Announcing-ABP-Studio-1.0-Stable-Release/new-migration-added.gif

Binary file not shown.

After

Width:  |  Height:  |  Size: 913 KiB

BIN
docs/en/Blog-Posts/2025-06-10-Announcing-ABP-Studio-1.0-Stable-Release/saas-health-check.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

BIN
docs/en/Blog-Posts/2025-06-10-Announcing-ABP-Studio-1.0-Stable-Release/theme-style-selection-leptonx.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 107 KiB

6
docs/en/Community-Articles/2020-09-09-Replacing-Email-Template-and-Sending-Emails/POST.md

@ -470,6 +470,12 @@ namespace TemplateReplace
* I highly recommend you to [check it out](https://commercial.abp.io/modules/Volo.TextTemplateManagement).
---
> 🛠 Liked this post? I now share all my content on Substack — real-world .NET, AI, and scalable software design.
> 👉 Subscribe here → engincanveske.substack.com
> 🎥 Also, check out my YouTube channel for hands-on demos and deep dives: https://www.youtube.com/@engincanv
---
## References
* [Text Templating](https://docs.abp.io/en/abp/latest/Text-Templating)

12
docs/en/Community-Articles/2020-12-10-How-to-Integrate-the-Telerik-Blazor-Component/POST.md

@ -4,6 +4,12 @@
Hi, in this step by step article, we will see how we can integrate the Telerik Blazor Components to our Blazor UI.
---
> 🛠 Liked this post? I now share all my content on Substack — real-world .NET, AI, and scalable software design.
> 👉 Subscribe here → engincanveske.substack.com
> 🎥 Also, check out my YouTube channel for hands-on demos and deep dives: https://www.youtube.com/@engincanv
---
## Creating the Solution
> ABP Framework offers startup templates to get into business faster.
@ -532,6 +538,12 @@ namespace TelerikComponents.Blazor.Pages
![final-result](./final-result.jpg)
---
> 🛠 Liked this post? I now share all my content on Substack — real-world .NET, AI, and scalable software design.
> 👉 Subscribe here → engincanveske.substack.com
> 🎥 Also, check out my YouTube channel for hands-on demos and deep dives: https://www.youtube.com/@engincanv
---
## Conclusion
In this article, I've tried to explain how we can integrate [Telerik Blazor Component](https://www.telerik.com/blazor-ui) to our Blazor UI. ABP Framework designed as modular, so that it can work with any UI library/framework.

16
docs/en/Community-Articles/2021-06-17-Using-Elsa-Workflow-with-ABP-Framework/POST.md

@ -1,11 +1,19 @@
# Using Elsa Workflow with ABP Framework
> **UPDATE:** There is a newer version of this article, which covers Elsa 3 with ABP Framework. You can check it at https://abp.io/community/articles/using-elsa-3-workflow-with-abp-framework-usqk8afg
**Elsa Core** is an open-source workflows library that can be used in any kind of .NET Core application. Using such a workflow library can be useful to implement business rules visually or programmatically.
![elsa-overview](./elsa-overview.gif)
This article shows how we can use this workflow library within our ABP-based application. We will start with a couple of examples and then we will integrate the **Elsa Dashboard** (you can see it in the above gif) into our application to be able to design our workflows visually.
---
> 🛠 Liked this post? I now share all my content on Substack — real-world .NET, AI, and scalable software design.
> 👉 Subscribe here → engincanveske.substack.com
> 🎥 Also, check out my YouTube channel for hands-on demos and deep dives: https://www.youtube.com/@engincanv
---
## Source Code
You can find the source of the example solution used in this article [here](https://github.com/abpframework/abp-samples/tree/master/ElsaDemo).
@ -453,4 +461,10 @@ namespace ElsaDemo.Web.Menus
* Now we can click the "Workflow" menu item, display the Elsa Dashboard and designing workflows.
![elsa-demo-result](./elsa-demo-result.gif)
![elsa-demo-result](./elsa-demo-result.gif)
---
> 🛠 Liked this post? I now share all my content on Substack — real-world .NET, AI, and scalable software design.
> 👉 Subscribe here → engincanveske.substack.com
> 🎥 Also, check out my YouTube channel for hands-on demos and deep dives: https://www.youtube.com/@engincanv
---

12
docs/en/Community-Articles/2021-10-31-Many-to-Many-Relationship-with-ABP-and-EF-Core/POST.md

@ -10,6 +10,12 @@ You can see the ER Diagram of our application below. This diagram will be helpfu
When we've examined the ER Diagram, we can see the one-to-many relationship between the **Author** and the **Book** tables. Also, the many-to-many relationship (**BookCategory** table) between the **Book** and the **Category** tables. (There can be more than one category on each book and vice-versa in our scenario).
---
> 🛠 Liked this post? I now share all my content on Substack — real-world .NET, AI, and scalable software design.
> 👉 Subscribe here → engincanveske.substack.com
> 🎥 Also, check out my YouTube channel for hands-on demos and deep dives: https://www.youtube.com/@engincanv
---
### Source Code
You can find the source code of the application at https://github.com/EngincanV/ABP-Many-to-Many-Relationship-Demo .
@ -1664,6 +1670,12 @@ namespace BookStore.Web.Pages.Books
![Edit Book Modal](./book-update-modal.png)
---
> 🛠 Liked this post? I now share all my content on Substack — real-world .NET, AI, and scalable software design.
> 👉 Subscribe here → engincanveske.substack.com
> 🎥 Also, check out my YouTube channel for hands-on demos and deep dives: https://www.youtube.com/@engincanv
---
### Conclusion
In this article, I've tried to explain how to create a many-to-many relationship by using the ABP framework. (by following DDD principles)

12
docs/en/Community-Articles/2021-12-13-Integrating-the-Syncfusion-MVC-Components-to-the-ABP-MVC-UI/POST.md

@ -4,6 +4,12 @@
In this article we will see how we can integrate the Syncfusion MVC Components into our ABP application.
---
> 🛠 Liked this post? I now share all my content on Substack — real-world .NET, AI, and scalable software design.
> 👉 Subscribe here → engincanveske.substack.com
> 🎥 Also, check out my YouTube channel for hands-on demos and deep dives: https://www.youtube.com/@engincanv
---
## Source Code
You can find the source code of the application at https://github.com/EngincanV/ABP-Syncfusion-Components-Demo.
@ -314,6 +320,12 @@ After injecting the Syncfusion style and script into our application, our config
![](./calendar-component.png)
---
> 🛠 Liked this post? I now share all my content on Substack — real-world .NET, AI, and scalable software design.
> 👉 Subscribe here → engincanveske.substack.com
> 🎥 Also, check out my YouTube channel for hands-on demos and deep dives: https://www.youtube.com/@engincanv
---
### Conclusion
In this article, we've explained how to integrate the **Syncfusion Components** into our applications. After following this article, you can use the Syncfusion components in your application.

10
docs/en/Community-Articles/2022-02-06-How-to-Hide-ABP-Related-Endpoints-on-Swagger-UI/POST.md

@ -8,6 +8,12 @@ In the issue, there are helpful comments about hiding the ABP related endpoints
I thought it would be better to enable/disable showing endpoints on runtime by simply selecting a checkbox on the Setting Management page and in this article I wanted to show you how, so let's dive in.
---
> 🛠 Liked this post? I now share all my content on Substack — real-world .NET, AI, and scalable software design.
> 👉 Subscribe here → engincanveske.substack.com
> 🎥 Also, check out my YouTube channel for hands-on demos and deep dives: https://www.youtube.com/@engincanv
---
## Source Code
You can find the source code of the application at https://github.com/EngincanV/ABP-Hide-Swagger-Endpoint-Demo.
@ -445,6 +451,10 @@ services.AddAbpSwaggerGen(
> For more info, please see the [Swagger Integration](https://docs.abp.io/en/abp/latest/API/Swagger-Integration#hide-abp-endpoints-on-swagger-ui) docs.
---
> 🛠 Liked this post? I now share all my content on Substack — real-world .NET, AI, and scalable software design.
> 👉 Subscribe here → engincanveske.substack.com
> 🎥 Also, check out my YouTube channel for hands-on demos and deep dives: https://www.youtube.com/@engincanv
---
Thanks for reading.

2
docs/en/Community-Articles/2022-03-09-abpio-platform-52-rc-has-been-published/post.md

@ -186,7 +186,7 @@ We organized the 3rd live [ABP Community Talks](https://community.abp.io/events)
* [Enis Necipoğlu](https://twitter.com/EnisNecipoglu) has also created [an article](https://community.abp.io/posts/using-autofilterer-with-abp-framework-uuqv81jm) to demonstrate how to use his own open source [AutoFilterer](https://github.com/enisn/AutoFilterer) library with the ABP Framework.
* [Jonathan Potts](https://github.com/jonathanpotts) has created his first ABP Community article that shows how to use Bootswatch themes with the ABP Framework. [See it here](https://community.abp.io/posts/customizing-the-abp-basic-theme-with-bootswatch-4luoqzr0).
Thanks to all the contributors. It is appreciated if you want to submit your post and share your knowledge with the ABP community: https://community.abp.io/posts/submit
Thanks to all the contributors. It is appreciated if you want to submit your post and share your knowledge with the ABP community: https://community.abp.io/posts/create
## Conclusion

12
docs/en/Community-Articles/2022-04-06-Concurrency-Check-in-ABP-Based-Applications/POST.md

@ -2,6 +2,12 @@
In this article, we'll create a basic application to demonstrate how "Concurrency Check/Control" can be implemented in an ABP project.
---
> 🛠 Liked this post? I now share all my content on Substack — real-world .NET, AI, and scalable software design.
> 👉 Subscribe here → engincanveske.substack.com
> 🎥 Also, check out my YouTube channel for hands-on demos and deep dives: https://www.youtube.com/@engincanv
---
## Creating the Solution
For this article, we will create a simple BookStore application and add CRUD functionality to the pages. Hence we deal with the concurrency situation.
@ -546,3 +552,9 @@ Then we can run the application, navigate to the **/Books** endpoint and see the
* After the first user updated the record, the second user tries to update the same record without getting the last state of the record. And therefore `AbpDbConcurrencyException` is thrown because **ConcurrencyStamp** values are different from each other.
* The second user should close and re-open the model to get the last state of the record and then they can make changes to the current record.
---
> 🛠 Liked this post? I now share all my content on Substack — real-world .NET, AI, and scalable software design.
> 👉 Subscribe here → engincanveske.substack.com
> 🎥 Also, check out my YouTube channel for hands-on demos and deep dives: https://www.youtube.com/@engincanv
---

12
docs/en/Community-Articles/2022-11-22-gRPC-JSON-Transcoding/POST.md

@ -4,6 +4,12 @@ In this article, I'll show you one of the new features that came with .NET 7: **
> I've created a community article to highlight some interesting features (briefly) that are now available with the release of .NET 7. You can check it from [here](https://community.abp.io/posts/whats-new-with-.net-7-tlq2g43w).
---
> 🛠 Liked this post? I now share all my content on Substack — real-world .NET, AI, and scalable software design.
> 👉 Subscribe here → engincanveske.substack.com
> 🎥 Also, check out my YouTube channel for hands-on demos and deep dives: https://www.youtube.com/@engincanv
---
## What is gRPC? What are the pros and cons?
[gRPC](https://grpc.io/) is a high-performance RPC framework and uses HTTP/2 and Protobuf (protocol buffers).
@ -189,6 +195,12 @@ In this article, I've briefly introduced the JSON Transcoding feature that was s
> See the [gRPC JSON transcoding in ASP.NET Core gRPC apps](https://learn.microsoft.com/en-us/aspnet/core/grpc/json-transcoding?view=aspnetcore-7.0) documentation for more information.
---
> 🛠 Liked this post? I now share all my content on Substack — real-world .NET, AI, and scalable software design.
> 👉 Subscribe here → engincanveske.substack.com
> 🎥 Also, check out my YouTube channel for hands-on demos and deep dives: https://www.youtube.com/@engincanv
---
## References
* https://devblogs.microsoft.com/dotnet/announcing-grpc-json-transcoding-for-dotnet/

12
docs/en/Community-Articles/2022-18-11-whats-new-with-net7/POST.md

@ -6,6 +6,12 @@ In this article, I will highlight a few interesting features that are now availa
There are many new features coming with this release. We are going to examine new features within 4 sub-sections: ASP.NET Core, C#11, EF 7 and MAUI. Let's start with ASP.NET Core.
---
> 🛠 Liked this post? I now share all my content on Substack — real-world .NET, AI, and scalable software design.
> 👉 Subscribe here → engincanveske.substack.com
> 🎥 Also, check out my YouTube channel for hands-on demos and deep dives: https://www.youtube.com/@engincanv
---
## ASP.NET Core
We will see the following features in this section:
@ -290,6 +296,12 @@ In this article, I've highlighted some features that were shipped with .NET 7.
Thanks for reading the article and I hope you find it helpful. See you in the next one!
---
> 🛠 Liked this post? I now share all my content on Substack — real-world .NET, AI, and scalable software design.
> 👉 Subscribe here → engincanveske.substack.com
> 🎥 Also, check out my YouTube channel for hands-on demos and deep dives: https://www.youtube.com/@engincanv
---
## References
* https://devblogs.microsoft.com/dotnet/announcing-dotnet-7/

12
docs/en/Community-Articles/2023-07-03-Image-Compression-And-Resize/POST.md

@ -8,6 +8,12 @@ ABP Framework provides services to compress and resize images and implements the
> Refer to the documentation for more info: [Image Manipulation](https://docs.abp.io/en/abp/7.3/Image-Manipulation)
---
> 🛠 Liked this post? I now share all my content on Substack — real-world .NET, AI, and scalable software design.
> 👉 Subscribe here → engincanveske.substack.com
> 🎥 Also, check out my YouTube channel for hands-on demos and deep dives: https://www.youtube.com/@engincanv
---
### Source Code
You can find the source code of the application at [https://github.com/abpframework/abp-samples/tree/master/ImageManipulation](https://github.com/abpframework/abp-samples/tree/master/ImageManipulation). Don't hesitate to check the source code, if you are stuck on any point.
@ -281,6 +287,12 @@ The results are impressive for the example above:
* The original image was 12 KB and now the compressed & resized image has been reduced to 8 KB.
* The original image was 225x225 and now resized as 200x200.
---
> 🛠 Liked this post? I now share all my content on Substack — real-world .NET, AI, and scalable software design.
> 👉 Subscribe here → engincanveske.substack.com
> 🎥 Also, check out my YouTube channel for hands-on demos and deep dives: https://www.youtube.com/@engincanv
---
## Conclusion
In this article, I have shown you how to compress and/or resize images with ABP Framework's Image Manipulation System by just defining some attributes to the top of the controller actions.

12
docs/en/Community-Articles/2023-08-12-ABP-Commercial-GDPR-Module-Overview/POST.md

@ -2,6 +2,12 @@
In this article, I will highlight ABP Commercial's [GDPR Module](https://commercial.abp.io/modules/Volo.Gdpr) and show you how to provide personal data to the GDPR Module that is collected by your application and make it aligned with personal data download results.
---
> 🛠 Liked this post? I now share all my content on Substack — real-world .NET, AI, and scalable software design.
> 👉 Subscribe here → engincanveske.substack.com
> 🎥 Also, check out my YouTube channel for hands-on demos and deep dives: https://www.youtube.com/@engincanv
---
## GDPR Module
[GDPR Module](https://docs.abp.io/en/commercial/latest/modules/gdpr) allows users to download and delete the data collected by the application. It's used for Personal Data Management obligating by the GDPR regulation and provides the following features:
@ -143,6 +149,12 @@ Then, when we clicked the download button, a zip file will be downloaded. We can
{"City":"Istanbul","Postcode":"..."}
```
---
> 🛠 Liked this post? I now share all my content on Substack — real-world .NET, AI, and scalable software design.
> 👉 Subscribe here → engincanveske.substack.com
> 🎥 Also, check out my YouTube channel for hands-on demos and deep dives: https://www.youtube.com/@engincanv
---
## Conclusion
In this article, I've explained the GDPR Module's data collection system and given you a brief overview of the module. GDPR Module allows you to request to download personal data, delete/anonymize your own personal data and delete your account permanently. It's pre-installed in the Application and Application(single layer) Pro Startup templates, but you can easily configure it to your existing application.

12
docs/en/Community-Articles/2023-10-30-NET-8-ASP-NET-Core-Metrics/POST.md

@ -2,6 +2,12 @@
In this article, I'll show you the new built-in metrics of .NET 8, which are basically numerical measurements reported over time in your application and can be used to monitor the health of your application and generate reports according to those numerical values. We will see what the metrics are, why to use them, and how to use them in detail. So, let's dive in.
---
> 🛠 Liked this post? I now share all my content on Substack — real-world .NET, AI, and scalable software design.
> 👉 Subscribe here → engincanveske.substack.com
> 🎥 Also, check out my YouTube channel for hands-on demos and deep dives: https://www.youtube.com/@engincanv
---
## What are Metrics?
Metrics are numerical measurements reported over time. These measurements are crucial for monitoring the health of an application and generating alerts when necessary. In the context of a web service, various metrics can be tracked, such as:
@ -185,6 +191,12 @@ If you want to build a dashboard, you can see [this documentation from Microsoft
Also, you can check [this video](https://www.youtube.com/watch?v=A2pKhNQoQUU) if you want to see it in action.
---
> 🛠 Liked this post? I now share all my content on Substack — real-world .NET, AI, and scalable software design.
> 👉 Subscribe here → engincanveske.substack.com
> 🎥 Also, check out my YouTube channel for hands-on demos and deep dives: https://www.youtube.com/@engincanv
---
## Conclusion
In this article, I've shown you the new built-in metrics of .NET8, described what metrics are, which pre-built metrics are provided by ASP.NET Core, how to use & view these pre-built metrics and finally, I have shown you how to create custom metrics and view them in a dashboard. If you want to learn more about the **Metrics System of .NET**, you can check out the references that I have shared below.

12
docs/en/Community-Articles/2023-11-16-Upgrading-Your-Existing-Projects-to-NET8/POST.md

@ -4,6 +4,12 @@ A new .NET version was released on November 14, 2023 and ABP 8.0 RC.1 shipped ba
Despite all the related dependency upgrades and changes made on the ABP Framework and ABP Commercial sides, we still need to make some changes. Let's see the required actions that need to be taken in the following sections.
---
> 🛠 Liked this post? I now share all my content on Substack — real-world .NET, AI, and scalable software design.
> 👉 Subscribe here → engincanveske.substack.com
> 🎥 Also, check out my YouTube channel for hands-on demos and deep dives: https://www.youtube.com/@engincanv
---
## Installing the .NET 8.0 SDK
To get started with ASP.NET Core in .NET 8.0, you need to install the .NET 8 SDK. You can install it at [https://dotnet.microsoft.com/en-us/download/dotnet/8.0](https://dotnet.microsoft.com/en-us/download/dotnet/8.0).
@ -99,3 +105,9 @@ After that, you need to check the migration guide documents, listed below:
That's it! These were all the related steps that need to be taken to upgrade your application to .NET 8 and ABP 8.0. Now, you can enjoy the .NET 8 & ABP 8.0 and benefit from the performance improvements and new features.
Happy Coding 🤗
---
> 🛠 Liked this post? I now share all my content on Substack — real-world .NET, AI, and scalable software design.
> 👉 Subscribe here → engincanveske.substack.com
> 🎥 Also, check out my YouTube channel for hands-on demos and deep dives: https://www.youtube.com/@engincanv
---

12
docs/en/Community-Articles/2024-01-18-ABP-Now-Supports-Keyed-Services/POST.md

@ -2,6 +2,12 @@
In this post, I describe the new **"keyed service"** support for the dependency injection container, which came with .NET 8.0. Then, I'll show you an example of usage within the ABP Framework.
---
> 🛠 Liked this post? I now share all my content on Substack — real-world .NET, AI, and scalable software design.
> 👉 Subscribe here → engincanveske.substack.com
> 🎥 Also, check out my YouTube channel for hands-on demos and deep dives: https://www.youtube.com/@engincanv
---
## What Are Keyed Services?
ASP.NET Core ships with a built-in dependency injection container, which is a pretty basic DI container that supports minimal features a dependency injection container is supposed to have. For that reason, most of the .NET users use third-party containers like [Autofac](https://autofac.org/), or Ninject.
@ -203,6 +209,12 @@ public class TaxCalculator: ICalculator, ITaxCalculator, ICanCalculate, ITransie
Please refer to the [Dependency Injection document](https://abp.io/docs/latest/framework/fundamentals/dependency-injection#exposekeyedservice-attribute) for further info.
---
> 🛠 Liked this post? I now share all my content on Substack — real-world .NET, AI, and scalable software design.
> 👉 Subscribe here → engincanveske.substack.com
> 🎥 Also, check out my YouTube channel for hands-on demos and deep dives: https://www.youtube.com/@engincanv
---
## Summary
In this post, I described the new **"keyed service"** support added to the built-in dependency injection container that was released in .NET 8, and wanted to announce it's being supported from v8.0.2 for ABP Framework. It's a really good addition to the built-in dependency injection container and can be pretty useful for certain use-cases.

2
docs/en/Community-Articles/2024-02-19-abpio-platform-81-rc-has-been-published/post.md

@ -228,7 +228,7 @@ There are exciting articles contributed by the ABP community as always. I will h
* [A Best Practice for Designing Interfaces in .NET C#](https://community.abp.io/posts/a-best-practice-for-designing-interfaces-in-.net-c-9xqc4h8d)
* [Invariance, Covariance, and Contravariance in .NET C#](https://community.abp.io/posts/invariance-covariance-and-contravariance-in-.net-c-9blmuhme)
Thanks to the ABP Community for all the content they have published. You can also [post your ABP-related (text or video) content](https://community.abp.io/posts/submit) to the ABP Community.
Thanks to the ABP Community for all the content they have published. You can also [post your ABP-related (text or video) content](https://community.abp.io/posts/create) to the ABP Community.
## Conclusion

6
docs/en/Community-Articles/2024-04-19-Performing-Case-Insensitive-Search-In-Postgresql/POST.md

@ -120,6 +120,12 @@ After these configurations, you should create a migration and apply it to your d
However, this solution comes with some problems, for example, by using non-deterministic collations, it's not yet possible to use pattern-matching operators such as `LIKE` on columns. This is a huge problem because it makes it hard to use LINQ. For example, you can't use the `.EndsWith` or `.StartsWith` methods, because they are [translated to `LIKE` command on the SQL level](https://www.npgsql.org/efcore/mapping/translations.html).
---
> 🛠 Liked this post? I now share all my content on Substack — real-world .NET, AI, and scalable software design.
> 👉 Subscribe here → engincanveske.substack.com
> 🎥 Also, check out my YouTube channel for hands-on demos and deep dives: https://www.youtube.com/@engincanv
---
## Conclusion
In PostgreSQL, you can perform case-insensitive searches by using the `citext` data type or by utilizing collation settings. Nevertheless, if you have an ABP-based PostgreSQL application or a plain .NET application with PostgreSQL as the database option, to make a decision to pick one of these options, you can follow the following points:

12
docs/en/Community-Articles/2024-05-10-Sentiment-Analysis-within-ABP-Based-Application/POST.md

@ -4,6 +4,12 @@ In this article, first I will briefly explain what sentiment analysis is and the
We will use ML.NET Framework, which is an open-source machine learning framework created by the dotnet team and also we will create a layered ABP Solution by using the application template and finally we will use CMS Kit's Comment Feature and extend its behavior by adding spam detection while creating or updating a comment, at that point we will make sentiment analysis.
---
> 🛠 Liked this post? I now share all my content on Substack — real-world .NET, AI, and scalable software design.
> 👉 Subscribe here → engincanveske.substack.com
> 🎥 Also, check out my YouTube channel for hands-on demos and deep dives: https://www.youtube.com/@engincanv
---
## Sentiment Analysis
[Sentiment Analysis (or opinion mining)](https://en.wikipedia.org/wiki/Sentiment_analysis) refers to determining the emotion from the given input. The primary goal of sentiment analysis is to identify, extract, and categorize (positive, negative, or neutral) the sentiments expressed in textual data.
@ -333,6 +339,12 @@ Then, finally, we can run the application to see the final results:
Once the model is trained and evaluated, we can save the trained model and use it directly for further use. In this way, you don’t have to retrain the model every time when you want to make predictions. It’s essential to save the trained model for future use and a must for the production-ready code. I created a separate article dedicated to that topic, and if you are interested, you can read it from [here](https://engincanv.github.io/machine-learning/sentiment-analysis/best-practises/2024/05/16/reusing-and-optimizing-machine-learning-models-in-dotnet.html).
---
> 🛠 Liked this post? I now share all my content on Substack — real-world .NET, AI, and scalable software design.
> 👉 Subscribe here → engincanveske.substack.com
> 🎥 Also, check out my YouTube channel for hands-on demos and deep dives: https://www.youtube.com/@engincanv
---
## Conclusion
In this article, I briefly explain what sentiment analysis is, created a sample ABP-based application, integrated the CMS Kit Module and finally, applied sentiment analysis to make spam checks whenever a new comment has been submitted or updated. You can get the source code of the demo from [https://github.com/EngincanV/SentimentAnalysisDemo](https://github.com/EngincanV/SentimentAnalysisDemo)

2
docs/en/Community-Articles/2024-05-24-abpio-platform-82-rc-has-been-published/post.md

@ -259,7 +259,7 @@ There are exciting articles contributed by the ABP community as always. I will h
* [Using FluentValidation with ABP Framework](https://community.abp.io/posts/using-fluentvalidation-with-abp-framework-2cxuwl70) by [Enes Döner](https://community.abp.io/members/Enes)
* [Using Blob Storage with ABP](https://community.abp.io/posts/using-blob-storage-with-abp-framework-jygtmhn4) by [Emre Kendirli](https://community.abp.io/members/emrekenderli)
Thanks to the ABP Community for all the content they have published. You can also [post your ABP-related (text or video) content](https://community.abp.io/posts/submit) to the ABP Community.
Thanks to the ABP Community for all the content they have published. You can also [post your ABP-related (text or video) content](https://community.abp.io/posts/create) to the ABP Community.
## Conclusion

2
docs/en/Community-Articles/2024-08-01-abpio-platform-83-rc-has-been-published/post.md

@ -165,7 +165,7 @@ There are exciting articles contributed by the ABP community as always. I will h
* [How to use .NET Aspire with ABP framework](https://abp.io/community/articles/how-to-use-.net-aspire-with-abp-framework-h29km4kk) by [Berkan Şaşmaz](https://twitter.com/berkansasmazz)
* [Exciting New Feature in ABP.IO CMS Kit: Marked Item System](https://abp.io/community/articles/exciting-new-feature-in-abp.io-cms-kit-marked-item-system.-2hvpq0me) by [Suhaib Mousa](https://abp.io/community/members/suhaibmousa032@gmail.com)
Thanks to the ABP Community for all the content they have published. You can also [post your ABP-related (text or video) content](https://abp.io/community/posts/submit) to the ABP Community.
Thanks to the ABP Community for all the content they have published. You can also [post your ABP-related (text or video) content](https://abp.io/community/posts/create) to the ABP Community.
## Conclusion

2
docs/en/Community-Articles/2024-09-12-abpio-platform-83-final-has-been-released/post.md

@ -70,7 +70,7 @@ As always, exciting articles have been contributed by the ABP community. I will
* [Introducing the Google Cloud Storage BLOB Provider](https://abp.io/community/articles/introducing-the-google-cloud-storage-blob-provider-yrt6azc0) by [Engincan Veske](https://twitter.com/EngincanVeske)
* [Switching Between Organization Units](https://abp.io/community/articles/switching-between-organization-units-i5tokpzt) by [Liming Ma](https://github.com/maliming)
Thanks to the ABP Community for all the content they have published. You can also [post your ABP-related (text or video) content](https://abp.io/community/posts/submit) to the ABP Community.
Thanks to the ABP Community for all the content they have published. You can also [post your ABP-related (text or video) content](https://abp.io/community/posts/create) to the ABP Community.
## About the Next Version

2
docs/en/Community-Articles/2024-10-23-abpio-platform-90-rc-has-been-published/post.md

@ -210,7 +210,7 @@ There are exciting articles contributed by the ABP community as always. I will h
* [ABP-Powered Web App with Inertia.js, React, and Vite](https://abp.io/community/articles/abppowered-web-app-with-inertia.js-react-and-vite-j7cccvad) by [Anto Subash](https://antosubash.com/)
* [Multi-Tenancy Support in Angular Apps with ABP.IO](https://abp.io/community/articles/multitenancy-support-in-angular-apps-with-abp.io-lw9l36c5) by [HeadChannel Team](https://headchannel.co.uk/)
Thanks to the ABP Community for all the content they have published. You can also [post your ABP-related (text or video) content](https://abp.io/community/posts/submit) to the ABP Community.
Thanks to the ABP Community for all the content they have published. You can also [post your ABP-related (text or video) content](https://abp.io/community/posts/create) to the ABP Community.
## Conclusion

12
docs/en/Community-Articles/2024-11-01-Hybrid-Cache-Net-9/POST.md

@ -6,6 +6,12 @@ It offers a flexible caching solution that combines the best aspects of local an
In this article, we’ll explore **HybridCache** in .NET 9 and how it integrates with ABP Framework using `AbpHybridCache`. This new feature offers a robust solution for applications that need to scale while maintaining efficient caching strategies.
---
> 🛠 Liked this post? I now share all my content on Substack — real-world .NET, AI, and scalable software design.
> 👉 Subscribe here → engincanveske.substack.com
> 🎥 Also, check out my YouTube channel for hands-on demos and deep dives: https://www.youtube.com/@engincanv
---
## What is HybridCache?
**HybridCache** is designed to merge different caching layers, commonly including an in-memory cache (for high-speed access) and a distributed cache (for scalability across multiple instances). This hybrid approach allows for:
@ -109,6 +115,12 @@ As you can see from the figure, it only set the cache item to the **LocalCache**
**Note:** If you configure distributed caching options, `HybridCache` service uses the distributed cache and sets the **BackendCache**.
---
> 🛠 Liked this post? I now share all my content on Substack — real-world .NET, AI, and scalable software design.
> 👉 Subscribe here → engincanveske.substack.com
> 🎥 Also, check out my YouTube channel for hands-on demos and deep dives: https://www.youtube.com/@engincanv
---
## Conclusion
The **HybridCache** library in .NET 9 provides a powerful tool for applications needing both high-speed caching and consistency in distributed environments.

2
docs/en/Community-Articles/2024-11-21-abpio-platform-90-has-been-released-based-on-net-90/post.md

@ -80,7 +80,7 @@ In addition to [the articles to highlight .NET 9.0 features written by our team]
* [How to create your Own AI Bot on WhatsApp Using an ABP.io Template](https://abp.io/community/articles/how-to-create-your-own-ai-bot-on-whatsapp-using-the-abp-framework-c6jgvt9c) by [Michael Kokula](https://abp.io/community/members/Michal_Kokula)
* [ABP Now Supports .NET 9](https://abp.io/community/articles/abp-now-supports-.net-9-zpkznc4f) by [Alper Ebiçoğlu](https://x.com/alperebicoglu)
Thanks to the ABP Community for all the content they have published. You can also [post your ABP related (text or video) content](https://abp.io/community/posts/submit) to the ABP Community.
Thanks to the ABP Community for all the content they have published. You can also [post your ABP related (text or video) content](https://abp.io/community/posts/create) to the ABP Community.
## Conclusion

2
docs/en/Community-Articles/2025-01-21-abp-platform-91-rc-has-been-released/post.md

@ -136,7 +136,7 @@ There are exciting articles contributed by the ABP community as always. I will h
* [The new Unit Test structure in ABP application](https://abp.io/community/articles/the-new-unit-test-structure-in-abp-application-4vvvp2oy) by [Liming Ma](https://github.com/maliming)
* [How to Use OpenAI API with ABP Framework](https://abp.io/community/articles/how-to-use-openai-api-with-abp-framework-rsfvihla) by [Berkan Şaşmaz](https://github.com/berkansasmaz)
Thanks to the ABP Community for all the content they have published. You can also [post your ABP-related (text or video) content](https://abp.io/community/posts/submit) to the ABP Community.
Thanks to the ABP Community for all the content they have published. You can also [post your ABP-related (text or video) content](https://abp.io/community/posts/create) to the ABP Community.
## Conclusion

12
docs/en/Community-Articles/2025-02-04-OpenIddict-Custom-Logic/POST.md

@ -6,6 +6,12 @@ OpenIddict provides an event-driven model ([event models](https://documentation.
In this article, we will explore OpenIddict event models, their key use cases, and how to implement them effectively.
---
> 🛠 Liked this post? I now share all my content on Substack — real-world .NET, AI, and scalable software design.
> 👉 Subscribe here → engincanveske.substack.com
> 🎥 Also, check out my YouTube channel for hands-on demos and deep dives: https://www.youtube.com/@engincanv
---
## Understanding OpenIddict Event Model
OpenIddict events are primarily used within the OpenIddict server component. These events provide hooks into the OpenID Connect flow, allowing developers to modify behavior at different stages of authentication & authorization processes.
@ -101,6 +107,12 @@ That's it! After these steps, your `SignOutEventHandler.HandleAsync()` method sh
Each event provides access to the relevant context, allowing you to access and modify the authentication flow's behavior.
---
> 🛠 Liked this post? I now share all my content on Substack — real-world .NET, AI, and scalable software design.
> 👉 Subscribe here → engincanveske.substack.com
> 🎥 Also, check out my YouTube channel for hands-on demos and deep dives: https://www.youtube.com/@engincanv
---
## Conclusion
ABP Framework integrates OpenIddict as its authentication and authorization module. OpenIddict provides an event-driven model that allows developers to customize authentication and authorization processes within their ABP applications. It's pre-installed & pre-configured in the ABP's startup templates.

2
docs/en/Community-Articles/2025-03-11-Developing-A-Multi-Timezone-Application-Using-The-ABP-Framework/post.md

@ -6,6 +6,8 @@ All these scenarios require us to handle timezone conversions correctly in our a
In this article, we'll show you step by step how to handle multi-timezone in the ABP framework.
> The content mentioned in this article will be available after the ABP 9.2 version
## Timezone Settings
The ABP framework provides a setting called `Abp.Timing.TimeZone` for setting and getting the timezone of users, tenants, or applications. The default value is empty, which means the application will use the server's time zone. Check out the [Timing documentation](https://abp.io/docs/latest/framework/infrastructure/timing) for more information.

2
docs/en/Community-Articles/2025-03-18-Using-Vue-Components/post.md

@ -75,7 +75,7 @@ Let's create a simple Vue component to display the TODO list.
```html
<div id="vue-app">
<message-component :message="'Welcome, @CurrentUser.UserName !'"></todo-component>
<message-component :message="'Welcome, @CurrentUser.UserName !'"></message-component>
</div>
```

4
docs/en/Community-Articles/2025-03-23-Understanding-the-Embedded-Files-in-ABP-Framework/post.md

@ -119,7 +119,7 @@ For example, if your filename is `zh.hans.json`, ABP will generate the following
[File] [/MyModule/Volo/Abp/MyModule/Localization/zh/hans.json]
```
Microsoft provides the `Microsoft.Extensions.FileProviders.Manifest` library to solve this problem.
Microsoft provides the `Microsoft.Extensions.FileProviders.Embedded` library to solve this problem.
We need to add this package dependency and set `<GenerateEmbeddedFilesManifest>true</GenerateEmbeddedFilesManifest>` in our project:
@ -136,7 +136,7 @@ We need to add this package dependency and set `<GenerateEmbeddedFilesManifest>t
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Hosting" Version="9.0.0" />
<PackageReference Include="Volo.Abp.VirtualFileSystem" Version="9.0.0" />
<PackageReference Include="Microsoft.Extensions.FileProviders.Manifest" Version="9.0.0" />
<PackageReference Include="Microsoft.Extensions.FileProviders.Embedded" Version="9.0.0" />
</ItemGroup>
<ItemGroup>

12
docs/en/Community-Articles/2025-03-24-How-to-Change-the-CurrentUser-in-ABP/POST.md

@ -4,6 +4,12 @@
In this article, we'll explore the [`CurrentUser` service](https://abp.io/docs/latest/framework/infrastructure/current-user), its use cases, and how to change it when necessary.
---
> 🛠 Liked this post? I now share all my content on Substack — real-world .NET, AI, and scalable software design.
> 👉 Subscribe here → engincanveske.substack.com
> 🎥 Also, check out my YouTube channel for hands-on demos and deep dives: https://www.youtube.com/@engincanv
---
## Understanding the ICurrentUser Service
The `ICurrentUser` interface is the primary service in ABP Framework for obtaining information about the logged-in user. It provides some key properties, such as `Id`, `UserName`, `TenantId`, `Roles` (roleNames), and more...
@ -108,6 +114,12 @@ Here's what the code does step by step:
This pattern is particularly useful in background jobs, event handlers, or any scenario where you need to perform operations under a specific user's context, regardless of the actual authenticated user.
---
> 🛠 Liked this post? I now share all my content on Substack — real-world .NET, AI, and scalable software design.
> 👉 Subscribe here → engincanveske.substack.com
> 🎥 Also, check out my YouTube channel for hands-on demos and deep dives: https://www.youtube.com/@engincanv
---
## Conclusion
The `CurrentUser` service in ABP Framework provides a simple way to access information about the authenticated user. While it works automatically in most scenarios, there are cases where you need to explicitly change the current user identity, particularly in background processing scenarios.

38
docs/en/Community-Articles/2025-03-27-Announcing-the-ABP-Contributor-Program/post.md

@ -0,0 +1,38 @@
We are excited to introduce the ABP Contributor Program, which is an amazing opportunity for community enthusiasts to contribute to the ABP ecosystem while getting valuable benefits\!
**Create, Contribute and Be Part of Something Bigger**
This is your opportunity to not only share your knowledge but also to grow alongside a passionate community of developers and creators. When you create and contribute to the ABP ecosystem, you’re not just building content, you’re also helping shape the future of ABP.
## **Why Become an ABP Contributor?**
By sharing your knowledge, creating valuable content, and engaging with the ABP Community, you’ll enjoy a range of benefits, including:
* Free ABP Personal License – If you meet all the requirements, you’ll receive an ABP Personal License at no cost
* Community Badge & Title – Stand out in the ABP Community with a special contributor badge and label next to your name.
* Exclusive Discord Role – Get a unique Contributor role on the ABP Community Discord server.
* Increased Visibility – Your contributions will be recognized by hundreds of thousands of developers worldwide.
Completely Free – No fees, just log in, contribute, and start collecting benefits\!
## **How to Apply?**
If you’re passionate about ABP and think you meet the required criteria, follow these simple steps:
Create content related to ABP: blog posts, tutorials, videos, or documentation. You can publish it on the ABP Community website or any external platform (just make sure to submit it to the ABP Community site).
Apply by email: Send your application to marketing@volosoft.com, and the ABP Team will review your eligibility.
Periodic Assessments: The team reviews submissions every three months to determine and renew contributor status. Keep contributing to continue enjoying the perks\!
## **Join Us & Grow\!**
This is your chance to give back to the community, grow your presence, and get rewarded for your contributions. Whether you love writing documentation, sharing tutorials, or building open-source projects, your efforts matter.
Apply today and be part of something impactful\!
[image1]: images/img_1.png

170
docs/en/Community-Articles/2025-04-20-IDX10204/POST.md

@ -0,0 +1,170 @@
# Common Errors in JWT Bearer Authentication
When implementing JWT Bearer authentication in an ABP(tiered) application, you might occasionally encounter errors starting with `IDX`. These errors are related to JWT Bearer Token validation and this article will help you understand and resolve them.
## Enable JWT Bearer authentication
Your API project usually contains the following code, which enables JWT Bearer authentication and makes it as the default authentication scheme.
We simply configure the JWT's `Authority` and `Audience` properties, and it will work fine.
```csharp
context.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.Authority = "https://localhost:44301/"; //configuration["AuthServer:Authority"];
options.Audience = "MyProjectName";
});
```
> `AddJwtBearer` and `AddAbpJwtBearer` will do the same thing, but `AddAbpJwtBearer` is recommended.
## JWT authentication process
Let's take a look at how the above code works.
A JWT Token usually consists of three parts: `Header`, `Payload`, and `Signature`.
- `Header`: Contains the type and signing algorithm of the token
- `Payload`: Contains the claims of the token, including `sub`, `aud`, `exp`, `iat`, `iss`, `jti`, `preferred_username`, `given_name`, `role`, `email`, etc.
- `Signature`: The cryptographic signature of the token used to verify its authenticity
Here is an example of a JWT Token issued by `AuthServer(OpenIddict)`:
The `Header` part:
![JWT Header](header.png)
The `Payload` part:
![JWT Payload](payload.png)
### TokenValidationParameters
In the `JwtBearerOptions`, there is a `TokenValidationParameters` property, which is used to validate the JWT Token.
The default implementation for JWT Token validation is `JsonWebTokenHandler`, which comes from the [Microsoft.IdentityModel.JsonWebTokens](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/) package.
We didn't set the `TokenValidationParameters` property in the code above, so the default values below will be used:
```csharp
//...
TokenValidationParameters.ValidateAudience = true
TokenValidationParameters.ValidAudience = "MyProjectName"
TokenValidationParameters.ValidAudiences = null
TokenValidationParameters.ValidateIssuer = true
TokenValidationParameters.ValidIssuer = null
TokenValidationParameters.ValidIssuers = null
//...
```
### JWT Bearer Token Validation Process
During JWT Bearer authentication, API website will get the token from the HTTP request and validate it.
The `JsonWebTokenHandler` will get the `OpenID Connect` metadata from the `AuthServer`, it will be used in the validation process, the current metadata request address is: https://localhost:44301/.well-known/openid-configuration , it is a fixed address calculated from the `Authority` property.
First, the token's Signature is verified using the public key obtained from `OpenID Connect` metadata(https://localhost:44301/.well-known/jwks).
Then, the payload is validated. The payload is a JSON object containing essential information such as the `token type`, `expiration time`, `issuer`, and `audience` etc.
Most of the validation problems we may encounter are payload validation failures, for example:
#### Lifetime
If the token in your request has expired, the validation will fail. You will see the exception information like `IDX10230` in the log.
#### Audience
The `ValidAudience` of `TokenValidationParameters` is `MyProjectName`, the `aud` in the payload of the token is also `MyProjectName`, if the token does not contain `aud` or the `aud` does not match, the validation will fail. You may see the exception information like `IDX10206`, `IDX10277` or `IDX10208`.
> If the `ValidateAudience` of `TokenValidationParameters` is `false`, then the `aud` will not be validated.
#### Issuer
The default value of `TokenValidationParameters.ValidateIssuer` is `true`, it requires the token's payload to contain the `issuer` field, and it must match one of `TokenValidationParameters.ValidIssuer` or `TokenValidationParameters.ValidIssuers`.
> The default value of `ValidIssuer` or `ValidIssuers` is `null`, it will use the `issuer` from the `OpenID Connect` metadata as the default value.
1. If the token's payload does not contain the `issuer` field, you may see the error `IDX10211`.
2. If the API website cannot get the `OpenID Connect` metadata from AuthServer website, the validation will fail. You may see the error `IDX10204`, the full exception message is: `IDX10204: Unable to validate issuer. validationParameters.ValidIssuer is null or whitespace AND validationParameters.ValidIssuers is null or empty.`
3. If the `issuer` does not match, the validation will fail. You may see the error `IDX10205` in the log.
> If the `ValidateIssuer` of `TokenValidationParameters` is `false`, then the `issuer` will not be validated.
> Please note that `OpenIddict` will use the current HTTP request information as the value of `issuer`. If the AuthServer website is deployed behind a reverse proxy or similar deployment configurations, the `issuer` in the token may not be the value you expect. In this case, please specify it manually.
```csharp
PreConfigure<OpenIddictServerBuilder>(serverBuilder =>
{
serverBuilder.SetIssuer("https://localhost:44301/");
});
```
## Troubleshooting
To troubleshoot any `IDX` errors during JWT authentication, you can enable detailed logging by configuring the `identitymodel` logs as follows:
```csharp
using System.Diagnostics.Tracing;
using Microsoft.IdentityModel.Logging;
public class Program
{
public async static Task<int> Main(string[] args)
{
IdentityModelEventSource.ShowPII = true;
IdentityModelEventSource.Logger.LogLevel = EventLevel.Verbose;
var wilsonTextLogger = newTextWriterEventListener("Logs/identitymodel.txt");
wilsonTextLogger.EnableEvents(IdentityModelEventSource.Logger, EventLevel.Verbose);
//...
}
}
```
Additionally, you can enable `OpenIddict`'s `Verbose` logs for more detailed debugging information:
```csharp
var loggerConfiguration = new LoggerConfiguration()
.MinimumLevel.Debug()
.MinimumLevel.Override("Microsoft.EntityFrameworkCore", LogEventLevel.Warning)
.MinimumLevel.Override("OpenIddict", LogEventLevel.Verbose)
.Enrich.FromLogContext()
.WriteTo.Async(c => c.File("Logs/logs.txt"))
```
## Summary
For JWT authentication, you need to pay attention to the following key points:
1. Ensure your API website can communicate with the AuthServer properly
2. Verify that the `aud` claim in your token matches the expected audience
3. Confirm that the `issuer` claim in your token is valid and matches the configuration
You can customize the `JwtBearerOptions`'s `TokenValidationParameters` to modify the validation rules to meet your actual needs.
For example, if your `issuer` needs to support multiple subdomains, you can use the [Owl.TokenWildcardIssuerValidator](https://github.com/maliming/Owl.TokenWildcardIssuerValidator) library to customize the validation.
```csharp
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.Authority = "https://abp.io";
options.Audience = "abp_io";
options.TokenValidationParameters.IssuerValidator = TokenWildcardIssuerValidator.IssuerValidator;
options.TokenValidationParameters.ValidIssuers = new[]
{
"https://{0}.abp.io"
};
});
```
## References
- [Configure JWT bearer authentication in ASP.NET Core]([https://learn.microsoft.com/en-us/aspnet/core/security/authentication/jwt-auth?view=aspnetcore-8.0](https://learn.microsoft.com/en-us/aspnet/core/security/authentication/configure-jwt-bearer-authentication))
- [OpenIddict](https://github.com/openiddict/openiddict-core)
- [IdentityModel](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet)
- [Owl.TokenWildcardIssuerValidator](https://github.com/maliming/Owl.TokenWildcardIssuerValidator)

BIN
docs/en/Community-Articles/2025-04-20-IDX10204/header.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

BIN
docs/en/Community-Articles/2025-04-20-IDX10204/payload.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 142 KiB

262
docs/en/Community-Articles/2025-04-25-AI-Comment-Summarization/POST.md

@ -0,0 +1,262 @@
# Using Microsoft AI Extensions Library and OpenAI to Summarize User Comments
Either you are building an e-commerce application or a simple blog, **user comments** (about your products or blog posts) **can grow rapidly**, making it harder for users to get the gist of discussions at a glance. AI is a pretty good tool to solve the problem. By using AI, you can **summarize all the user comments** and show a single paragraph to your users, so they can easily understand the overall thought of users about the product or the blog post.
In this tutorial, we’ll walk through a real-life implementation of using AI to summarize multiple user comments in an application. I will implement the solution based on ABP's **[CMS Kit](https://abp.io/docs/latest/modules/cms-kit)** library, as it already features a **[commenting system](https://abp.io/docs/latest/modules/cms-kit/comments)** and a [demo application](https://cms-kit-demo.abpdemo.com/) that displays user comments on **[gallery images](https://cms-kit-demo.abpdemo.com/image-gallery)** (it has not a comment summary feature yet, we will implement it in this tutorial).
## A Screenshot
Here, an example screenshot from the application with the comment summary feature:
![comment-example](comment-example.png)
## Cloning the Repository
If you want to follow the development, you can clone the [CMS Kit Demo repository](https://github.com/abpframework/cms-kit-demo) to your computer and make it running by following the instructions on the [README file](https://github.com/abpframework/cms-kit-demo?tab=readme-ov-file#cms-kit-demo).
I suggest to you to play a little with [the application](https://cms-kit-demo.abpdemo.com/) (create a new user for yourself, add some comments to the images in the gallery), so you understand how it works.
## Preparing the Solution for AI
I will use [Microsoft AI Extensions Library](https://learn.microsoft.com/en-us/dotnet/ai/ai-extensions) to use the AI features. It is an abstraction library that can work with multiple AI models and tools. I will use an OpenAI model in the demo.
The first step is to add the [Microsoft.Extensions.AI.OpenAI](http://nuget.org/packages/Microsoft.Extensions.AI.OpenAI) NuGet package to the project:
````bash
dotnet add package Microsoft.Extensions.AI.OpenAI --prerelease
````
>The Microsoft AI Extensions Library was in preview at the time when I wrote this article. If it has a stable release now, you can remove the `--prerelease` parameter for the preceding command.
We will store the OpenAI key and model name in user secrets. So, locate the root path of the CMS Kit project (`src\CmsKitDemo` folder) and execute the following commands in order in a command-line terminal:
````bash
dotnet user-secrets init
dotnet user-secrets set OpenAIKey <your-openai-key>
dotnet user-secrets set ModelName <your-openai-model-name>
````
For this example, you need to have an [OpenAI API Key](https://platform.openai.com/). That's all. Now, we are ready to use the AI.
## Implementing the AI Summarization
Let's start from the most important point of this article: Comment summarization. I will create a class named `AiCommentSummarizer` to implement the summarization work. Here, the full content of that class:
````csharp
using System.Text;
using Microsoft.Extensions.AI;
using OpenAI;
using Volo.Abp.DependencyInjection;
namespace CmsKitDemo.Utils;
public class AiCommentSummarizer : ITransientDependency
{
private readonly IConfiguration _configuration;
public AiCommentSummarizer(IConfiguration configuration)
{
_configuration = configuration;
}
public async Task<string> SummarizeAsync(string[] commentTexts)
{
// Get the model and key from the configuration
var aiModel = _configuration["ModelName"];
var apiKey = _configuration["OpenAIKey"];
if (aiModel.IsNullOrEmpty() || apiKey.IsNullOrEmpty())
{
return "";
}
// Create the IChatClient
var client = new OpenAIClient(apiKey)
.GetChatClient(aiModel)
.AsIChatClient();
// Create a prompt (input for AI)
var promptBuilder = new StringBuilder();
promptBuilder.AppendLine(
@"There are comments from different users of our website about an image.
We want to summarize the comments into a single comment.
Return a single comment with a maximum of 512 characters. Comments are separated by a newline character and given below."
);
promptBuilder.AppendLine();
foreach (var commentText in commentTexts)
{
promptBuilder.AppendLine("User comment:");
promptBuilder.AppendLine(commentText);
promptBuilder.AppendLine();
}
// Submit the prompt and get the response
var response = await client.GetResponseAsync(
promptBuilder.ToString(),
new ChatOptions { MaxOutputTokens = 1024 }
);
return response.Text;
}
}
````
That class is pretty simple and already decorated with comments:
* First, we are getting the API Key and an OpenAI model name from user secrets. I used `gpt-4.1` as the model name, but you can use another available model.
* Then we are obtaining an `IChatClient` reference for OpenAI. `IChatClient` interface is an abstraction that is provided by the [Microsoft AI Extensions Library](https://learn.microsoft.com/en-us/dotnet/ai/ai-extensions) library, so we can implement rest of the code independently from OpenAI.
* Then we continue by building a proper prompt (input) for the AI operation.
* And finally we are using the AI to generate a response (the summary).
At this point, all the AI-related work has already been done. The rest of this article explains how to integrate that summarization feature with the [CMS Kit Demo application](https://cms-kit-demo.abpdemo.com/).
## Adding a CommentsSummary Property to the GalleryImage Entity
The `GalleryImage` entity is used to represent an image on [the image gallery](https://cms-kit-demo.abpdemo.com/image-gallery). I add a `CommentsSummary` property to that entity:
````csharp
public class GalleryImage : CreationAuditedAggregateRoot<Guid>
{
public string Description { get; set; }
public Guid CoverImageMediaId { get; set; }
public string CommentsSummary { get; set; } // The new property is here
//...
}
````
Since the CMS Kit Demo application uses Entity Framework Core, I need to add a new database schema migration and update the database:
````bash
dotnet ef migrations add Added_Summary_To_GalleryImage
dotnet ef database update
````
## Updating the Summary
Great, we have a `GalleryImage.CommentsSummary` property now. But, how will it be updated when a users adds or removes a comment for an image? To implement that;
* We will listen all the change events for user comments (when a user adds, removes or updates a comment).
* Whenever a comment is changed, we will find the related gallery image, retrieve all the user comments for this image, use the `AiCommentSummarizer` class to summarize all the comments.
* Finally, we wil set the `GalleryImage.CommentsSummary` property with the generated summary text.
Here, the implementation:
````csharp
using CmsKitDemo.Entities;
using CmsKitDemo.Utils;
using Microsoft.EntityFrameworkCore;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Domain.Entities.Events;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.EventBus;
using Volo.CmsKit.Comments;
namespace CmsKitDemo.EventHandlers;
public class GalleryImageCommentListener :
ILocalEventHandler<EntityChangedEventData<Comment>>,
ITransientDependency
{
private readonly IRepository<GalleryImage, Guid> _galleryImageRepository;
private readonly IRepository<Comment, Guid> _commentRepository;
private readonly AiCommentSummarizer _aiCommentSummarizer;
public GalleryImageCommentListener(
IRepository<GalleryImage, Guid> galleryImageRepository,
IRepository<Comment, Guid> commentRepository,
AiCommentSummarizer aiCommentSummarizer)
{
_galleryImageRepository = galleryImageRepository;
_commentRepository = commentRepository;
_aiCommentSummarizer = aiCommentSummarizer;
}
public async Task HandleEventAsync(EntityChangedEventData<Comment> eventData)
{
var comment = eventData.Entity;
//Here, we only interest in comments related to image gallery items
if (comment.EntityType != CmsKitDemoConsts.ImageGalleryEntityType)
{
return;
}
if (!Guid.TryParse(comment.EntityId, out var galleryImageId))
{
return;
}
// Get the related image from database
var galleryImage = await _galleryImageRepository.FindAsync(galleryImageId);
if (galleryImage == null)
{
return;
}
// Get all the comments related to the image
var queryable = await _commentRepository.GetQueryableAsync();
var allCommentTexts = await queryable
.Where(c => c.EntityType == CmsKitDemoConsts.ImageGalleryEntityType &&
c.EntityId == comment.EntityId)
.Select(c => c.Text)
.ToArrayAsync();
// Update the summary of comments related to the image
if (allCommentTexts.Length <= 0)
{
galleryImage.CommentsSummary = "";
}
else
{
galleryImage.CommentsSummary =
await _aiCommentSummarizer.SummarizeAsync(allCommentTexts);
}
// Update the image in database
await _galleryImageRepository.UpdateAsync(galleryImage);
}
}
````
Let's explain that class:
* `GalleryImageCommentListener` implements the `ILocalEventHandler<EntityChangedEventData<Comment>>` interface. In this way, it can handle an event whenever a `Comment` [entity](https://abp.io/docs/latest/framework/architecture/domain-driven-design/entities) is changed (created, updated or deleted). We are using ABP's [local event bus](https://abp.io/docs/latest/framework/infrastructure/event-bus/local) and its [pre-defined events](https://abp.io/docs/latest/framework/infrastructure/event-bus/local#pre-built-events).
* `HandleEventAsync` is called by the ABP Framework whenever a new `Comment` is created, or an existing `Comment` is deleted or updated.
* ABP's `Comment` entity is reusable and it can be associated with any kind of objects (blog posts, images, etc). So, first we are checking if this comment is related to an image gallery item.
* Then we are getting the related `GalleryImage` entity from the database.
* And getting all comments (including the new one) from the database for this image.
* Finally, using the `AiCommentSummarizer` class to generate the summary and set the `CommentsSummary` property.
## Show the Summary Card on the UI
Everything is ready on the backend. Now, we can show the summary text on the user interface. To do, that, I added `CommentsSummary` property also to the `GalleryImageDto` class and used it on the `/Pages/Gallery/Detail.cshtml` view:
````csharp
@if (!Model.Image.CommentsSummary.IsNullOrEmpty())
{
<div class="card mt-3">
<div class="card-body">
<h6 class="card-title">Summary of the User Comments</h6>
<p class="mb-auto">@Model.Image.CommentsSummary</p>
</div>
</div>
}
````
That section renders the following card on the user interface:
![summary-card](summary-card.png)
## Conclusion
In this article, I demonstrated how to use [Microsoft AI Extensions Library](https://learn.microsoft.com/en-us/dotnet/ai/ai-extensions) to work with OpenAI for summarization of multiple user comments. I reused the [ABP's CMS Kit Demo application](https://github.com/abpframework/cms-kit-demo) to show it in a more real world example.
## Source Code
* [Source code of the CMS Kit Demo application](https://github.com/abpframework/cms-kit-demo)
* [All the changes made for this article (as a pull request)](https://github.com/abpframework/cms-kit-demo/pull/18)

BIN
docs/en/Community-Articles/2025-04-25-AI-Comment-Summarization/comment-example.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

BIN
docs/en/Community-Articles/2025-04-25-AI-Comment-Summarization/summary-card.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

134
docs/en/Community-Articles/2025-05-11-AI-Chat/POST.md

@ -0,0 +1,134 @@
# Integrating .NET AI Chat Template with ABP Framework
This article demonstrates how to integrate the [.NET AI Chat Template](https://devblogs.microsoft.com/dotnet/announcing-dotnet-ai-template-preview2/) into an ABP Framework application, enabling powerful AI chat capabilities in your ABP-based solution.
![cover](cover.png)
## Step 1: Create a New ABP Project
First, let's create a new [single-layer Blazor Server project](https://abp.io/docs/latest/solution-templates/single-layer-web-application/overview) named `AbpAiChat` using ABP Studio, You can also use the following ABP CLI command to create the project:
```bash
abp new AbpAiChat -t app-nolayers --ui-framework blazor-server --use-open-source-template
```
## Step 2: Integrate AI Chat Template
The integration process involves copying and adapting the .NET AI Chat Template code into our ABP project. The template code is already included in our sample project, so you don't need to install it separately.
### 2.1 Project Structure Changes
1. Copy Blazor components to the `Components` folder
2. Copy AI service classes to the `Services` folder
3. Add required entities(`IngestedDocument`, `IngestedRecord`) to the `AbpAiChatDbContext` and add new migration
4. Copy frontend resources to the `wwwroot` folder
5. Adjust some styles to capatible with the ABP theme
### 2.2 Required NuGet Packages
Add the following packages to `AbpAiChat.csproj`:
```xml
<PackageReference Include="Microsoft.Extensions.AI.OpenAI" Version="9.4.3-preview.1.25230.7" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="9.0.4" />
<PackageReference Include="Microsoft.Extensions.AI" Version="9.4.3-preview.1.25230.7" />
<PackageReference Include="Microsoft.SemanticKernel.Core" Version="1.47.0" />
<PackageReference Include="PdfPig" Version="0.1.9" />
<PackageReference Include="System.Linq.Async" Version="6.0.1" />
```
### 2.3 Configure AI Services
Add the following configuration to `AbpAiChatModule.cs`:
```csharp
private void ConfigureAi(ServiceConfigurationContext context)
{
var credential = new ApiKeyCredential(context.Services.GetConfiguration()["GitHubToken"] ?? throw new InvalidOperationException("Missing configuration: GitHubToken. See the README for details."));
var openAiOptions = new OpenAIClientOptions()
{
Endpoint = new Uri("https://models.inference.ai.azure.com")
};
var ghModelsClient = new OpenAIClient(credential, openAiOptions);
var chatClient = ghModelsClient.GetChatClient("gpt-4o-mini").AsIChatClient();
var embeddingGenerator = ghModelsClient.GetEmbeddingClient("text-embedding-3-small").AsIEmbeddingGenerator();
var vectorStore = new JsonVectorStore(Path.Combine(AppContext.BaseDirectory, "vector-store"));
context.Services.AddSingleton<IVectorStore>(vectorStore);
context.Services.AddScoped<DataIngestor>();
context.Services.AddSingleton<SemanticSearch>();
context.Services.AddChatClient(chatClient).UseFunctionInvocation().UseLogging();
context.Services.AddEmbeddingGenerator(embeddingGenerator);
context.Services.Configure<AbpAspNetCoreContentOptions>(options =>
{
options.ContentTypeMaps.Add(".mjs", "application/javascript");
});
}
```
The `ConfigureAi` method is called in the `ConfigureServices` method of `AbpAiChatModule`. It sets up the AI services, including the OpenAI client, chat client, embedding generator, and vector store.
### 2.4 Configure GitHub Token
Add your GitHub Personal Access Token to `appsettings.json`:
```json
{
"GitHubToken": "your-github-token"
}
```
You can obtain your token from [GitHub Personal Access Tokens](https://github.com/settings/personal-access-tokens).
## Step 3: Add Custom AI Functionality
Let's add a custom AI function to retrieve the current user's information. Update the `Chat.razor` component:
```csharp
chatOptions.Tools =
[
AIFunctionFactory.Create(SearchAsync),
AIFunctionFactory.Create(GetWeather),
AIFunctionFactory.Create(GetCurrentUserInfo)
];
[Description("Get current user information")]
private Task<string> GetCurrentUserInfo()
{
return Task.FromResult(CurrentUser.IsAuthenticated ?
$"UserId: {CurrentUser.Id}, Name: {CurrentUser.UserName}, Email: {CurrentUser.Email}, Roles: {string.Join(", ", CurrentUser.Roles)}" :
"No user information available.");
}
```
## Step 4: Add Navigation
Add a `Chat` menu item in `AbpAiChatMenuContributor` to navigate to the AI Chat component.
## Running the Application
After completing the integration, you can run the application and access the AI chat functionality. The chat interface allows you to:
- Get weather information
- Ask questions about PDF content
- Retrieve current user information
- And more!
![AI Chat Interface](ai-chat.png)
## Conclusion
This integration demonstrates how to leverage the power of AI in your ABP Framework applications. The .NET AI Chat Template provides a solid foundation for building intelligent chat interfaces, and ABP Framework makes it more powerful.
## References
- [ABP Single Layer Solution](https://abp.io/docs/latest/solution-templates/single-layer-web-application/overview)
- [.NET AI Template Documentation](https://devblogs.microsoft.com/dotnet/announcing-dotnet-ai-template-preview1/)
- [GitHub Personal Access Tokens Guide](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens)
## Source Code
- [AbpAiChat Source Code](https://github.com/abpframework/abp-samples/tree/master/AIChat)

BIN
docs/en/Community-Articles/2025-05-11-AI-Chat/ai-chat.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 236 KiB

BIN
docs/en/Community-Articles/2025-05-11-AI-Chat/cover.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 MiB

268
docs/en/Community-Articles/2025-05-19-RouteTenantResolveContributor/POST.md

@ -0,0 +1,268 @@
# Resolving Tenant from Route in ABP Framework
The ABP Framework provides multi-tenancy support with various ways to resolve tenant information, including: Cookie, Header, Domain, Route, and more.
This article will demonstrate how to resolve tenant information from the route.
## Tenant Information in Routes
In the ABP Framework, tenant information in routes is handled by the `RouteTenantResolveContributor`.
Let's say your application is hosted at `https://abp.io` and you have a tenant named `acme`. You can add the `{__tenant}` variable to your controller or page routes like this:
```csharp
[Route("{__tenant}/[Controller]")]
public class MyController : MyProjectNameController
{
[HttpGet]
public IActionResult Get()
{
return Ok("Hello My Page");
}
}
```
```cshtml
@page "{__tenant?}/mypage"
@model MyPageModel
<html>
<body>
<h1>My Page</h1>
</body>
</html>
```
When you access `https://abp.io/acme/my` or `https://abp.io/acme/mypage`, ABP will automatically resolve the tenant information from the route.
## Adding __tenant to Global Routes
While we've shown how to add `{__tenant}` to individual controllers or pages, you might want to add it globally to your entire application. Here's how to implement this:
```cs
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNetCore.Mvc.ApplicationModels;
namespace MyCompanyName;
public class AddTenantRouteToPages : IPageRouteModelConvention, IApplicationModelConvention
{
public void Apply(PageRouteModel model)
{
var selectorCount = model.Selectors.Count;
var selectorModels = new List<SelectorModel>();
for (var i = 0; i < selectorCount; i++)
{
var selector = model.Selectors[i];
selectorModels.Add(new SelectorModel
{
AttributeRouteModel = new AttributeRouteModel
{
Template = AttributeRouteModel.CombineTemplates("{__tenant:regex(^[a-zA-Z0-9]+$)}", selector.AttributeRouteModel!.Template!.RemovePreFix("/"))
}
});
}
foreach (var selectorModel in selectorModels)
{
model.Selectors.Add(selectorModel);
}
}
}
public class AddTenantRouteToControllers :IApplicationModelConvention
{
public void Apply(ApplicationModel application)
{
var controllers = application.Controllers;
foreach (var controller in controllers)
{
var selector = controller.Selectors.FirstOrDefault();
if (selector == null || selector.AttributeRouteModel == null)
{
controller.Selectors.Add(new SelectorModel
{
AttributeRouteModel = new AttributeRouteModel
{
Template = AttributeRouteModel.CombineTemplates("{__tenant:regex(^[[a-zA-Z0-9]]+$)}", controller.ControllerName)
}
});
controller.Selectors.Add(new SelectorModel
{
AttributeRouteModel = new AttributeRouteModel
{
Template = controller.ControllerName
}
});
}
else
{
var template = selector.AttributeRouteModel?.Template;
template = template.IsNullOrWhiteSpace() ? "{__tenant:regex(^[[a-zA-Z0-9]]+$)}" : AttributeRouteModel.CombineTemplates("{__tenant:regex(^[[a-zA-Z0-9]]+$)}", template.RemovePreFix("/"));
controller.Selectors.Add(new SelectorModel
{
AttributeRouteModel = new AttributeRouteModel
{
Template = template
}
});
}
}
}
}
```
Register the services:
```cs
public override void ConfigureServices(ServiceConfigurationContext context)
{
//...
PostConfigure<RazorPagesOptions>(options =>
{
options.Conventions.Add(new AddTenantRouteToPages());
});
PostConfigure<MvcOptions>(options =>
{
options.Conventions.Add(new AddTenantRouteToControllers());
});
// Configure cookie path to prevent authentication cookie loss
context.Services.ConfigureApplicationCookie(x =>
{
x.Cookie.Path = "/";
});
//...
}
```
After implementing this, you'll notice that all controllers in your Swagger UI will have the `{__tenant}` route added:
![Swagger UI](./swagger-ui.png)
## Handling Navigation Links
To ensure navigation links automatically include tenant information, we need to add middleware that dynamically adds the tenant to the PathBase:
```cs
public override void OnApplicationInitialization(ApplicationInitializationContext context)
{
//...
app.Use(async (httpContext, next) =>
{
var tenantMatch = Regex.Match(httpContext.Request.Path, "^/([^/.]+)(?:/.*)?$");
if (tenantMatch.Groups.Count > 1 && !string.IsNullOrEmpty(tenantMatch.Groups[1].Value))
{
var tenantName = tenantMatch.Groups[1].Value;
if (!tenantName.IsNullOrWhiteSpace())
{
var tenantStore = httpContext.RequestServices.GetRequiredService<ITenantStore>();
var tenantNormalizer = httpContext.RequestServices.GetRequiredService<ITenantNormalizer>();
var tenantInfo = await tenantStore.FindAsync(tenantNormalizer.NormalizeName(tenantName)!);
if (tenantInfo != null)
{
if (httpContext.Request.Path.StartsWithSegments(new PathString(tenantName.EnsureStartsWith('/')), out var matchedPath, out var remainingPath))
{
var originalPath = httpContext.Request.Path;
var originalPathBase = httpContext.Request.PathBase;
httpContext.Request.Path = remainingPath;
httpContext.Request.PathBase = originalPathBase.Add(matchedPath);
try
{
await next(httpContext);
}
finally
{
httpContext.Request.Path = originalPath;
httpContext.Request.PathBase = originalPathBase;
}
return;
}
}
}
}
await next(httpContext);
});
app.UseRouting();
app.MapAbpStaticAssets();
//...
}
```
![ui](ui.png)
After setting the PathBase, we need to add a custom tenant resolver to extract tenant information from the `PathBase`:
```cs
public class MyRouteTenantResolveContributor : RouteTenantResolveContributor
{
public const string ContributorName = "MyRoute";
public override string Name => ContributorName;
protected override Task<string?> GetTenantIdOrNameFromHttpContextOrNullAsync(ITenantResolveContext context, HttpContext httpContext)
{
var tenantId = httpContext.GetRouteValue(context.GetAbpAspNetCoreMultiTenancyOptions().TenantKey) ?? httpContext.Request.PathBase.ToString();
var tenantIdStr = tenantId?.ToString()?.RemovePreFix("/");
return Task.FromResult(!tenantIdStr.IsNullOrWhiteSpace() ? Convert.ToString(tenantIdStr) : null);
}
}
```
Register the MyRouteTenantResolveContributor with the ABP Framework:
```cs
public override void ConfigureServices(ServiceConfigurationContext context)
{
//...
Configure<AbpTenantResolveOptions>(options =>
{
options.TenantResolvers.Add(new MyRouteTenantResolveContributor());
});
//...
}
```
### Modifying abp.appPath
```csharp
public override void ConfigureServices(ServiceConfigurationContext context)
{
//...
context.Services.AddOptions<AbpThemingOptions>().Configure<IServiceProvider>((options, rootServiceProvider) =>
{
var currentTenant = rootServiceProvider.GetRequiredService<ICurrentTenant>();
if (!currentTenant.Name.IsNullOrWhiteSpace())
{
options.BaseUrl = currentTenant.Name.EnsureStartsWith('/').EnsureEndsWith('/');
}
});
context.Services.RemoveAll(x => x.ServiceType == typeof(IOptions<AbpThemingOptions>));
context.Services.Add(ServiceDescriptor.Scoped(typeof(IOptions<>), typeof(OptionsManager<>)));
//...
}
```
Browser console output:
```cs
> https://localhost:44303/acme/
> abp.appPath
> '/acme/'
```
## Summary
By following these steps, you can implement tenant resolution from routes in the ABP Framework and handle navigation links appropriately. This approach provides a clean and maintainable way to manage multi-tenancy in your application.
## References
- [ABP Multi-Tenancy](https://docs.abp.io/en/abp/latest/Multi-Tenancy)
- [Routing in ASP.NET Core](https://learn.microsoft.com/en-us/aspnet/core/fundamentals/routing)
- [HTML base tag](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/base)

BIN
docs/en/Community-Articles/2025-05-19-RouteTenantResolveContributor/cover.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

BIN
docs/en/Community-Articles/2025-05-19-RouteTenantResolveContributor/swagger-ui.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 275 KiB

BIN
docs/en/Community-Articles/2025-05-19-RouteTenantResolveContributor/ui.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 112 KiB

38
docs/en/Community-Articles/2025-06-10-bootcamp/post.md

@ -0,0 +1,38 @@
You Asked, We Delivered: Introducing Our New Training Bootcamp\!
Over the past months we’ve heard from countless freelancers, individuals and small teams asking for a focused, high-impact training without the overwhelming commitment or high costs of traditional bootcamps. So here we are\!
We're excited to introduce **ABP Bootcamp: Mastering Infrastructure & Features**, a full training experience designed to help developers level up fast with practical knowledge they can apply immediately.
This live, instructor-led program delivers four days of in-depth, real-world training on ABP’s infrastructure and core features.
**Bootcamp Details**
Dates: July 1,2,3,4 2025
Time: 17:00-19:00 (UTC) each day
Format: Live, online sessions
Price: $399 (discounted $799)
Seats: Limited to a small group
### **What You’ll Learn**
By the end of this bootcamp, you’ll have:
\-A solid understanding of ABP’s infrastructure, systems, and design patterns
\-Practical experience with features like dependency injection, configuration, logging, and localization
\-The ability to implement email templating, event bus, caching, and custom settings in real applications
\-Knowledge of best practices for building scalable, maintainable, and high-performance solutions with ABP
### **Who It’s For**
This bootcamp is ideal for:
\-Developers and freelancers using ABP in their daily work
\-Teams looking to speed up onboarding and improve development efficiency
\-Anyone who wants practical ABP knowledge without committing to long-format training programs
### **Reserve Your Spot**
Seats are limited to keep the experience interactive and personalized. With the current 50% discount, this is the most accessible way to gain hands-on ABP experience with expert guidance.
**Registration is now open. Secure your place today and master the infrastructure that powers ABP. Register here: [https://docs.google.com/forms/d/e/1FAIpQLSckMZChdqIJIuWiEvg\_KsSDmrxagRdc5WBYceAemHLrmT1oiA/viewform](https://docs.google.com/forms/d/e/1FAIpQLSckMZChdqIJIuWiEvg_KsSDmrxagRdc5WBYceAemHLrmT1oiA/viewform)**

BIN
docs/en/Community-Articles/2025-06-12-fix-mongodb-guid-abp-v9.2.0-upgrade/mongo-db.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

93
docs/en/Community-Articles/2025-06-12-fix-mongodb-guid-abp-v9.2.0-upgrade/post.md

@ -0,0 +1,93 @@
# Solving MongoDB GUID Issues After an ABP Framework Upgrade
So, you've just upgraded your ABP Framework application to a newer version (like v9.2.0+) and suddenly, your application can't read data from its MongoDB database. You're seeing strange deserialization errors, especially related to `Guid` types. What's going on?
You've likely run into a classic compatibility issue with the MongoDB .NET driver.
### The Problem: Legacy vs. Standard GUIDs
Here's the short version:
* **Old MongoDB Drivers** (used in older ABP versions) stored `Guid` values in a format called `CSharpLegacy`.
* **New MongoDB Drivers** (v3.0+), now default to a universal `Standard` format.
When your newly upgraded app tries to read old data, the new driver expects the `Standard` format but finds `CSharpLegacy`. The byte orders don't match, and... boom. Deserialization fails.
The ABP Framework team has an excellent official guide covering this topic in detail. We highly recommend reading their **[MongoDB Driver 2 to 3 Migration Guide](https://abp.io/docs/latest/release-info/migration-guides/MongoDB-Driver-2-to-3)** for a full understanding.
Our tip below serves as a fast, application-level fix if you need to get your system back online quickly without performing a full data migration.
### The Quick Fix: Tell the Driver to Use the Old Format
Instead of changing your data, you can simply tell the new driver to continue using the old `CSharpLegacy` format for all `Guid` and `Guid?` properties. This provides immediate backward compatibility without touching your database.
It’s a simple, two-step process.
#### Step 1: Create a Custom Convention
First, create this class in your `.MongoDb` project. It tells the serializer how to handle `Guid` types.
```csharp
using MongoDB.Bson;
using MongoDB.Bson.Serialization;
using MongoDB.Bson.Serialization.Conventions;
using MongoDB.Bson.Serialization.Serializers;
using System;
public class LegacyGuidConvention : ConventionBase, IMemberMapConvention
{
public void Apply(BsonMemberMap memberMap)
{
if (memberMap.MemberType == typeof(Guid))
{
memberMap.SetSerializer(new GuidSerializer(GuidRepresentation.CSharpLegacy));
}
else if (memberMap.MemberType == typeof(Guid?))
{
var guidSerializer = new GuidSerializer(GuidRepresentation.CSharpLegacy);
var nullableGuidSerializer = new NullableSerializer<Guid>(guidSerializer);
memberMap.SetSerializer(nullableGuidSerializer);
}
}
}
```
#### Step 2: Register the Convention at Startup
Now, register this convention in your `YourProjectMongoDbModule.cs` file. Add this code to the top of the `ConfigureServices` method. This ensures your rule is applied globally as soon as the application starts.
```csharp
using Volo.Abp.Modularity;
using MongoDB.Bson.Serialization;
using MongoDB.Bson.Serialization.Conventions;
public class YourProjectMongoDbModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
// Fix Start
var conventionPack = new ConventionPack { new LegacyGuidConvention() };
ConventionRegistry.Register(
"LegacyGuidConvention",
conventionPack,
t => true); // Apply to all types
// Fix End
// ... Your existing ConfigureServices code
}
}
```
### An Alternative to Full Data Migration
It's important to note that the method described here is an **application-level fix**. It's a fantastic alternative to performing a full data migration, which involves writing scripts to convert every legacy GUID in your database.
If you are interested in the more permanent, data-centric approach, the ABP.IO community has a detailed guide on [**Migrating MongoDB GUIDs from Legacy to Standard Format**](https://abp.io/community/articles/migrating-mongodb-guids-from-legacy-to-standard-format-mongodb-v2-to-v3-dqwybdtw).
Our quick fix is ideal for getting a system back online fast or when a database migration is too complex. The full migration is better for long-term standards compliance. Choose the path that best fits your project's needs!
### That's It!
Restart your application, and the errors should be gone. Your app can now correctly read its old `Guid` data, and it will continue to write new data in the same legacy format, ensuring consistency.
This approach is a lifesaver for existing projects, saving you from a risky and time-consuming data migration. For brand-new projects, you might consider starting with the `Standard` representation, but for everything else, this is a clean and effective fix. Happy coding!

113
docs/en/Community-Articles/2025-06-13-modular-docker-container-management/modular-docker-container-management.md

@ -0,0 +1,113 @@
# 🚀 New in ABP Studio: Modular Docker Container Management
We're excited to announce a new improvement to Docker integration in **ABP Studio**!
With the latest update, you can now manage Docker containers **individually**, add or remove them dynamically, and launch them **either separately or collectively** — all within the Studio.
![solution-runner-containers](solution-runner-containers.png)
------
## 🔄 What Has Changed?
In previous versions, Docker dependencies were handled using a **single `docker-compose.override.yml` file**, which was **automatically generated** when creating a new solution if it is needed.
By default, this file included common development dependencies like PostgreSQL, Redis, RabbitMQ, etc., and was executed through a predefined script named `docker-dependencies` in the Solution Runner.
While this approach worked well for simple setups, it had some limitations:
- All services were bundled into a **single compose file**.
- Adding or removing services required modifying this central file.
- It wasn't possible to **start or stop individual containers independently**.
------
## ✅ What's New?
With the latest ABP Studio update:
- Each Docker container can now be defined in its **own `docker-compose` file**.
- Compose files can be **added or removed** from the Studio UI.
- Containers can be:
- **Started or stopped individually**.
- **Started/stopped in bulk**.
- The **Solution Runner** recognizes Docker containers and can run them alongside application projects.
------
## ⚠️ Important Notes Before You Start
### Required: Use `container_name` for Docker Service Matching
When working with the new modular Docker system in ABP Studio, each service **must define a `container_name`**.
This name is used by ABP Studio to **identify and map** Docker containers to their corresponding service entries in the Studio UI.
#### Why is this mandatory?
- ABP Studio relies on `container_name` to:
- Detect whether the service is stopped or continue running.
- Perform **start**, **stop**, and **status check** operations reliably.
- Match Studio UI entries with actual running Docker containers.
- Without a `container_name`, container discovery may fail and **service management features might not work as expected**.
#### Example:
```
services:
redis:
container_name: redis
image: redis:7
ports:
- "6379:6379"
networks:
- my-network
```
> If you do **not** define `container_name`, ABP Studio will be unable to track or control the service properly.
------
## 📥 Migrating from the Old System
If you're using the old method with a centralized compose file:
Before:
```
docker-compose -f docker-compose.override.yml up -d
```
Now:
1. Create separate `docker-compose` files for each service
(e.g., `docker-compose.postgres.yml`, `docker-compose.redis.yml`).
2. Go to the **Solution Runner tab in ABP Studio**.
3. Use the **“Add Docker Service”** option in Studio to register each file.
4. Optionally remove or archive the old monolithic compose file.
> If your original `docker-compose.override.yml` contains multiple services, you can split it into individual files — Docker Compose and ABP Studio both support modular composition.
------
## ⚙️ Advanced: Shared Network
If your containers need to communicate over a shared network, you can define an external network in each compose file like this:
```
networks:
my-network:
external: true
```
ABP Studio automatically creates the network if they do no exist. But if you like you can create the network once using:
```
docker network create my-network
```
------
## 📚 Additional Resources
- Docker Compose Documentation
- ABP Studio Documentation (link to updated docs when ready)
- [Report Issues on GitHub](https://github.com/abpframework/abp/issues)

BIN
docs/en/Community-Articles/2025-06-13-modular-docker-container-management/solution-runner-containers.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

1
docs/en/cli/index.md

@ -889,6 +889,7 @@ Some features of the CLI requires to be logged in to ABP Platform. The login com
```bash
abp login # Opens a default browser to log in to ABP Platform via abp.io
abp login --device # Use device login flow
abp login username -p ****** --password # Use user password login
```
A new login with an already active session overwrites the previous session.

66
docs/en/docs-nav.json

@ -83,47 +83,59 @@
{
"text": "Overview",
"path": "tutorials/book-store",
"isIndex": true
"isIndex": true,
"isInSeries": true
},
{
"text": "1: Creating the Server Side",
"path": "tutorials/book-store/part-01.md"
"path": "tutorials/book-store/part-01.md",
"isInSeries": true
},
{
"text": "2: The Book List Page",
"path": "tutorials/book-store/part-02.md"
"path": "tutorials/book-store/part-02.md",
"isInSeries": true
},
{
"text": "3: Creating, Updating and Deleting Books",
"path": "tutorials/book-store/part-03.md"
"path": "tutorials/book-store/part-03.md",
"isInSeries": true
},
{
"text": "4: Integration Tests",
"path": "tutorials/book-store/part-04.md"
"path": "tutorials/book-store/part-04.md",
"isInSeries": true
},
{
"text": "5: Authorization",
"path": "tutorials/book-store/part-05.md"
"path": "tutorials/book-store/part-05.md",
"isInSeries": true
},
{
"text": "6: Authors: Domain Layer",
"path": "tutorials/book-store/part-06.md"
"path": "tutorials/book-store/part-06.md",
"isInSeries": true
},
{
"text": "7: Authors: Database Integration",
"path": "tutorials/book-store/part-07.md"
"path": "tutorials/book-store/part-07.md",
"isInSeries": true
},
{
"text": "8: Authors: Application Layer",
"path": "tutorials/book-store/part-08.md"
"path": "tutorials/book-store/part-08.md",
"isInSeries": true
},
{
"text": "9: Authors: User Interface",
"path": "tutorials/book-store/part-09.md"
"path": "tutorials/book-store/part-09.md",
"isInSeries": true
},
{
"text": "10: Book to Author Relation",
"path": "tutorials/book-store/part-10.md"
"path": "tutorials/book-store/part-10.md",
"isInSeries": true
}
]
},
@ -135,27 +147,33 @@
{
"text": "Overview",
"path": "tutorials/book-store-with-abp-suite",
"isIndex": true
"isIndex": true,
"isInSeries": true
},
{
"text": "1: Creating the Solution",
"path": "tutorials/book-store-with-abp-suite/part-01.md"
"path": "tutorials/book-store-with-abp-suite/part-01.md",
"isInSeries": true
},
{
"text": "2: Creating the Books",
"path": "tutorials/book-store-with-abp-suite/part-02.md"
"path": "tutorials/book-store-with-abp-suite/part-02.md",
"isInSeries": true
},
{
"text": "3: Creating the Authors",
"path": "tutorials/book-store-with-abp-suite/part-03.md"
"path": "tutorials/book-store-with-abp-suite/part-03.md",
"isInSeries": true
},
{
"text": "4: Book to Author Relation",
"path": "tutorials/book-store-with-abp-suite/part-04.md"
"path": "tutorials/book-store-with-abp-suite/part-04.md",
"isInSeries": true
},
{
"text": "5: Customizing the Generated Code",
"path": "tutorials/book-store-with-abp-suite/part-05.md"
"path": "tutorials/book-store-with-abp-suite/part-05.md",
"isInSeries": true
}
]
},
@ -614,7 +632,7 @@
"path": "framework/infrastructure/blob-storing/google.md"
},
{
"text": "Bunny Provider",
"text": "Bunny.Net Provider",
"path": "framework/infrastructure/blob-storing/bunny.md"
},
{
@ -2070,19 +2088,23 @@
"items": [
{
"text": "Deploy to Azure Web App Service",
"path": "solution-templates/layered-web-application/deployment/azure-deployment/azure-deployment.md"
"path": "solution-templates/layered-web-application/deployment/azure-deployment/azure-deployment.md",
"isInSeries": true
},
{
"text": "Creating an Azure Web App Service Environment",
"path": "solution-templates/layered-web-application/deployment/azure-deployment/step1-create-azure-resources.md"
"path": "solution-templates/layered-web-application/deployment/azure-deployment/step1-create-azure-resources.md",
"isInSeries": true
},
{
"text": "Customizing the Configuration of Your ABP Application",
"path": "solution-templates/layered-web-application/deployment/azure-deployment/step2-configuration-application.md"
"path": "solution-templates/layered-web-application/deployment/azure-deployment/step2-configuration-application.md",
"isInSeries": true
},
{
"text": "Deploying Application With GitHub Actions",
"path": "solution-templates/layered-web-application/deployment/azure-deployment/step3-deployment-github-action.md"
"path": "solution-templates/layered-web-application/deployment/azure-deployment/step3-deployment-github-action.md",
"isInSeries": true
}
]
},

2
docs/en/framework/api-development/static-csharp-clients.md

@ -47,7 +47,7 @@ Implement this class in your service application. You can use [auto API controll
First, add [Volo.Abp.Http.Client](https://www.nuget.org/packages/Volo.Abp.Http.Client) nuget package to your client project:
````
Install-Package Volo.Abp.Http.Client
dotnet add package Volo.Abp.Http.Client
````
Then add `AbpHttpClientModule` dependency to your module:

2
docs/en/framework/api-development/swagger.md

@ -29,7 +29,7 @@ If you want to manually install;
1. Add the [Volo.Abp.Swashbuckle](https://www.nuget.org/packages/Volo.Abp.Swashbuckle) NuGet package to your `Web` or `HttpApi.Host` project:
`Install-Package Volo.Abp.Swashbuckle`
`dotnet add package Volo.Abp.Swashbuckle`
2. Add the `AbpSwashbuckleModule` to the dependency list of your module:

12
docs/en/framework/data/entity-framework-core/mysql.md

@ -17,10 +17,20 @@ Find ***YourProjectName*EntityFrameworkCoreModule** class inside the `.EntityFra
Find `UseSqlServer()` calls in your solution. Check the following files:
* *YourProjectName*EntityFrameworkCoreModule.cs inside the `.EntityFrameworkCore` project. Replace `UseSqlServer()` with `UseMySQL()`.
* *YourProjectName*DbContextFactory.cs inside the `.EntityFrameworkCore` project. Replace `UseSqlServer()` with `UseMySql()`. Then add a new parameter (`ServerVersion`) to `UseMySql()` method. Example: `.UseMySql(configuration.GetConnectionString("Default"), ServerVersion.Parse("8.0.21-mysql"))`. See [this issue](https://github.com/PomeloFoundation/Pomelo.EntityFrameworkCore.MySql/pull/1233) for more information about `ServerVersion`)
* *YourProjectName*DbContextFactory.cs inside the `.EntityFrameworkCore` project. Replace `UseSqlServer()` with `UseMySQL()`.
> Depending on your solution structure, you may find more code files need to be changed.
## Use Pomelo Provider
Alternatively, you can use the [Pomelo.EntityFrameworkCore.MySql](https://www.nuget.org/packages/Pomelo.EntityFrameworkCore.MySql) provider. Replace the [Volo.Abp.EntityFrameworkCore.MySQL](https://www.nuget.org/packages/Volo.Abp.EntityFrameworkCore.MySQL) package with the [Volo.Abp.EntityFrameworkCore.MySQL.Pomelo](https://www.nuget.org/packages/Volo.Abp.EntityFrameworkCore.MySQL.Pomelo) package in your `.EntityFrameworkCore` project.
Find ***YourProjectName*EntityFrameworkCoreModule** class inside the `.EntityFrameworkCore` project, replace `typeof(AbpEntityFrameworkCoreMySQLModule)` with `typeof(AbpEntityFrameworkCoreMySQLPomeloModule)` in the `DependsOn` attribute.
> Depending on your solution structure, you may find more code files need to be changed.
The `UseMySQL()` method calls remain the same, no changes needed.
## Change the Connection Strings
MySQL connection strings are different than SQL Server connection strings. So, check all `appsettings.json` files in your solution and replace the connection strings inside them. See the [connectionstrings.com](https://www.connectionstrings.com/mysql) for details of MySQL connection string options.

2
docs/en/framework/fundamentals/fluent-validation.md

@ -21,7 +21,7 @@ If you want to manually install;
1. Add the [Volo.Abp.FluentValidation](https://www.nuget.org/packages/Volo.Abp.FluentValidation) NuGet package to your project:
````
Install-Package Volo.Abp.FluentValidation
dotnet add package Volo.Abp.FluentValidation
````
2. Add the `AbpFluentValidationModule` to the dependency list of your module:

2
docs/en/framework/infrastructure/background-jobs/hangfire.md

@ -25,7 +25,7 @@ If you want to manually install;
1. Add the [Volo.Abp.BackgroundJobs.HangFire](https://www.nuget.org/packages/Volo.Abp.BackgroundJobs.HangFire) NuGet package to your project:
````
Install-Package Volo.Abp.BackgroundJobs.HangFire
dotnet add package Volo.Abp.BackgroundJobs.HangFire
````
2. Add the `AbpBackgroundJobsHangfireModule` to the dependency list of your module:

19
docs/en/framework/infrastructure/background-jobs/index.md

@ -134,6 +134,25 @@ namespace MyProject
}
```
##### Custom Job Name
You can configure `GetBackgroundJobName` delegate of the `AbpBackgroundJobOptions` to change the default job name.
```csharp
Configure<AbpBackgroundJobOptions>(options =>
{
options.GetBackgroundJobName = (jobType) =>
{
if (jobTyep == typeof(EmailSendingArgs))
{
return "emails";
}
return BackgroundJobNameAttribute.GetName(jobType);
};
});
```
### Queue a Job Item
Now, you can queue an email sending job using the `IBackgroundJobManager` service:

2
docs/en/framework/infrastructure/background-jobs/quartz.md

@ -25,7 +25,7 @@ If you want to manually install;
1. Add the [Volo.Abp.BackgroundJobs.Quartz](https://www.nuget.org/packages/Volo.Abp.BackgroundJobs.Quartz) NuGet package to your project:
````
Install-Package Volo.Abp.BackgroundJobs.Quartz
dotnet add package Volo.Abp.BackgroundJobs.Quartz
````
2. Add the `AbpBackgroundJobsQuartzModule` to the dependency list of your module:

2
docs/en/framework/infrastructure/background-workers/hangfire.md

@ -23,7 +23,7 @@ If you want to manually install;
1. Add the [Volo.Abp.BackgroundWorkers.Hangfire](https://www.nuget.org/packages/Volo.Abp.BackgroundWorkers.Hangfire) NuGet package to your project:
````
Install-Package Volo.Abp.BackgroundWorkers.Hangfire
dotnet add package Volo.Abp.BackgroundWorkers.Hangfire
````
2. Add the `AbpBackgroundWorkersHangfireModule` to the dependency list of your module:

3
docs/en/framework/infrastructure/background-workers/index.md

@ -41,6 +41,8 @@ Start your worker in the `StartAsync` (which is called when the application begi
Assume that we want to make a user passive, if the user has not logged in to the application in last 30 days. `AsyncPeriodicBackgroundWorkerBase` class simplifies to create periodic workers, so we will use it for the example below:
> You can use `CronExpression` property to set the cron expression for the background worker if you will use the [Hangfire Background Worker Manager](./hangfire.md) or [Quartz Background Worker Manager](./quartz.md).
````csharp
public class PassiveUserCheckerWorker : AsyncPeriodicBackgroundWorkerBase
{
@ -52,6 +54,7 @@ public class PassiveUserCheckerWorker : AsyncPeriodicBackgroundWorkerBase
serviceScopeFactory)
{
Timer.Period = 600000; //10 minutes
//CronExpression = "0 0/10 * * * ?"; //Run every 10 minutes, Only for Quartz or Hangfire integration.
}
protected async override Task DoWorkAsync(

2
docs/en/framework/infrastructure/background-workers/quartz.md

@ -21,7 +21,7 @@ If you want to manually install;
1. Add the [Volo.Abp.BackgroundWorkers.Quartz](https://www.nuget.org/packages/Volo.Abp.BackgroundWorkers.Quartz) NuGet package to your project:
````
Install-Package Volo.Abp.BackgroundWorkers.Quartz
dotnet add package Volo.Abp.BackgroundWorkers.Quartz
````
2. Add the `AbpBackgroundWorkersQuartzModule` to the dependency list of your module:

8
docs/en/framework/infrastructure/image-manipulation.md

@ -22,7 +22,7 @@ If you want to manually install;
1. Add the [Volo.Abp.Imaging.Abstractions](https://www.nuget.org/packages/Volo.Abp.Imaging.Abstractions) NuGet package to your project:
```
Install-Package Volo.Abp.Imaging.Abstractions
dotnet add package Volo.Abp.Imaging.Abstractions
```
2. Add the `AbpImagingAbstractionsModule` to the dependency list of your module:
@ -240,7 +240,7 @@ If you want to manually install;
1. Add the [Volo.Abp.Imaging.MagickNet](https://www.nuget.org/packages/Volo.Abp.Imaging.MagickNet) NuGet package to your project:
```
Install-Package Volo.Abp.Imaging.MagickNet
dotnet add package Volo.Abp.Imaging.MagickNet
```
2. Add `AbpImagingMagickNetModule` to your [module](../architecture/modularity/basics.md)'s dependency list:
@ -284,7 +284,7 @@ If you want to manually install;
1. Add the [Volo.Abp.Imaging.ImageSharp](https://www.nuget.org/packages/Volo.Abp.Imaging.ImageSharp) NuGet package to your project:
```
Install-Package Volo.Abp.Imaging.ImageSharp
dotnet add package Volo.Abp.Imaging.ImageSharp
```
2. Add `AbpImagingImageSharpModule` to your [module](../architecture/modularity/basics.md)'s dependency list:
@ -350,7 +350,7 @@ If you want to manually install;
1. Add the [Volo.Abp.Imaging.AspNetCore](https://www.nuget.org/packages/Volo.Abp.Imaging.AspNetCore) NuGet package to your project:
```
Install-Package Volo.Abp.Imaging.AspNetCore
dotnet add package Volo.Abp.Imaging.AspNetCore
```
2. Add `AbpImagingAspNetCoreModule` to your [module](../architecture/modularity/basics.md)'s dependency list:

2
docs/en/framework/infrastructure/sms-sending.md

@ -26,7 +26,7 @@ If you want to manually install;
1. Add the [Volo.Abp.Sms](https://www.nuget.org/packages/Volo.Abp.Sms) NuGet package to your project:
```
Install-Package Volo.Abp.Sms
dotnet add package Volo.Abp.Sms
```
2. Add the `AbpSmsModule` to the dependency list of your module:

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save