Browse Source

Merge branch 'dev' into ai

pull/23533/head
enisn 1 year ago
parent
commit
2af4ec2d5a
No known key found for this signature in database GPG Key ID: A052619F04155D1C
  1. 20
      .github/workflows/auto-pr.yml
  2. 6
      .github/workflows/build-and-test.yml
  3. 271
      Directory.Packages.props
  4. 2
      README.md
  5. 8
      abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json
  6. 2
      abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json
  7. 11
      abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/en.json
  8. 4
      common.props
  9. 86
      docs/en/Blog-Posts/2025-06-02 v9_2_Release_Stable/POST.md
  10. BIN
      docs/en/Blog-Posts/2025-06-02 v9_2_Release_Stable/cover-image.png
  11. BIN
      docs/en/Blog-Posts/2025-06-02 v9_2_Release_Stable/upgrade-abp-packages.png
  12. 97
      docs/en/Blog-Posts/2025-06-10-Announcing-ABP-Studio-1.0-Stable-Release/POST.md
  13. BIN
      docs/en/Blog-Posts/2025-06-10-Announcing-ABP-Studio-1.0-Stable-Release/abp-studio-check-for-updates.png
  14. BIN
      docs/en/Blog-Posts/2025-06-10-Announcing-ABP-Studio-1.0-Stable-Release/abp-studio-download.png
  15. BIN
      docs/en/Blog-Posts/2025-06-10-Announcing-ABP-Studio-1.0-Stable-Release/containers-type.png
  16. BIN
      docs/en/Blog-Posts/2025-06-10-Announcing-ABP-Studio-1.0-Stable-Release/cover-image.png
  17. BIN
      docs/en/Blog-Posts/2025-06-10-Announcing-ABP-Studio-1.0-Stable-Release/health-checks.png
  18. BIN
      docs/en/Blog-Posts/2025-06-10-Announcing-ABP-Studio-1.0-Stable-Release/new-migration-added.gif
  19. BIN
      docs/en/Blog-Posts/2025-06-10-Announcing-ABP-Studio-1.0-Stable-Release/saas-health-check.png
  20. BIN
      docs/en/Blog-Posts/2025-06-10-Announcing-ABP-Studio-1.0-Stable-Release/theme-style-selection-leptonx.png
  21. 203
      docs/en/Blog-Posts/2025-06-18 v9_3_Preview/POST.md
  22. BIN
      docs/en/Blog-Posts/2025-06-18 v9_3_Preview/abp-studio.png
  23. BIN
      docs/en/Blog-Posts/2025-06-18 v9_3_Preview/audit-logs-export-to-excel.png
  24. BIN
      docs/en/Blog-Posts/2025-06-18 v9_3_Preview/bootcamp.png
  25. BIN
      docs/en/Blog-Posts/2025-06-18 v9_3_Preview/community-talk-2025-5.png
  26. BIN
      docs/en/Blog-Posts/2025-06-18 v9_3_Preview/cover-image.png
  27. BIN
      docs/en/Blog-Posts/2025-06-18 v9_3_Preview/download-pdf-on-docs.png
  28. BIN
      docs/en/Blog-Posts/2025-06-18 v9_3_Preview/generate-pdf-docs.png
  29. BIN
      docs/en/Blog-Posts/2025-06-18 v9_3_Preview/studio-switch-to-preview.png
  30. 6
      docs/en/Community-Articles/2020-09-09-Replacing-Email-Template-and-Sending-Emails/POST.md
  31. 12
      docs/en/Community-Articles/2020-12-10-How-to-Integrate-the-Telerik-Blazor-Component/POST.md
  32. 16
      docs/en/Community-Articles/2021-06-17-Using-Elsa-Workflow-with-ABP-Framework/POST.md
  33. 12
      docs/en/Community-Articles/2021-10-31-Many-to-Many-Relationship-with-ABP-and-EF-Core/POST.md
  34. 12
      docs/en/Community-Articles/2021-12-13-Integrating-the-Syncfusion-MVC-Components-to-the-ABP-MVC-UI/POST.md
  35. 10
      docs/en/Community-Articles/2022-02-06-How-to-Hide-ABP-Related-Endpoints-on-Swagger-UI/POST.md
  36. 12
      docs/en/Community-Articles/2022-04-06-Concurrency-Check-in-ABP-Based-Applications/POST.md
  37. 12
      docs/en/Community-Articles/2022-11-22-gRPC-JSON-Transcoding/POST.md
  38. 12
      docs/en/Community-Articles/2022-18-11-whats-new-with-net7/POST.md
  39. 12
      docs/en/Community-Articles/2023-07-03-Image-Compression-And-Resize/POST.md
  40. 12
      docs/en/Community-Articles/2023-08-12-ABP-Commercial-GDPR-Module-Overview/POST.md
  41. 12
      docs/en/Community-Articles/2023-10-30-NET-8-ASP-NET-Core-Metrics/POST.md
  42. 12
      docs/en/Community-Articles/2023-11-16-Upgrading-Your-Existing-Projects-to-NET8/POST.md
  43. 12
      docs/en/Community-Articles/2024-01-18-ABP-Now-Supports-Keyed-Services/POST.md
  44. 6
      docs/en/Community-Articles/2024-04-19-Performing-Case-Insensitive-Search-In-Postgresql/POST.md
  45. 12
      docs/en/Community-Articles/2024-05-10-Sentiment-Analysis-within-ABP-Based-Application/POST.md
  46. 12
      docs/en/Community-Articles/2024-11-01-Hybrid-Cache-Net-9/POST.md
  47. 12
      docs/en/Community-Articles/2025-02-04-OpenIddict-Custom-Logic/POST.md
  48. 4
      docs/en/Community-Articles/2025-03-23-Understanding-the-Embedded-Files-in-ABP-Framework/post.md
  49. 12
      docs/en/Community-Articles/2025-03-24-How-to-Change-the-CurrentUser-in-ABP/POST.md
  50. BIN
      docs/en/Community-Articles/2025-04-20-IDX10204/header.png
  51. BIN
      docs/en/Community-Articles/2025-04-20-IDX10204/payload.png
  52. BIN
      docs/en/Community-Articles/2025-04-25-AI-Comment-Summarization/summary-card.png
  53. 134
      docs/en/Community-Articles/2025-05-11-AI-Chat/POST.md
  54. BIN
      docs/en/Community-Articles/2025-05-11-AI-Chat/ai-chat.png
  55. BIN
      docs/en/Community-Articles/2025-05-11-AI-Chat/cover.png
  56. 268
      docs/en/Community-Articles/2025-05-19-RouteTenantResolveContributor/POST.md
  57. BIN
      docs/en/Community-Articles/2025-05-19-RouteTenantResolveContributor/cover.png
  58. BIN
      docs/en/Community-Articles/2025-05-19-RouteTenantResolveContributor/swagger-ui.png
  59. BIN
      docs/en/Community-Articles/2025-05-19-RouteTenantResolveContributor/ui.png
  60. 38
      docs/en/Community-Articles/2025-06-10-bootcamp/post.md
  61. BIN
      docs/en/Community-Articles/2025-06-12-fix-mongodb-guid-abp-v9.2.0-upgrade/mongo-db.jpg
  62. 93
      docs/en/Community-Articles/2025-06-12-fix-mongodb-guid-abp-v9.2.0-upgrade/post.md
  63. 113
      docs/en/Community-Articles/2025-06-13-modular-docker-container-management/modular-docker-container-management.md
  64. BIN
      docs/en/Community-Articles/2025-06-13-modular-docker-container-management/solution-runner-containers.png
  65. 250
      docs/en/Community-Articles/2025-06-20-Using-Hangfire-Dashboard-in-ABP-API-website/POST.md
  66. BIN
      docs/en/Community-Articles/2025-06-20-Using-Hangfire-Dashboard-in-ABP-API-website/gif.gif
  67. 2
      docs/en/cli/differences-between-old-and-new-cli.md
  68. 6
      docs/en/cli/index.md
  69. 68
      docs/en/docs-nav.json
  70. 14
      docs/en/framework/architecture/modularity/basics.md
  71. 221
      docs/en/framework/architecture/modularity/installer-projects.md
  72. 13
      docs/en/framework/architecture/multi-tenancy/index.md
  73. 33
      docs/en/framework/data/entity-framework-core/index.md
  74. 51
      docs/en/framework/fundamentals/configuration.md
  75. 63
      docs/en/framework/infrastructure/background-jobs/hangfire.md
  76. 19
      docs/en/framework/infrastructure/background-jobs/index.md
  77. 3
      docs/en/framework/infrastructure/background-workers/index.md
  78. 2
      docs/en/framework/infrastructure/features.md
  79. 4
      docs/en/framework/infrastructure/simple-state-checker.md
  80. 4
      docs/en/framework/real-time/signalr.md
  81. 2
      docs/en/framework/ui/mvc-razor-pages/basic-theme.md
  82. 11
      docs/en/framework/ui/mvc-razor-pages/client-side-package-management.md
  83. BIN
      docs/en/get-started/images/abp-studio-new-solution-dialog-modularity.png
  84. BIN
      docs/en/get-started/images/abp-studio-no-layers-new-solution-dialog-ui-framework-0.9.13.png
  85. BIN
      docs/en/get-started/images/abp-studio-no-layers-new-solution-modularity.png
  86. 10
      docs/en/get-started/layered-web-application.md
  87. 4
      docs/en/get-started/maui.md
  88. 4
      docs/en/get-started/microservice.md
  89. 8
      docs/en/get-started/pre-requirements.md
  90. 16
      docs/en/get-started/single-layer-web-application.md
  91. BIN
      docs/en/images/azure-deploy-create-web-app-2.png
  92. BIN
      docs/en/images/azure-deploy-create-web-app-6.png
  93. 2
      docs/en/modules/account/idle-session-timeout.md
  94. 40
      docs/en/modules/audit-logging-pro.md
  95. 11
      docs/en/modules/language-management.md
  96. 6
      docs/en/modules/payment-custom-gateway.md
  97. 46
      docs/en/release-info/migration-guides/abp-9-3.md
  98. 1
      docs/en/release-info/migration-guides/index.md
  99. 13
      docs/en/release-info/release-notes.md
  100. 6
      docs/en/release-info/road-map.md

20
.github/workflows/auto-pr.yml

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

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

@ -48,7 +48,7 @@ permissions:
jobs: jobs:
build-test: build-test:
runs-on: ubuntu-22.04 runs-on: ubuntu-22.04
timeout-minutes: 40 timeout-minutes: 50
if: ${{ !github.event.pull_request.draft }} if: ${{ !github.event.pull_request.draft }}
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
@ -56,10 +56,6 @@ jobs:
with: with:
dotnet-version: 9.0.100 dotnet-version: 9.0.100
- name: chown
run: |
sudo chown -R $USER:$USER /home/runneradmin
- name: Build All - name: Build All
run: ./build-all.ps1 run: ./build-all.ps1
working-directory: ./build working-directory: ./build

271
Directory.Packages.props

@ -3,188 +3,187 @@
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally> <ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageVersion Include="AlibabaCloud.SDK.Dysmsapi20170525" Version="3.0.0" /> <PackageVersion Include="AlibabaCloud.SDK.Dysmsapi20170525" Version="4.0.0" />
<PackageVersion Include="aliyun-net-sdk-sts" Version="3.1.2" /> <PackageVersion Include="aliyun-net-sdk-sts" Version="3.1.2" />
<PackageVersion Include="Aliyun.OSS.SDK.NetCore" Version="2.14.1" /> <PackageVersion Include="Aliyun.OSS.SDK.NetCore" Version="2.14.1" />
<PackageVersion Include="AsyncKeyedLock" Version="7.1.3" /> <PackageVersion Include="AsyncKeyedLock" Version="7.1.6" />
<PackageVersion Include="Autofac" Version="8.1.0" /> <PackageVersion Include="Autofac" Version="8.2.1" />
<PackageVersion Include="Autofac.Extensions.DependencyInjection" Version="10.0.0" /> <PackageVersion Include="Autofac.Extensions.DependencyInjection" Version="10.0.0" />
<PackageVersion Include="Autofac.Extras.DynamicProxy" Version="7.1.0" /> <PackageVersion Include="Autofac.Extras.DynamicProxy" Version="7.1.0" />
<PackageVersion Include="AutoMapper" Version="13.0.1" /> <PackageVersion Include="AutoMapper" Version="14.0.0" />
<PackageVersion Include="Asp.Versioning.Mvc" Version="8.1.0" /> <PackageVersion Include="Asp.Versioning.Mvc" Version="8.1.0" />
<PackageVersion Include="Asp.Versioning.Mvc.ApiExplorer" Version="8.1.0" /> <PackageVersion Include="Asp.Versioning.Mvc.ApiExplorer" Version="8.1.0" />
<PackageVersion Include="AWSSDK.S3" Version="3.7.410.9" /> <PackageVersion Include="AWSSDK.S3" Version="4.0.0" />
<PackageVersion Include="AWSSDK.SecurityToken" Version="3.7.401.16" /> <PackageVersion Include="AWSSDK.SecurityToken" Version="4.0.0" />
<PackageVersion Include="BunnyCDN.Net.Storage" Version="1.0.4" /> <PackageVersion Include="BunnyCDN.Net.Storage" Version="1.0.4" />
<PackageVersion Include="Azure.Messaging.ServiceBus" Version="7.18.1" /> <PackageVersion Include="Azure.Messaging.ServiceBus" Version="7.19.0" />
<PackageVersion Include="Azure.Storage.Blobs" Version="12.22.1" /> <PackageVersion Include="Azure.Storage.Blobs" Version="12.24.0" />
<PackageVersion Include="Blazorise" Version="1.7.6" /> <PackageVersion Include="Blazorise" Version="1.8.0" />
<PackageVersion Include="Blazorise.Components" Version="1.7.6" /> <PackageVersion Include="Blazorise.Components" Version="1.8.0" />
<PackageVersion Include="Blazorise.DataGrid" Version="1.7.6" /> <PackageVersion Include="Blazorise.DataGrid" Version="1.8.0" />
<PackageVersion Include="Blazorise.Snackbar" Version="1.7.6" /> <PackageVersion Include="Blazorise.Snackbar" Version="1.8.0" />
<PackageVersion Include="Castle.Core" Version="5.1.1" /> <PackageVersion Include="Castle.Core" Version="5.1.1" />
<PackageVersion Include="Castle.Core.AsyncInterceptor" Version="2.1.0" /> <PackageVersion Include="Castle.Core.AsyncInterceptor" Version="2.1.0" />
<PackageVersion Include="CommonMark.NET" Version="0.15.1" /> <PackageVersion Include="CommonMark.NET" Version="0.15.1" />
<PackageVersion Include="Confluent.Kafka" Version="2.5.3" /> <PackageVersion Include="Confluent.Kafka" Version="2.10.0" />
<PackageVersion Include="Dapper" Version="2.1.44" /> <PackageVersion Include="Dapper" Version="2.1.66" />
<PackageVersion Include="Dapr.AspNetCore" Version="1.14.0" /> <PackageVersion Include="Dapr.AspNetCore" Version="1.15.4" />
<PackageVersion Include="Dapr.Client" Version="1.14.0" /> <PackageVersion Include="Dapr.Client" Version="1.15.4" />
<PackageVersion Include="DeviceDetector.NET" Version="6.3.3" /> <PackageVersion Include="MyCSharp.HttpUserAgentParser" Version="3.0.25" />
<PackageVersion Include="Devart.Data.Oracle.EFCore" Version="10.4.190.9" /> <PackageVersion Include="Devart.Data.Oracle.EFCore" Version="10.4.235.9" />
<PackageVersion Include="DistributedLock.Core" Version="1.0.7" /> <PackageVersion Include="DistributedLock.Core" Version="1.0.8" />
<PackageVersion Include="DistributedLock.Redis" Version="1.0.3" /> <PackageVersion Include="DistributedLock.Redis" Version="1.0.3" />
<PackageVersion Include="DeepL.net" Version="1.10.0" /> <PackageVersion Include="DeepL.net" Version="1.15.0" />
<PackageVersion Include="EphemeralMongo.Core" Version="1.1.3" /> <PackageVersion Include="itext.bouncy-castle-adapter" Version="9.2.0" />
<PackageVersion Include="EphemeralMongo6.runtime.linux-x64" Version="1.1.3" /> <PackageVersion Include="itext7" Version="9.2.0" />
<PackageVersion Include="EphemeralMongo6.runtime.osx-x64" Version="1.1.3" /> <PackageVersion Include="itext7.pdfhtml" Version="6.2.0" />
<PackageVersion Include="EphemeralMongo6.runtime.win-x64" Version="1.1.3" /> <PackageVersion Include="MongoSandbox.Core" Version="2.0.0" />
<PackageVersion Include="MongoSandbox.Core" Version="1.0.1" /> <PackageVersion Include="MongoSandbox8.runtime.linux-x64" Version="2.0.0" />
<PackageVersion Include="MongoSandbox6.runtime.linux-x64" Version="1.0.1" /> <PackageVersion Include="MongoSandbox8.runtime.osx-arm64" Version="2.0.0" />
<PackageVersion Include="MongoSandbox6.runtime.osx-x64" Version="1.0.1" /> <PackageVersion Include="MongoSandbox8.runtime.win-x64" Version="2.0.0" />
<PackageVersion Include="MongoSandbox6.runtime.win-x64" Version="1.0.1" /> <PackageVersion Include="FluentValidation" Version="11.11.0" />
<PackageVersion Include="FluentValidation" Version="11.10.0" /> <PackageVersion Include="Google.Cloud.Storage.V1" Version="4.13.0" />
<PackageVersion Include="Google.Cloud.Storage.V1" Version="4.10.0" />
<PackageVersion Include="Hangfire.AspNetCore" Version="1.8.18" /> <PackageVersion Include="Hangfire.AspNetCore" Version="1.8.18" />
<PackageVersion Include="Hangfire.SqlServer" Version="1.8.18" /> <PackageVersion Include="Hangfire.SqlServer" Version="1.8.18" />
<PackageVersion Include="HtmlSanitizer" Version="8.1.870" /> <PackageVersion Include="HtmlSanitizer" Version="9.0.884" />
<PackageVersion Include="IdentityModel" Version="7.0.0" /> <PackageVersion Include="IdentityModel" Version="7.0.0" />
<PackageVersion Include="IdentityServer4" Version="4.1.2" /> <PackageVersion Include="IdentityServer4" Version="4.1.2" />
<PackageVersion Include="IdentityServer4.AspNetIdentity" Version="4.1.2" /> <PackageVersion Include="IdentityServer4.AspNetIdentity" Version="4.1.2" />
<PackageVersion Include="JetBrains.Annotations" Version="2024.2.0" /> <PackageVersion Include="JetBrains.Annotations" Version="2024.3.0" />
<PackageVersion Include="LdapForNet" Version="2.7.15" /> <PackageVersion Include="LdapForNet" Version="2.7.15" />
<PackageVersion Include="LibGit2Sharp" Version="0.30.0" /> <PackageVersion Include="LibGit2Sharp" Version="0.31.0" />
<PackageVersion Include="Magick.NET-Q16-AnyCPU" Version="13.4.0" /> <PackageVersion Include="Magick.NET-Q16-AnyCPU" Version="13.4.0" />
<PackageVersion Include="MailKit" Version="4.8.0" /> <PackageVersion Include="MailKit" Version="4.12.0" />
<PackageVersion Include="Markdig.Signed" Version="0.37.0" /> <PackageVersion Include="Markdig.Signed" Version="0.41.1" />
<PackageVersion Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="9.0.2" /> <PackageVersion Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="9.0.5" />
<PackageVersion Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="9.0.2" /> <PackageVersion Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="9.0.5" />
<PackageVersion Include="Microsoft.AspNetCore.Authorization" Version="9.0.2" /> <PackageVersion Include="Microsoft.AspNetCore.Authorization" Version="9.0.5" />
<PackageVersion Include="Microsoft.AspNetCore.Components" Version="9.0.2" /> <PackageVersion Include="Microsoft.AspNetCore.Components" Version="9.0.5" />
<PackageVersion Include="Microsoft.AspNetCore.Components.Authorization" Version="9.0.2" /> <PackageVersion Include="Microsoft.AspNetCore.Components.Authorization" Version="9.0.5" />
<PackageVersion Include="Microsoft.AspNetCore.Components.Web" Version="9.0.2" /> <PackageVersion Include="Microsoft.AspNetCore.Components.Web" Version="9.0.5" />
<PackageVersion Include="Microsoft.AspNetCore.Components.WebAssembly" Version="9.0.2" /> <PackageVersion Include="Microsoft.AspNetCore.Components.WebAssembly" Version="9.0.5" />
<PackageVersion Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="9.0.2" /> <PackageVersion Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="9.0.5" />
<PackageVersion Include="Microsoft.AspNetCore.Components.WebAssembly.Authentication" Version="9.0.2" /> <PackageVersion Include="Microsoft.AspNetCore.Components.WebAssembly.Authentication" Version="9.0.5" />
<PackageVersion Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="9.0.2" /> <PackageVersion Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="9.0.5" />
<PackageVersion Include="Microsoft.AspNetCore.Components.WebView.Maui" Version="9.0.30" /> <PackageVersion Include="Microsoft.AspNetCore.Components.WebView.Maui" Version="9.0.60" />
<PackageVersion Include="Microsoft.Maui.Controls" Version="9.0.30" /> <PackageVersion Include="Microsoft.Maui.Controls" Version="9.0.60" />
<PackageVersion Include="Microsoft.AspNetCore.DataProtection.StackExchangeRedis" Version="9.0.2" /> <PackageVersion Include="Microsoft.AspNetCore.DataProtection.StackExchangeRedis" Version="9.0.5" />
<PackageVersion Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="9.0.2" /> <PackageVersion Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="9.0.5" />
<PackageVersion Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="9.0.2" /> <PackageVersion Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="9.0.5" />
<PackageVersion Include="Microsoft.AspNetCore.Mvc.Testing" Version="9.0.2" /> <PackageVersion Include="Microsoft.AspNetCore.Mvc.Testing" Version="9.0.5" />
<PackageVersion Include="Microsoft.AspNetCore.Razor.Language" Version="6.0.36" /> <PackageVersion Include="Microsoft.AspNetCore.Razor.Language" Version="6.0.36" />
<PackageVersion Include="Microsoft.AspNetCore.TestHost" Version="9.0.2" /> <PackageVersion Include="Microsoft.AspNetCore.TestHost" Version="9.0.5" />
<PackageVersion Include="Microsoft.AspNetCore.WebUtilities" Version="9.0.2" /> <PackageVersion Include="Microsoft.AspNetCore.WebUtilities" Version="9.0.5" />
<PackageVersion Include="Microsoft.Bcl.AsyncInterfaces" Version="9.0.2" /> <PackageVersion Include="Microsoft.Bcl.AsyncInterfaces" Version="9.0.5" />
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="4.5.0" /> <PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="4.5.0" />
<PackageVersion Include="Microsoft.CSharp" Version="4.7.0" /> <PackageVersion Include="Microsoft.CSharp" Version="4.7.0" />
<PackageVersion Include="Microsoft.Data.Sqlite" Version="9.0.2" /> <PackageVersion Include="Microsoft.Data.Sqlite" Version="9.0.5" />
<PackageVersion Include="Microsoft.Data.SqlClient" Version="6.0.1" /> <PackageVersion Include="Microsoft.Data.SqlClient" Version="6.0.2" />
<PackageVersion Include="Microsoft.EntityFrameworkCore" Version="9.0.2" /> <PackageVersion Include="Microsoft.EntityFrameworkCore" Version="9.0.5" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Design" Version="9.0.2" /> <PackageVersion Include="Microsoft.EntityFrameworkCore.Design" Version="9.0.5" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.InMemory" Version="9.0.2" /> <PackageVersion Include="Microsoft.EntityFrameworkCore.InMemory" Version="9.0.5" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Proxies" Version="9.0.2" /> <PackageVersion Include="Microsoft.EntityFrameworkCore.Proxies" Version="9.0.5" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Relational" Version="9.0.2" /> <PackageVersion Include="Microsoft.EntityFrameworkCore.Relational" Version="9.0.5" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Sqlite" Version="9.0.2" /> <PackageVersion Include="Microsoft.EntityFrameworkCore.Sqlite" Version="9.0.5" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.SqlServer" Version="9.0.2" /> <PackageVersion Include="Microsoft.EntityFrameworkCore.SqlServer" Version="9.0.5" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Tools" Version="9.0.2" /> <PackageVersion Include="Microsoft.EntityFrameworkCore.Tools" Version="9.0.5" />
<PackageVersion Include="Microsoft.Extensions.AI" Version="9.4.0-preview.1.25207.5" /> <PackageVersion Include="Microsoft.Extensions.AI" Version="9.4.0-preview.1.25207.5" />
<PackageVersion Include="Microsoft.Extensions.Caching.Hybrid" Version="9.0.0-preview.7.24406.2" /> <PackageVersion Include="Microsoft.Extensions.Caching.Hybrid" Version="9.4.0" />
<PackageVersion Include="Microsoft.Extensions.Caching.Memory" Version="9.0.2" /> <PackageVersion Include="Microsoft.Extensions.Caching.Memory" Version="9.0.5" />
<PackageVersion Include="Microsoft.Extensions.Caching.StackExchangeRedis" Version="9.0.2" /> <PackageVersion Include="Microsoft.Extensions.Caching.StackExchangeRedis" Version="9.0.5" />
<PackageVersion Include="Microsoft.Extensions.Configuration.Binder" Version="9.0.2" /> <PackageVersion Include="Microsoft.Extensions.Configuration.Binder" Version="9.0.5" />
<PackageVersion Include="Microsoft.Extensions.Configuration.CommandLine" Version="9.0.2" /> <PackageVersion Include="Microsoft.Extensions.Configuration.CommandLine" Version="9.0.5" />
<PackageVersion Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="9.0.2" /> <PackageVersion Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="9.0.5" />
<PackageVersion Include="Microsoft.Extensions.Configuration.UserSecrets" Version="9.0.2" /> <PackageVersion Include="Microsoft.Extensions.Configuration.UserSecrets" Version="9.0.5" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="9.0.2" /> <PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="9.0.5" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="9.0.2" /> <PackageVersion Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="9.0.5" />
<PackageVersion Include="Microsoft.Extensions.FileProviders.Composite" Version="9.0.2" /> <PackageVersion Include="Microsoft.Extensions.FileProviders.Composite" Version="9.0.5" />
<PackageVersion Include="Microsoft.Extensions.FileProviders.Embedded" Version="9.0.2" /> <PackageVersion Include="Microsoft.Extensions.FileProviders.Embedded" Version="9.0.5" />
<PackageVersion Include="Microsoft.Extensions.FileProviders.Physical" Version="9.0.2" /> <PackageVersion Include="Microsoft.Extensions.FileProviders.Physical" Version="9.0.5" />
<PackageVersion Include="Microsoft.Extensions.FileSystemGlobbing" Version="9.0.2" /> <PackageVersion Include="Microsoft.Extensions.FileSystemGlobbing" Version="9.0.5" />
<PackageVersion Include="Microsoft.Extensions.Hosting" Version="9.0.2" /> <PackageVersion Include="Microsoft.Extensions.Hosting" Version="9.0.5" />
<PackageVersion Include="Microsoft.Extensions.Hosting.Abstractions" Version="9.0.2" /> <PackageVersion Include="Microsoft.Extensions.Hosting.Abstractions" Version="9.0.5" />
<PackageVersion Include="Microsoft.Extensions.Http" Version="9.0.2" /> <PackageVersion Include="Microsoft.Extensions.Http" Version="9.0.5" />
<PackageVersion Include="Microsoft.Extensions.Identity.Core" Version="9.0.2" /> <PackageVersion Include="Microsoft.Extensions.Identity.Core" Version="9.0.5" />
<PackageVersion Include="Microsoft.Extensions.Localization" Version="9.0.2" /> <PackageVersion Include="Microsoft.Extensions.Localization" Version="9.0.5" />
<PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="9.0.2" /> <PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="9.0.5" />
<PackageVersion Include="Microsoft.Extensions.Logging" Version="9.0.2" /> <PackageVersion Include="Microsoft.Extensions.Logging" Version="9.0.5" />
<PackageVersion Include="Microsoft.Extensions.Logging.Console" Version="9.0.2" /> <PackageVersion Include="Microsoft.Extensions.Logging.Console" Version="9.0.5" />
<PackageVersion Include="Microsoft.Extensions.Options" Version="9.0.2" /> <PackageVersion Include="Microsoft.Extensions.Options" Version="9.0.5" />
<PackageVersion Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="9.0.2" /> <PackageVersion Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="9.0.5" />
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.13.0" /> <PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.13.0" />
<PackageVersion Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="9.0.0" /> <PackageVersion Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="9.0.0" />
<PackageVersion Include="Microsoft.SourceLink.GitHub" Version="8.0.0" /> <PackageVersion Include="Microsoft.SourceLink.GitHub" Version="8.0.0" />
<PackageVersion Include="System.IdentityModel.Tokens.Jwt" Version="8.6.0" /> <PackageVersion Include="System.IdentityModel.Tokens.Jwt" Version="8.12.0" />
<PackageVersion Include="Microsoft.IdentityModel.Protocols.OpenIdConnect" Version="8.6.0" /> <PackageVersion Include="Microsoft.IdentityModel.Protocols.OpenIdConnect" Version="8.12.0" />
<PackageVersion Include="Microsoft.IdentityModel.Tokens" Version="8.6.0" /> <PackageVersion Include="Microsoft.IdentityModel.Tokens" Version="8.12.0" />
<PackageVersion Include="Microsoft.IdentityModel.JsonWebTokens" Version="8.6.0" /> <PackageVersion Include="Microsoft.IdentityModel.JsonWebTokens" Version="8.12.0" />
<PackageVersion Include="Minio" Version="6.0.3" /> <PackageVersion Include="Minio" Version="6.0.4" />
<PackageVersion Include="MongoDB.Driver" Version="3.3.0" /> <PackageVersion Include="MongoDB.Driver" Version="3.3.0" />
<PackageVersion Include="NEST" Version="7.17.5" /> <PackageVersion Include="NEST" Version="7.17.5" />
<PackageVersion Include="Newtonsoft.Json" Version="13.0.3" /> <PackageVersion Include="Newtonsoft.Json" Version="13.0.3" />
<PackageVersion Include="Nito.AsyncEx.Context" Version="5.1.2" /> <PackageVersion Include="Nito.AsyncEx.Context" Version="5.1.2" />
<PackageVersion Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="9.0.4" /> <PackageVersion Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="9.0.4" />
<PackageVersion Include="NSubstitute" Version="5.1.0" /> <PackageVersion Include="NSubstitute" Version="5.3.0" />
<PackageVersion Include="NuGet.Versioning" Version="6.11.1" /> <PackageVersion Include="NuGet.Versioning" Version="6.13.2" />
<PackageVersion Include="NUglify" Version="1.21.9" /> <PackageVersion Include="NUglify" Version="1.21.15" />
<PackageVersion Include="Nullable" Version="1.3.1" /> <PackageVersion Include="Nullable" Version="1.3.1" />
<PackageVersion Include="Octokit" Version="13.0.1" /> <PackageVersion Include="Octokit" Version="14.0.0" />
<PackageVersion Include="OpenIddict.Abstractions" Version="6.1.1" /> <PackageVersion Include="OpenIddict.Abstractions" Version="7.0.0" />
<PackageVersion Include="OpenIddict.Core" Version="6.1.1" /> <PackageVersion Include="OpenIddict.Core" Version="7.0.0" />
<PackageVersion Include="OpenIddict.Server.AspNetCore" Version="6.1.1" /> <PackageVersion Include="OpenIddict.Server.AspNetCore" Version="7.0.0" />
<PackageVersion Include="OpenIddict.Validation.AspNetCore" Version="6.1.1" /> <PackageVersion Include="OpenIddict.Validation.AspNetCore" Version="7.0.0" />
<PackageVersion Include="OpenIddict.Validation.ServerIntegration" Version="6.1.1" /> <PackageVersion Include="OpenIddict.Validation.ServerIntegration" Version="7.0.0" />
<PackageVersion Include="Oracle.EntityFrameworkCore" Version="9.23.60" /> <PackageVersion Include="Oracle.EntityFrameworkCore" Version="9.23.80" />
<PackageVersion Include="Polly" Version="8.4.2" /> <PackageVersion Include="Polly" Version="8.5.2" />
<PackageVersion Include="Polly.Extensions.Http" Version="3.0.0" /> <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-preview.3.efcore.9.0.0" />
<PackageVersion Include="Quartz" Version="3.13.0" /> <PackageVersion Include="Quartz" Version="3.14.0" />
<PackageVersion Include="Quartz.Extensions.DependencyInjection" Version="3.13.0" /> <PackageVersion Include="Quartz.Extensions.DependencyInjection" Version="3.14.0" />
<PackageVersion Include="Quartz.Plugins.TimeZoneConverter" Version="3.13.0" /> <PackageVersion Include="Quartz.Plugins.TimeZoneConverter" Version="3.14.0" />
<PackageVersion Include="Quartz.Serialization.Json" Version="3.13.0" /> <PackageVersion Include="Quartz.Serialization.Json" Version="3.14.0" />
<PackageVersion Include="RabbitMQ.Client" Version="7.1.2" /> <PackageVersion Include="RabbitMQ.Client" Version="7.1.2" />
<PackageVersion Include="Rebus" Version="8.6.0" /> <PackageVersion Include="Rebus" Version="8.8.0" />
<PackageVersion Include="Rebus.ServiceProvider" Version="10.2.0" /> <PackageVersion Include="Rebus.ServiceProvider" Version="10.3.0" />
<PackageVersion Include="Scriban" Version="5.10.0" /> <PackageVersion Include="Scriban" Version="6.2.1" />
<PackageVersion Include="Serilog" Version="4.0.2" /> <PackageVersion Include="Serilog" Version="4.2.0" />
<PackageVersion Include="Serilog.AspNetCore" Version="8.0.2" /> <PackageVersion Include="Serilog.AspNetCore" Version="9.0.0" />
<PackageVersion Include="Serilog.Extensions.Hosting" Version="8.0.0" /> <PackageVersion Include="Serilog.Extensions.Hosting" Version="9.0.0" />
<PackageVersion Include="Serilog.Extensions.Logging" Version="8.0.0" /> <PackageVersion Include="Serilog.Extensions.Logging" Version="9.0.1" />
<PackageVersion Include="Serilog.Sinks.Async" Version="2.0.0" /> <PackageVersion Include="Serilog.Sinks.Async" Version="2.1.0" />
<PackageVersion Include="Serilog.Sinks.Console" Version="6.0.0" /> <PackageVersion Include="Serilog.Sinks.Console" Version="6.0.0" />
<PackageVersion Include="Serilog.Sinks.File" Version="6.0.0" /> <PackageVersion Include="Serilog.Sinks.File" Version="7.0.0" />
<PackageVersion Include="SharpZipLib" Version="1.4.2" /> <PackageVersion Include="SharpZipLib" Version="1.4.2" />
<PackageVersion Include="Shouldly" Version="4.2.1" /> <PackageVersion Include="Shouldly" Version="4.3.0" />
<PackageVersion Include="SixLabors.ImageSharp" Version="3.1.5" /> <PackageVersion Include="SixLabors.ImageSharp" Version="3.1.8" />
<PackageVersion Include="SixLabors.ImageSharp.Drawing" Version="2.1.4" /> <PackageVersion Include="SixLabors.ImageSharp.Drawing" Version="2.1.6" />
<PackageVersion Include="SkiaSharp" Version="2.88.8" /> <PackageVersion Include="SkiaSharp" Version="2.88.8" />
<PackageVersion Include="SkiaSharp.NativeAssets.Linux" Version="2.88.8" /> <PackageVersion Include="SkiaSharp.NativeAssets.Linux" Version="2.88.8" />
<PackageVersion Include="SkiaSharp.NativeAssets.macOS" Version="2.88.8" /> <PackageVersion Include="SkiaSharp.NativeAssets.macOS" Version="2.88.8" />
<PackageVersion Include="Slugify.Core" Version="4.0.1" /> <PackageVersion Include="Slugify.Core" Version="4.0.1" />
<PackageVersion Include="Spectre.Console" Version="0.49.1" /> <PackageVersion Include="Spectre.Console" Version="0.50.0" />
<PackageVersion Include="StackExchange.Redis" Version="2.8.16" /> <PackageVersion Include="StackExchange.Redis" Version="2.8.31" />
<PackageVersion Include="Swashbuckle.AspNetCore" Version="6.8.1" /> <PackageVersion Include="Swashbuckle.AspNetCore" Version="8.1.1" />
<PackageVersion Include="System.Collections.Immutable" Version="9.0.2" /> <PackageVersion Include="System.Collections.Immutable" Version="9.0.5" />
<PackageVersion Include="System.ComponentModel.Annotations" Version="5.0.0" /> <PackageVersion Include="System.ComponentModel.Annotations" Version="5.0.0" />
<PackageVersion Include="System.Linq.Async" Version="6.0.1" /> <PackageVersion Include="System.Linq.Async" Version="6.0.1" />
<PackageVersion Include="System.Linq.Dynamic.Core" Version="1.6.1" /> <PackageVersion Include="System.Linq.Dynamic.Core" Version="1.6.2" />
<PackageVersion Include="System.Linq.Queryable" Version="4.3.0" /> <PackageVersion Include="System.Linq.Queryable" Version="4.3.0" />
<PackageVersion Include="System.Runtime.Loader" Version="4.3.0" /> <PackageVersion Include="System.Runtime.Loader" Version="4.3.0" />
<PackageVersion Include="System.Security.Permissions" Version="9.0.2" /> <PackageVersion Include="System.Security.Permissions" Version="9.0.5" />
<PackageVersion Include="System.Security.Principal.Windows" Version="5.0.0" /> <PackageVersion Include="System.Security.Principal.Windows" Version="5.0.0" />
<PackageVersion Include="System.Text.Encoding.CodePages" Version="9.0.2" /> <PackageVersion Include="System.Text.Encoding.CodePages" Version="9.0.5" />
<PackageVersion Include="System.Text.Encodings.Web" Version="9.0.2" /> <PackageVersion Include="System.Text.Encodings.Web" Version="9.0.5" />
<PackageVersion Include="System.Text.Json" Version="9.0.2" /> <PackageVersion Include="System.Text.Json" Version="9.0.5" />
<PackageVersion Include="System.Threading.Tasks.Extensions" Version="4.6.0" /> <PackageVersion Include="System.Threading.Tasks.Extensions" Version="4.6.3" />
<PackageVersion Include="TencentCloudSDK.Sms" Version="3.0.1142" /> <PackageVersion Include="TencentCloudSDK.Sms" Version="3.0.1231" />
<PackageVersion Include="TimeZoneConverter" Version="7.0.0" /> <PackageVersion Include="TimeZoneConverter" Version="7.0.0" />
<PackageVersion Include="Unidecode.NET" Version="2.1.0" /> <PackageVersion Include="Unidecode.NET" Version="2.1.0" />
<PackageVersion Include="xunit" Version="2.9.2" /> <PackageVersion Include="xunit" Version="2.9.3" />
<PackageVersion Include="xunit.extensibility.execution" Version="2.9.2" /> <PackageVersion Include="xunit.extensibility.execution" Version="2.9.3" />
<PackageVersion Include="xunit.runner.visualstudio" Version="2.8.2" /> <PackageVersion Include="xunit.runner.visualstudio" Version="3.0.2" />
<PackageVersion Include="coverlet.collector" Version="6.0.2" /> <PackageVersion Include="coverlet.collector" Version="6.0.4" />
<PackageVersion Include="ConfigureAwait.Fody" Version="3.3.2" /> <PackageVersion Include="ConfigureAwait.Fody" Version="3.3.2" />
<PackageVersion Include="Fody" Version="6.8.2" /> <PackageVersion Include="Fody" Version="6.9.2" />
</ItemGroup> </ItemGroup>
</Project> </Project>

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: 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) * [Microservices](https://abp.io/docs/latest/framework/architecture/microservices)
* [Modularity](https://abp.io/docs/latest/framework/architecture/modularity/basics) * [Modularity](https://abp.io/docs/latest/framework/architecture/modularity/basics)
* [Multi-Tenancy](https://abp.io/docs/latest/framework/architecture/multi-tenancy) * [Multi-Tenancy](https://abp.io/docs/latest/framework/architecture/multi-tenancy)

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

@ -717,6 +717,12 @@
"IncludePrereleaseInfo": "Gets or sets whether to include prerelease versions in the cache", "IncludePrereleaseInfo": "Gets or sets whether to include prerelease versions in the cache",
"CacheVersionCount": "Cache Version Count", "CacheVersionCount": "Cache Version Count",
"CacheVersionCountInfo": "Gets or sets the number of versions to cache", "CacheVersionCountInfo": "Gets or sets the number of versions to cache",
"CacheLatestVersionsInfo": "This caches the latest versions of the NuGet packages" "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",
"Permission:ViewCounts": "View counts",
"ReadCount": "Read Count"
} }
} }

2
abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json

@ -987,7 +987,7 @@
"Summary": "Summary", "Summary": "Summary",
"TrainingPack": "Training pack", "TrainingPack": "Training pack",
"TrainingPackDiscount": "Training pack discount", "TrainingPackDiscount": "Training pack discount",
"Purchase_OnboardingTraining_Description": "This live training is valid for a class of 8 students and this discount is only valid when purchased with the new license. <a href=\"{0}\" class=\"text-white\">Learn more <i class=\"fa fa-external-link ms-1\"></i></a>", "Purchase_OnboardingTraining_Description": "This live training is valid for a class of 8 students and this discount is only valid when purchased with the new license. <a href=\"{0}\">Learn more <i class=\"fa fa-external-link ms-1\"></i></a>",
"Purchase_Save": "{0}% <span class=\"save ms-1\">Save {1}</span>", "Purchase_Save": "{0}% <span class=\"save ms-1\">Save {1}</span>",
"RemoveBasket": "Remove from basket", "RemoveBasket": "Remove from basket",
"WhyABPIOPlatform?": "Why <span class=\"gradient-commercial\">ABP.IO Platform</span>?", "WhyABPIOPlatform?": "Why <span class=\"gradient-commercial\">ABP.IO Platform</span>?",

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

@ -66,7 +66,7 @@
"AuditLogging": "Audit Logging", "AuditLogging": "Audit Logging",
"Caching": "Caching", "Caching": "Caching",
"Multitenancy": "Multitenancy", "Multitenancy": "Multitenancy",
"DataFiltering": "Data filtering", "DataFiltering": "Data Filtering",
"ConventionOverConfiguration": "Convention Over Configuration", "ConventionOverConfiguration": "Convention Over Configuration",
"ConventionOverConfigurationExplanation": "ABP implements common application conventions by default with minimal or zero configuration.", "ConventionOverConfigurationExplanation": "ABP implements common application conventions by default with minimal or zero configuration.",
"ConventionOverConfigurationExplanationList1": "Auto registers known services to dependency injection.", "ConventionOverConfigurationExplanationList1": "Auto registers known services to dependency injection.",
@ -534,7 +534,7 @@
"WhenShouldIRenewMyLicenseExplanation2": "{0} for Team Licenses;", "WhenShouldIRenewMyLicenseExplanation2": "{0} for Team Licenses;",
"WhenShouldIRenewMyLicenseExplanation3": "{0} for Business and Enterprise Licenses;", "WhenShouldIRenewMyLicenseExplanation3": "{0} for Business and Enterprise Licenses;",
"WhenShouldIRenewMyLicenseExplanation4": "However, if you renew your license more than {0} days after the expiry date, the renewal price will be the same as the initial purchase price of the license, with no discounts applied to your renewal.", "WhenShouldIRenewMyLicenseExplanation4": "However, if you renew your license more than {0} days after the expiry date, the renewal price will be the same as the initial purchase price of the license, with no discounts applied to your renewal.",
"DoesTheSubscriptionRenewAutomaticallyExplanationAutoRenewal": "ABP Platform allows you to auto-renew your license. This is an optional free service. You can toggle this feature when you purchase a new license or later enable it from your <a href=\"{0}\">organization management page</a>. If you want to turn on or off the auto-renewal, visit the <a href=\"{0}\">organization management page</a>, go to the 'Payments Method' section and either check or uncheck the 'Automatic Renewal' checkbox. When you turn off the auto-renewal feature, it will be your responsibility to renew your license manually.", "DoesTheSubscriptionRenewAutomaticallyExplanationAutoRenewal": "ABP Platform allows you to auto-renew your license. This is an optional free service. You can toggle this feature when you purchase a new license or later enable it from your <a href=\"{0}\">organization management page</a>. If you want to turn on or off the auto-renewal, visit the <a href=\"{0}\">organization management page</a>, go to the 'Payments Method' section and either check or uncheck the 'Automatic Renewal' checkbox. When you turn off the auto-renewal feature, it will be your responsibility to renew your license manually. <br> The <strong>renewals (manual)</strong> are non-refundable. On the other hand, all subscription <strong>auto-renewals</strong> are non-refundable after <strong>10 calendar days</strong> from the auto-renewal date. If you don't wish to continue your license, it is your responsibility to manage the renewal settings and cancel the subscription before the automatic renewal date.",
"TrialPlanExplanation": "Yes, to start your free trial, please contact <a href=\"mailto:sales@volosoft.com?subject=Trial License Request\">sales@volosoft.com</a>. We also offer a 30-day money-back guarantee for the Team license, with no questions asked! You can request a full refund within the first 30 days of purchasing the license. For Business and Enterprise licenses, we provide a 60% refund if requested within 30 days of purchase. This policy is due to the inclusion of the full source code for all modules and themes in the Business and Enterprise licenses.", "TrialPlanExplanation": "Yes, to start your free trial, please contact <a href=\"mailto:sales@volosoft.com?subject=Trial License Request\">sales@volosoft.com</a>. We also offer a 30-day money-back guarantee for the Team license, with no questions asked! You can request a full refund within the first 30 days of purchasing the license. For Business and Enterprise licenses, we provide a 60% refund if requested within 30 days of purchase. This policy is due to the inclusion of the full source code for all modules and themes in the Business and Enterprise licenses.",
"BlazoriseLicenseExplanation": "We have an agreement between Volosoft and Megabit, according to which the Blazorise license is bundled with the ABP Platform’s commercial licenses. Therefore, our paid users do not need to purchase an additional Blazorise license.", "BlazoriseLicenseExplanation": "We have an agreement between Volosoft and Megabit, according to which the Blazorise license is bundled with the ABP Platform’s commercial licenses. Therefore, our paid users do not need to purchase an additional Blazorise license.",
"HowToUpgradeExplanation1": "When you create a new application using the ABP startup templates, all the modules and themes are used as NuGet and NPM packages. This setup allows for easy upgrades to newer versions of the packages.", "HowToUpgradeExplanation1": "When you create a new application using the ABP startup templates, all the modules and themes are used as NuGet and NPM packages. This setup allows for easy upgrades to newer versions of the packages.",
@ -1425,7 +1425,7 @@
"TotalDevelopers": "Total {0} developer(s)", "TotalDevelopers": "Total {0} developer(s)",
"CustomPurchaseExplanation": "Tailored to your specific needs", "CustomPurchaseExplanation": "Tailored to your specific needs",
"WhereDidYouHearAboutUs": "Where did you hear about us?", "WhereDidYouHearAboutUs": "Where did you hear about us?",
"Twitter": "Twitter", "Twitter": "Twitter (X)",
"Facebook": "Facebook", "Facebook": "Facebook",
"Youtube": "YouTube", "Youtube": "YouTube",
"Google": "Google", "Google": "Google",
@ -1889,6 +1889,9 @@
"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.", "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\").", "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 Title" "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",
"MostPopular": "Most Popular"
} }
} }

4
common.props

@ -1,8 +1,8 @@
<Project> <Project>
<PropertyGroup> <PropertyGroup>
<LangVersion>latest</LangVersion> <LangVersion>latest</LangVersion>
<Version>9.3.0-preview</Version> <Version>10.0.0-preview</Version>
<LeptonXVersion>4.3.0-preview</LeptonXVersion> <LeptonXVersion>5.0.0-preview</LeptonXVersion>
<NoWarn>$(NoWarn);CS1591;CS0436</NoWarn> <NoWarn>$(NoWarn);CS1591;CS0436</NoWarn>
<PackageIconUrl>https://abp.io/assets/abp_nupkg.png</PackageIconUrl> <PackageIconUrl>https://abp.io/assets/abp_nupkg.png</PackageIconUrl>
<PackageProjectUrl>https://abp.io/</PackageProjectUrl> <PackageProjectUrl>https://abp.io/</PackageProjectUrl>

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

203
docs/en/Blog-Posts/2025-06-18 v9_3_Preview/POST.md

@ -0,0 +1,203 @@
# ABP Platform 9.3 RC Has Been Released
We are happy to release [ABP](https://abp.io) version **9.3 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.3! Thanks to you in advance.
## Get Started with the 9.3 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.2 or earlier: [ABP Version 9.3 Migration Guide](https://abp.io/docs/9.3/release-info/migration-guides/abp-9-3)
## What's New with ABP v9.3?
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:
* Cron Expression Support for Background Workers
* Docs Module: PDF Export
* Angular UI: Standalone Package Structure
* Upgraded to Blazorise v1.7.7
* Audit Logging Module: Excel Export
### Cron Expression Support for Background Workers
We've enhanced the [Background Workers System](https://abp.io/docs/9.3/framework/infrastructure/background-workers) by adding support for Cron expressions when using [Hangfire](https://abp.io/docs/9.3/framework/infrastructure/background-workers/hangfire) or [Quartz](https://abp.io/docs/9.3/framework/infrastructure/background-workers/quartz) as the background worker manager. This new feature provides more flexibility in scheduling background tasks compared to the simple period-based timing system.
Now you can define complex scheduling patterns using standard Cron expressions. For example, you can schedule a task to run: "Every day at midnight", "Every Monday at 9 AM", or "First day of every month".
Here's how you can use it in your background worker:
```csharp
public class MyPeriodicBackgroundWorker : AsyncPeriodicBackgroundWorkerBase
{
public MyPeriodicBackgroundWorker(
AbpAsyncTimer timer,
IServiceScopeFactory serviceScopeFactory)
: base(timer, serviceScopeFactory)
{
// You can either use Period for simple intervals
Timer.Period = 600000; //10 minutes
// 👇 or use CronExpression for more complex scheduling 👇
CronExpression = "0 0/10 * * * ?"; //Run every 10 minutes
}
protected async override Task DoWorkAsync(
PeriodicBackgroundWorkerContext context)
{
// Your background work...
}
}
```
The `CronExpression` property takes precedence over the `Period` property when both are set. This feature is available when you use either the [Hangfire](https://abp.io/docs/9.3/framework/infrastructure/background-workers/hangfire) or [Quartz](https://abp.io/docs/9.3/framework/infrastructure/background-workers/quartz) background worker managers.
> See the [Background Workers documentation](https://abp.io/docs/9.3/framework/infrastructure/background-workers) for more information about configuring and using background workers with Cron expressions.
### Docs Module: PDF Export
We're excited to introduce a new feature in the Docs Module that allows users to export documentation as PDF files. This feature makes it easier for users to access documentation offline or share it with team members who might not have immediate access to the online documentation system.
**Administrators can generate PDF files from the back-office side**:
![PDF generation settings in the admin side](generate-pdf-docs.png)
and **then a "Download PDF" button appears in the document system** (as shown in the image below - the bottom right of the navigation menu -), allowing users to download the compiled documentation as a PDF file:
![Download PDF button in the documentation system](download-pdf-on-docs.png)
The feature supports multiple versions of documentation, different language variants, and ensures proper formatting of all content including code blocks and technical documentation.
### Angular UI: Standalone Package Structure
ABP v9.3 introduces support for Angular's standalone components architecture while maintaining **full compatibility with existing module-based applications**. This update aligns with Angular's strategic direction toward standalone components as the recommended approach for building Angular applications.
The key improvements include:
* **Dual-support routing configurations** that work seamlessly with both module-based and standalone approaches
* **ABP Suite integration** for generating code that supports standalone components
* **Updated schematics** that provide templates for both development patterns
This enhancement gives developers the flexibility to choose their preferred Angular architecture. Existing module-based applications **continue to work without modifications**, while new projects can leverage the standalone approach for simplified dependency management, reduced boilerplate code, and better lazy-loading capabilities.
> For developers interested in migrating to standalone components or starting new projects, we'll be publishing a comprehensive blog post with detailed guidance and best practices. In the meantime, you can check [#22829](https://github.com/abpframework/abp/pull/22829) for implementation details of the standalone package structure and make the necessary changes to your project.
### Upgraded to Blazorise v1.7.7
Upgraded the [Blazorise](https://blazorise.com/) library to v1.7.7 for Blazor UI. If you are upgrading your project to v9.3.0, please ensure that all the Blazorise-related packages are using v1.7.7 in your application. Otherwise, you might get errors due to incompatible versions.
> See [#23013](https://github.com/abpframework/abp/pull/23013) for the updated NuGet packages.
### Audit Logging Module: Excel Export
In this version, we've added Excel export capabilities to the [Audit Logging Module](https://abp.io/docs/latest/modules/audit-logging-pro), allowing administrators to export audit logs and entity changes to Excel files for further analysis or reporting purposes.
![](audit-logs-export-to-excel.png)
This feature enables users to:
- Export audit logs with filtering options
- Export entity changes with detailed information
- Receive email notifications when exports are completed or fail
- Download exported files via secure links
The export process runs in the background, and once completed, users receive an email with a download link. This approach ensures that even large audit log exports don't block the UI or time out during processing.
You can configure various aspects of this feature using the `AuditLogExcelFileOptions` in your module's configuration:
```csharp
Configure<AuditLogExcelFileOptions>(options =>
{
// How long to keep exported files before cleanup
options.FileRetentionHours = 48;
// Base URL for download links in notification emails
options.DownloadBaseUrl = "https://yourdomain.com";
// Configure the cleanup worker schedule
options.ExcelFileCleanupOptions.Period = (int)TimeSpan.FromHours(24).TotalMilliseconds;
// Use cron expression for more advanced scheduling (requires Hangfire or Quartz)
options.ExcelFileCleanupOptions.CronExpression = "0 2 * * *"; // Run at 2 AM daily
});
```
The module includes pre-configured email templates for notifications about completed or failed exports, ensuring users are always informed about the status of their export requests.
> **Note**: This feature requires a configured BLOB storage provider to store the generated Excel files. See the [BLOB Storing documentation](https://abp.io/docs/9.3/framework/infrastructure/blob-storing) for more information.
For more details about the Audit Logging Module and its Excel export capabilities, please refer to the [official documentation](https://abp.io/docs/9.3/modules/audit-logging-pro).
## Community News
### Announcing ABP Studio 1.0 General Availability 🚀
![](abp-studio.png)
We are thrilled to announce that ABP Studio has reached version 1.0 and is now generally available! This marks a significant milestone for our integrated development environment designed specifically for ABP developers. The stable release brings several powerful features including:
* Enhanced Solution Runner with health monitoring capabilities
* Theme style selection during project creation (Basic, LeptonX Lite, and LeptonX Themes)
* New "Container" application type for better Docker container management
* Improved handling of multiple DbContexts for migration operations
> For a detailed overview of these features and to learn more about what's coming next, check out our [announcement post](https://abp.io/community/articles/announcing-abp-studio-1-0-general-availability-82yw62bt).
### ABP Community Talks 2025.05: Empower Elsa Workflows with AI in .NET + ABP Framework
In this episode of ABP Community Talks, 2025.05, we are thrilled to host [**Sipke Schoorstra**](https://github.com/sfmskywalker), the creator of the [Elsa Workflows](https://docs.elsaworkflows.io/) library! This month's session is all about **"Empower Elsa Workflows with AI in .NET + ABP Framework"**.
![](community-talk-2025-5.png)
Sipke will join us to demonstrate how you can leverage AI within Elsa Workflows using .NET and the ABP Framework. The session will explore practical techniques and showcase how to integrate AI capabilities to enhance and automate your business processes within the Elsa workflow engine.
> 👉 Don't miss this opportunity to learn directly from the creator of Elsa and see real-world examples of building intelligent, automated workflows! You can register from [here](https://kommunity.com/volosoft/events/abp-community-talks-202505empower-elsa-workflows-with-ai-in-netabp-framework-3965dd32).
### ABP Bootcamp: Mastering Infrastructure & Features
We are excited to announce the very first **ABP Bootcamp: Mastering Infrastructure & Features**! This is a live training program designed to give you hands-on, practical experience with ABP's core infrastructure and features.
![ABP Bootcamp: Mastering Infrastructure & Features](bootcamp.png)
Join the ABP Bootcamp to learn directly from the core team in a focused, hands-on program designed for busy developers. Over four days, you'll gain a deep understanding of ABP's infrastructure, best practices, and practical skills you can immediately apply to your projects.
> **Seats are limited!** Don't miss this opportunity to level up your ABP skills with direct guidance from the experts.
>
> 👉 [See full details and reserve your seat!](https://abp.io/bootcamp)
### New ABP Community Articles
There are exciting articles contributed by the ABP community as always. I will highlight some of them here:
* [Prabhjot Singh](https://abp.io/community/members/prabhjot) has published 3 new articles:
* [Accessing Multiple Remote ABP based Backends Using HttpApi.Client](https://abp.io/community/articles/consume-multi-backends-using-clients-6f4vcggh)
* [Adopting the new .slnx format to organize applications and services](https://abp.io/community/articles/adopting-the-new-.slnx-format-to-organize-applications-6cm3vl8k)
* [Replacing Dynamic client proxies with Static client proxies](https://abp.io/community/articles/replacing-dynamic-client-proxies-with-static-client-proxies-g30lf0vx)
* [Liming Ma](https://github.com/maliming) has published 2 new articles:
* [Resolving Tenant from Route in ABP Framework](https://abp.io/community/articles/resolving-tenant-from-route-in-abp-framework-ah7oru97)
* [Integrating .NET AI Chat Template with ABP Framework](https://abp.io/community/articles/integrating-.net-ai-chat-template-with-abp-framework-qavb5p2j)
* [Engincan Veske](https://engincanveske.substack.com/) has published 2 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)
* [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)
* [New in ABP Studio: Docker Container Management](https://abp.io/community/articles/abp-studio-docker-container-management-ex7r27y8) by [Yunus Emre Kalkan](https://github.com/yekalkan)
* [Solving MongoDB GUID Issues After an ABP Framework Upgrade](https://abp.io/community/articles/solving-mongodb-guid-issues-after-an-abp-framework-upgrade-tv8waw1n) by [Burak Demir](https://abp.io/community/members/burakdemir)
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.3/release-info/road-map) documentation to learn about the release schedule and planned features for the next releases. Please try ABP v9.3 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-06-18 v9_3_Preview/abp-studio.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 455 KiB

BIN
docs/en/Blog-Posts/2025-06-18 v9_3_Preview/audit-logs-export-to-excel.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 147 KiB

BIN
docs/en/Blog-Posts/2025-06-18 v9_3_Preview/bootcamp.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 300 KiB

BIN
docs/en/Blog-Posts/2025-06-18 v9_3_Preview/community-talk-2025-5.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 239 KiB

BIN
docs/en/Blog-Posts/2025-06-18 v9_3_Preview/cover-image.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 676 KiB

BIN
docs/en/Blog-Posts/2025-06-18 v9_3_Preview/download-pdf-on-docs.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

BIN
docs/en/Blog-Posts/2025-06-18 v9_3_Preview/generate-pdf-docs.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

BIN
docs/en/Blog-Posts/2025-06-18 v9_3_Preview/studio-switch-to-preview.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 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). * 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 ## References
* [Text Templating](https://docs.abp.io/en/abp/latest/Text-Templating) * [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. 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 ## Creating the Solution
> ABP Framework offers startup templates to get into business faster. > ABP Framework offers startup templates to get into business faster.
@ -532,6 +538,12 @@ namespace TelerikComponents.Blazor.Pages
![final-result](./final-result.jpg) ![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 ## 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. 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 # 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 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) ![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. 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 ## 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). 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. * 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). 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 ### Source Code
You can find the source code of the application at https://github.com/EngincanV/ABP-Many-to-Many-Relationship-Demo . 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) ![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 ### 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) 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. 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 ## Source Code
You can find the source code of the application at https://github.com/EngincanV/ABP-Syncfusion-Components-Demo. 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) ![](./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 ### 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. 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. 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 ## Source Code
You can find the source code of the application at https://github.com/EngincanV/ABP-Hide-Swagger-Endpoint-Demo. 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. > 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. Thanks for reading.

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. 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 ## 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. 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. * 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. * 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). > 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? ## 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). [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. > 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 ## References
* https://devblogs.microsoft.com/dotnet/announcing-grpc-json-transcoding-for-dotnet/ * 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. 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 ## ASP.NET Core
We will see the following features in this section: 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! 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 ## References
* https://devblogs.microsoft.com/dotnet/announcing-dotnet-7/ * 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) > 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 ### 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. 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 12 KB and now the compressed & resized image has been reduced to 8 KB.
* The original image was 225x225 and now resized as 200x200. * 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 ## 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. 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. 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
[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: [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":"..."} {"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 ## 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. 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. 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? ## 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: 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. 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 ## 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. 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. 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 ## 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). 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. 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 🤗 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. 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? ## 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. 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. 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 ## 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. 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.

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). 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 ## 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: 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. 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
[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. [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). 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 ## 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) 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)

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. 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? ## 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: **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**. **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 ## Conclusion
The **HybridCache** library in .NET 9 provides a powerful tool for applications needing both high-speed caching and consistency in distributed environments. The **HybridCache** library in .NET 9 provides a powerful tool for applications needing both high-speed caching and consistency in distributed environments.

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. 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 ## 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. 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. 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 ## 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. 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.

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] [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: 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> <ItemGroup>
<PackageReference Include="Microsoft.Extensions.Hosting" Version="9.0.0" /> <PackageReference Include="Microsoft.Extensions.Hosting" Version="9.0.0" />
<PackageReference Include="Volo.Abp.VirtualFileSystem" 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>
<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. 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 ## 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... 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. 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 ## 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. 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.

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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

After

Width:  |  Height:  |  Size: 45 KiB

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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 228 KiB

After

Width:  |  Height:  |  Size: 142 KiB

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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

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

250
docs/en/Community-Articles/2025-06-20-Using-Hangfire-Dashboard-in-ABP-API-website/POST.md

@ -0,0 +1,250 @@
# Using Hangfire Dashboard in ABP API Website 🚀
## Introduction
In this article, I'll show you how to integrate and use the Hangfire Dashboard in an ABP API website.
Typically, API websites use `JWT Bearer` authentication, but the Hangfire Dashboard isn't compatible with `JWT Bearer` authentication. Therefore, we need to implement `Cookies` and `OpenIdConnect` authentication for the Hangfire Dashboard access.
## Creating a New ABP Demo Project 🛠️
We'll create a new ABP Demo `Tiered` project that includes `AuthServer`, `API`, and `Web` projects.
```bash
abp new AbpHangfireDemoApp -t app --tiered
```
Now let's add the Hangfire Dashboard to the `API` project and configure it to use `Cookies` and `OpenIdConnect` authentication for accessing the dashboard.
## Adding a New Hangfire Application 🔧
We need to add a new Hangfire application to the `appsettings.json` file in the `DbMigrator` project:
> **Note:** Replace `44371` with your `API` project's port.
```json
"OpenIddict": {
"Applications": {
//...
"AbpHangfireDemoApp_Hangfire": {
"ClientId": "AbpHangfireDemoApp_Hangfire",
"RootUrl": "https://localhost:44371/"
}
//...
}
}
```
2. Update the `OpenIddictDataSeedContributor`'s `CreateApplicationsAsync` method in the `Domain` project to seed the new Hangfire application.
```csharp
//Hangfire Client
var hangfireClientId = configurationSection["AbpHangfireDemoApp_Hangfire:ClientId"];
if (!hangfireClientId.IsNullOrWhiteSpace())
{
var hangfireClientRootUrl = configurationSection["AbpHangfireDemoApp_Hangfire:RootUrl"]!.EnsureEndsWith('/');
await CreateApplicationAsync(
applicationType: OpenIddictConstants.ApplicationTypes.Web,
name: hangfireClientId!,
type: OpenIddictConstants.ClientTypes.Confidential,
consentType: OpenIddictConstants.ConsentTypes.Implicit,
displayName: "Hangfire Application",
secret: configurationSection["AbpHangfireDemoApp_Hangfire:ClientSecret"] ?? "1q2w3e*",
grantTypes: new List<string> //Hybrid flow
{
OpenIddictConstants.GrantTypes.AuthorizationCode, OpenIddictConstants.GrantTypes.Implicit
},
scopes: commonScopes,
redirectUris: new List<string> { $"{hangfireClientRootUrl}signin-oidc" },
postLogoutRedirectUris: new List<string> { $"{hangfireClientRootUrl}signout-callback-oidc" },
clientUri: hangfireClientRootUrl,
logoUri: "/images/clients/aspnetcore.svg"
);
}
```
3. Run the `DbMigrator` project to seed the new Hangfire application.
### Adding Hangfire Dashboard to the `API` Project 📦
1. Add the following packages and modules dependencies to the `API` project:
```bash
<PackageReference Include="Volo.Abp.BackgroundJobs.HangFire" Version="9.2.0" />
<PackageReference Include="Volo.Abp.AspNetCore.Authentication.OpenIdConnect" Version="9.2.0" />
<PackageReference Include="Hangfire.SqlServer" Version="1.8.20" />
```
```cs
typeof(AbpBackgroundJobsHangfireModule),
typeof(AbpAspNetCoreAuthenticationOpenIdConnectModule)
```
2. Add the `HangfireClientId` and `HangfireClientSecret` to the `appsettings.json` file in the `API` project:
```csharp
"AuthServer": {
"Authority": "https://localhost:44358",
"RequireHttpsMetadata": true,
"MetaAddress": "https://localhost:44358",
"SwaggerClientId": "AbpHangfireDemoApp_Swagger",
"HangfireClientId": "AbpHangfireDemoApp_Hangfire",
"HangfireClientSecret": "1q2w3e*"
}
```
3. Add the `ConfigureHangfire` method to the `API` project to configure Hangfire:
```csharp
public override void ConfigureServices(ServiceConfigurationContext context)
{
var configuration = context.Services.GetConfiguration();
var hostingEnvironment = context.Services.GetHostingEnvironment();
//...
//Add Hangfire
ConfigureHangfire(context, configuration);
//...
}
private void ConfigureHangfire(ServiceConfigurationContext context, IConfiguration configuration)
{
context.Services.AddHangfire(config =>
{
config.UseSqlServerStorage(configuration.GetConnectionString("Default"));
});
}
```
4. Modify the `ConfigureAuthentication` method to add new `Cookies` and `OpenIdConnect` authentication schemes:
```csharp
private void ConfigureAuthentication(ServiceConfigurationContext context, IConfiguration configuration)
{
context.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddAbpJwtBearer(options =>
{
options.Authority = configuration["AuthServer:Authority"];
options.RequireHttpsMetadata = configuration.GetValue<bool>("AuthServer:RequireHttpsMetadata");
options.Audience = "AbpHangfireDemoApp";
options.ForwardDefaultSelector = httpContext => httpContext.Request.Path.StartsWithSegments("/hangfire", StringComparison.OrdinalIgnoreCase)
? CookieAuthenticationDefaults.AuthenticationScheme
: null;
})
.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme)
.AddAbpOpenIdConnect(OpenIdConnectDefaults.AuthenticationScheme, options =>
{
options.Authority = configuration["AuthServer:Authority"];
options.RequireHttpsMetadata = Convert.ToBoolean(configuration["AuthServer:RequireHttpsMetadata"]);
options.ResponseType = OpenIdConnectResponseType.Code;
options.ClientId = configuration["AuthServer:HangfireClientId"];
options.ClientSecret = configuration["AuthServer:HangfireClientSecret"];
options.UsePkce = true;
options.SaveTokens = true;
options.GetClaimsFromUserInfoEndpoint = true;
options.Scope.Add("roles");
options.Scope.Add("email");
options.Scope.Add("phone");
options.Scope.Add("AbpHangfireDemoApp");
options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
});
//...
}
```
5. Add a custom middleware and `UseAbpHangfireDashboard` after `UseAuthorization` in the `OnApplicationInitialization` method:
```csharp
//...
app.UseAuthorization();
app.Use(async (httpContext, next) =>
{
if (httpContext.Request.Path.StartsWithSegments("/hangfire", StringComparison.OrdinalIgnoreCase))
{
var authenticateResult = await httpContext.AuthenticateAsync(CookieAuthenticationDefaults.AuthenticationScheme);
if (!authenticateResult.Succeeded)
{
await httpContext.ChallengeAsync(
OpenIdConnectDefaults.AuthenticationScheme,
new AuthenticationProperties
{
RedirectUri = httpContext.Request.Path + httpContext.Request.QueryString
});
return;
}
}
await next.Invoke();
});
app.UseAbpHangfireDashboard("/hangfire", options =>
{
options.AsyncAuthorization = new[]
{
new AbpHangfireAuthorizationFilter()
};
});
//...
```
Perfect! 🎉 Now you can run the `AuthServer` and `API` projects and access the Hangfire Dashboard at `https://localhost:44371/hangfire`.
> **Note:** Replace `44371` with your `API` project's port.
The first time you access the Hangfire Dashboard, you'll be redirected to the login page of the `AuthServer` project. After you log in, you'll be redirected back to the Hangfire Dashboard.
![Hangfire Dashboard](gif.gif)
## Key Points 🔑
### 1. Authentication Scheme Selection
The default authentication scheme in API websites is `JWT Bearer`. We've implemented `Cookies` and `OpenIdConnect` specifically for the Hangfire Dashboard.
We've configured the `JwtBearerOptions`'s `ForwardDefaultSelector` to use `CookieAuthenticationDefaults.AuthenticationScheme` for Hangfire Dashboard requests.
This means that if the request path starts with `/hangfire`, the request will be authenticated using the `Cookies` authentication scheme; otherwise, it will use the `JwtBearer` authentication scheme.
```csharp
options.ForwardDefaultSelector = httpContext => httpContext.Request.Path.StartsWithSegments("/hangfire", StringComparison.OrdinalIgnoreCase)
? CookieAuthenticationDefaults.AuthenticationScheme
: null;
```
### 2. Custom Middleware for Authentication
We've also implemented a custom middleware to handle `Cookies` authentication for the Hangfire Dashboard. If the current request isn't authenticated with the `Cookies` authentication scheme, it will be redirected to the login page.
```csharp
app.Use(async (httpContext, next) =>
{
if (httpContext.Request.Path.StartsWithSegments("/hangfire", StringComparison.OrdinalIgnoreCase))
{
var authenticateResult = await httpContext.AuthenticateAsync(CookieAuthenticationDefaults.AuthenticationScheme);
if (!authenticateResult.Succeeded)
{
await httpContext.ChallengeAsync(
OpenIdConnectDefaults.AuthenticationScheme,
new AuthenticationProperties
{
RedirectUri = httpContext.Request.Path + httpContext.Request.QueryString
});
return;
}
}
await next.Invoke();
});
```
## References 📚
- [ABP Hangfire Background Job Manager](https://abp.io/docs/latest/framework/infrastructure/background-jobs/hangfire)
- [Use cookie authentication in ASP.NET Core](https://learn.microsoft.com/en-us/aspnet/core/security/authentication/cookie?view=aspnetcore-9.0)

BIN
docs/en/Community-Articles/2025-06-20-Using-Hangfire-Dashboard-in-ABP-API-website/gif.gif

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 MiB

2
docs/en/cli/differences-between-old-and-new-cli.md

@ -16,8 +16,6 @@ This change allows you to create your application with the new templating system
> If you installed [ABP Studio](../studio/index.md) recently, then you may skip this section because ABP Studio automatically uninstalls the old CLI and replaces it with the new CLI. Therefore, you don't need to manually switch to the new ABP CLI. > If you installed [ABP Studio](../studio/index.md) recently, then you may skip this section because ABP Studio automatically uninstalls the old CLI and replaces it with the new CLI. Therefore, you don't need to manually switch to the new ABP CLI.
> 🛈 The new ABP CLI is in the beta version for now. If you have any issues, you can always use the old ABP CLI by following the instructions in the _Using the old ABP CLI_ section below.
ABP CLI has two variations, which are `Volo.Abp.Studio.Cli` (new) and `Volo.Abp.Cli` (old). If you are using ABP earlier than v8.2+, then you are probably using the old ABP CLI and can easily switch to the new CLI by simply uninstalling the old one and installing the new CLI by executing the commands below: ABP CLI has two variations, which are `Volo.Abp.Studio.Cli` (new) and `Volo.Abp.Cli` (old). If you are using ABP earlier than v8.2+, then you are probably using the old ABP CLI and can easily switch to the new CLI by simply uninstalling the old one and installing the new CLI by executing the commands below:
```bash ```bash

6
docs/en/cli/index.md

@ -161,7 +161,7 @@ For more samples, go to [ABP CLI Create Solution Samples](new-command-samples.md
* `--database-provider` or `-d`: Specifies the database provider. Default provider is `ef`. Available providers: * `--database-provider` or `-d`: Specifies the database provider. Default provider is `ef`. Available providers:
* `ef`: Entity Framework Core. * `ef`: Entity Framework Core.
* `mongodb`: MongoDB. * `mongodb`: MongoDB.
* `--connection-string` or `-cs`: Overwrites the default connection strings in all `appsettings.json` files. The default connection string is `Server=localhost;Database=MyProjectName;Trusted_Connection=True` for EF Core and it is configured to use the SQL Server. If you want to use the EF Core, but need to change the DBMS, you can change it as [described here](../framework/data/entity-framework-core/other-dbms.md) (after creating the solution). * `--connection-string` or `-cs`: Overwrites the default connection strings in all `appsettings.json` files. The default connection string is `Server=localhost;Database=MyProjectName;Trusted_Connection=True` for EF Core and it is configured to use the SQL Server. If you want to use the EF Core, but need to change the DBMS, you can change it as [described here](../framework/data/entity-framework-core/other-dbms.md) (after creating the solution). **Note:** When specifying the connection string, make sure to enclose it in double quotes, for example: `--connection-string "Server=localhost;Database=MyProjectName;Trusted_Connection=True"`.
* `--skip-migrations` or `-sm`: Skips the creating initial database migration step. * `--skip-migrations` or `-sm`: Skips the creating initial database migration step.
* `--skip-migrator` or `-smr`: Skips the run database migrator step. * `--skip-migrator` or `-smr`: Skips the run database migrator step.
* `--public-website`: Public Website is a front-facing website for describing your project, listing your products and doing SEO for marketing purposes. Users can login and register on your website with this website. This option is only included in PRO templates. * `--public-website`: Public Website is a front-facing website for describing your project, listing your products and doing SEO for marketing purposes. Users can login and register on your website with this website. This option is only included in PRO templates.
@ -183,7 +183,7 @@ For more samples, go to [ABP CLI Create Solution Samples](new-command-samples.md
* `--database-provider` or `-d`: Specifies the database provider. Default provider is `ef`. Available providers: * `--database-provider` or `-d`: Specifies the database provider. Default provider is `ef`. Available providers:
* `ef`: Entity Framework Core. * `ef`: Entity Framework Core.
* `mongodb`: MongoDB. * `mongodb`: MongoDB.
* `--connection-string` or `-cs`: Overwrites the default connection strings in all `appsettings.json` files. The default connection string is `Server=localhost;Database=MyProjectName;Trusted_Connection=True` for EF Core and it is configured to use the SQL Server. If you want to use the EF Core, but need to change the DBMS, you can change it as [described here](../framework/data/entity-framework-core/other-dbms.md) (after creating the solution). * `--connection-string` or `-cs`: Overwrites the default connection strings in all `appsettings.json` files. The default connection string is `Server=localhost;Database=MyProjectName;Trusted_Connection=True` for EF Core and it is configured to use the SQL Server. If you want to use the EF Core, but need to change the DBMS, you can change it as [described here](../framework/data/entity-framework-core/other-dbms.md) (after creating the solution). **Note:** When specifying the connection string, make sure to enclose it in double quotes, for example: `--connection-string "Server=localhost;Database=MyProjectName;Trusted_Connection=True"`.
* `--skip-migrations` or `-sm`: Skips the creating initial database migration step. * `--skip-migrations` or `-sm`: Skips the creating initial database migration step.
* `--skip-migrator` or `-smr`: Skips the run database migrator step. * `--skip-migrator` or `-smr`: Skips the run database migrator step.
* `--sample-crud-page` or `-scp`: It adds the [BookStore](./../tutorials/book-store/index.md) sample to your solution. * `--sample-crud-page` or `-scp`: It adds the [BookStore](./../tutorials/book-store/index.md) sample to your solution.
@ -295,7 +295,7 @@ abp new-package --name Acme.BookStore.Domain --template lib.domain
* `lib.ef` * `lib.ef`
* `--include-migrations`: Allows migration operations on this package. * `--include-migrations`: Allows migration operations on this package.
* `--connection-string-name`: Default value is the last part of the package's namespace (or package name simply). * `--connection-string-name`: Default value is the last part of the package's namespace (or package name simply).
* `--connection-string`: Connection string value. Defaut value is null. You can set it alter. * `--connection-string`: Connection string value. Defaut value is null. You can set it alter. **Note:** When specifying the connection string, make sure to enclose it in double quotes, for example: `--connection-string "Server=localhost;Database=MyProjectName;Trusted_Connection=True"`.
* `lib.mongodb` * `lib.mongodb`
* `lib.http-api` * `lib.http-api`
* `lib.http-api-client` * `lib.http-api-client`

68
docs/en/docs-nav.json

@ -83,47 +83,59 @@
{ {
"text": "Overview", "text": "Overview",
"path": "tutorials/book-store", "path": "tutorials/book-store",
"isIndex": true "isIndex": true,
"isInSeries": true
}, },
{ {
"text": "1: Creating the Server Side", "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", "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", "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", "text": "4: Integration Tests",
"path": "tutorials/book-store/part-04.md" "path": "tutorials/book-store/part-04.md",
"isInSeries": true
}, },
{ {
"text": "5: Authorization", "text": "5: Authorization",
"path": "tutorials/book-store/part-05.md" "path": "tutorials/book-store/part-05.md",
"isInSeries": true
}, },
{ {
"text": "6: Authors: Domain Layer", "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", "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", "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", "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", "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", "text": "Overview",
"path": "tutorials/book-store-with-abp-suite", "path": "tutorials/book-store-with-abp-suite",
"isIndex": true "isIndex": true,
"isInSeries": true
}, },
{ {
"text": "1: Creating the Solution", "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", "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", "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", "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", "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
} }
] ]
}, },
@ -174,11 +192,11 @@
"path": "tutorials/modular-crm/part-01.md" "path": "tutorials/modular-crm/part-01.md"
}, },
{ {
"text": "2: Creating the Initial Products Module", "text": "2: Setting Up the Catalog Module",
"path": "tutorials/modular-crm/part-02.md" "path": "tutorials/modular-crm/part-02.md"
}, },
{ {
"text": "3: Building the Products Module", "text": "3: Building the Catalog Module",
"path": "tutorials/modular-crm/part-03.md" "path": "tutorials/modular-crm/part-03.md"
}, },
{ {
@ -2070,19 +2088,23 @@
"items": [ "items": [
{ {
"text": "Deploy to Azure Web App Service", "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", "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", "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", "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
} }
] ]
}, },

14
docs/en/framework/architecture/modularity/basics.md

@ -1,13 +1,12 @@
# Modularity # Modularity
## Introduction
ABP was designed to support to build fully modular applications and systems where every module may have entities, services, database integration, APIs, UI components and so on; ABP was designed to support to build fully modular applications and systems where every module may have entities, services, database integration, APIs, UI components and so on;
* This document introduces the basics of the module system. * This document introduces the **basics** of the module system.
* [Module development best practice guide](../best-practices) explains some **best practices** to develop **re-usable application modules** based on **DDD** principles and layers. A module designed based on this guide will be **database independent** and can be deployed as a **microservice** if needed. * The [modular monolith application development tutorial](../../../tutorials/modular-crm/index.md) explains and demonstrates how to build **modular monolith applications** with ABP.
* [Pre-built application modules](../../../modules) are **ready to use** in any kind of application. * [Pre-built application modules](../../../modules/index.md) are **ready to use** in any kind of application.
* [Module startup template](../../../solution-templates/application-module) is a jump start way to **create a new module**. * [Module startup template](../../../solution-templates/application-module/index.md) is a jump start way to **create a new reusable application module**.
* [Module development best practice guide](../best-practices/index.md) explains some **best practices** to develop **re-usable application modules** based on **DDD** principles and layers. A module designed based on this guide will be **database independent** and can be deployed as a **microservice** if needed.
* [ABP CLI](../../../cli/index.md) has commands to support modular development. * [ABP CLI](../../../cli/index.md) has commands to support modular development.
* All other framework features are compatible to the modularity system. * All other framework features are compatible to the modularity system.
@ -191,4 +190,5 @@ There are **two types of modules.** They don't have any structural difference bu
- **Application modules**: These modules implement **specific application/business functionalities** like blogging, document management, identity management, tenant management... etc. They generally have their own entities, services, APIs and UI components. See [pre-built application modules](../../../modules). - **Application modules**: These modules implement **specific application/business functionalities** like blogging, document management, identity management, tenant management... etc. They generally have their own entities, services, APIs and UI components. See [pre-built application modules](../../../modules).
## See Also ## See Also
* [Video tutorial](https://abp.io/video-courses/essentials/modularity) * [Modular monolith application development tutorial](../../../tutorials/modular-crm/index.md)
* [Video tutorial for basic modularity](https://abp.io/video-courses/essentials/modularity)

221
docs/en/framework/architecture/modularity/installer-projects.md

@ -0,0 +1,221 @@
# Module Installer Projects
Each ABP module includes an `.Installer` project (e.g., `Volo.Abp.Account.Installer`) that serves as a **Virtual File System container** for module installation and resource management. These projects are essential for the ABP CLI to understand and install modules properly.
## Purpose of Installer Projects
Installer projects have three main purposes:
1. **Virtual File System Integration**: Register the module's embedded resources with ABP's Virtual File System
2. **Resource Packaging**: Package module metadata files (`.abpmdl` and `.abppkg`) as embedded resources
3. **CLI Integration**: Enable the ABP CLI to understand module structure and install modules automatically
## Structure of Installer Projects
### Project Files
- **`{ModuleName}.Installer.csproj`**: References `Volo.Abp.VirtualFileSystem` and embeds module metadata files
- **`InstallationNotes.md`**: Documentation for the module
- **`Volo/Abp/{ModuleName}/Abp{ModuleName}InstallerModule.cs`**: The core module class that registers embedded resources
### Example Installer Module
```csharp
using Volo.Abp.Modularity;
using Volo.Abp.VirtualFileSystem;
namespace Volo.Abp.Account;
[DependsOn(typeof(AbpVirtualFileSystemModule))]
public class AbpAccountInstallerModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
Configure<AbpVirtualFileSystemOptions>(options =>
{
options.FileSets.AddEmbedded<AbpAccountInstallerModule>();
});
}
}
```
### Project Configuration
The `.csproj` file embeds module metadata as content:
```xml
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<GenerateEmbeddedFilesManifest>true</GenerateEmbeddedFilesManifest>
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\..\framework\src\Volo.Abp.VirtualFileSystem\Volo.Abp.VirtualFileSystem.csproj" />
</ItemGroup>
<ItemGroup>
<!-- Embed module definition file -->
<Content Include="..\..\Volo.Abp.Account.abpmdl">
<Pack>true</Pack>
<PackagePath>content\</PackagePath>
</Content>
<!-- Embed package definition files -->
<Content Include="..\..\**\*.abppkg*">
<Pack>true</Pack>
<PackagePath>content\</PackagePath>
</Content>
</ItemGroup>
</Project>
```
## Module Metadata Files
### `.abpmdl` (Module Definition)
The module definition file describes the module's structure and packages:
```json
{
"folders": {
"items": {
"src": {},
"test": {}
}
},
"packages": {
"Volo.Abp.Account.Web": {
"path": "src/Volo.Abp.Account.Web/Volo.Abp.Account.Web.abppkg",
"folder": "src"
},
"Volo.Abp.Account.Application": {
"path": "src/Volo.Abp.Account.Application/Volo.Abp.Account.Application.abppkg",
"folder": "src"
}
}
}
```
### `.abppkg` (Package Definition)
Each package has a definition file that specifies its role:
```json
{
"role": "lib.application"
}
```
Common roles:
- `lib.application`: Application layer package
- `lib.mvc`: MVC/Web layer package
- `lib.domain`: Domain layer package
- `lib.domain-shared`: Shared domain layer package
- `lib.efcore`: Entity Framework Core package
## How Installer Projects Work
### 1. CLI Installation Process
When you run `abp add-module Volo.Abp.Account`:
1. **Download Installer Package**: CLI downloads `Volo.Abp.Account.Installer` from NuGet
2. **Read Module Definition**: CLI reads the embedded `.abpmdl` file to understand module structure
3. **Read Package Definitions**: CLI reads `.abppkg` files to understand package roles
4. **Install Packages**: CLI installs appropriate packages to correct project types based on roles
5. **Add Dependencies**: CLI adds module dependencies to project module classes
### 2. Virtual File System Integration
The `InstallerModule` registers itself with the Virtual File System:
```csharp
options.FileSets.AddEmbedded<AbpAccountInstallerModule>();
```
This makes embedded resources available at runtime and enables:
- Access to module metadata
- Resource file management
- Module configuration
## Creating Installer Projects for New Modules
### Required Files
1. **Project File**: `{ModuleName}.Installer.csproj`
2. **Module Class**: `Abp{ModuleName}InstallerModule.cs`
3. **Documentation**: `InstallationNotes.md`
4. **Module Definition**: `{ModuleName}.abpmdl` (in module root)
5. **Package Definitions**: `{PackageName}.abppkg` (in each package)
### Template Structure
```
modules/your-module/
├── src/
│ ├── Volo.Abp.YourModule.Installer/
│ │ ├── Volo.Abp.YourModule.Installer.csproj
│ │ ├── InstallationNotes.md
│ │ └── Volo/
│ │ └── Abp/
│ │ └── YourModule/
│ │ └── AbpYourModuleInstallerModule.cs
│ └── [other packages]/
├── Volo.Abp.YourModule.abpmdl
└── [other module files]
```
### Package Definition Examples
For different package types:
```json
// Application package
{ "role": "lib.application" }
// MVC package
{ "role": "lib.mvc" }
// Domain package
{ "role": "lib.domain" }
// EF Core package
{ "role": "lib.efcore" }
```
## Why Installer Projects Appear "Empty"
Installer projects appear minimal because their primary function is infrastructure, not business logic:
- **No Business Logic**: Business logic belongs in the actual module packages
- **Pure Infrastructure**: They only handle module installation and resource management
- **CLI Integration**: They enable automated module installation through the ABP CLI
- **Resource Management**: They package and distribute module metadata
## Best Practices
1. **Follow Naming Convention**: Use `{ModuleName}.Installer` for the project name
2. **Include Documentation**: Always provide `InstallationNotes.md` with module information
3. **Proper Dependencies**: Only depend on `Volo.Abp.VirtualFileSystem`
4. **Embed All Metadata**: Include both `.abpmdl` and `.abppkg` files
5. **Test Installation**: Verify your installer works with `abp add-module` command
## Troubleshooting
### Common Issues
1. **Missing .abpmdl file**: Ensure the module definition file exists in the module root
2. **Missing .abppkg files**: Each package needs a definition file
3. **Incorrect roles**: Use appropriate roles for each package type
4. **CLI not finding module**: Verify the installer package is published to NuGet
### Verification Steps
1. Build the installer project: `dotnet build`
2. Check embedded resources: Verify `.abpmdl` and `.abppkg` files are embedded
3. Test CLI installation: `abp add-module YourModule`
4. Verify dependencies: Check that module dependencies are added correctly
This installer system enables ABP's sophisticated module architecture, allowing for automated installation with proper dependency resolution and project type matching.

13
docs/en/framework/architecture/multi-tenancy/index.md

@ -380,6 +380,19 @@ namespace MultiTenancyDemo.Web
* A tenant resolver should set `context.TenantIdOrName` if it can determine it. If not, just leave it as is to allow the next resolver to determine it. * A tenant resolver should set `context.TenantIdOrName` if it can determine it. If not, just leave it as is to allow the next resolver to determine it.
* `context.ServiceProvider` can be used if you need to additional services to resolve from the [dependency injection](../../fundamentals/dependency-injection.md) system. * `context.ServiceProvider` can be used if you need to additional services to resolve from the [dependency injection](../../fundamentals/dependency-injection.md) system.
##### The Fallback Tenant
If you want to always fallback to a tenant (in case of no tenant was found by the tenant resolution logic), you can set the `AbpTenantResolveOptions.FallbackTenant` option:
```csharp
Configure<AbpTenantResolveOptions>(options =>
{
options.FallbackTenant = "acme";
});
```
The `FallbackTenant` value can be a tenant name or tenant's Id. This option can be helpful on development time or some specific scenarios to set a constant tenant for the application. It is a simple and consistent way to ensure that a tenant context is always available when needed. However, when you do that, no way to switch to the host side. It is not something you will need it most of the time, but here if you need such a resolution logic.
#### Multi-Tenancy Middleware #### Multi-Tenancy Middleware
Multi-Tenancy middleware is an ASP.NET Core request pipeline [middleware](https://docs.microsoft.com/en-us/aspnet/core/fundamentals/middleware) that determines the current tenant from the HTTP request and sets the `ICurrentTenant` properties. Multi-Tenancy middleware is an ASP.NET Core request pipeline [middleware](https://docs.microsoft.com/en-us/aspnet/core/fundamentals/middleware) that determines the current tenant from the HTTP request and sets the `ICurrentTenant` properties.

33
docs/en/framework/data/entity-framework-core/index.md

@ -142,24 +142,27 @@ Configure<AbpDbContextOptions>(options =>
Add actions for the `ConfigureConventions` and `OnModelCreating` methods of the `DbContext` as shown below: Add actions for the `ConfigureConventions` and `OnModelCreating` methods of the `DbContext` as shown below:
````csharp ````csharp
options.DefaultConventionAction = (dbContext, builder) => Configure<AbpDbContextOptions>(options =>
{ {
// This action is called for ConfigureConventions method of all DbContexts. options.ConfigureDefaultConvention((dbContext, builder) =>
}; {
// This action is called for ConfigureConventions method of all DbContexts.
});
options.ConfigureConventions<YourDbContext>((dbContext, builder) => options.ConfigureConventions<YourDbContext>((dbContext, builder) =>
{ {
// This action is called for ConfigureConventions method of specific DbContext. // This action is called for ConfigureConventions method of specific DbContext.
}); });
options.DefaultOnModelCreatingAction = (dbContext, builder) => options.ConfigureDefaultOnModelCreating((dbContext, builder) =>
{ {
// This action is called for OnModelCreating method of all DbContexts. // This action is called for OnModelCreating method of all DbContexts.
}; });
options.ConfigureOnModelCreating<YourDbContext>((dbContext, builder) => options.ConfigureOnModelCreating<YourDbContext>((dbContext, builder) =>
{ {
// This action is called for OnModelCreating method of specific DbContext. // This action is called for OnModelCreating method of specific DbContext.
});
}); });
```` ````
@ -972,4 +975,4 @@ public class MyCustomEfCoreBulkOperationProvider
* [Entities](../../architecture/domain-driven-design/entities.md) * [Entities](../../architecture/domain-driven-design/entities.md)
* [Repositories](../../architecture/domain-driven-design/repositories.md) * [Repositories](../../architecture/domain-driven-design/repositories.md)
* [Video tutorial](https://abp.io/video-courses/essentials/abp-ef-core) * [Video tutorial](https://abp.io/video-courses/essentials/abp-ef-core)

51
docs/en/framework/fundamentals/configuration.md

@ -1,3 +1,52 @@
# Configuration # Configuration
ASP.NET Core has an flexible and extensible key-value based configuration system. In fact, the configuration system is a part of Microsoft.Extensions libraries and it is independent from ASP.NET Core. That means it can be used in any type of application. See [Microsoft's documentation](https://docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration/) to learn the configuration infrastructure. ABP is 100% compatible with the configuration system. ASP.NET Core has an flexible and extensible key-value based configuration system. The configuration system is a part of Microsoft.Extensions libraries and it is independent from ASP.NET Core. That means it can be used in any type of application.
See [Microsoft's documentation](https://docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration/) to learn the configuration infrastructure. ABP is 100% compatible with the configuration system.
## Getting the Configuration
You may need to get the `IConfiguration` service in various places in your codebase. The following section shows two common ways.
### In Module Classes
You typically need to get configuration while initializing your application. You can get the `IConfiguration` service using the `ServiceConfigurationContext.Configuration` property inside your [module class](../architecture/modularity/basics.md) as the following example:
````csharp
public class MyAppModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
var connectionString = context.Configuration["ConnectionStrings:Default"];
}
}
````
`context.Configuration` is a shortcut property for the `context.Services.GetConfiguration()` method. In general, prefer using `context.Configuration` for simplicity and readability when working within module classes. Use `context.Services.GetConfiguration()` in other contexts where you have an `IServiceCollection` object but do not have access to the `context.Configuration` property. (`IServiceCollection.GetConfiguration` is an extension method that can be used whenever you have an `IServiceCollection` object).
### In Your Services
You can directly [inject](dependency-injection.md) the `IConfiguration` service into your services:
````csharp
public class MyService : ITransientDependency
{
private readonly IConfiguration _configuration;
public MyService(IConfiguration configuration)
{
_configuration = configuration;
}
public string? GetConnectionString()
{
return _configuration["ConnectionStrings:Default"];
}
}
````
## See Also
* [Microsoft's Configuration Documentation](https://docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration/)
* [The Options Pattern](options.md)

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

@ -159,14 +159,24 @@ app.UseAbpHangfireDashboard("/hangfire", options =>
`AbpHangfireAuthorizationFilter` class has the following fields: `AbpHangfireAuthorizationFilter` class has the following fields:
* **`enableTenant` (`bool`, default: `false`):** Enables/disables accessing the Hangfire dashboard on tenant users. * **`enableTenant` (`bool`, default: `false`):** Enables/disables accessing the Hangfire dashboard on tenant users.
* **`requiredPermissionName` (`string`, default: `null`):** Hangfire dashboard is accessible only if the current user has the specified permission. In this case, if we specify a permission name, we don't need to set `enableTenant` `true` because the permission system already does it. * **`requiredPermissionName` (`string`, default: `null`):** Hangfire dashboard is accessible only if the current user has the specified permission.
* **`requiredRoleNames` (`string[]`, default: `[]`):** Hangfire dashboard is accessible only if the current user has one of the specified roles.
If you want to require an additional permission, you can pass it into the constructor as below: If you want to require more policies, you can use the `PolicyBuilder` property of the `AbpHangfireAuthorizationFilter` class.
```csharp ```csharp
app.UseAbpHangfireDashboard("/hangfire", options => app.UseAbpHangfireDashboard("/hangfire", options =>
{ {
options.AsyncAuthorization = new[] { new AbpHangfireAuthorizationFilter(requiredPermissionName: "MyHangFireDashboardPermissionName") }; var hangfireAuthorizationFilter = new AbpHangfireAuthorizationFilter(requiredPermissionName: "MyHangFireDashboardPermissionName");
//hangfireAuthorizationFilter.PolicyBuilder.AddRequirements(new PermissionRequirement("YourPermissionName"));
//hangfireAuthorizationFilter.PolicyBuilder.RequireRole("YourCustomRole");
//hangfireAuthorizationFilter.PolicyBuilder.Requirements.Add(new YourCustomRequirement());
options.AsyncAuthorization = new[]
{
hangfireAuthorizationFilter
};
}); });
``` ```
@ -190,18 +200,20 @@ private void ConfigureAuthentication(ServiceConfigurationContext context, IConfi
options.Authority = configuration["AuthServer:Authority"]; options.Authority = configuration["AuthServer:Authority"];
options.RequireHttpsMetadata = configuration.GetValue<bool>("AuthServer:RequireHttpsMetadata"); options.RequireHttpsMetadata = configuration.GetValue<bool>("AuthServer:RequireHttpsMetadata");
options.Audience = "MyProjectName"; options.Audience = "MyProjectName";
});
context.Services.AddAuthentication() options.ForwardDefaultSelector = httpContext => httpContext.Request.Path.StartsWithSegments("/hangfire", StringComparison.OrdinalIgnoreCase)
.AddCookie("Cookies") ? CookieAuthenticationDefaults.AuthenticationScheme
.AddOpenIdConnect("oidc", options => : null;
})
.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme)
.AddAbpOpenIdConnect(OpenIdConnectDefaults.AuthenticationScheme, options =>
{ {
options.Authority = configuration["AuthServer:Authority"]; options.Authority = configuration["AuthServer:Authority"];
options.RequireHttpsMetadata = configuration.GetValue<bool>("AuthServer:RequireHttpsMetadata"); options.RequireHttpsMetadata = Convert.ToBoolean(configuration["AuthServer:RequireHttpsMetadata"]);
options.ResponseType = OpenIdConnectResponseType.CodeIdToken; options.ResponseType = OpenIdConnectResponseType.Code;
options.ClientId = configuration["AuthServer:ClientId"]; options.ClientId = configuration["AuthServer:HangfireClientId"];
options.ClientSecret = configuration["AuthServer:ClientSecret"]; options.ClientSecret = configuration["AuthServer:HangfireClientSecret"];
options.UsePkce = true; options.UsePkce = true;
options.SaveTokens = true; options.SaveTokens = true;
@ -211,6 +223,8 @@ private void ConfigureAuthentication(ServiceConfigurationContext context, IConfi
options.Scope.Add("email"); options.Scope.Add("email");
options.Scope.Add("phone"); options.Scope.Add("phone");
options.Scope.Add("MyProjectName"); options.Scope.Add("MyProjectName");
options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
}); });
} }
``` ```
@ -218,26 +232,27 @@ private void ConfigureAuthentication(ServiceConfigurationContext context, IConfi
```csharp ```csharp
app.Use(async (httpContext, next) => app.Use(async (httpContext, next) =>
{ {
if (httpContext.Request.Path.StartsWithSegments("/hangfire")) if (httpContext.Request.Path.StartsWithSegments("/hangfire", StringComparison.OrdinalIgnoreCase))
{ {
var result = await httpContext.AuthenticateAsync("Cookies"); var authenticateResult = await httpContext.AuthenticateAsync(CookieAuthenticationDefaults.AuthenticationScheme);
if (result.Succeeded) if (!authenticateResult.Succeeded)
{ {
httpContext.User = result.Principal; await httpContext.ChallengeAsync(
await next(httpContext); OpenIdConnectDefaults.AuthenticationScheme,
new AuthenticationProperties
{
RedirectUri = httpContext.Request.Path + httpContext.Request.QueryString
});
return; return;
} }
await httpContext.ChallengeAsync("oidc");
}
else
{
await next(httpContext);
} }
await next.Invoke();
}); });
app.UseAbpHangfireDashboard("/hangfire", options => app.UseAbpHangfireDashboard("/hangfire", options =>
{ {
options.AsyncAuthorization = new[] {new AbpHangfireAuthorizationFilter()}; options.AsyncAuthorization = new[]
{
new AbpHangfireAuthorizationFilter()
};
}); });
``` ```

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 ### Queue a Job Item
Now, you can queue an email sending job using the `IBackgroundJobManager` service: Now, you can queue an email sending job using the `IBackgroundJobManager` service:

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: 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 ````csharp
public class PassiveUserCheckerWorker : AsyncPeriodicBackgroundWorkerBase public class PassiveUserCheckerWorker : AsyncPeriodicBackgroundWorkerBase
{ {
@ -52,6 +54,7 @@ public class PassiveUserCheckerWorker : AsyncPeriodicBackgroundWorkerBase
serviceScopeFactory) serviceScopeFactory)
{ {
Timer.Period = 600000; //10 minutes Timer.Period = 600000; //10 minutes
//CronExpression = "0 0/10 * * * ?"; //Run every 10 minutes, Only for Quartz or Hangfire integration.
} }
protected async override Task DoWorkAsync( protected async override Task DoWorkAsync(

2
docs/en/framework/infrastructure/features.md

@ -424,7 +424,7 @@ namespace FeaturesDemo
return Task.FromResult("true"); return Task.FromResult("true");
} }
return null; return Task.FromResult<string>(null);
} }
} }
} }

4
docs/en/framework/infrastructure/simple-state-checker.md

@ -11,11 +11,11 @@ public class MyObject : IHasSimpleStateCheckers<MyObject>
{ {
public int Id { get; set; } public int Id { get; set; }
public List<ISimpleStateChecker<MyObject>> SimpleStateCheckers { get; } public List<ISimpleStateChecker<MyObject>> StateCheckers { get; }
public MyObject() public MyObject()
{ {
SimpleStateCheckers = new List<ISimpleStateChecker<MyObject>>(); StateCheckers = new List<ISimpleStateChecker<MyObject>>();
} }
} }
```` ````

4
docs/en/framework/real-time/signalr.md

@ -55,11 +55,9 @@ Client side installation depends on your UI framework / client type.
Run the following command in the root folder of your web project: Run the following command in the root folder of your web project:
```bash ```bash
yarn add @abp/signalr abp add-package @abp/signalr
``` ```
> This requires to [install yarn](https://yarnpkg.com/) if you haven't install before.
This will add the `@abp/signalr` to the dependencies in the `package.json` of your project: This will add the `@abp/signalr` to the dependencies in the `package.json` of your project:
```json ```json

2
docs/en/framework/ui/mvc-razor-pages/basic-theme.md

@ -14,7 +14,7 @@ If you need to manually this theme, follow the steps below:
* Install the [Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic](https://www.nuget.org/packages/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic) NuGet package to your web project. * Install the [Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic](https://www.nuget.org/packages/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic) NuGet package to your web project.
* Add `AbpAspNetCoreMvcUiBasicThemeModule` into the `[DependsOn(...)]` attribute for your [module class](../../architecture/modularity/basics.md) in the web project. * Add `AbpAspNetCoreMvcUiBasicThemeModule` into the `[DependsOn(...)]` attribute for your [module class](../../architecture/modularity/basics.md) in the web project.
* Install the [@abp/aspnetcore.mvc.ui.theme.basic](https://www.npmjs.com/package/@abp/aspnetcore.mvc.ui.theme.basic) NPM package to your web project (e.g. `npm install @abp/aspnetcore.mvc.ui.theme.basic` or `yarn add @abp/aspnetcore.mvc.ui.theme.basic`). * Install the [@abp/aspnetcore.mvc.ui.theme.basic](https://www.npmjs.com/package/@abp/aspnetcore.mvc.ui.theme.basic) NPM package to your web project (e.g. `abp add-package @abp/aspnetcore.mvc.ui.theme.basic`).
* Run `abp install-libs` command in a command line terminal in the web project's folder. * Run `abp install-libs` command in a command line terminal in the web project's folder.
## Layouts ## Layouts

11
docs/en/framework/ui/mvc-razor-pages/client-side-package-management.md

@ -3,9 +3,8 @@
ABP can work with any type of client side package management systems. You can even decide to use no package management system and manage your dependencies manually. ABP can work with any type of client side package management systems. You can even decide to use no package management system and manage your dependencies manually.
However, ABP works best with **NPM/Yarn**. By default, built-in modules are configured to work with NPM/Yarn. However, ABP works best with **NPM**. By default, built-in modules are configured to work with NPM.
Finally, we suggest the [**Yarn**](https://classic.yarnpkg.com/) over the NPM since it's faster, stable and also compatible with the NPM.
### @ABP NPM Packages ### @ABP NPM Packages
@ -35,14 +34,12 @@ It's suggested to depend on a standard package instead of directly depending on
#### Package Installation #### Package Installation
After depending on a NPM package, all you should do is to run the **yarn** command from the command line to install all the packages and their dependencies: After depending on a NPM package, you should run the **abp install-libs** command from the command line to install all the packages and their dependencies, and copy the required resources to the wwwroot/libs folder:
```bash ```bash
yarn abp install-libs
``` ```
Alternatively, you can use `npm install` but [Yarn v1.22+ (not v2)](https://classic.yarnpkg.com/en/docs/install) is suggested as mentioned before.
#### Package Contribution #### Package Contribution
If you need a third-party NPM package that is not in the standard set of packages, you can create a Pull Request on the Github [repository](https://github.com/volosoft/abp). A pull request that follows these rules is accepted: If you need a third-party NPM package that is not in the standard set of packages, you can create a Pull Request on the Github [repository](https://github.com/volosoft/abp). A pull request that follows these rules is accepted:
@ -57,7 +54,7 @@ See current standard packages for examples.
### Mapping The Library Resources ### Mapping The Library Resources
Using NPM packages and NPM/Yarn tool is the de facto standard for client side libraries. NPM/Yarn tool creates a **node_modules** folder in the root folder of your web project. Using NPM packages and NPM tool is the de facto standard for client side libraries. NPM tool creates a **node_modules** folder in the root folder of your web project.
Next challenge is copying needed resources (js, css, img... files) from the `node_modules` into a folder inside the **wwwroot** folder to make it accessible to the clients/browsers. Next challenge is copying needed resources (js, css, img... files) from the `node_modules` into a folder inside the **wwwroot** folder to make it accessible to the clients/browsers.

BIN
docs/en/get-started/images/abp-studio-new-solution-dialog-modularity.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

BIN
docs/en/get-started/images/abp-studio-no-layers-new-solution-dialog-ui-framework-0.9.13.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 117 KiB

After

Width:  |  Height:  |  Size: 459 KiB

BIN
docs/en/get-started/images/abp-studio-no-layers-new-solution-modularity.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

10
docs/en/get-started/layered-web-application.md

@ -17,7 +17,7 @@ First things first! Let's setup your development environment before creating the
* [Visual Studio 2022](https://visualstudio.microsoft.com/) or another IDE that supports [.NET 9.0+](https://dotnet.microsoft.com/download/dotnet) development. * [Visual Studio 2022](https://visualstudio.microsoft.com/) or another IDE that supports [.NET 9.0+](https://dotnet.microsoft.com/download/dotnet) development.
* [.NET 9.0+](https://dotnet.microsoft.com/en-us/download/dotnet){{ if UI != "Blazor" }} * [.NET 9.0+](https://dotnet.microsoft.com/en-us/download/dotnet){{ if UI != "Blazor" }}
* [Node v22.11+](https://nodejs.org/) * [Node v22.11+](https://nodejs.org/){{ end }}{{ if UI == "NG" }}
* [Yarn v1.22+ (not v2+)](https://classic.yarnpkg.com/en/docs/install) or npm v10+ (already installed with Node){{ end }} * [Yarn v1.22+ (not v2+)](https://classic.yarnpkg.com/en/docs/install) or npm v10+ (already installed with Node){{ end }}
* [Docker Desktop](https://www.docker.com/products/docker-desktop/) * [Docker Desktop](https://www.docker.com/products/docker-desktop/)
@ -25,8 +25,6 @@ First things first! Let's setup your development environment before creating the
## Creating a New Solution ## Creating a New Solution
> This document uses [ABP Studio](../studio/index.md) to create new ABP solutions. **ABP Studio** is in the beta version now. If you have any issues, you can use the [ABP CLI](../cli/index.md) to create new solutions. You can also use the [getting started page](https://abp.io/get-started) to easily build ABP CLI commands for new project creations.
> ABP startup solution templates have many options for your specific needs. If you don't understand an option that probably means you don't need it. We selected common defaults for you, so you can leave these options as they are. > ABP startup solution templates have many options for your specific needs. If you don't understand an option that probably means you don't need it. We selected common defaults for you, so you can leave these options as they are.
Assuming that you have [installed and logged in](../studio/installation.md) to the application, you should see the following screen when you open ABP Studio: Assuming that you have [installed and logged in](../studio/installation.md) to the application, you should see the following screen when you open ABP Studio:
@ -105,6 +103,12 @@ Here, you can select the database management systems (DBMS){{ if DB == "EF" }} a
If you uncheck the *Kubernetes Configuration* option, the solution will not include the Kubernetes configuration files, such as Helm charts and other Kubernetes-related files. You can also specify *Social Logins*; if you uncheck this option, the solution will not be configured for social login. Lastly, you can specify the *Include Tests* option to include or exclude the test projects from the solution. If you uncheck the *Kubernetes Configuration* option, the solution will not include the Kubernetes configuration files, such as Helm charts and other Kubernetes-related files. You can also specify *Social Logins*; if you uncheck this option, the solution will not be configured for social login. Lastly, you can specify the *Include Tests* option to include or exclude the test projects from the solution.
On the next screen, you can configure the modularity options for your solution:
> If you select the *Setup as a modular solution* option, the solution is created more ready for [modular monolith development](../tutorials/modular-crm/index.md) and allows you to add sub-modules during the solution creation phase.
![abp-studio-new-solution-modularity](images/abp-studio-new-solution-dialog-modularity.png)
Now, we are ready to allow ABP Studio to create our solution. Just click the *Create* button and let the ABP Studio do the rest for you. After clicking the Create button, the dialog is closed and your solution is loaded into ABP Studio: Now, we are ready to allow ABP Studio to create our solution. Just click the *Create* button and let the ABP Studio do the rest for you. After clicking the Create button, the dialog is closed and your solution is loaded into ABP Studio:
![abp-studio-created-new-solution](images/abp-studio-created-new-solution.png) ![abp-studio-created-new-solution](images/abp-studio-created-new-solution.png)

4
docs/en/get-started/maui.md

@ -13,9 +13,11 @@ dotnet tool install -g Volo.Abp.Studio.Cli
Then use the `abp new` command in an empty folder to create a new solution: Then use the `abp new` command in an empty folder to create a new solution:
````bash ````bash
abp new Acme.MyMauiApp -t maui abp new Acme.MyMauiApp -t maui --old
```` ````
> **Note**: Since this startup template is not provided by the new ABP Studio Templates yet, you need to pass the `--old` parameter at the end of the command to use the old CLI & templating system for this startup template.
`Acme.MyMauiApp` is the solution name, like *YourCompany.YourProduct*. You can use single level, two-levels or three-levels naming. `Acme.MyMauiApp` is the solution name, like *YourCompany.YourProduct*. You can use single level, two-levels or three-levels naming.
## Solution Structure ## Solution Structure

4
docs/en/get-started/microservice.md

@ -11,7 +11,7 @@ First things first! Let's setup your development environment before creating the
* [Visual Studio 2022](https://visualstudio.microsoft.com/vs/) or another IDE that supports .NET development * [Visual Studio 2022](https://visualstudio.microsoft.com/vs/) or another IDE that supports .NET development
* [.NET 9.0+](https://dotnet.microsoft.com/en-us/download/dotnet) * [.NET 9.0+](https://dotnet.microsoft.com/en-us/download/dotnet)
* [Node v22.11+](https://nodejs.org/) * [Node v22.11+](https://nodejs.org/)
* [Yarn v1.22+ (not v2+)](https://classic.yarnpkg.com/en/docs/install) or npm v10+ (already installed with Node) * [Yarn v1.22+ (not v2+)](https://classic.yarnpkg.com/en/docs/install) or npm v10+ (already installed with Node), **This is required for the Angular applications.**
* [Docker Desktop (with Kubernetes enabled)](https://www.docker.com/products/docker-desktop/) * [Docker Desktop (with Kubernetes enabled)](https://www.docker.com/products/docker-desktop/)
* [Helm](https://helm.sh/docs/intro/install/) * [Helm](https://helm.sh/docs/intro/install/)
* [NGINX Ingress Controller](https://kubernetes.github.io/ingress-nginx/deploy/) * [NGINX Ingress Controller](https://kubernetes.github.io/ingress-nginx/deploy/)
@ -21,8 +21,6 @@ First things first! Let's setup your development environment before creating the
## Creating a New Solution ## Creating a New Solution
> 🛈 This document uses [ABP Studio](../studio/index.md) to create new ABP solutions. **ABP Studio** is in the beta version now. If you have any issues, you can use the [ABP CLI](../cli/index.md) to create new solutions. You can also use the [getting started page](https://abp.io/get-started) to easily build ABP CLI commands for new project creations.
> ABP startup solution templates have many options for your specific needs. If you don't understand an option that probably means you don't need it. We selected common defaults for you, so you can leave these options as they are. > ABP startup solution templates have many options for your specific needs. If you don't understand an option that probably means you don't need it. We selected common defaults for you, so you can leave these options as they are.
Assuming that you have [installed and logged in](../studio/installation.md) to the application, you should see the following screen when you open ABP Studio: Assuming that you have [installed and logged in](../studio/installation.md) to the application, you should see the following screen when you open ABP Studio:

8
docs/en/get-started/pre-requirements.md

@ -47,11 +47,13 @@ If you have already installed the `EF Core CLI`, you can update it by running th
dotnet tool update --global dotnet-ef dotnet tool update --global dotnet-ef
``` ```
## Node.js and Yarn ## Node.js
ABP projects include some frontend resource packages, so you need to install Node.js and Yarn to manage these resource packages. You can download Node.js from the [official Node.js website](https://nodejs.org/). We recommend installing version v20.11+. ABP projects include some frontend resource packages, so you need to install Node.js/NPM manage these resource packages. You can download Node.js from the [official Node.js website](https://nodejs.org/). We recommend installing version v20.11+.
Using Yarn (classic) to manage frontend resource packages is faster and more stable than using npm. You can download `Yarn` from the [Yarn official website](https://classic.yarnpkg.com/en/docs/install). We recommend installing Yarn v1.22+ (make sure to install the Classic version, not v2+). ## Yarn (Required Only for Angular Projects)
ABP Angular projects use Yarn as the package manager to manage frontend dependencies and run build tasks, You can download `Yarn` from the [Yarn official website](https://classic.yarnpkg.com/en/docs/install). We recommend installing Yarn v1.22+ (make sure to install the Classic version, not v2+).
To install Yarn using npm, run the following command: To install Yarn using npm, run the following command:

16
docs/en/get-started/single-layer-web-application.md

@ -3,7 +3,7 @@
````json ````json
//[doc-params] //[doc-params]
{ {
"UI": ["MVC", "Blazor", "BlazorServer", "NG"], "UI": ["MVC", "Blazor", "BlazorServer", "BlazorWebApp", "NG"],
"DB": ["EF", "Mongo"] "DB": ["EF", "Mongo"]
} }
```` ````
@ -16,14 +16,14 @@ First things first! Let's setup your development environment before creating the
* [Visual Studio 2022](https://visualstudio.microsoft.com/) or another IDE that supports [.NET 9.0+](https://dotnet.microsoft.com/download/dotnet) development. * [Visual Studio 2022](https://visualstudio.microsoft.com/) or another IDE that supports [.NET 9.0+](https://dotnet.microsoft.com/download/dotnet) development.
* [.NET 9.0+](https://dotnet.microsoft.com/en-us/download/dotnet){{ if UI != "Blazor" }} * [.NET 9.0+](https://dotnet.microsoft.com/en-us/download/dotnet){{ if UI != "Blazor" }}
* [Node v22.11+](https://nodejs.org/) * [Node v22.11+](https://nodejs.org/){{ end }}{{ if UI == "NG" }}
* [Yarn v1.22+ (not v2+)](https://classic.yarnpkg.com/en/docs/install) or npm v10+ (already installed with Node){{ end }} * [Yarn v1.22+ (not v2+)](https://classic.yarnpkg.com/en/docs/install) or npm v10+ (already installed with Node){{ end }}
> Check the [Pre-requirements document](pre-requirements.md) for more detailed information about these tools. > Check the [Pre-requirements document](pre-requirements.md) for more detailed information about these tools.
## Creating a New Solution ## Creating a New Solution
> 🛈 This document uses [ABP Studio](../studio/index.md) to create new ABP solutions. **ABP Studio** is in the beta version now. If you have any issues, you can use the [ABP CLI](../cli/index.md) to create new solutions. You can also use the [getting started page](https://abp.io/get-started) to easily build ABP CLI commands for new project creations. > 🛈 This document uses [ABP Studio](../studio/index.md) to create new ABP solutions. You can also use the [ABP CLI](../cli/index.md) to create new solutions and use the [getting started page](https://abp.io/get-started) to easily build ABP CLI commands.
> ABP startup solution templates have many options for your specific needs. If you don't understand an option that probably means you don't need it. We selected common defaults for you, so you can leave these options as they are. > ABP startup solution templates have many options for your specific needs. If you don't understand an option that probably means you don't need it. We selected common defaults for you, so you can leave these options as they are.
@ -31,7 +31,7 @@ Assuming that you have [installed and logged in](../studio/installation.md) to t
![abp-studio-welcome-screen](images/abp-studio-welcome-screen.png) ![abp-studio-welcome-screen](images/abp-studio-welcome-screen.png)
Select the *File* -> *New Solution* in the main menu, or click the *New solution* button on the Welcome screen to open the *Create new solution* wizard: Select the *File* -> *New Solution* in the main menu, or click the *New solution* button on the *Welcome* screen to open the *Create new solution* wizard:
![abp-studio-new-solution-dialog](images/abp-studio-no-layers-new-solution-dialog-0.9.13.png) ![abp-studio-new-solution-dialog](images/abp-studio-no-layers-new-solution-dialog-0.9.13.png)
@ -73,9 +73,15 @@ Here, you can select the database management systems (DBMS){{ if DB == "EF" }} a
![abp-studio-no-layers-new-solution-additional-options](images/abp-studio-no-layers-new-solution-additional-options-0.9.13.png) ![abp-studio-no-layers-new-solution-additional-options](images/abp-studio-no-layers-new-solution-additional-options-0.9.13.png)
Configure any additional options as needed and click the *Next* button to continue. On the next screen, you can configure the modularity options for your solution:
> If you select the *Setup as a modular solution* option, the solution is created more ready for [modular monolith development](../tutorials/modular-crm/index.md) and allows you to add sub-modules during the solution creation phase.
![abp-studio-no-layers-new-solution-modularity](images/abp-studio-no-layers-new-solution-modularity.png)
Now, we are ready to allow ABP Studio to create our solution. Just click the *Create* button and let the ABP Studio do the rest for you. Now, we are ready to allow ABP Studio to create our solution. Just click the *Create* button and let the ABP Studio do the rest for you.
After clicking the Create button, the dialog is closed and your solution is loaded into ABP Studio: After clicking the *Create* button, the dialog is closed and your solution is loaded into ABP Studio:
![abp-studio-created-new-solution](images/abp-studio-no-layers-created-new-solution.png) ![abp-studio-created-new-solution](images/abp-studio-no-layers-created-new-solution.png)

BIN
docs/en/images/azure-deploy-create-web-app-2.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 200 KiB

After

Width:  |  Height:  |  Size: 141 KiB

BIN
docs/en/images/azure-deploy-create-web-app-6.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 296 KiB

After

Width:  |  Height:  |  Size: 183 KiB

2
docs/en/modules/account/idle-session-timeout.md

@ -6,6 +6,8 @@ The `Idle Session Timeout` feature allows you to automatically log out users aft
You can enable/disable the `Idle Session Timeout` feature in the `Setting > Account > Idle Session Timeout` page. You can enable/disable the `Idle Session Timeout` feature in the `Setting > Account > Idle Session Timeout` page.
> This feature will be disabled if you select the `Remember Me` option on the login page.
The default idle session timeout is 1 hour. You can change it by selecting a different value from the dropdown list or entering a custom value (in minutes). The default idle session timeout is 1 hour. You can change it by selecting a different value from the dropdown list or entering a custom value (in minutes).
![idle-setting](../../images/idle-setting.png) ![idle-setting](../../images/idle-setting.png)

40
docs/en/modules/audit-logging-pro.md

@ -9,6 +9,8 @@ This module implements the Audit Logging system of an application;
* See all changes of entities and filter entity change logs. * See all changes of entities and filter entity change logs.
* View details of an entity change. * View details of an entity change.
* View all changes of an entity. * View all changes of an entity.
* Export audit logs and entity changes to Excel.
* Receive email notifications for completed or failed exports.
* This module also defines reusable "Average Execution Duration Per Day" and "Error Rate" widgets. * This module also defines reusable "Average Execution Duration Per Day" and "Error Rate" widgets.
* Periodic clean up of audit logs. * Periodic clean up of audit logs.
@ -56,6 +58,10 @@ You can view details of an audit log by clicking the magnifier icon on each audi
* **Actions:** This tab shows list of actions (controller actions and application service method calls with their parameters) executed during a web request. * **Actions:** This tab shows list of actions (controller actions and application service method calls with their parameters) executed during a web request.
* **Changes:** This tab shows changed entities during the web request. * **Changes:** This tab shows changed entities during the web request.
##### Export to Excel
You can export audit logs to Excel by clicking the "Export to Excel" button in the toolbar. If the result set is small (less than a configurable threshold), the file will be generated and downloaded immediately. For larger result sets, the export will be processed as a background job and you'll receive an email with a download link once the export is completed.
#### Entity Changes #### Entity Changes
Entity changes tab is used to list, view and filter entity change logs. Entity changes tab is used to list, view and filter entity change logs.
@ -80,6 +86,10 @@ You can view details of all changes of an entity by clicking the "Full Change Hi
![audit-logging-module-full-entity-change-details-modal](../images/audit-logging-module-full-entity-change-details-modal.png) ![audit-logging-module-full-entity-change-details-modal](../images/audit-logging-module-full-entity-change-details-modal.png)
##### Export to Excel
You can export entity changes to Excel by clicking the "Export to Excel" button in the toolbar. Similar to audit logs export, for large datasets the export will be processed as a background job and you'll receive an email notification once completed.
#### Audit Log Settings #### Audit Log Settings
The *Audit Log* settings tab is used to configure audit log settings. You can enable or disable the clean up service system wide. This way, you can shut down the clean up service for all tenants and host. If the system wide clean up service is enabled, you can configure the global *Expired Item Deletion Period* for all tenants and host. The *Audit Log* settings tab is used to configure audit log settings. You can enable or disable the clean up service system wide. This way, you can shut down the clean up service for all tenants and host. If the system wide clean up service is enabled, you can configure the global *Expired Item Deletion Period* for all tenants and host.
@ -121,11 +131,32 @@ To see `AbpAuditingOptions` properties, please see its [documentation](../framew
Configure<ExpiredAuditLogDeleterOptions>(options => Configure<ExpiredAuditLogDeleterOptions>(options =>
{ {
options.Period = (int)TimeSpan.FromSeconds(30).TotalMilliseconds; options.Period = (int)TimeSpan.FromSeconds(30).TotalMilliseconds;
options.CronExpression = "0 23 * * *"; // This Cron expression only works if Hangfire or Quartz is used for background workers.
}); });
``` ```
The *Period* doesn't mean the *Expired Item Deletion Period*. It's the period of the worker to run clean up service system wide. The default value is 1 day. The *Period* doesn't mean the *Expired Item Deletion Period*. It's the period of the worker to run clean up service system wide. The default value is 1 day.
### AuditLogExcelFileOptions
`AuditLogExcelFileOptions` can be configured in the UI layer, within the `ConfigureServices` method of your [module](../framework/architecture/modularity/basics.md). Example:
```csharp
Configure<AuditLogExcelFileOptions>(options =>
{
options.FileRetentionHours = 24; // How long to keep files before cleanup (default: 24 hours)
options.DownloadBaseUrl = "https://yourdomain.com"; // Base URL for download links in emails
options.ExcelFileCleanupOptions.Period = (int)TimeSpan.FromHours(24).TotalMilliseconds; // Interval of the cleanup worker (default: 24 hours)
options.ExcelFileCleanupOptions.CronExpression = "0 23 * * *"; // This Cron expression only works if Hangfire or Quartz is used for background workers.
});
```
> Note: The `FileRetentionHours` value determines when files become eligible for deletion, but actual deletion depends on when the cleanup worker runs. If the worker hasn't run after the retention period expires, files will remain accessible. Therefore, `FileRetentionHours` represents the minimum intended retention time, but the actual retention time might be longer depending on the worker's execution schedule.
These settings control where Excel export files are stored, how long they are kept before automatic cleanup, and what base URL is used in email download links.
> You must use a valid [BLOB Storage Provider](https://abp.io/docs/latest/framework/infrastructure/blob-storing#blob-storage-providers) to use this feature.
## Internals ## Internals
### Domain layer ### Domain layer
@ -156,6 +187,15 @@ Following custom repositories are defined for this module:
* `AuditLogsAppService` (implements `IAuditLogsAppService`): Implements the use cases of the audit logs management UI. * `AuditLogsAppService` (implements `IAuditLogsAppService`): Implements the use cases of the audit logs management UI.
#### Email Templates
The module provides email templates for notifications:
* `AuditLogExportCompleted`: Sent when an audit log export is successfully completed, including a download link.
* `AuditLogExportFailed`: Sent when an audit log export fails, including error details.
* `EntityChangeExportCompleted`: Sent when an entity change export is successfully completed, including a download link.
* `EntityChangeExportFailed`: Sent when an entity change export fails, including error details.
### Database providers ### Database providers
#### Common #### Common

11
docs/en/modules/language-management.md

@ -77,6 +77,11 @@ This module follows the [Entity Best Practices & Conventions](../framework/archi
* `Language` (aggregate root): Represents a language in the system. * `Language` (aggregate root): Represents a language in the system.
* `LanguageText` (aggregate root): Represents a language text in the system. * `LanguageText` (aggregate root): Represents a language text in the system.
##### Dynamic Localization
* `LocalizationResourceRecord` (aggregate root): Represents a localization resource in the system.
* `LocalizationTextRecord` (aggregate root): Represents all texts of a localization resource in the system.
#### Repositories #### Repositories
This module follows the [Repository Best Practices & Conventions](../framework/architecture/best-practices/repositories.md) guide. This module follows the [Repository Best Practices & Conventions](../framework/architecture/best-practices/repositories.md) guide.
@ -85,6 +90,8 @@ Following custom repositories are defined for this module:
* `ILanguageRepository` * `ILanguageRepository`
* `ILanguageTextRepository` * `ILanguageTextRepository`
* `ILocalizationResourceRecordRepository`
* `ILocalizationTextRecordRepository`
#### Domain Services #### Domain Services
@ -121,6 +128,8 @@ See the [connection strings](../framework/fundamentals/connection-strings.md) do
* **AbpLanguages** * **AbpLanguages**
* **AbpLanguageTexts** * **AbpLanguageTexts**
* **AbpLocalizationResources**
* **AbpLocalizationTexts**
#### MongoDB #### MongoDB
@ -128,6 +137,8 @@ See the [connection strings](../framework/fundamentals/connection-strings.md) do
* **AbpLanguages** * **AbpLanguages**
* **AbpLanguageTexts** * **AbpLanguageTexts**
* **AbpLocalizationResources**
* **AbpLocalizationTexts**
### Permissions ### Permissions

6
docs/en/modules/payment-custom-gateway.md

@ -6,7 +6,7 @@ This document explains creating custom a payment gateway that's different than t
## Creating Core Operations ## Creating Core Operations
- Create **MyPaymentGateway.cs** and implement `IPaymentGateway` - Create **MyPaymentGateway.cs** in the **Domain** layer of your project and implement `IPaymentGateway`.
```csharp ```csharp
public class MyPaymentGateway : IPaymentGateway, ITransientDependency public class MyPaymentGateway : IPaymentGateway, ITransientDependency
@ -57,7 +57,7 @@ This document explains creating custom a payment gateway that's different than t
} }
``` ```
- You should configure your gateway in `PaymentOptions` - You should also configure `PaymentOptions` for your gateway in the **Domain** layer of your project as shown below.
```csharp ```csharp
Configure<PaymentOptions>(options => Configure<PaymentOptions>(options =>
@ -119,7 +119,7 @@ There are 2 types of pages that are supported by default. You can define a pre-p
<h3>Operation Done</h3> <h3>Operation Done</h3>
``` ```
- Configure your pages in `PaymentWebOptions` - Configure your pages using `PaymentWebOptions` in **Web** layer of your project.
```csharp ```csharp
Configure<PaymentWebOptions>(options => Configure<PaymentWebOptions>(options =>

46
docs/en/release-info/migration-guides/abp-9-3.md

@ -0,0 +1,46 @@
# ABP Version 9.3 Migration Guide
This document is a guide for upgrading ABP v9.2 solutions to ABP v9.3. There are some changes in this version that may affect your applications, please read it carefully and apply the necessary changes to your application.
## Updated `RabbitMQ.Client` to `7.x`
In this version, we updated `RabbitMQ.Client` to `7.1.2`. [This is a major version update](https://github.com/rabbitmq/rabbitmq-dotnet-client/blob/main/v7-MIGRATION.md) that brings significant improvements to the library:
1. Full async/await support throughout the entire public API and internals
2. Improved performance and resource utilization
3. Better error handling and connection management
With this update, you should update your method calls to use the new async/await support (in the RabbitMQ related provider packages). There are some method signature changes and new API calls, aligned with the new API. You can see the internal changes we made in [#22510](https://github.com/abpframework/abp/pull/22510) and make the relevant changes in your code.
## Docs Module: Export as PDF
In this version, we have introduced a new feature to the [Docs Module](../../modules/docs.md) that allows you to export the documentation as a PDF file. (Administrators generate PDF files from the back-office side, and then "Download PDF" button appears on the document system, allowing users to download the compiled documentation as a PDF file.)
While implementing this feature, we have made changes in some services of the Docs Module. Typically, you don't need to make any changes in your code unless you have overridden or used internal services of the Docs Module.
For example, the `ProjectAdminAppService` constructor has been changed to accept a new parameter:
```diff
public class ProjectAdminAppService : ApplicationService, IProjectAdminAppService
{
public ProjectAdminAppService(
IProjectRepository projectRepository,
IDocumentRepository documentRepository,
IDocumentFullSearch elasticSearchService,
IGuidGenerator guidGenerator,
+ IProjectPdfFileStore projectPdfFileStore)
}
```
You can see the all internal changes we made in [#22430](https://github.com/abpframework/abp/pull/22430) and [#22922](https://github.com/abpframework/abp/pull/22922) and make the relevant changes in your code if needed.
## Angular UI: Migrating NPM Packages to Standalone Structure
In this version, we've updated our Angular packages to support the new standalone components architecture. This is a non-breaking change - your existing module-based applications will continue to work without any modifications. However, if you wish to migrate to the standalone approach, [we've provided the necessary updates in our packages](https://github.com/abpframework/abp/pull/22829).
The main changes include:
- Updated routing configurations to support both module-based and standalone approaches
- Added support for standalone components in ABP Suite code generation
- Updated schematics to support both module-based and standalone templates
For detailed migration steps and best practices, please refer to our upcoming documentation and/or blog post. The migration is optional, and you can continue using the module-based approach if you prefer.

1
docs/en/release-info/migration-guides/index.md

@ -2,6 +2,7 @@
The following documents explain how to migrate your existing ABP applications. We write migration documents only if you need to take an action while upgrading your solution. Otherwise, you can easily upgrade your solution using the [abp update command](../upgrading.md). The following documents explain how to migrate your existing ABP applications. We write migration documents only if you need to take an action while upgrading your solution. Otherwise, you can easily upgrade your solution using the [abp update command](../upgrading.md).
- [9.2 to 9.3](abp-9-3.md)
- [9.x to 9.2](abp-9-2.md) - [9.x to 9.2](abp-9-2.md)
- [9.0 to 9.1](abp-9-1.md) - [9.0 to 9.1](abp-9-1.md)
- [8.x to 9.0](abp-9-0.md) - [8.x to 9.0](abp-9-0.md)

13
docs/en/release-info/release-notes.md

@ -7,10 +7,19 @@ Also see the following notes about ABP releases:
* [ABP Studio release notes](../studio/release-notes.md) * [ABP Studio release notes](../studio/release-notes.md)
* [Change logs for ABP pro packages](https://abp.io/pro-releases) * [Change logs for ABP pro packages](https://abp.io/pro-releases)
## 9.3 (2025-06-17)
## 9.2 (2025-03-25) This is currently a RC (release-candidate) and you can see the detailed **[blog post / announcement](https://abp.io/community/articles/announcing-abp-9-3-release-candidate-4dqgiryf)** for the v9.3 release.
This is currently a RC (release-candidate) and you can see the detailed **[blog post / announcement](https://abp.io/community/articles/abp-platform-9.2-rc-has-been-released-jpq072nh)** for the v9.2 release. * Cron Expression Support for Background Workers
* Docs Module: PDF Export
* Angular UI: Standalone Package Structure
* Upgraded to `Blazorise` **v1.7.7**
* Audit Logging Module: Excel Export
## 9.2 (2025-06-02)
See the detailed **[blog post / announcement](https://abp.io/community/articles/announcing-abp-9-2-stable-release-061qmtzb)** for the v9.2 release.
* Added `ApplicationName` Property to Isolate Background Jobs & Background Workers * Added `ApplicationName` Property to Isolate Background Jobs & Background Workers
* Docs Module: Added "Alternative Words" to Filter Items * Docs Module: Added "Alternative Words" to Filter Items

6
docs/en/release-info/road-map.md

@ -4,11 +4,12 @@ This document provides a road map, release schedule, and planned features for th
## Next Versions ## Next Versions
### v9.3 ### v10.0
The next version will be 9.3 and planned to release the stable 9.3 version in July 2025. We will be mostly working on the following topics: The next version will be 10.0 and planned to release the stable 10.0 version in December 2025. We will be mostly working on the following topics:
* Framework * Framework
* Upgrading to .NET 10
* Upgrading 3rd-party dependencies * Upgrading 3rd-party dependencies
* Enhancements in the core points * Enhancements in the core points
@ -16,7 +17,6 @@ The next version will be 9.3 and planned to release the stable 9.3 version in Ju
* Define navigation properties without target string property dependency * Define navigation properties without target string property dependency
* Improvements one-to-many scenarios * Improvements one-to-many scenarios
* File Upload Modal enhancements * File Upload Modal enhancements
* Master/Detail DataGrid Toggle Detail Row Enhancements for Blazor UI
* ABP Studio * ABP Studio

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

Loading…
Cancel
Save