Browse Source

Merge remote-tracking branch 'origin/rel-9.1' into pr/21329

pull/21329/head
Enis Necipoglu 1 year ago
parent
commit
7c4a5e2d44
No known key found for this signature in database GPG Key ID: 1EC55E13241E1680
  1. 20
      .github/workflows/auto-pr.yml
  2. 3
      .github/workflows/build-and-test.yml
  3. 145
      Directory.Packages.props
  4. 4
      README.md
  5. 5
      abp_io/AbpIoLocalization/AbpIoLocalization/Account/Localization/Resources/en.json
  6. 5
      abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json
  7. 4
      abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/en.json
  8. 4
      common.props
  9. 2
      docs/en/Blog-Posts/2022-05-09 v5_3_Preview/POST.md
  10. 1
      docs/en/Blog-Posts/2022-07-26 v6_0_Preview/POST.md
  11. 7
      docs/en/Blog-Posts/2023-04-03-What-is-ABP-Framework/post.md
  12. BIN
      docs/en/Blog-Posts/2024-11-19 v9_0_Release_Stable/community-talks.png
  13. BIN
      docs/en/Blog-Posts/2024-11-19 v9_0_Release_Stable/cover-image.png
  14. 93
      docs/en/Blog-Posts/2024-11-19 v9_0_Release_Stable/post.md
  15. BIN
      docs/en/Blog-Posts/2024-11-19 v9_0_Release_Stable/switch-to-stable.png
  16. 67
      docs/en/Blog-Posts/2024-12-15-ABP-Studio-R2R/POST.md
  17. 4
      docs/en/Community-Articles/2022-09-15-Grpc-Demo/POST.md
  18. 16
      docs/en/Community-Articles/2024-01-18-ABP-Now-Supports-Keyed-Services/POST.md
  19. BIN
      docs/en/Community-Articles/2024-11-13-BuiltIn-OpenApi-Documentation/img2.png
  20. BIN
      docs/en/Community-Articles/2024-11-13-BuiltIn-OpenApi-Documentation/img3.png
  21. 309
      docs/en/Community-Articles/2024-11-25-Global-Assets/POST.md
  22. BIN
      docs/en/Community-Articles/2024-11-25-Global-Assets/image.png
  23. 385
      docs/en/Community-Articles/2024-12-01-OpenAI-Integration/POST.md
  24. BIN
      docs/en/Community-Articles/2024-12-01-OpenAI-Integration/chat-example.gif
  25. BIN
      docs/en/Community-Articles/2024-12-01-OpenAI-Integration/cover-image.png
  26. BIN
      docs/en/Community-Articles/2024-12-01-OpenAI-Integration/image-generation-example.gif
  27. BIN
      docs/en/Community-Articles/2024-12-01-OpenAI-Integration/rag-example-1.gif
  28. BIN
      docs/en/Community-Articles/2024-12-01-OpenAI-Integration/rag-example-2.gif
  29. BIN
      docs/en/Community-Articles/2024-12-01-OpenAI-Integration/sample-page.png
  30. 234
      docs/en/Community-Articles/2024-12-09-Unit-Test/POST.md
  31. 10
      docs/en/cli/index.md
  32. 2
      docs/en/cli/new-command-samples.md
  33. 6
      docs/en/contribution/index.md
  34. 6
      docs/en/deployment/configuring-openIddict.md
  35. 710
      docs/en/docs-nav.json
  36. 1
      docs/en/docs-params.json
  37. 44
      docs/en/framework/architecture/best-practices/application-services.md
  38. 6
      docs/en/framework/architecture/best-practices/data-transfer-objects.md
  39. 10
      docs/en/framework/architecture/best-practices/domain-services.md
  40. 33
      docs/en/framework/architecture/best-practices/entities.md
  41. 18
      docs/en/framework/architecture/best-practices/entity-framework-core-integration.md
  42. 4
      docs/en/framework/architecture/best-practices/module-architecture.md
  43. 18
      docs/en/framework/architecture/best-practices/mongodb-integration.md
  44. 10
      docs/en/framework/architecture/best-practices/repositories.md
  45. 2
      docs/en/framework/architecture/domain-driven-design/data-transfer-objects.md
  46. 2
      docs/en/framework/architecture/domain-driven-design/domain-services.md
  47. 44
      docs/en/framework/fundamentals/caching.md
  48. 2
      docs/en/framework/fundamentals/dependency-injection.md
  49. 18
      docs/en/framework/infrastructure/audit-logging.md
  50. 7
      docs/en/framework/infrastructure/background-jobs/index.md
  51. 12
      docs/en/framework/infrastructure/features.md
  52. 2
      docs/en/framework/ui/angular/quick-start.md
  53. 109
      docs/en/framework/ui/blazor/global-scripts-styles.md
  54. 3
      docs/en/framework/ui/maui/index.md
  55. 2
      docs/en/framework/ui/mvc-razor-pages/client-side-package-management.md
  56. 6
      docs/en/framework/ui/mvc-razor-pages/tag-helpers/dynamic-forms.md
  57. 2
      docs/en/framework/ui/react-native/index.md
  58. BIN
      docs/en/get-started/images/abp-studio-microservice-solution-runner-docker-dependencies.png
  59. BIN
      docs/en/get-started/images/abp-studio-microservice-solution-runner-enable-watch-1.png
  60. BIN
      docs/en/get-started/images/abp-studio-microservice-solution-runner-enable-watch-2.png
  61. BIN
      docs/en/get-started/images/abp-studio-microservice-solution-runner-enable-watch.png
  62. BIN
      docs/en/get-started/images/abp-studio-no-layers-new-solution-additional-options-0.9.13.png
  63. BIN
      docs/en/get-started/images/abp-studio-no-layers-new-solution-dialog-0.9.13.png
  64. BIN
      docs/en/get-started/images/abp-studio-no-layers-new-solution-dialog-database-configurations-efcore-0.9.13.png
  65. BIN
      docs/en/get-started/images/abp-studio-no-layers-new-solution-dialog-database-configurations-mongo-0.9.13.png
  66. BIN
      docs/en/get-started/images/abp-studio-no-layers-new-solution-dialog-database-provider-efcore-0.9.13.png
  67. BIN
      docs/en/get-started/images/abp-studio-no-layers-new-solution-dialog-database-provider-mongo-0.9.13.png
  68. BIN
      docs/en/get-started/images/abp-studio-no-layers-new-solution-dialog-solution-properties-0.9.13.png
  69. BIN
      docs/en/get-started/images/abp-studio-no-layers-new-solution-dialog-ui-framework-0.9.13.png
  70. BIN
      docs/en/get-started/images/abp-studio-nolayers-new-solution-dialog-ui-theme-0.9.13.png
  71. 2
      docs/en/get-started/index.md
  72. 34
      docs/en/get-started/layered-web-application.md
  73. 61
      docs/en/get-started/microservice.md
  74. 107
      docs/en/get-started/pre-requirements.md
  75. 53
      docs/en/get-started/single-layer-web-application.md
  76. BIN
      docs/en/images/generic-repositories.png
  77. BIN
      docs/en/images/idle-message.png
  78. BIN
      docs/en/images/idle-setting.png
  79. BIN
      docs/en/images/pen-test-alert-list-9.0.png
  80. BIN
      docs/en/images/suite-registry.png
  81. 5
      docs/en/kb/can-not-login-with-admin-user.md
  82. 7
      docs/en/kb/index.md
  83. 49
      docs/en/kb/when-to-use-a-distributed-cache-server.md
  84. 2
      docs/en/kb/windows-path-too-long-fix.md
  85. 1
      docs/en/modules/account-pro.md
  86. 19
      docs/en/modules/account/idle-session-timeout.md
  87. 36
      docs/en/modules/docs.md
  88. 46
      docs/en/others/penetration-test-report.md
  89. 28
      docs/en/release-info/migration-guides/openiddict5-to-6.md
  90. 2
      docs/en/samples/easy-crm.md
  91. 5
      docs/en/samples/eshop-on-abp/index.md
  92. 4
      docs/en/samples/index.md
  93. BIN
      docs/en/solution-templates/application-module/images/additional-options.png
  94. BIN
      docs/en/solution-templates/application-module/images/create-new-module.png
  95. BIN
      docs/en/solution-templates/application-module/images/issuemanagement-module-solution.png
  96. BIN
      docs/en/solution-templates/application-module/images/new-module.png
  97. BIN
      docs/en/solution-templates/application-module/images/new-solution.png
  98. BIN
      docs/en/solution-templates/application-module/images/select-database-provider.png
  99. BIN
      docs/en/solution-templates/application-module/images/select-user-interface.png
  100. BIN
      docs/en/solution-templates/application-module/images/solution-properties.png

20
.github/workflows/auto-pr.yml

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

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

@ -18,6 +18,7 @@ on:
- 'templates/**/*.razor'
- 'Directory.Build.props'
- 'Directory.Packages.props'
- '.github/workflows/build-and-test.yml'
pull_request:
paths:
@ -35,6 +36,7 @@ on:
- 'templates/**/*.razor'
- 'Directory.Build.props'
- 'Directory.Packages.props'
- '.github/workflows/build-and-test.yml'
types:
- opened
- synchronize
@ -46,6 +48,7 @@ permissions:
jobs:
build-test:
runs-on: ubuntu-latest
timeout-minutes: 40
if: ${{ !github.event.pull_request.draft }}
steps:
- uses: actions/checkout@v2

145
Directory.Packages.props

@ -13,8 +13,8 @@
<PackageVersion Include="AutoMapper" Version="13.0.1" />
<PackageVersion Include="Asp.Versioning.Mvc" Version="8.1.0" />
<PackageVersion Include="Asp.Versioning.Mvc.ApiExplorer" Version="8.1.0" />
<PackageVersion Include="AWSSDK.S3" Version="3.7.400.30" />
<PackageVersion Include="AWSSDK.SecurityToken" Version="3.7.400.30" />
<PackageVersion Include="AWSSDK.S3" Version="3.7.410.9" />
<PackageVersion Include="AWSSDK.SecurityToken" Version="3.7.401.16" />
<PackageVersion Include="Azure.Messaging.ServiceBus" Version="7.18.1" />
<PackageVersion Include="Azure.Storage.Blobs" Version="12.22.1" />
<PackageVersion Include="Blazorise" Version="1.6.2" />
@ -29,7 +29,7 @@
<PackageVersion Include="Dapr.AspNetCore" Version="1.14.0" />
<PackageVersion Include="Dapr.Client" Version="1.14.0" />
<PackageVersion Include="DeviceDetector.NET" Version="6.3.3" />
<PackageVersion Include="Devart.Data.Oracle.EFCore" Version="10.3.21.8" />
<PackageVersion Include="Devart.Data.Oracle.EFCore" Version="10.4.190.9" />
<PackageVersion Include="DistributedLock.Core" Version="1.0.7" />
<PackageVersion Include="DistributedLock.Redis" Version="1.0.3" />
<PackageVersion Include="DeepL.net" Version="1.10.0" />
@ -39,8 +39,8 @@
<PackageVersion Include="EphemeralMongo6.runtime.win-x64" Version="1.1.3" />
<PackageVersion Include="FluentValidation" Version="11.10.0" />
<PackageVersion Include="Google.Cloud.Storage.V1" Version="4.10.0" />
<PackageVersion Include="Hangfire.AspNetCore" Version="1.8.14" />
<PackageVersion Include="Hangfire.SqlServer" Version="1.8.14" />
<PackageVersion Include="Hangfire.AspNetCore" Version="1.8.17" />
<PackageVersion Include="Hangfire.SqlServer" Version="1.8.17" />
<PackageVersion Include="HtmlSanitizer" Version="8.1.870" />
<PackageVersion Include="IdentityModel" Version="7.0.0" />
<PackageVersion Include="IdentityServer4" Version="4.1.2" />
@ -51,84 +51,85 @@
<PackageVersion Include="Magick.NET-Q16-AnyCPU" Version="13.4.0" />
<PackageVersion Include="MailKit" Version="4.8.0" />
<PackageVersion Include="Markdig.Signed" Version="0.37.0" />
<PackageVersion Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="9.0.0.0" />
<PackageVersion Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="9.0.0.0" />
<PackageVersion Include="Microsoft.AspNetCore.Authorization" Version="9.0.0.0" />
<PackageVersion Include="Microsoft.AspNetCore.Components" Version="9.0.0.0" />
<PackageVersion Include="Microsoft.AspNetCore.Components.Authorization" Version="9.0.0.0" />
<PackageVersion Include="Microsoft.AspNetCore.Components.Web" Version="9.0.0.0" />
<PackageVersion Include="Microsoft.AspNetCore.Components.WebAssembly" Version="9.0.0.0" />
<PackageVersion Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="9.0.0.0" />
<PackageVersion Include="Microsoft.AspNetCore.Components.WebAssembly.Authentication" Version="9.0.0.0" />
<PackageVersion Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="9.0.0.0" />
<PackageVersion Include="Microsoft.AspNetCore.DataProtection.StackExchangeRedis" Version="9.0.0.0" />
<PackageVersion Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="9.0.0.0" />
<PackageVersion Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="9.0.0.0" />
<PackageVersion Include="Microsoft.AspNetCore.Mvc.Testing" Version="9.0.0.0" />
<PackageVersion Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="9.0.0" />
<PackageVersion Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="9.0.0" />
<PackageVersion Include="Microsoft.AspNetCore.Authorization" Version="9.0.0" />
<PackageVersion Include="Microsoft.AspNetCore.Components" Version="9.0.0" />
<PackageVersion Include="Microsoft.AspNetCore.Components.Authorization" Version="9.0.0" />
<PackageVersion Include="Microsoft.AspNetCore.Components.Web" Version="9.0.0" />
<PackageVersion Include="Microsoft.AspNetCore.Components.WebAssembly" Version="9.0.0" />
<PackageVersion Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="9.0.0" />
<PackageVersion Include="Microsoft.AspNetCore.Components.WebAssembly.Authentication" Version="9.0.0" />
<PackageVersion Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="9.0.0" />
<PackageVersion Include="Microsoft.AspNetCore.DataProtection.StackExchangeRedis" Version="9.0.0" />
<PackageVersion Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="9.0.0" />
<PackageVersion Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="9.0.0" />
<PackageVersion Include="Microsoft.AspNetCore.Mvc.Testing" Version="9.0.0" />
<PackageVersion Include="Microsoft.AspNetCore.Razor.Language" Version="6.0.33" />
<PackageVersion Include="Microsoft.AspNetCore.TestHost" Version="9.0.0.0" />
<PackageVersion Include="Microsoft.AspNetCore.WebUtilities" Version="9.0.0.0" />
<PackageVersion Include="Microsoft.Bcl.AsyncInterfaces" Version="9.0.0.0" />
<PackageVersion Include="Microsoft.AspNetCore.TestHost" Version="9.0.0" />
<PackageVersion Include="Microsoft.AspNetCore.WebUtilities" Version="9.0.0" />
<PackageVersion Include="Microsoft.Bcl.AsyncInterfaces" Version="9.0.0" />
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="4.5.0" />
<PackageVersion Include="Microsoft.CSharp" Version="4.7.0" />
<PackageVersion Include="Microsoft.Data.Sqlite" Version="9.0.0.0" />
<PackageVersion Include="Microsoft.EntityFrameworkCore" Version="9.0.0.0" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Design" Version="9.0.0.0" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.InMemory" Version="9.0.0.0" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Proxies" Version="9.0.0.0" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Relational" Version="9.0.0.0" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Sqlite" Version="9.0.0.0" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.SqlServer" Version="9.0.0.0" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Tools" Version="9.0.0.0" />
<PackageVersion Include="Microsoft.Data.Sqlite" Version="9.0.0" />
<PackageVersion Include="Microsoft.EntityFrameworkCore" Version="9.0.0" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Design" Version="9.0.0" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.InMemory" Version="9.0.0" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Proxies" Version="9.0.0" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Relational" Version="9.0.0" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Sqlite" Version="9.0.0" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.SqlServer" Version="9.0.0" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Tools" Version="9.0.0" />
<PackageVersion Include="Microsoft.Extensions.Caching.Hybrid" Version="9.0.0-preview.7.24406.2" />
<PackageVersion Include="Microsoft.Extensions.Caching.Memory" Version="9.0.0.0" />
<PackageVersion Include="Microsoft.Extensions.Caching.StackExchangeRedis" Version="9.0.0.0" />
<PackageVersion Include="Microsoft.Extensions.Configuration.Binder" Version="9.0.0.0" />
<PackageVersion Include="Microsoft.Extensions.Configuration.CommandLine" Version="9.0.0.0" />
<PackageVersion Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="9.0.0.0" />
<PackageVersion Include="Microsoft.Extensions.Configuration.UserSecrets" Version="9.0.0.0" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="9.0.0.0" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="9.0.0.0" />
<PackageVersion Include="Microsoft.Extensions.FileProviders.Composite" Version="9.0.0.0" />
<PackageVersion Include="Microsoft.Extensions.FileProviders.Embedded" Version="9.0.0.0" />
<PackageVersion Include="Microsoft.Extensions.FileProviders.Physical" Version="9.0.0.0" />
<PackageVersion Include="Microsoft.Extensions.FileSystemGlobbing" Version="9.0.0.0" />
<PackageVersion Include="Microsoft.Extensions.Hosting" Version="9.0.0.0" />
<PackageVersion Include="Microsoft.Extensions.Hosting.Abstractions" Version="9.0.0.0" />
<PackageVersion Include="Microsoft.Extensions.Http" Version="9.0.0.0" />
<PackageVersion Include="Microsoft.Extensions.Identity.Core" Version="9.0.0.0" />
<PackageVersion Include="Microsoft.Extensions.Localization" Version="9.0.0.0" />
<PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="9.0.0.0" />
<PackageVersion Include="Microsoft.Extensions.Logging" Version="9.0.0.0" />
<PackageVersion Include="Microsoft.Extensions.Logging.Console" Version="9.0.0.0" />
<PackageVersion Include="Microsoft.Extensions.Options" Version="9.0.0.0" />
<PackageVersion Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="9.0.0.0" />
<PackageVersion Include="Microsoft.Extensions.Caching.Memory" Version="9.0.0" />
<PackageVersion Include="Microsoft.Extensions.Caching.StackExchangeRedis" Version="9.0.0" />
<PackageVersion Include="Microsoft.Extensions.Configuration.Binder" Version="9.0.0" />
<PackageVersion Include="Microsoft.Extensions.Configuration.CommandLine" Version="9.0.0" />
<PackageVersion Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="9.0.0" />
<PackageVersion Include="Microsoft.Extensions.Configuration.UserSecrets" Version="9.0.0" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="9.0.0" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="9.0.0" />
<PackageVersion Include="Microsoft.Extensions.FileProviders.Composite" Version="9.0.0" />
<PackageVersion Include="Microsoft.Extensions.FileProviders.Embedded" Version="9.0.0" />
<PackageVersion Include="Microsoft.Extensions.FileProviders.Physical" Version="9.0.0" />
<PackageVersion Include="Microsoft.Extensions.FileSystemGlobbing" Version="9.0.0" />
<PackageVersion Include="Microsoft.Extensions.Hosting" Version="9.0.0" />
<PackageVersion Include="Microsoft.Extensions.Hosting.Abstractions" Version="9.0.0" />
<PackageVersion Include="Microsoft.Extensions.Http" Version="9.0.0" />
<PackageVersion Include="Microsoft.Extensions.Identity.Core" Version="9.0.0" />
<PackageVersion Include="Microsoft.Extensions.Localization" Version="9.0.0" />
<PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="9.0.0" />
<PackageVersion Include="Microsoft.Extensions.Logging" Version="9.0.0" />
<PackageVersion Include="Microsoft.Extensions.Logging.Console" Version="9.0.0" />
<PackageVersion Include="Microsoft.Extensions.Options" Version="9.0.0" />
<PackageVersion Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="9.0.0" />
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.11.1" />
<PackageVersion Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="9.0.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.IdentityModel.Protocols.OpenIdConnect" Version="8.1.0" />
<PackageVersion Include="Microsoft.IdentityModel.Tokens" Version="8.1.0" />
<PackageVersion Include="Microsoft.IdentityModel.JsonWebTokens" Version="8.1.0" />
<PackageVersion Include="System.IdentityModel.Tokens.Jwt" Version="8.3.0" />
<PackageVersion Include="Microsoft.IdentityModel.Protocols.OpenIdConnect" Version="8.3.0" />
<PackageVersion Include="Microsoft.IdentityModel.Tokens" Version="8.3.0" />
<PackageVersion Include="Microsoft.IdentityModel.JsonWebTokens" Version="8.3.0" />
<PackageVersion Include="Minio" Version="6.0.3" />
<PackageVersion Include="MongoDB.Driver" Version="2.29.0" />
<PackageVersion Include="NEST" Version="7.17.5" />
<PackageVersion Include="Newtonsoft.Json" Version="13.0.3" />
<PackageVersion Include="Nito.AsyncEx.Context" Version="5.1.2" />
<PackageVersion Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="9.0.0" />
<PackageVersion Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="9.0.2" />
<PackageVersion Include="NSubstitute" Version="5.1.0" />
<PackageVersion Include="NuGet.Versioning" Version="6.11.1" />
<PackageVersion Include="NUglify" Version="1.21.9" />
<PackageVersion Include="Nullable" Version="1.3.1" />
<PackageVersion Include="Octokit" Version="13.0.1" />
<PackageVersion Include="OpenIddict.Abstractions" Version="5.8.0" />
<PackageVersion Include="OpenIddict.Core" Version="5.8.0" />
<PackageVersion Include="OpenIddict.Server.AspNetCore" Version="5.8.0" />
<PackageVersion Include="OpenIddict.Validation.AspNetCore" Version="5.8.0" />
<PackageVersion Include="OpenIddict.Validation.ServerIntegration" Version="5.8.0" />
<PackageVersion Include="Oracle.EntityFrameworkCore" Version="8.23.60" />
<PackageVersion Include="OpenIddict.Abstractions" Version="6.0.0" />
<PackageVersion Include="OpenIddict.Core" Version="6.0.0" />
<PackageVersion Include="OpenIddict.Server.AspNetCore" Version="6.0.0" />
<PackageVersion Include="OpenIddict.Validation.AspNetCore" Version="6.0.0" />
<PackageVersion Include="OpenIddict.Validation.ServerIntegration" Version="6.0.0" />
<PackageVersion Include="Oracle.EntityFrameworkCore" Version="9.23.60" />
<PackageVersion Include="Polly" Version="8.4.2" />
<PackageVersion Include="Polly.Extensions.Http" Version="3.0.0" />
<PackageVersion Include="Pomelo.EntityFrameworkCore.MySql" Version="9.0.0-preview.1" />
<PackageVersion Include="Pomelo.EntityFrameworkCore.MySql" Version="9.0.0-preview.2.efcore.9.0.0" />
<PackageVersion Include="Quartz" Version="3.13.0" />
<PackageVersion Include="Quartz.Extensions.DependencyInjection" Version="3.13.0" />
<PackageVersion Include="Quartz.Plugins.TimeZoneConverter" Version="3.13.0" />
@ -155,19 +156,19 @@
<PackageVersion Include="Spectre.Console" Version="0.49.1" />
<PackageVersion Include="StackExchange.Redis" Version="2.8.16" />
<PackageVersion Include="Swashbuckle.AspNetCore" Version="6.8.1" />
<PackageVersion Include="System.Collections.Immutable" Version="9.0.0.0" />
<PackageVersion Include="System.Collections.Immutable" Version="9.0.0" />
<PackageVersion Include="System.ComponentModel.Annotations" Version="5.0.0" />
<PackageVersion Include="System.Linq.Async" Version="6.0.1" />
<PackageVersion Include="System.Linq.Dynamic.Core" Version="1.4.5" />
<PackageVersion Include="System.Linq.Queryable" Version="4.3.0" />
<PackageVersion Include="System.Runtime.Loader" Version="4.3.0" />
<PackageVersion Include="System.Security.Permissions" Version="9.0.0.0" />
<PackageVersion Include="System.Security.Permissions" Version="9.0.0" />
<PackageVersion Include="System.Security.Principal.Windows" Version="5.0.0" />
<PackageVersion Include="System.Text.Encoding.CodePages" Version="9.0.0.0" />
<PackageVersion Include="System.Text.Encodings.Web" Version="9.0.0.0" />
<PackageVersion Include="System.Text.Json" Version="9.0.0.0" />
<PackageVersion Include="System.Text.Encoding.CodePages" Version="9.0.0" />
<PackageVersion Include="System.Text.Encodings.Web" Version="9.0.0" />
<PackageVersion Include="System.Text.Json" Version="9.0.0" />
<PackageVersion Include="System.Threading.Tasks.Extensions" Version="4.5.4" />
<PackageVersion Include="System.IdentityModel.Tokens.Jwt" Version="8.1.0" />
<PackageVersion Include="TencentCloudSDK.Sms" Version="3.0.1142" />
<PackageVersion Include="TimeZoneConverter" Version="6.1.0" />
<PackageVersion Include="Unidecode.NET" Version="2.1.0" />
<PackageVersion Include="xunit" Version="2.9.2" />
@ -177,4 +178,4 @@
<PackageVersion Include="ConfigureAwait.Fody" Version="3.3.2" />
<PackageVersion Include="Fody" Version="6.8.2" />
</ItemGroup>
</Project>
</Project>

4
README.md

@ -1,7 +1,7 @@
# ABP Framework
![build and test](https://img.shields.io/github/actions/workflow/status/abpframework/abp/build-and-test.yml?branch=dev&style=flat-square) 🔹 [![codecov](https://codecov.io/gh/abpframework/abp/branch/dev/graph/badge.svg?token=jUKLCxa6HF)](https://codecov.io/gh/abpframework/abp) 🔹 [![NuGet](https://img.shields.io/nuget/v/Volo.Abp.Core.svg?style=flat-square)](https://www.nuget.org/packages/Volo.Abp.Core) 🔹 [![NuGet (with prereleases)](https://img.shields.io/nuget/vpre/Volo.Abp.Core.svg?style=flat-square)](https://www.nuget.org/packages/Volo.Abp.Core) 🔹 [![MyGet (nightly builds)](https://img.shields.io/myget/abp-nightly/vpre/Volo.Abp.svg?style=flat-square)](https://abp.io/docs/latest/release-info/nightly-builds) 🔹
[![NuGet Download](https://img.shields.io/nuget/dt/Volo.Abp.Core.svg?style=flat-square)](https://www.nuget.org/packages/Volo.Abp.Core) 🔹 [![Code of Conduct](https://img.shields.io/badge/Contributor%20Covenant-v2.0%20adopted-ff69b4.svg)](https://github.com/abpframework/abp/blob/dev/CODE_OF_CONDUCT.md) 🔹 [![CLA Signed](https://cla-assistant.io/readme/badge/abpframework/abp)](https://cla-assistant.io/abpframework/abp) 🔹 [![Discord Shield](https://discord.com/api/guilds/951497912645476422/widget.png?style=shield)](https://discord.gg/abp)
[![NuGet Download](https://img.shields.io/nuget/dt/Volo.Abp.Core.svg?style=flat-square)](https://www.nuget.org/packages/Volo.Abp.Core) 🔹 [![Code of Conduct](https://img.shields.io/badge/Contributor%20Covenant-v2.0%20adopted-ff69b4.svg)](https://github.com/abpframework/abp/blob/dev/CODE_OF_CONDUCT.md) 🔹 [![CLA Signed](https://cla-assistant.io/readme/badge/abpframework/abp)](https://cla-assistant.io/abpframework/abp) 🔹 [![Discord Shield](https://discord.com/api/guilds/951497912645476422/widget.png?style=shield)](https://abp.io/join-discord)
[ABP](https://abp.io/) offers an **opinionated architecture** to build enterprise software solutions with **best practices** on top of the **.NET** and the **ASP.NET Core** platforms. It provides the fundamental infrastructure, production-ready startup templates, pre-built application modules, UI themes, tooling, guides and documentation to implement that architecture properly and **automate the details** and repetitive works as much as possible.
@ -121,4 +121,4 @@ GitHub repository stars are an important indicator of popularity and the size of
## Discord Server
We have a Discord server where you can chat with other ABP users. Share your ideas, report technical issues, showcase your creations, share the tips that worked for you and catch up with the latest news and announcements about ABP Framework. Join 👉 https://discord.gg/abp.
We have a Discord server where you can chat with other ABP users. Share your ideas, report technical issues, showcase your creations, share the tips that worked for you and catch up with the latest news and announcements about ABP Framework. Join 👉 https://abp.io/join-discord.

5
abp_io/AbpIoLocalization/AbpIoLocalization/Account/Localization/Resources/en.json

@ -13,6 +13,9 @@
"ManageAccount": "My Account | ABP.IO",
"ManageYourProfile": "Manage your profile",
"ReturnToApplication": "Return to application",
"IdentityUserNotAvailable:Deleted": "This email address is not available. Reason: Already deleted."
"IdentityUserNotAvailable:Deleted": "This email address is not available. Reason: Already deleted.",
"SelectYourOrganization": "Select your organization",
"PleaseSelectOrganization": "Please select an organization to continue",
"Continue": "Continue"
}
}

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

@ -664,6 +664,9 @@
"EditWinners": "Edit winners",
"EditAttendees": "Edit attendees",
"ExportAttendeesAsExcel": "Export attendees as Excel",
"DuplicateRaffle": "Duplicate raffle"
"DuplicateRaffle": "Duplicate raffle",
"Menu:RedisManagement": "Redis Management",
"RedisManagement": "Redis Management",
"Permission:RedisManagement": "Redis Management"
}
}

4
abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/en.json

@ -242,14 +242,14 @@
"ReturnOnInvestment": "Return on Investment",
"PromotionalOffers": "Promotional Offers",
"PromotionalOffersDefinition": "Discounts, seasonal campaigns, etc.",
"EventsDefinition": "Community Talks, Webinars, ABP .NET Conference, etc.",
"EventsDefinition": "Community Talks, Webinars, ABP DOTNET Conference, etc.",
"ReleaseNotesDefinition": "ABP.IO Platform releases, new products, etc.",
"Newsletter": "Newsletter",
"NewsletterDefinition": "Blog posts, community news, etc.",
"OrganizationOverview": "Organization Overview",
"EmailPreferences": "Email Preferences",
"VideoCourses": "Essential Videos",
"DoYouAgreePrivacyPolicy": "By clicking <b>Subscribe</b> button you agree to the <a href=\"https://account.abp.io/Account/TermsConditions\">Terms & Conditions</a> and <a href=\"https://account.abp.io/Account/Privacy\">Privacy Policy</a>.",
"DoYouAgreePrivacyPolicy": "By clicking <b>Subscribe</b> button you agree to the <a href=\"/terms-conditions\">Terms & Conditions</a> and <a href=\"/privacy\">Privacy Policy</a>.",
"AbpConferenceDescription": "ABP Conference is a virtual event for .NET developers to learn and connect with the community.",
"Mobile": "Mobile",
"MetaTwitterCard": "summary_large_image"

4
common.props

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

2
docs/en/Blog-Posts/2022-05-09 v5_3_Preview/POST.md

@ -255,4 +255,4 @@ We've created an official ABP Discord server so the ABP Community can interact w
Thanks to the ABP Community, **700+** people joined our Discord Server so far and it grows every day.
You can join our Discord Server from [here](https://discord.gg/abp), if you haven't yet.
You can join our Discord Server from [here](https://abp.io/join-discord), if you haven't yet.

1
docs/en/Blog-Posts/2022-07-26 v6_0_Preview/POST.md

@ -187,7 +187,6 @@ The following improvements have been made on [eShopOnAbp project](https://github
* Some improvements have been made on the Admin Application for Order Management for Angular UI. See [#110](https://github.com/abpframework/eShopOnAbp/pull/110).
* `SignalR` error on Kubernetes & Docker Compose has been fixed. See [#113](https://github.com/abpframework/eShopOnAbp/pull/113).
* eShopOnAbp project has been deployed to Azure Kubernetes Service. See [#114](https://github.com/abpframework/eShopOnAbp/pull/114). The live demo can be seen from [eshoponabp.com](https://eshoponabp.com/).
* Configurations have been made for some services on the `docker-compose.yml` file. See [#112](https://github.com/abpframework/eShopOnAbp/pull/112).
* Gateway Redirect Loop problem on Kubernetes has been fixed. See [the commit](https://github.com/abpframework/eShopOnAbp/commit/6413ef15c91cd8a5309050b63bb4dbca23587607).

7
docs/en/Blog-Posts/2023-04-03-What-is-ABP-Framework/post.md

@ -105,9 +105,12 @@ ASP.NET modularity, ASP.NET modular development, ASP.NET localization, ASP.NET m
## Microservice Example: eShopOnAbp
[eShopOnAbp](https://www.eshoponabp.com/) is a microservice example built on top ABP. It is a sample net application, similar to the Microsoft's [eShopOnContainer](https://github.com/dotnet-architecture/eShopOnContainers) project. It is a reference microservice solution built with the ABP Framework and .NET, runs on Kubernetes with Helm configuration, includes API Gateways, Angular and ASP.NET Core MVC applications with PostgreSQL and MongoDB databases. For more information, check out https://github.com/abpframework/eShopOnAbp.
[eShopOnAbp](https://github.com/abpframework/eShopOnAbp) is a microservice example built on top ABP. It is a sample net application, similar to the Microsoft's [eShopOnContainer](https://github.com/dotnet-architecture/eShopOnContainers) project. It is a reference microservice solution built with the ABP Framework and .NET, runs on Kubernetes with Helm configuration, includes API Gateways, Angular and ASP.NET Core MVC applications with PostgreSQL and MongoDB databases. For more information, check out https://github.com/abpframework/eShopOnAbp.
> ⚠️ **Important Notice**
> This project, "eshoponabp," is outdated. It served as a reference project for microservice architecture using the ABP Framework, but we now recommend using the [ABP Microservice Solution Template](https://abp.io/docs/latest/solution-templates/microservice) for new projects.
>
> The new template offers a modernized and officially supported starting point for building microservices with ABP. Please consider transitioning to the new template for the latest features and improvements.
## Conclusion

BIN
docs/en/Blog-Posts/2024-11-19 v9_0_Release_Stable/community-talks.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 189 KiB

BIN
docs/en/Blog-Posts/2024-11-19 v9_0_Release_Stable/cover-image.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 525 KiB

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

@ -0,0 +1,93 @@
# ABP.IO Platform 9.0 Has Been Released Based on .NET 9.0
![](cover-image.png)
Today, [ABP](https://abp.io/) 9.0 stable version has been released based on [.NET 9.0](https://dotnet.microsoft.com/en-us/download/dotnet/9.0). You can create solutions with ABP 9.0 starting from ABP Studio v0.9.11 or by using the ABP CLI as explained in the following sections.
## What's New With Version 9.0?
All the new features were explained in detail in the [9.0 RC Announcement Post](https://abp.io/blog/announcing-abp-9-0-release-candidate), so there is no need to review them again. You can check it out for more details.
## Getting Started with 9.0
### 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.
By default, ABP Studio uses stable versions to create solutions. Therefore, it will be creating the solution with the latest stable version, which is v9.0 for now, so you don't need to specify the version. **You can create solutions with ABP 9.0 starting from v0.9.11.**
### 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 to align it with ABP v9.0. 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 **Switch to stable** action button to instantly upgrade your solution:
![](switch-to-stable.png)
> Please note that ABP CLI & ABP Studio only upgrade the related ABP packages, so you need to upgrade the other packages for .NET 9.0 manually.
### 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.
> Please note that ABP CLI & ABP Studio only upgrade the related ABP packages, so you need to upgrade the other packages for .NET 9.0 manually.
## 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 v8.x: [ABP Version 9.0 Migration Guide](https://abp.io/docs/9.0/release-info/migration-guides/abp-9-0)
## Community News
### Highlights from .NET 9.0
Our team has closely followed the ASP.NET Core and Entity Framework Core 9.0 releases, read Microsoft's guides and documentation, and adapted the changes to our ABP.IO Platform. We are proud to say that we've shipped the ABP 9.0 based on .NET 9.0 just after Microsoft's .NET 9.0 release.
In addition to the ABP's .NET 9.0 upgrade, our team has created many great articles to highlight the important features coming with ASP.NET Core 9.0 and Entity Framework Core 9.0.
> You can read [this post](https://volosoft.com/blog/Highlights-for-ASP-NET-Entity-Framework-Core-NET-9-0) to see the list of all articles.
### New ABP Community Articles
In addition to [the articles to highlight .NET 9.0 features written by our team](https://volosoft.com/blog/Highlights-for-ASP-NET-Entity-Framework-Core-NET-9-0), here are some of the recent posts added to the [ABP Community](https://abp.io/community):
* [Video: Building Modular Monolith Applications with ASP.NET Core & ABP Studio](https://abp.io/community/videos/building-modular-monolith-applications-with-asp.net-core-abp-studio-66znukvf) by [Halil İbrahim Kalkan](https://x.com/hibrahimkalkan)
* [How to create your Own AI Bot on WhatsApp Using an ABP.io Template](https://abp.io/community/articles/how-to-create-your-own-ai-bot-on-whatsapp-using-the-abp-framework-c6jgvt9c) by [Michael Kokula](https://abp.io/community/members/Michal_Kokula)
* [ABP Now Supports .NET 9](https://abp.io/community/articles/abp-now-supports-.net-9-zpkznc4f) by [Alper Ebiçoğlu](https://x.com/alperebicoglu)
Thanks to the ABP Community for all the content they have published. You can also [post your ABP related (text or video) content](https://abp.io/community/posts/submit) to the ABP Community.
### ABP Community Talks 2024.7: What’s New with .NET 9 & ABP 9?
![](community-talks.png)
In this episode of ABP Community Talks, 2024.7; we will dive into the features that came with .NET 9.0 with [Alper Ebicoglu](https://github.com/ebicoglu), [Engincan Veske](https://github.com/EngincanV), [Berkan Sasmaz](https://github.com/berkansasmaz) and [Ahmet Faruk Ulu](https://github.com/ahmetfarukulu).
## Conclusion
This version comes with some new features and a lot of enhancements to the existing features. You can see the [Road Map](https://docs.abp.io/en/abp/9.0/Road-Map) documentation to learn about the release schedule and planned features for the next releases. Please try ABP v9.0 and provide feedback to help us release more stable versions.
Thanks for being a part of this community!

BIN
docs/en/Blog-Posts/2024-11-19 v9_0_Release_Stable/switch-to-stable.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

67
docs/en/Blog-Posts/2024-12-15-ABP-Studio-R2R/POST.md

@ -0,0 +1,67 @@
# ABP Studio Goes AOT: Faster Startups with Ready-to-Run (R2R) Publishing
We're excited that [ABP Studio](https://abp.io/studio) now supports [Ready-to-Run (R2R) publishing](https://learn.microsoft.com/en-us/dotnet/core/deploying/ready-to-run) (starting from v0.9.16+), a hybrid form of ahead-of-time (AOT) compilation. This enhancement significantly improves the startup time and overall performance of ABP Studio, making it faster and more performant than ever before.
Let's dive into what R2R publishing is, how it works, and the benefits it brings to ABP Studio.
## What is Ready-to-Run (R2R) Publishing?
Ready-to-Run (R2R) is a form of AOT compilation available in the .NET ecosystem. Unlike traditional just-in-time (JIT) compilation, R2R precompiles parts of your application to native code before deployment. This precompiled code helps reduce the startup time by minimizing the work needed during runtime.
However, R2R isn't a complete AOT compilation. Instead, it's a hybrid approach because it stores both:
* **Native code for precompiled methods** (to improve startup time and performance)
* **Intermediate Language (IL) code** for methods that may need further JIT compilation
This hybrid nature is why R2R binaries are typically larger. For ABP Studio, the storage size increased by ~150 MB with R2R enabled, but the trade-off is well worth it for the performance and startup-time gains.
## How R2R (Ready-to-Run) Improves ABP Studio
### Faster Startup Time 🚀
One of the biggest advantages of R2R publishing is its impact on startup times. In our local tests, enabling R2R resulted in startup times being **reduced by 2.5x** ⬇️.
This means you can get to work faster, without waiting for the application to being startup from the beginning. Whether you're launching ABP Studio to manage projects, generate code, or deploy applications, the improved responsiveness is noticeable.
### Performance Enhancements 📈
In addition to faster startups, R2R publishing contributes to overall performance improvements. By precompiling frequently used methods, R2R reduces the workload on the JIT compiler during execution, leading to smoother and more efficient operations.
### Trade-offs: Increased Storage Size 🆙
With great performance comes a slight trade-off: storage size. R2R binaries include both **native** and **IL code**, which increases the file size. In the case of ABP Studio, the storage footprint increased by ~150 MB. However, the substantial improvements in speed and responsiveness make this a worthwhile investment.
## How to Enable R2R Publishing in Your Applications?
If you're developing applications and want to benefit from R2R, here's a quick guide on how to enable it in your .NET projects:
1. You can add the following configuration to your final project's `.csproj` file:
```xml
<PropertyGroup>
<PublishReadyToRun>true</PublishReadyToRun>
</PropertyGroup>
```
2. Then, publish your application with the `dotnet publish` command:
```bash
dotnet publish -c Release
```
Alternatively, you can specify the _PublishReadyToRun_ flag directly to the `dotnet publish` command as follows:
```bash
dotnet publish -c Release -r win-x64 -p:PublishReadyToRun=true
```
That's it! Your application will now include precompiled native code for faster startup and great performance benefits.
> Please refer to the [official documentation](https://learn.microsoft.com/en-us/dotnet/core/deploying/ready-to-run) before publishing your application with R2R.
## Conclusion
As ABP team, we're always looking for ways to improve the developer experience. By adopting **Ready-to-Run (R2R) publishing** for ABP Studio, we're aiming to deliver a faster and more efficient tool for your development needs.
Stay tuned for more updates and enhancements as we continue to optimize ABP Studio and please provide us with your invaluable feedback.

4
docs/en/Community-Articles/2022-09-15-Grpc-Demo/POST.md

@ -240,3 +240,7 @@ gRPC on .NET has different approaches, features, configurations and more details
* You can find the completed source code here: https://github.com/abpframework/abp-samples/tree/master/GrpcDemo2
* You can also see all the changes I've done in this article here: https://github.com/abpframework/abp-samples/pull/200/files
## See Also
* [Consuming gRPC Services from Blazor WebAssembly Application Using gRPC-Web](https://abp.io/community/articles/consuming-grpc-services-from-blazor-webassembly-application-using-grpcweb-dqjry3rv)

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

@ -187,11 +187,21 @@ On the other hand, resolving keyed services from `LazyServiceProvider` is not su
### Automatically Registering Keyed Services
Currently, if you want to register a keyed service, you need to do it manually as we see in the previous sections by using one of the overloads (`.AddKeyedTransient`, `.AddKeyedScoped` and `.AddKeyedSingleton`).
ABP provides the `ExposeKeyedServiceAttribute` to control which keyed services are provided by the related class.
It would be good if we could make this process automatically and not need to manually register services, and for that purpose, I have [created an issue](https://github.com/abpframework/abp/issues/18794) that aims to introduce an attribute, which allows us to automatically register multiple services as keyed services.
For example, if you want to register a keyed service as a transient dependency, you can do it as follows:
You can [follow the issue](https://github.com/abpframework/abp/issues/18794) if you are considering using keyed services in your application and don't want to register them manually.
```csharp
[ExposeKeyedService<ITaxCalculator>("taxCalculator")]
[ExposeKeyedService<ICalculator>("calculator")]
public class TaxCalculator: ICalculator, ITaxCalculator, ICanCalculate, ITransientDependency
{
}
```
> Notice that the ExposeKeyedServiceAttribute only exposes the keyed services. So, you can not inject the ITaxCalculator or ICalculator interfaces in your application without using the FromKeyedServicesAttribute as shown in the example above. If you want to expose both keyed and non-keyed services, you can use the ExposeServicesAttribute and ExposeKeyedServiceAttribute attributes altogether.
Please refer to the [Dependency Injection document](https://abp.io/docs/latest/framework/fundamentals/dependency-injection#exposekeyedservice-attribute) for further info.
## Summary

BIN
docs/en/Community-Articles/2024-11-13-BuiltIn-OpenApi-Documentation/img2.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 183 KiB

After

Width:  |  Height:  |  Size: 175 KiB

BIN
docs/en/Community-Articles/2024-11-13-BuiltIn-OpenApi-Documentation/img3.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 294 KiB

After

Width:  |  Height:  |  Size: 271 KiB

309
docs/en/Community-Articles/2024-11-25-Global-Assets/POST.md

@ -0,0 +1,309 @@
# ABP Global Assets - New way to bundle JavaScript/CSS files in Blazor WebAssembly app
We have introduced a new feature in the ABP framework to bundle the `JavaScript/CSS` files in the Blazor wasm app. This feature is called `Global Assets`.
With this feature, you don't need to run the `abp bundle` command to manually create/maintain the `global.js` and `global.css` files in your Blazor wasm app.
## How Global Assets works?
The new `Blazor wasm app` has two projects:
1. `MyProjectName` (ASP.NET Core app)
2. `MyProjectName.Client` (Blazor wasm app)
The `MyProjectName` reference the `MyProjectName.Client` project, and will be the entry point of the application, which means the `MyProjectName` project will be the `host` project of the `MyProjectName.Client` project.
The static/virtual files of `MyProjectName` can be accessed by the `MyProjectName.Client` project, so we can create dynamic global assets in the `MyProjectName` project and use them in the `MyProjectName.Client` project.
## How it works in ABP?
We have created a new package `WebAssembly.Theme.Bundling` for the theme `WebAssembly` module and used the `Volo.Abp.AspNetCore.Mvc.UI.Bundling.BundleContributor` to add `JavaScript/CSS` files to the bundling system.
* LeptonXLiteTheme: `AbpAspNetCoreComponentsWebAssemblyLeptonXLiteThemeBundlingModule`
* LeptonXTheme: `AbpAspNetCoreComponentsWebAssemblyLeptonXThemeBundlingModule`
* LeptonTheme: `AbpAspNetCoreComponentsWebAssemblyLeptonThemeBundlingModule`
* BasicTheme: `AbpAspNetCoreComponentsWebAssemblyBasicThemeBundlingModule`
The new `ThemeBundlingModule` only depends on `AbpAspNetCoreComponentsWebAssemblyThemingBundlingModule(new package)`. It's an `abstractions module`, which only depends on `AbpAspNetCoreMvcUiBundlingAbstractionsModule`.
We will get all `JavaScript/CSS` files on `OnApplicationInitializationAsync` method of `AbpAspNetCoreMvcUiBundlingModule` from bundling system and add them to `IDynamicFileProvider` service. After that, we can access the `JavaScript/CSS` files in the Blazor wasm app.
## Add the Global Assets in the module
If your module has `JavaScript/CSS` files that need to the bundling system, You have to create a new project(`YourModuleName.Blazor.WebAssembly.Bundling`) to your module solution, and reference the new project in the `MyProjectName` project and module dependencies.
The new project should **only** depend on the `AbpAspNetCoreComponentsWebAssemblyThemingBundlingModule` and define `BundleContributor` classes to contribute the `JavaScript/CSS` files.
> Q: The new project(`YourModuleName.Blazor.WebAssembly.Bundling`) doesn't have the `libs/myscript.js` and `libs/myscript.css` files why the files can be added to the bundling system?
> A: Because the `MyProjectName.Client` will depend on the `MyBlazorModule(YourModuleName.Blazor)` that contains the `JavaScript/CSS` files, The `MyProjectName` is referencing the `MyProjectName.Client` project, so the `MyProjectName` project can access the `JavaScript/CSS` files in the `MyProjectName.Client` project and add them to the bundling system.
```csharp
[DependsOn(
typeof(AbpAspNetCoreComponentsWebAssemblyThemingBundlingModule)
)]
public class MyBlazorWebAssemblyBundlingModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
Configure<AbpBundlingOptions>(options =>
{
// Script Bundles
options.ScriptBundles.Get(BlazorWebAssemblyStandardBundles.Scripts.Global).AddContributors(typeof(MyModuleBundleScriptContributor));
// Style Bundles
options.ScriptBundles.Get(BlazorWebAssemblyStandardBundles.Scripts.Global).AddContributors(typeof(MyModuleBundleStyleBundleContributor));
});
}
}
```
```csharp
public class MyModuleBundleScriptContributor : BundleContributor
{
public override void ConfigureBundle(BundleConfigurationContext context)
{
context.Files.AddIfNotContains("_content/MyModule.Blazor/libs/myscript.js");
}
}
public class MyModuleBundleStyleBundleContributor : BundleContributor
{
public override void ConfigureBundle(BundleConfigurationContext context)
{
context.Files.AddIfNotContains("_content/MyModule.Blazor/libs/myscript.css");
}
}
```
## Use the Global Assets in the Blazor WASM
### MyCompanyName.MyProjectName.Blazor
Convert your `MyCompanyName.MyProjectName.Blazor` project to integrate the `ABP module` system and depend on the `AbpAspNetCoreMvcUiBundlingModule` and `AbpAspNetCoreComponentsWebAssemblyLeptonXLiteThemeBundlingModule/AbpAspNetCoreComponentsWebAssemblyLeptonXThemeBundlingModule`:
* The `AbpAspNetCoreMvcUiBundlingModule` uses to create the `JavaScript/CSS` files to virtual files.
* The `AbpAspNetCoreComponentsWebAssemblyLeptonXLiteThemeBundlingModule/AbpAspNetCoreComponentsWebAssemblyLeptonXThemeBundlingModule` uses to add theme `JavaScript/CSS` to the bundling system.
Here is how your project files look like:
**`Program.cs`:**
```csharp
public class Program
{
public async static Task<int> Main(string[] args)
{
//...
var builder = WebApplication.CreateBuilder(args);
builder.Host.AddAppSettingsSecretsJson()
.UseAutofac()
.UseSerilog();
await builder.AddApplicationAsync<MyProjectNameBlazorModule>();
var app = builder.Build();
await app.InitializeApplicationAsync();
await app.RunAsync();
return 0;
//...
}
}
```
**`MyProjectNameBlazorModule.cs`:**
```csharp
[DependsOn(
typeof(AbpAutofacModule),
typeof(AbpAspNetCoreMvcUiBundlingModule),
typeof(AbpAspNetCoreComponentsWebAssemblyLeptonXLiteThemeBundlingModule/AbpAspNetCoreComponentsWebAssemblyLeptonXThemeBundlingModule) //Should be added!
)]
public class MyProjectNameBlazorModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
//https://github.com/dotnet/aspnetcore/issues/52530
Configure<RouteOptions>(options =>
{
options.SuppressCheckForUnhandledSecurityMetadata = true;
});
// Add services to the container.
context.Services.AddRazorComponents()
.AddInteractiveWebAssemblyComponents();
}
public override void OnApplicationInitialization(ApplicationInitializationContext context)
{
var env = context.GetEnvironment();
var app = context.GetApplicationBuilder();
// Configure the HTTP request pipeline.
if (env.IsDevelopment())
{
app.UseWebAssemblyDebugging();
}
else
{
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.MapAbpStaticAssets();
app.UseRouting();
app.UseAntiforgery();
app.UseConfiguredEndpoints(builder =>
{
builder.MapRazorComponents<App>()
.AddInteractiveWebAssemblyRenderMode()
.AddAdditionalAssemblies(WebAppAdditionalAssembliesHelper.GetAssemblies<MyProjectNameBlazorClientModule>());
});
}
}
```
**`MyCompanyName.MyProjectName.Blazor.csproj`:**
```xml
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="9.0.0.0" />
<PackageReference Include="Volo.Abp.Autofac" Version="9.0.0" />
<PackageReference Include="Volo.Abp.AspNetCore.Mvc.UI.Bundling" Version="9.0.0" />
<PackageReference Include="Volo.Abp.AspNetCore.Components.WebAssembly.LeptonXLiteTheme.Bundling" Version="9.0.0" />
<!-- <PackageReference Include="Volo.Abp.AspNetCore.Components.WebAssembly.LeptonXTheme.Bundling" Version="9.0.0" /> --> if you're using LeptonXTheme
<ProjectReference Include="..\MyProjectName.Blazor.Client\MyProjectName.Blazor.Client.csproj" />
</ItemGroup>
```
### BlazorWebAssemblyBundlingModule in the ABP commercial
Here is the list of `Bundling Modules` in the ABP commercial. If you're using the pro template, you should add them to the `MyCompanyName.MyProjectName.Blazor` project.
| BundlingModules | Nuget Package |
|---------------------------------------------|-----------------------------------------------------|
| AbpAuditLoggingBlazorWebAssemblyBundlingModule | Volo.Abp.AuditLogging.Blazor.WebAssembly.Bundling |
| FileManagementBlazorWebAssemblyBundlingModule | Volo.FileManagement.Blazor.WebAssembly.Bundling |
| SaasHostBlazorWebAssemblyBundlingModule | Volo.Saas.Host.Blazor.WebAssembly.Bundling |
| ChatBlazorWebAssemblyBundlingModule | Volo.Chat.Blazor.WebAssembly.Bundling |
| CmsKitProAdminBlazorWebAssemblyBundlingModule | Volo.CmsKit.Pro.Admin.Blazor.WebAssembly.Bundling |
### MyCompanyName.MyProjectName.Blazor.Client
1. Remove the `global.JavaScript/CSS` files from the `MyCompanyName.MyProjectName.Blazor`'s `wwwroot` folder.
2. Remove the `AbpCli:Bundle` section from the `appsettings.json` file.
3. Remove all BundleContributor classes that inherit from IBundleContributor. Then, create `MyProjectNameStyleBundleContributor` and `MyProjectNameScriptBundleContributor` classes to add your style and JavaScript files. Finally, add them to `AbpBundlingOptions`.
```cs
public class MyProjectNameStyleBundleContributor : BundleContributor
{
public override void ConfigureBundle(BundleConfigurationContext context)
{
context.Files.Add(new BundleFile("main.css", true));
}
}
public class MyProjectNameScriptBundleContributor : BundleContributor
{
public override void ConfigureBundle(BundleConfigurationContext context)
{
context.Files.Add(new BundleFile("main.js", true));
}
}
```
```cs
Configure<AbpBundlingOptions>(options =>
{
var globalStyles = options.StyleBundles.Get(BlazorWebAssemblyStandardBundles.Styles.Global);
globalStyles.AddContributors(typeof(MyProjectNameStyleBundleContributor));
var globalScripts = options.ScriptBundles.Get(BlazorWebAssemblyStandardBundles.Scripts.Global);
globalScripts.AddContributors(typeof(MyProjectNameScriptBundleContributor));
});
```
## Use the Global Assets in the Blazor WebApp
### MyCompanyName.MyProjectName.Blazor.WebApp
Depending on the `AbpAspNetCoreComponentsWebAssemblyLeptonXLiteThemeBundlingModule/AbpAspNetCoreComponentsWebAssemblyLeptonXThemeBundlingModule` in your `MyCompanyName.MyProjectName.Blazor.WebApp` project.
* The `AbpAspNetCoreComponentsWebAssemblyLeptonXLiteThemeBundlingModule/AbpAspNetCoreComponentsWebAssemblyLeptonXThemeBundlingModule` uses to add theme `JavaScript/CSS` to the bundling system.
### BlazorWebAssemblyBundlingModule in the ABP commercial
Here is the list of `Bundling Modules` in the ABP commercial. If you're using the pro template, you should add them to the `MyCompanyName.MyProjectName.Blazor.WebApp` project.
| BundlingModules | Nuget Package |
|---------------------------------------------|-----------------------------------------------------|
| AbpAuditLoggingBlazorWebAssemblyBundlingModule | Volo.Abp.AuditLogging.Blazor.WebAssembly.Bundling |
| FileManagementBlazorWebAssemblyBundlingModule | Volo.FileManagement.Blazor.WebAssembly.Bundling |
| SaasHostBlazorWebAssemblyBundlingModule | Volo.Saas.Host.Blazor.WebAssembly.Bundling |
| ChatBlazorWebAssemblyBundlingModule | Volo.Chat.Blazor.WebAssembly.Bundling |
| CmsKitProAdminBlazorWebAssemblyBundlingModule | Volo.CmsKit.Pro.Admin.Blazor.WebAssembly.Bundling |
### MyCompanyName.MyProjectName.Blazor.WebApp.Client
1. Remove the `global.JavaScript/CSS` files from the `MyCompanyName.MyProjectName.Blazor.WebApp.Client`'s `wwwroot` folder.
2. Remove the `AbpCli:Bundle` section from the `appsettings.json` file.
3. Remove all BundleContributor classes that inherit from IBundleContributor. Then, create `MyProjectNameStyleBundleContributor` and `MyProjectNameScriptBundleContributor` classes to add your style and JavaScript files. Finally, add them to `AbpBundlingOptions`.
```cs
public class MyProjectNameStyleBundleContributor : BundleContributor
{
public override void ConfigureBundle(BundleConfigurationContext context)
{
context.Files.Add(new BundleFile("main.css", true));
}
}
public class MyProjectNameScriptBundleContributor : BundleContributor
{
public override void ConfigureBundle(BundleConfigurationContext context)
{
context.Files.Add(new BundleFile("main.js", true));
}
}
```
```cs
Configure<AbpBundlingOptions>(options =>
{
var globalStyles = options.StyleBundles.Get(BlazorWebAssemblyStandardBundles.Styles.Global);
globalStyles.AddContributors(typeof(MyProjectNameStyleBundleContributor));
var globalScripts = options.ScriptBundles.Get(BlazorWebAssemblyStandardBundles.Scripts.Global);
globalScripts.AddContributors(typeof(MyProjectNameScriptBundleContributor));
});
```
### Check the Global Assets
Run the `MyProject` project and check the `https://localhost/global.js` and `https://localhost/global.css` files. You should be able to see the `JavaScript/CSS` files content from the Bundling system:
![global](image.png)
## GlobalAssets(AbpBundlingGlobalAssetsOptions)
You can configure the JavaScript and CSS file names in the `GlobalAssets` property of the `AbpBundlingOptions` class.
The default values are `global.js` and `global.css`.
## Conclusion
With the new `Global Assets` feature, you can easily bundle the `JavaScript/CSS` files in the Blazor wasm app. This feature is very useful for the Blazor wasm app, and it will save you a lot of time and effort. We hope you will enjoy this feature and use it in your projects.
## References
* [Virtual Files](https://docs.abp.io/en/abp/latest/Virtual-Files)
* [Bundle Contributors](https://abp.io/docs/latest/framework/ui/mvc-razor-pages/bundling-minification#bundle-contributors)
* [Global Assets Pull Request](https://github.com/abpframework/abp/pull/19968)

BIN
docs/en/Community-Articles/2024-11-25-Global-Assets/image.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 360 KiB

385
docs/en/Community-Articles/2024-12-01-OpenAI-Integration/POST.md

@ -0,0 +1,385 @@
# How to Use OpenAI API with ABP Framework
In this article, I will show you how to integrate and use the [OpenAI API](https://github.com/openai/openai-dotnet?tab=readme-ov-file#getting-started) with the [ABP Framework](https://abp.io/). We will explore step-by-step how these technologies can work together to enhance your application with powerful AI capabilities, such as natural language processing, image generation, and more.
![cover-image](cover-image.png)
## Creating an ABP Project
To begin integrating OpenAI API with ABP Framework, you first need to create an ABP project. Follow these steps to create and set up your ABP project:
### Step 1: Install ABP CLI
The ABP CLI is a command-line interface tool that helps you create and manage ABP projects easily. To install the ABP CLI, run the following command in your terminal:
```bash
dotnet tool install -g Volo.Abp.Studio.Cli
```
### Step 2: Create a New ABP Project
Once you have installed the ABP CLI, you can create a new ABP project using the following command:
```bash
abp new Acme.OpenAIIntegration -t app --ui-framework mvc --database-provider ef -dbms PostgreSQL --csf
```
> This command will generate a complete ABP project with an [MVC UI](https://abp.io/docs/latest/framework/ui/mvc-razor-pages/overall). The examples provided in this article make use of UI controllers for demonstration purposes. However, the same approach can easily be applied to other UI types supported by ABP, such as Blazor or Angular. You can find other options [here](https://abp.io/docs/latest/cli).
## OpenAI Integration Setup
To begin integrating OpenAI API with ABP Framework, follow these steps:
### Step 1: Create an API Key
To use the OpenAI services, you first need an API key. To obtain one, first [create a new OpenAI account](https://platform.openai.com/signup) or [log in](https://platform.openai.com/login). Next, navigate to the [API key page](https://platform.openai.com/account/api-keys) and select "Create new secret key", optionally naming the key. Make sure to save your API key somewhere safe and do not share it with anyone.
This key will be used to authenticate your application when making requests to the OpenAI endpoints.
### Step 2: Adding *Microsoft.Extensions.AI* Package
To integrate OpenAI API with ABP, we use [Microsoft.Extensions.AI](https://www.nuget.org/packages/Microsoft.Extensions.AI.OpenAI/). This package offers a unified API for integrating AI services, making it easy for developers to work with different AI providers. You can find more details in [this blog post](https://devblogs.microsoft.com/dotnet/introducing-microsoft-extensions-ai-preview/).
To begin integrating OpenAI API with ABP Framework, follow these steps:
1. Add the **Microsoft.Extensions.AI** and **Microsoft.Extensions.AI.OpenAI** (used to interact specifically with OpenAI services. Additionally, this package has alternatives like [Azure OpenAI](https://www.nuget.org/packages/Microsoft.Extensions.AI.OpenAI/), [Azure AI Inference](https://www.nuget.org/packages/Microsoft.Extensions.AI.AzureAIInference/), and [Ollama](https://www.nuget.org/packages/Microsoft.Extensions.AI.Ollama/), offering flexibility for developers to choose the AI provider that best fits their needs) packages:
```bash
dotnet add package Microsoft.Extensions.AI --prerelease
dotnet add package Microsoft.Extensions.AI.OpenAI --prerelease
```
2. Add the required configuration to the `appsettings.json` file located inside the `Acme.OpenAIIntegration.Web` project and dependencies to your `ConfigureServices` method:
```json
"AI": {
"OpenAI": {
"Key": "YOUR-API-KEY",
"Chat": {
"ModelId": "gpt-4o-mini"
}
}
}
```
> Replace the value of the `Key` with your OpenAI API key.
Next, add the following code to the `ConfigureServices` method in `OpenAIIntegrationBlazorModule`:
```csharp
context.Services.AddSingleton(new OpenAIClient(configuration["AI:OpenAI:Key"]));
context.Services.AddChatClient(services =>
services.GetRequiredService<OpenAIClient>().AsChatClient(configuration["AI:OpenAI:Chat:ModelId"] ?? "gpt-4o-mini"));
```
## Creating a Sample Page
To demonstrate the use of OpenAI API, let's create a page named `Sample` in the `Acme.OpenAIIntegration.Web` project:
Create a `Sample` folder under the `Pages` folder of the `Acme.OpenAIIntegration.Web` project. Add a new Razor Page by right-clicking the `Sample` folder then selecting `Add > Razor Page`. Name it `Index`.
Open the `Index.cshtml` and change the whole content as shown below:
> Note: This example demonstrates a simple implementation of a sample page that interacts with the OpenAI API, covering chat, [retrieval-augmented generation (RAG)](https://github.com/openai/openai-dotnet?tab=readme-ov-file#how-to-use-assistants-with-retrieval-augmented-generation-rag), and image generation features. Each example is explained in detail in the next section, so feel free to continue for a better understanding of the steps and logic involved.
```html
@page
@model Acme.OpenAIIntegration.Web.Pages.Sample
@{
ViewData["Title"] = "OpenAI API Demonstration";
}
<h1>@ViewData["Title"]</h1>
<br/><br/>
<div class="row">
<div class="col-md-4">
<h2>Chat Example</h2>
<form method="post" asp-page-handler="Chat">
<div class="form-group">
<label asp-for="ChatInput">Enter your message:</label>
<textarea asp-for="ChatInput" class="form-control" rows="4"></textarea>
</div>
<button type="submit" class="btn btn-primary mt-2">Send</button>
</form>
@if (!string.IsNullOrEmpty(Model.ChatResponse))
{
<h3 class="mt-3">Response:</h3>
<p>@Model.ChatResponse</p>
}
</div>
<div class="col-md-4">
<h2>RAG Example</h2>
<form method="post" asp-page-handler="RAG">
<div class="form-group mt-2">
<label asp-for="RAGQuery">Query:</label>
<input asp-for="RAGQuery" class="form-control" />
</div>
<button type="submit" class="btn btn-primary mt-2">Ask</button>
</form>
@if (!string.IsNullOrEmpty(Model.RAGResponse))
{
<h3 class="mt-3">Result:</h3>
<p>@Model.RAGResponse</p>
}
</div>
<div class="col-md-4">
<h2>Image Generation Example</h2>
<form method="post" asp-page-handler="ImageGeneration">
<div class="form-group">
<label asp-for="ImagePrompt">Image Description:</label>
<input asp-for="ImagePrompt" class="form-control" />
</div>
<button type="submit" class="btn btn-primary mt-2">Generate Image</button>
</form>
@if (Model.GeneratedImageBytes != null)
{
<h3 class="mt-3">Generated Image:</h3>
<img src="data:image/png;base64,@Convert.ToBase64String(Model.GeneratedImageBytes)" alt="Generated image" class="img-fluid mt-2" />
}
</div>
</div>
```
`Index.cshtml.cs` content should be like that:
```csharp
using System;
using System.ClientModel;
using System.IO;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.Extensions.AI;
using OpenAI;
using OpenAI.Assistants;
using OpenAI.Files;
using OpenAI.Images;
namespace Acme.OpenAIIntegration.Web.Pages;
public class Sample : PageModel
{
[BindProperty]
public string ChatInput { get; set; }
public string ChatResponse { get; set; }
[BindProperty]
public string RAGQuery { get; set; }
public string RAGResponse { get; set; }
[BindProperty]
public string ImagePrompt { get; set; }
public byte[] GeneratedImageBytes { get; set; }
private readonly IChatClient _chatClient;
private readonly OpenAIClient _openAiClient;
public Sample(
IChatClient chatClient,
OpenAIClient openAiClient)
{
_chatClient = chatClient;
_openAiClient = openAiClient;
}
public async Task<IActionResult> OnPostChatAsync()
{
ChatResponse = $"Chat response: {(await _chatClient.CompleteAsync(ChatInput)).Message}";
return Page();
}
public async Task<IActionResult> OnPostRAGAsync()
{
#pragma warning disable OPENAI001
var fileClient = _openAiClient.GetOpenAIFileClient();
var assistantClient = _openAiClient.GetAssistantClient();
using var document = BinaryData.FromBytes(GetExceptionHandlingDocumentContent().ToArray()).ToStream();
var exceptionHandlingDoc = await fileClient.UploadFileAsync(
document,
"ExceptionHandling.md",
FileUploadPurpose.Assistants);
AssistantCreationOptions assistantOptions = new()
{
Name = "Exception Handling Assistant",
Instructions =
"""
This assistant helps you with exception handling in ABP Framework. You can ask questions about exception handling and get answers.
- Do not make any assumptions when asked for information that is not in the document
- Give the most accurate information possible
- Give short(max 1-2 sentence) and concise answers
- Do not provide file citations
""",
Tools =
{
new FileSearchToolDefinition(),
},
ToolResources = new()
{
FileSearch = new()
{
NewVectorStores =
{
new VectorStoreCreationHelper([exceptionHandlingDoc.Value.Id]),
}
}
},
};
var assistant = await assistantClient.CreateAssistantAsync("gpt-4o", assistantOptions);
ThreadCreationOptions threadOptions = new()
{
InitialMessages = { RAGQuery }
};
ThreadRun threadRun = assistantClient.CreateThreadAndRun(assistant.Value.Id, threadOptions);
do
{
Thread.Sleep(TimeSpan.FromSeconds(1));
threadRun = assistantClient.GetRun(threadRun.ThreadId, threadRun.Id);
} while (!threadRun.Status.IsTerminal);
CollectionResult<ThreadMessage> messages
= assistantClient.GetMessages(threadRun.ThreadId,
new MessageCollectionOptions() { Order = MessageCollectionOrder.Ascending });
var response = new StringBuilder();
foreach (var message in messages)
{
response.AppendLine($"[{message.Role.ToString().ToUpper()}]: ");
foreach (var contentItem in message.Content)
{
if (!string.IsNullOrEmpty(contentItem.Text))
{
response.AppendLine(contentItem.Text);
if (contentItem.TextAnnotations.Count > 0)
{
response.AppendLine("");
}
}
}
response.AppendLine("");
#pragma warning restore OPENAI001
}
RAGResponse = response.ToString();
return Page();
}
public async Task<IActionResult> OnPostImageGenerationAsync()
{
var client = _openAiClient.GetImageClient("dall-e-3");
var image = await client.GenerateImageAsync(ImagePrompt, new ImageGenerationOptions
{
ResponseFormat = GeneratedImageFormat.Bytes
});
var imageBytes = image.Value.ImageBytes;
using var memoryStream = new MemoryStream();
await imageBytes.ToStream().CopyToAsync(memoryStream);
GeneratedImageBytes = memoryStream.ToArray();
return Page();
}
public ReadOnlySpan<byte> GetExceptionHandlingDocumentContent()
{
return """
# Exception Handling
ABP provides a built-in infrastructure and offers a standard model for handling exceptions.
* Automatically **handles all exceptions** and sends a standard **formatted error message** to the client for an API/AJAX request.
* Automatically hides **internal infrastructure errors** and returns a standard error message.
* Provides an easy and configurable way to **localize** exception messages.
* Automatically maps standard exceptions to **HTTP status codes** and provides a configurable option to map custom exceptions.
## Automatic Exception Handling
`AbpExceptionFilter` handles an exception if **any of the following conditions** are met:
* Exception is thrown by a **controller action** which returns an **object result** (not a view result).
* The request is an AJAX request (`X-Requested-With` HTTP header value is `XMLHttpRequest`).
* Client explicitly accepts the `application/json` content type (via `accept` HTTP header).
If the exception is handled it's automatically **logged** and a formatted **JSON message** is returned to the client.
## Business Exceptions
Most of your own exceptions will be business exceptions. The `IBusinessException` interface is used to mark an exception as a business exception.
`BusinessException` implements the `IBusinessException` interface in addition to the `IHasErrorCode`, `IHasErrorDetails` and `IHasLogLevel` interfaces. The default log level is `Warning`.
Usually you have an error code related to a particular business exception. For example:
````C#
throw new BusinessException(QaErrorCodes.CanNotVoteYourOwnAnswer);
````
### User Friendly Exception
If an exception implements the `IUserFriendlyException` interface, then ABP does not change it's `Message` and `Details` properties and directly send it to the client.
`UserFriendlyException` class is the built-in implementation of the `IUserFriendlyException` interface. Example usage:
````C#
throw new UserFriendlyException(
"Username should be unique!"
);
````
* The `IUserFriendlyException` interface is derived from the `IBusinessException` and the `UserFriendlyException` class is derived from the `BusinessException` class.
"""u8;
}
}
```
## Running the Application
After completing the setup, you can run the application using the following command:
```bash
dotnet run --project ./src/Acme.OpenAIIntegration.Web
```
Once the application is running, open your browser and navigate to `/Sample`. You should see the `Sample` page we created, which contains sections for Chat, RAG (Retrieval-Augmented Generation), and Image Generation. You can find the screenshot of the page below:
![sample page](sample-page.png)
## Examples Overview
To showcase the integration of the OpenAI API with the ABP Framework, we implemented three different examples:
1. **Chat Example**: This example demonstrates how to use OpenAI's chat capabilities by allowing users to enter a message and receive an AI-generated response. The implementation involves setting up a simple form on the `Sample` page where users can input their message. The form submission triggers the `OnPostChatAsync` method, which uses the `IChatClient` to generate a response.
![chat-example](chat-example.gif)
2. **Retrieval-Augmented Generation (RAG) Example**: In this example, we use OpenAI to answer user queries by referencing custom documents uploaded to the OpenAI API. The implementation involves uploading a document using the `OpenAIFileClient` and creating an assistant with specific instructions to handle the uploaded content. In this case, the document is a section from ABP's Exception Handling documentation, which includes examples on how ABP handles exceptions, user-friendly error messages, and business exceptions. Users can input their query on the `Sample` page, and the `OnPostRAGAsync` method processes the query to generate precise answers based on the document content. If users ask questions that are not covered in the document, the assistant clearly indicates that the information is not available, as per the instructions provided. For example, when asked about `Object Extensions`, the response begins with: "The uploaded document does not contain information about `Object Extensions`...". This demonstrates how the assistant adheres to the provided instructions. You can also find this example illustrated in the GIF below.
![rag-example-1](rag-example-1.gif)
![rag-example-2](rag-example-2.gif)
3. **Image Generation Example**: This example leverages the [DALL-E](https://openai.com/index/dall-e-3/) model to generate images based on user-provided prompts. On the `Sample` page, users can provide a description of the image they want to generate, and the `OnPostImageGenerationAsync` method uses the `OpenAIClient` to generate the image.
![image-generation-example](image-generation-example.gif)
## Conclusion
In this article, we covered how to integrate the OpenAI API with the ABP Framework by creating a sample project, setting up the OpenAI services, and implementing examples for conversational AI, knowledge-based assistance, and image generation. By following these steps, you can add powerful AI-driven capabilities to your application, making it more interactive, intelligent, and capable of meeting user needs effectively.

BIN
docs/en/Community-Articles/2024-12-01-OpenAI-Integration/chat-example.gif

Binary file not shown.

After

Width:  |  Height:  |  Size: 147 KiB

BIN
docs/en/Community-Articles/2024-12-01-OpenAI-Integration/cover-image.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 565 KiB

BIN
docs/en/Community-Articles/2024-12-01-OpenAI-Integration/image-generation-example.gif

Binary file not shown.

After

Width:  |  Height:  |  Size: 954 KiB

BIN
docs/en/Community-Articles/2024-12-01-OpenAI-Integration/rag-example-1.gif

Binary file not shown.

After

Width:  |  Height:  |  Size: 160 KiB

BIN
docs/en/Community-Articles/2024-12-01-OpenAI-Integration/rag-example-2.gif

Binary file not shown.

After

Width:  |  Height:  |  Size: 220 KiB

BIN
docs/en/Community-Articles/2024-12-01-OpenAI-Integration/sample-page.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

234
docs/en/Community-Articles/2024-12-09-Unit-Test/POST.md

@ -0,0 +1,234 @@
# The new Unit Test structure in ABP application
A typical ABP modular project usually consists of three main projects: `Application`, `Domain`, and `EntityFrameworkCore/MongoDB`. In these projects, we may provide many services that require unit testing.
Using abstract unit test classes involves first writing tests in the `Application` and `Domain` layers that are independent of the storage technology, ensuring the correctness of core business logic. These abstract tests are then implemented in `EntityFrameworkCore` or `MongoDB`. The benefits of this approach include:
1. **Reduced Coupling**: Core logic tests do not depend on specific storage technologies, so switching databases does not require rewriting test code.
2. **Better Isolation**: Focuses on verifying business logic correctness, avoiding interference from database operations.
3. **Increased Reusability**: The same abstract tests can be reused with different storage implementations.
4. **Easier Maintenance and Extensibility**: Different storage implementations can be extended independently without breaking existing tests.
5. **Faster and More Reliable Tests**: Reduces dependency on databases, making tests faster and more stable.
## How to migrate old unit tests to the new unit test structure
Assume our project name is `MyCompanyName.MyProjectName`.
### Changes to the `MyCompanyName.MyProjectName.Application.Tests` project:
1. Remove the `MyCompanyName.MyProjectName.Application.Tests` project's `MyProjectNameApplicationCollection` class.
2. Modify the `MyCompanyName.MyProjectName.Application.Tests` project's `MyProjectNameApplicationTestBase` class.
```csharp
public abstract class MyProjectNameApplicationTestBase<TStartupModule> : MyProjectNameTestBase<TStartupModule>
where TStartupModule : IAbpModule
{
//...
}
```
3. Modify the `MyCompanyName.MyProjectName.Application.Tests` project's unit test classes to become abstract unit test classes, such as: `SampleAppServiceTests`.
```csharp
public abstract class SampleAppServiceTests<TStartupModule> : MyProjectNameApplicationTestBase<TStartupModule>
where TStartupModule : IAbpModule
{
[Fact]
public async Task Initial_Data_Should_Contain_Admin_User()
{
//...
}
}
```
### Changes to the `MyCompanyName.MyProjectName.Domain.Tests` project:
1. Remove the `MyCompanyName.MyProjectName.Domain.Tests` project's `MyProjectNameDomainCollection` class.
2. Modify the `MyCompanyName.MyProjectName.Domain.Tests` project's `MyProjectNameDomainTestBase` class.
```csharp
public abstract class MyProjectNameDomainTestBase<TStartupModule> : MyProjectNameTestBase<TStartupModule>
where TStartupModule : IAbpModule
{
//...
}
```
3. Modify the `MyCompanyName.MyProjectName.Domain.Tests` project's unit test classes to become abstract unit test classes, such as: `SampleDomainTests`.
```csharp
public abstract class SampleDomainTests<TStartupModule> : MyProjectNameDomainTestBase<TStartupModule>
where TStartupModule : IAbpModule
{
[Fact]
public async Task Should_Set_Email_Of_A_User()
{
//...
}
}
```
4. Modify the `MyCompanyName.MyProjectName.Domain.Tests` project's `csproj` and module class. Remove references to `EntityFrameworkCore/MongoDB`.
`MyCompanyName.MyProjectName.Domain.Tests.csproj`:
```xml
<Project Sdk="Microsoft.NET.Sdk">
//...
<ItemGroup>
<ProjectReference Include="..\..\src\MyCompanyName.MyProjectName.Domain\MyCompanyName.MyProjectName.Domain.csproj" />
<ProjectReference Include="..\MyCompanyName.MyProjectName.TestBase\MyCompanyName.MyProjectName.TestBase.csproj" />
</ItemGroup>
</Project>
```
`MyProjectNameDomainTestModule.cs`:
```csharp
[DependsOn(
typeof(MyProjectNameDomainModule),
typeof(MyProjectNameTestBaseModule)
)]
public class MyProjectNameDomainTestModule : AbpModule
{
//...
}
```
### Changes to the `MyCompanyName.MyProjectName.EntityFrameworkCore.Tests` project:
Here, we need to create implementation classes for all abstract unit tests.
```csharp
[Collection(MyProjectNameTestConsts.CollectionDefinitionName)]
public class EfCoreSampleAppServiceTests : SampleAppServiceTests<MyProjectNameEntityFrameworkCoreTestModule>
{
//...
}
```
```csharp
[Collection(MyProjectNameTestConsts.CollectionDefinitionName)]
public class EfCoreSampleDomainTests : SampleDomainTests<MyProjectNameEntityFrameworkCoreTestModule>
{
//...
}
```
We also need to modify the project's dependencies and module class, which should directly or indirectly reference the `Application` and `Domain` test projects.
`MyCompanyName.MyProjectName.EntityFrameworkCore.Tests.csproj`:
```xml
<Project Sdk="Microsoft.NET.Sdk">
//...
<ItemGroup>
<ProjectReference Include="..\..\src\MyCompanyName.MyProjectName.EntityFrameworkCore\MyCompanyName.MyProjectName.EntityFrameworkCore.csproj" />
<ProjectReference Include="..\MyCompanyName.MyProjectName.Application.Tests\MyCompanyName.MyProjectName.Application.Tests.csproj" />
<ProjectReference Include="..\..\..\..\..\framework\src\Volo.Abp.EntityFrameworkCore.Sqlite\Volo.Abp.EntityFrameworkCore.Sqlite.csproj" />
</ItemGroup>
</Project>
```
`MyProjectNameEntityFrameworkCoreTestModule.cs`:
```csharp
[DependsOn(
typeof(MyProjectNameApplicationTestModule),
typeof(MyProjectNameEntityFrameworkCoreModule),
typeof(AbpEntityFrameworkCoreSqliteModule)
)]
public class MyProjectNameEntityFrameworkCoreTestModule : AbpModule
{
//...
}
```
### Changes to the `MyCompanyName.MyProjectName.MongoDB.Tests` project (skip this step if not using MongoDB):
Like the `EntityFrameworkCore` project, we need to create implementation classes for all abstract unit tests and modify the project's dependencies and module class.
```csharp
[Collection(MyProjectNameTestConsts.CollectionDefinitionName)]
public class MongoDBSampleAppServiceTests : SampleAppServiceTests<MyProjectNameMongoDbTestModule>
{
//...
}
```
```csharp
[Collection(MyProjectNameTestConsts.CollectionDefinitionName)]
public class MongoDBSampleDomainTests : SampleDomainTests<MyProjectNameMongoDbTestModule>
{
//...
}
```
```xml
<Project Sdk="Microsoft.NET.Sdk">
//...
<ItemGroup>
<ProjectReference Include="..\..\src\MyCompanyName.MyProjectName.MongoDB\MyCompanyName.MyProjectName.MongoDB.csproj" />
<ProjectReference Include="..\MyCompanyName.MyProjectName.Application.Tests\MyCompanyName.MyProjectName.Application.Tests.csproj" />
</ItemGroup>
</Project>
```
```csharp
[DependsOn(
typeof(MyProjectNameApplicationTestModule),
typeof(MyProjectNameMongoDbModule)
)]
public class MyProjectNameMongoDbTestModule : AbpModule
{
//...
}
```
### Changes to the `MyCompanyName.MyProjectName.Web.Tests` project:
We need to reference the `EntityFrameworkCore/MongoDB` test projects in this test project.
```xml
<Project Sdk="Microsoft.NET.Sdk">
//...
<ItemGroup>
<ProjectReference Include="..\MyCompanyName.MyProjectName.Application.Tests\MyCompanyName.MyProjectName.Application.Tests.csproj" />
<ProjectReference Include="..\..\src\MyCompanyName.MyProjectName.Web\MyCompanyName.MyProjectName.Web.csproj" />
<ProjectReference Include="..\..\..\..\..\framework\src\Volo.Abp.AspNetCore.TestBase\Volo.Abp.AspNetCore.TestBase.csproj" />
<ProjectReference Include="..\MyCompanyName.MyProjectName.EntityFrameworkCore.Tests\MyCompanyName.MyProjectName.EntityFrameworkCore.Tests.csproj" />
</ItemGroup>
</Project>
```
```csharp
[DependsOn(
typeof(AbpAspNetCoreTestBaseModule),
typeof(MyProjectNameWebModule),
typeof(MyProjectNameApplicationTestModule),
typeof(MyProjectNameEntityFrameworkCoreTestModule)
)]
public class MyProjectNameWebTestModule : AbpModule
{
//...
}
```
We no longer need the `MyProjectNameWebCollection` class in this project. Please delete it and use `[Collection(MyProjectNameTestConsts.CollectionDefinitionName)]` instead.
## Conclusion
This is our new unit test structure. Decoupling unit tests from storage technologies ensures the independence of business logic and allows easy switching between storage implementations. Abstract unit test classes improve test reusability, maintainability, and efficiency, reducing refactoring costs and providing flexibility for future tech updates.
## References
- [Unit Test](https://abp.io/docs/latest/testing/unit-tests)
- [Abstract all db-related unit tests](https://github.com/abpframework/abp/pull/17880)

10
docs/en/cli/index.md

@ -112,7 +112,7 @@ abp cli clear-cache
### new
Generates a new solution based on the ABP [startup templates](../solution-templates).
Generates a new solution based on the ABP [startup templates](../solution-templates). See [new solution create sample commands](new-command-samples.md)
Usage:
@ -211,6 +211,7 @@ For more samples, go to [ABP CLI Create Solution Samples](new-command-samples.md
* `leptonx`: LeptonX Theme.
* `basic`: Basic Theme.
* `--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.
* `--no-grafana-dashboard` or `-ngd`: Does not add example Grafana Dashboard to the solution.
* `--output-folder` or `-o`: Specifies the output folder. Default value is the current directory.
* `--local-framework-ref` or `-lfr`: Uses local projects references to the ABP framework instead of using the NuGet packages. It tries to find the paths from `ide-state.json`. The file is located at `%UserProfile%\.abp\studio\ui\ide-state.json` (for Windows) and `~/.abp/studio/ui/ide-state.json` (for MAC).
* `--create-solution-folder` or `-csf`: Specifies if the project will be in a new folder in the output folder or directly the output folder.
@ -225,15 +226,16 @@ For more samples, go to [ABP CLI Create Solution Samples](new-command-samples.md
* `--dont-run-bundling`: Skip bundling for Blazor packages.
* `--no-kubernetes-configuration` or `-nkc`: Skips the Kubernetes configuration files.
* `--no-social-logins` or `-nsl`: Skipts the social login configuration.
* *Module Options*: You can skip some modules if you don't want to add them to your solution (*Available for* ***Team*** *or higher licenses*). Available commands:
* `--no-tests` or `-ntp`: Does not add test projects.
* *Module Options*: You can skip some modules if you don't want to add them to your solution, or include if you want them (*Available for* ***Team*** *or higher licenses*). Available commands:
* `-no-saas`: Skips the Saas module.
* `-no-gdpr`: Skips the GDPR module.
* `-no-openiddict-admin-ui`: Skips the OpenIddict Admin UI module.
* `-no-audit-logging`: Skips the Audit Logging module.
* `-no-file-management`: Skips the File Management module.
* `-no-language-management`: Skips the Language Management module.
* `-no-text-template-management`: Skips the Text Template Management module.
* `-no-chat`: Skips the Chat module.
* `-file-management`: Includes the File Management module.
* `-chat`: Includes the Chat module.
* `--legacy`: Generates a legacy solution.
* `trust-version`: Trusts the user's version and does not check if the version exists or not. If the template with the given version is found in the cache, it will be used, otherwise throws an exception.

2
docs/en/cli/new-command-samples.md

@ -21,7 +21,7 @@ The following commands are for creating Angular UI projects:
* **Entity Framework Core**, **custom connection string**, creates the project in a new folder:
```bash
abp new Acme.BookStore -u angular -csf --connection-string Server=localhost;Database=MyDatabase;Trusted_Connection=True
abp new Acme.BookStore -u angular -csf --connection-string "Server=localhost;Database=MyDatabase;Trusted_Connection=True"
```
* **MongoDB**, default app template, mobile project included, creates solution in `C:\MyProjects\Acme.BookStore`

6
docs/en/contribution/index.md

@ -50,6 +50,12 @@ This is the recommended approach, since it automatically finds all missing texts
If you want to make a change on a specific resource file, you can find the file yourself, make the necessary change (or create a new file for your language) and send a pull request on GitHub.
### Commercial Modules
The commercial modules are not open source, and their localization files are not available in the public repository. The open-source module, `Account`, and the commercial module, `Account.Pro`, may have different translations.
If you would like to translate a commercial module, please [create an issue](https://github.com/abpframework/abp/issues/new) on Github, and we will provide the necessary files (`abp-translation.json` for one or all modules).
## Bug Report
If you find any bug, please [create an issue on the Github repository](https://github.com/abpframework/abp/issues/new).

6
docs/en/deployment/configuring-openIddict.md

@ -4,6 +4,8 @@ This document introduces how to configure `OpenIddict` in the `AuthServer` proje
There are different configurations in the `AuthServer` project for the `Development` and `Production` environments.
> If your solution does not include a project named `.AuthServer`, it means that you might have another project that depends on `AbpAccountPublicWebOpenIddictModule`. The project name can be `MyProject`, `MyProject.Web`, or `MyProject.HttpApi.Host`. They are both `Authentication Server` projects in that context.
````csharp
public override void PreConfigureServices(ServiceConfigurationContext context)
{
@ -38,10 +40,14 @@ To avoid that, consider creating self-signed certificates and storing them in th
You can use the `dotnet dev-certs https -v -ep openiddict.pfx -p 00000000-0000-0000-0000-000000000000` command to generate the `openiddict.pfx` certificate.
> `openiddict.pfx` is just an example of a filename. You can use any filename for the pfx file.
> `00000000-0000-0000-0000-000000000000` is the password of the certificate, you can change it to any password you want.
> Also, please remember to copy `openiddict.pfx` to the [Content Root Folder](https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.hosting.ihostingenvironment.contentrootpath?view=aspnetcore-7.0) of the `AuthServer` website.
> It is recommended to use **two** RSA certificates, distinct from the certificate(s) used for HTTPS: one for encryption, one for signing.
> If you encounter a deployment error on IIS that says **File not found** even though the file exists, it is recommended to set the application pool’s advanced settings **Load User Profile** to **True** to resolve the issue.
For more information, please refer to: https://documentation.openiddict.com/configuration/encryption-and-signing-credentials.html#registering-a-certificate-recommended-for-production-ready-scenarios

710
docs/en/docs-nav.json

File diff suppressed because it is too large

1
docs/en/docs-params.json

@ -8,6 +8,7 @@
"Blazor": "Blazor WebAssembly",
"BlazorServer": "Blazor Server",
"BlazorWebApp": "Blazor WebApp",
"MAUIBlazor": "MAUI Blazor (Hybrid)",
"NG": "Angular"
}
},

44
docs/en/framework/architecture/best-practices/application-services.md

@ -1,8 +1,14 @@
# Application Services Best Practices & Conventions
> This document offers best practices for implementing Application Services classes in your modules and applications based on Domain-Driven-Design principles.
>
> **Ensure you've read the [*Application Services*](../domain-driven-design/application-services.md) document first.**
## General
* **Do** create an application service for each **aggregate root**.
### Application Service Interface
## Application Service Interface
* **Do** define an `interface` for each application service in the **application contracts** package.
* **Do** inherit from the `IApplicationService` interface.
@ -11,11 +17,11 @@
* **Do not** get/return entities for the service methods.
* **Do** define DTOs based on the [DTO best practices](data-transfer-objects.md).
#### Outputs
### Outputs
* **Avoid** to define too many output DTOs for same or related entities. Instead, define a **basic** and a **detailed** DTO for an entity.
##### Basic DTO
#### Basic DTO
**Do** define a **basic** DTO for an aggregate root.
@ -44,7 +50,7 @@ public class IssueLabelDto
}
```
##### Detailed DTO
#### Detailed DTO
**Do** define a **detailed** DTO for an entity if it has reference(s) to other aggregate roots.
@ -81,20 +87,20 @@ public class LabelDto : ExtensibleEntityDto<Guid>
}
````
#### Inputs
### Inputs
* **Do not** define any property in an input DTO that is not used in the service class.
* **Do not** share input DTOs between application service methods.
* **Do not** inherit an input DTO class from another one.
* **May** inherit from an abstract base DTO class and share some properties between different DTOs in that way. However, should be very careful in that case because manipulating the base DTO would effect all related DTOs and service methods. Avoid from that as a good practice.
#### Methods
### Methods
* **Do** define service methods as asynchronous with **Async** postfix.
* **Do not** repeat the entity name in the method names.
* Example: Define `GetAsync(...)` instead of `GetProductAsync(...)` in the `IProductAppService`.
##### Getting A Single Entity
#### Getting A Single Entity
* **Do** use the `GetAsync` **method name**.
* **Do** get Id with a **primitive** method parameter.
@ -104,7 +110,7 @@ public class LabelDto : ExtensibleEntityDto<Guid>
Task<QuestionWithDetailsDto> GetAsync(Guid id);
````
##### Getting A List Of Entities
#### Getting A List Of Entities
* **Do** use the `GetListAsync` **method name**.
* **Do** get a single DTO argument for **filtering**, **sorting** and **paging** if necessary.
@ -117,7 +123,7 @@ Task<QuestionWithDetailsDto> GetAsync(Guid id);
Task<List<QuestionWithDetailsDto>> GetListAsync(QuestionListQueryDto queryDto);
````
##### Creating A New Entity
#### Creating A New Entity
* **Do** use the `CreateAsync` **method name**.
* **Do** get a **specialized input** DTO to create the entity.
@ -151,7 +157,7 @@ public class CreateQuestionDto : ExtensibleObject
}
````
##### Updating An Existing Entity
#### Updating An Existing Entity
- **Do** use the `UpdateAsync` **method name**.
- **Do** get a **specialized input** DTO to update the entity.
@ -167,7 +173,7 @@ Example:
Task<QuestionWithDetailsDto> UpdateAsync(Guid id, UpdateQuestionDto updateQuestionDto);
````
##### Deleting An Existing Entity
#### Deleting An Existing Entity
- **Do** use the `DeleteAsync` **method name**.
- **Do** get Id with a **primitive** method parameter. Example:
@ -176,7 +182,7 @@ Task<QuestionWithDetailsDto> UpdateAsync(Guid id, UpdateQuestionDto updateQuesti
Task DeleteAsync(Guid id);
````
##### Other Methods
#### Other Methods
* **Can** define additional methods to perform operations on the entity. Example:
@ -186,7 +192,7 @@ Task<int> VoteAsync(Guid id, VoteType type);
This method votes a question and returns the current score of the question.
### Application Service Implementation
## Application Service Implementation
* **Do** develop the application layer **completely independent from the web layer**.
* **Do** implement application service interfaces in the **application layer**.
@ -195,30 +201,30 @@ This method votes a question and returns the current score of the question.
* **Do** make all public methods **virtual**, so developers may inherit and override them.
* **Do not** make **private** methods. Instead make them **protected virtual**, so developers may inherit and override them.
#### Using Repositories
### Using Repositories
* **Do** use the specifically designed repositories (like `IProductRepository`).
* **Do not** use generic repositories (like `IRepository<Product>`).
#### Querying Data
### Querying Data
* **Do not** use LINQ/SQL for querying data from database inside the application service methods. It's repository's responsibility to perform LINQ/SQL queries from the data source.
#### Extra Properties
### Extra Properties
* **Do** use either `MapExtraPropertiesTo` extension method ([see](../../fundamentals/object-extensions.md)) or configure the object mapper (`MapExtraProperties`) to allow application developers to be able to extend the objects and services.
#### Manipulating / Deleting Entities
### Manipulating / Deleting Entities
* **Do** always get all the related entities from repositories to perform the operations on them.
* **Do** call repository's Update/UpdateAsync method after updating an entity. Because, not all database APIs support change tracking & auto update.
#### Handle files
### Handle files
* **Do not** use any web components like `IFormFile` or `Stream` in the application services. If you want to serve a file you can use `byte[]`.
* **Do** use a `Controller` to handle file uploading then pass the `byte[]` of the file to the application service method.
#### Using Other Application Services
### Using Other Application Services
* **Do not** use other application services of the same module/application. Instead;
* Use domain layer to perform the required task.

6
docs/en/framework/architecture/best-practices/data-transfer-objects.md

@ -1,5 +1,11 @@
# Data Transfer Objects Best Practices & Conventions
> This document offers best practices for implementing Data Transfer Object classes in your modules and applications based on Domain-Driven-Design principles.
>
> **Ensure you've read the [*Data Transfer Objects*](../domain-driven-design/data-transfer-objects.md) document first.**
## General
* **Do** define DTOs in the **application contracts** package.
* **Do** inherit from the pre-built **base DTO classes** where possible and necessary (like `EntityDto<TKey>`, `CreationAuditedEntityDto<TKey>`, `AuditedEntityDto<TKey>`, `FullAuditedEntityDto<TKey>` and so on).
* **Do** inherit from the **extensible DTO** classes for the **aggregate roots** (like `ExtensibleAuditedEntityDto<TKey>`), because aggregate roots are extensible objects and extra properties are mapped to DTOs in this way.

10
docs/en/framework/architecture/best-practices/domain-services.md

@ -1,6 +1,10 @@
# Domain Services Best Practices & Conventions
### Domain Service
> This document offers best practices for implementing Domain Service classes in your modules and applications based on Domain-Driven-Design principles.
>
> **Ensure you've read the [*Domain Services*](../domain-driven-design/domain-services.md) document first.**
## Domain Services
- **Do** define domain services in the **domain layer**.
- **Do not** create interfaces for the domain services **unless** you have a good reason to (like mock and test different implementations).
@ -14,7 +18,7 @@ public class IssueManager : DomainService
}
```
### Domain Service Methods
## Domain Service Methods
- **Do not** define `GET` methods. `GET` methods do not change the state of an entity. Hence, use the repository directly in the Application Service instead of Domain Service method.
@ -57,8 +61,6 @@ public async Task AssignToAsync(Issue issue, IdentityUser user)
- **Do not** return `DTO`. Return only domain objects when you need.
- **Do not** involve authenticated user logic. Instead, define extra parameter and send the related data of ` CurrentUser` from the Application Service layer.
## See Also
* [Video tutorial](https://abp.io/video-courses/essentials/domain-services)

33
docs/en/framework/architecture/best-practices/entities.md

@ -1,12 +1,16 @@
# Entity Best Practices & Conventions
### Entities
> This document offers best practices for implementing Aggregate Root and Entity classes in your modules and applications based on Domain-Driven-Design principles.
>
> **Ensure you've read the [*Entities*](../domain-driven-design/entities.md) document first.**
## Entities
Every aggregate root is also an entity. So, these rules are valid for aggregate roots too unless aggregate root rules override them.
- **Do** define entities in the **domain layer**.
#### Primary Constructor
### Primary Constructor
* **Do** define a **primary constructor** that ensures the validity of the entity on creation. Primary constructors are used to create a new instance of the entity by the application code.
@ -14,15 +18,15 @@ Every aggregate root is also an entity. So, these rules are valid for aggregate
- **Do** always initialize sub collections in the primary constructor.
- **Do not** generate `Guid` keys inside the constructor. Get it as a parameter, so the calling code will use `IGuidGenerator` to generate a new `Guid` value.
#### Parameterless Constructor
### Parameterless Constructor
- **Do** always define a `protected` parameterless constructor to be compatible with ORMs.
#### References
### References
- **Do** always **reference** to other aggregate roots **by Id**. Never add navigation properties to other aggregate roots.
#### Other Class Members
### Other Class Members
- **Do** always define properties and methods as `virtual` (except `private` methods, obviously). Because some ORMs and dynamic proxy tools require it.
- **Do** keep the entity as always **valid** and **consistent** within its own boundary.
@ -30,27 +34,27 @@ Every aggregate root is also an entity. So, these rules are valid for aggregate
- **Do** define `public `, `internal` or `protected internal` (virtual) **methods** to change the properties (with non-public setters) if necessary.
- **Do** return the entity object (`this`) from the setter methods.
### Aggregate Roots
## Aggregate Roots
#### Primary Keys
### Primary Keys
* **Do** always use a **Id** property for the aggregate root key.
* **Do not** use **composite keys** for aggregate roots.
* **Do** use **Guid** as the **primary key** of all aggregate roots.
#### Base Class
### Base Class
* **Do** inherit from the `AggregateRoot<TKey>` or one of the audited classes (`CreationAuditedAggregateRoot<TKey>`, `AuditedAggregateRoot<TKey>` or `FullAuditedAggregateRoot<TKey>`) based on requirements.
#### Aggregate Boundary
### Aggregate Boundary
* **Do** keep aggregates **as small as possible**. Most of the aggregates will only have primitive properties and will not have sub collections. Consider these as design decisions:
* **Performance** & **memory** cost of loading & saving aggregates (keep in mind that an aggregate is normally loaded & saved as a single unit). Larger aggregates will consume more CPU & memory.
* **Consistency** & **validity** boundary.
### Example
## Example
#### Aggregate Root
### Aggregate Root
````C#
public class Issue : FullAuditedAggregateRoot<Guid> //Using Guid as the key/identifier
@ -130,7 +134,7 @@ public class Issue : FullAuditedAggregateRoot<Guid> //Using Guid as the key/iden
}
````
#### The Entity
### Entity
````C#
public class IssueLabel : Entity
@ -151,11 +155,12 @@ public class IssueLabel : Entity
}
````
### References
## References
* Effective Aggregate Design by Vaughn Vernon
http://dddcommunity.org/library/vernon_2011
## See Also
## See Also
* [Video tutorial](https://abp.io/video-courses/essentials/entities)

18
docs/en/framework/architecture/best-practices/entity-framework-core-integration.md

@ -1,12 +1,16 @@
# Entity Framework Core Integration Best Practices
> See [Entity Framework Core Integration document](../../data/entity-framework-core) for the basics of the EF Core integration.
> This document offers best practices for implementing Entity Framework Core integration in your modules and applications.
>
> **Ensure you've read the [*Entity Framework Core Integration*](../../data/entity-framework-core/index.md) document first.**
## General
- **Do** define a separated `DbContext` interface and class for each module.
- **Do not** rely on lazy loading on the application development.
- **Do not** enable lazy loading for the `DbContext`.
### DbContext Interface
## DbContext Interface
- **Do** define an **interface** for the `DbContext` that inherits from `IEfCoreDbContext`.
- **Do** add a `ConnectionStringName` **attribute** to the `DbContext` interface.
@ -23,7 +27,7 @@ public interface IIdentityDbContext : IEfCoreDbContext
* **Do not** define `set;` for the properties in this interface.
### DbContext class
## DbContext class
* **Do** inherit the `DbContext` from the `AbpDbContext<TDbContext>` class.
* **Do** add a `ConnectionStringName` attribute to the `DbContext` class.
@ -46,7 +50,7 @@ public class IdentityDbContext : AbpDbContext<IdentityDbContext>, IIdentityDbCon
}
````
### Table Prefix and Schema
## Table Prefix and Schema
- **Do** add static `TablePrefix` and `Schema` **properties** to the `DbContext` class. Set default value from a constant. Example:
@ -58,7 +62,7 @@ public static string Schema { get; set; } = AbpIdentityConsts.DefaultDbSchema;
- **Do** always use a short `TablePrefix` value for a module to create **unique table names** in a shared database. `Abp` table prefix is reserved for ABP core modules.
- **Do** set `Schema` to `null` as default.
### Model Mapping
## Model Mapping
- **Do** explicitly **configure all entities** by overriding the `OnModelCreating` method of the `DbContext`. Example:
@ -100,7 +104,7 @@ public static class IdentityDbContextModelBuilderExtensions
* **Do** call `b.ConfigureByConvention();` for each entity mapping (as shown above).
### Repository Implementation
## Repository Implementation
- **Do** **inherit** the repository from the `EfCoreRepository<TDbContext, TEntity, TKey>` class and implement the corresponding repository interface. Example:
@ -168,7 +172,7 @@ public override async Task<IQueryable<IdentityUser>> WithDetailsAsync()
}
````
### Module Class
## Module Class
- **Do** define a module class for the Entity Framework Core integration package.
- **Do** add `DbContext` to the `IServiceCollection` using the `AddAbpDbContext<TDbContext>` method.

4
docs/en/framework/architecture/best-practices/module-architecture.md

@ -1,13 +1,13 @@
# Module Architecture Best Practices & Conventions
### Solution Structure
## Solution Structure
* **Do** create a separated Visual Studio solution for every module.
* **Do** name the solution as *CompanyName.ModuleName* (for core ABP modules, it's *Volo.Abp.ModuleName*).
* **Do** develop the module as layered, so it has several packages (projects) those are related to each other.
* Every package has its own module definition file and explicitly declares the dependencies for the depended packages/modules.
### Layers & Packages
## Layers & Packages
The following diagram shows the packages of a well-layered module and dependencies of those packages between them:

18
docs/en/framework/architecture/best-practices/mongodb-integration.md

@ -1,8 +1,14 @@
# MongoDB Integration
> This document offers best practices for implementing MongoDB integration in your modules and applications.
>
> **Ensure you've read the [*MongoDB Integration*](../../data/entity-framework-core/index.md) document first.**
## General
* Do define a separated `MongoDbContext` interface and class for each module.
### MongoDbContext Interface
## MongoDbContext Interface
- **Do** define an **interface** for the `MongoDbContext` that inherits from `IAbpMongoDbContext`.
- **Do** add a `ConnectionStringName` **attribute** to the `MongoDbContext` interface.
@ -17,7 +23,7 @@ public interface IAbpIdentityMongoDbContext : IAbpMongoDbContext
}
````
### MongoDbContext class
## MongoDbContext class
- **Do** inherit the `MongoDbContext` from the `AbpMongoDbContext` class.
- **Do** add a `ConnectionStringName` attribute to the `MongoDbContext` class.
@ -34,7 +40,7 @@ public class AbpIdentityMongoDbContext : AbpMongoDbContext, IAbpIdentityMongoDbC
}
```
### Collection Prefix
## Collection Prefix
- **Do** add static `CollectionPrefix` **property** to the `DbContext` class. Set default value from a constant. Example:
@ -46,7 +52,7 @@ Used the same constant defined for the EF Core integration table prefix in this
- **Do** always use a short `CollectionPrefix` value for a module to create **unique collection names** in a shared database. `Abp` collection prefix is reserved for ABP core modules.
### Collection Mapping
## Collection Mapping
- **Do** explicitly **configure all aggregate roots** by overriding the `CreateModel` method of the `MongoDbContext`. Example:
@ -83,7 +89,7 @@ public static class AbpIdentityMongoDbContextExtensions
}
```
### Repository Implementation
## Repository Implementation
- **Do** **inherit** the repository from the `MongoDbRepository<TMongoDbContext, TEntity, TKey>` class and implement the corresponding repository interface. Example:
@ -124,7 +130,7 @@ public async Task<IdentityUser> FindByNormalizedUserNameAsync(
* Using `IQueryable<TEntity>` makes the code as much as similar to the EF Core repository implementation and easy to write and read.
* **Do** implement data filtering if it is not possible to use the `GetMongoQueryable()` method.
### Module Class
## Module Class
- **Do** define a module class for the MongoDB integration package.
- **Do** add `MongoDbContext` to the `IServiceCollection` using the `AddMongoDbContext<TMongoDbContext>` method.

10
docs/en/framework/architecture/best-practices/repositories.md

@ -1,6 +1,10 @@
# Repository Best Practices & Conventions
### Repository Interfaces
> This document offers best practices for implementing Repository classes in your modules and applications based on Domain-Driven-Design principles.
>
> **Ensure you've read the [*Repositories*](../domain-driven-design/repositories.md) document first.**
## Repository Interfaces
* **Do** define repository interfaces in the **domain layer**.
* **Do** define a repository interface (like `IIdentityUserRepository`) and create its corresponding implementations for **each aggregate root**.
@ -30,7 +34,7 @@ public interface IIdentityUserRepository : IBasicRepository<IdentityUser, Guid>
* **Do** inherit the repository interface from `IBasicRepository<TEntity, TKey>` (as normally) or a lower-featured interface, like `IReadOnlyRepository<TEntity, TKey>` (if it's needed).
* **Do not** define repositories for entities those are **not aggregate roots**.
### Repository Methods
## Repository Methods
* **Do** define all repository methods as **asynchronous**.
* **Do** add an **optional** `cancellationToken` parameter to every method of the repository. Example:
@ -68,7 +72,7 @@ Task<List<IdentityUser>> GetListByNormalizedRoleNameAsync(
* **Avoid** to create projection classes for entities to get less property of an entity from the repository. Example: Avoid to create BasicUserView class to select a few properties needed for the use case needs. Instead, directly use the aggregate root class. However, there may be some exceptions for this rule, where:
* Performance is so critical for the use case and getting the whole aggregate root highly impacts the performance.
### See Also
## See Also
* [Entity Framework Core Integration](./entity-framework-core-integration.md)
* [MongoDB Integration](./mongodb-integration.md)

2
docs/en/framework/architecture/domain-driven-design/data-transfer-objects.md

@ -1,7 +1,5 @@
# Data Transfer Objects
## Introduction
**Data Transfer Objects** (DTO) are used to transfer data between the **Application Layer** and the **Presentation Layer** or other type of clients.
Typically, an [application service](./application-services.md) is called from the presentation layer (optionally) with a **DTO** as the parameter. It uses domain objects to **perform some specific business logic** and (optionally) returns a DTO back to the presentation layer. Thus, the presentation layer is completely **isolated** from domain layer.

2
docs/en/framework/architecture/domain-driven-design/domain-services.md

@ -1,7 +1,5 @@
# Domain Services
## Introduction
In a [Domain Driven Design](../domain-driven-design) (DDD) solution, the core business logic is generally implemented in aggregates ([entities](./entities.md)) and the Domain Services. Creating a Domain Service is especially needed when;
* You implement a core domain logic that depends on some services (like repositories or other external services).

44
docs/en/framework/fundamentals/caching.md

@ -1,14 +1,14 @@
# Distributed Caching
ABP extends the [ASP.NET Core distributed cache](https://docs.microsoft.com/en-us/aspnet/core/performance/caching/distributed).
ABP extends the [ASP.NET Core distributed cache](https://docs.microsoft.com/en-us/aspnet/core/performance/caching/distributed) to provide a more comfortable and easy-to-use cache service.
> **Default implementation of the `IDistributedCache` interface is` MemoryDistributedCache` which works in-memory.** See [ASP.NET Core's documentation](https://docs.microsoft.com/en-us/aspnet/core/performance/caching/distributed) to see how to switch to Redis or another cache provider. Also, see the [Redis Cache](./redis-cache.md) document if you want to use Redis as the distributed cache server.
> **Default implementation of the `IDistributedCache` interface is` MemoryDistributedCache` which works in-memory.** Memory cache is only useful if you are building a monolith application and you run a single instance of your application. For other cases, consider using a distributed cache server. See the ***[When to Use a Distributed Cache Server](../../kb/when-to-use-a-distributed-cache-server.md)*** document for more details.
## Installation
> This package is already installed by default with the [application startup template](../../solution-templates/layered-web-application). So, most of the time, you don't need to install it manually.
> This package is already installed by default in [startup templates](../../solution-templates/index.md). So, most of the time, you don't need to install it manually.
[Volo.Abp.Caching](https://www.nuget.org/packages/Volo.Abp.Caching) is the main package of the caching system. You can install it a project using the add-package command of the [ABP CLI](../../cli):
[Volo.Abp.Caching](https://www.nuget.org/packages/Volo.Abp.Caching) is the main package of the caching system. You can install it as a project using the add-package command of the [ABP CLI](../../cli):
```bash
abp add-package Volo.Abp.Caching
@ -24,10 +24,10 @@ ASP.NET Core defines the `IDistributedCache` interface to get/set the cache valu
* It works with **byte arrays** rather than .NET objects. So, you need to **serialize/deserialize** the objects you need to cache.
* It provides a **single key pool** for all cache items, so;
* You need to care about the keys to distinguish **different type of objects**.
* You need to care about the keys to distinguish **different types of objects**.
* You need to care about the cache items of **different tenants** in a [multi-tenant](../architecture/multi-tenancy) system.
> `IDistributedCache` is defined in the `Microsoft.Extensions.Caching.Abstractions` package. That means it is not only usable for ASP.NET Core applications, but also available to **any type of applications**.
> `IDistributedCache` is defined in the `Microsoft.Extensions.Caching.Abstractions` package. That means it is not only usable for ASP.NET Core applications but also available to **any type of applications**.
See [ASP.NET Core's distributed caching document](https://docs.microsoft.com/en-us/aspnet/core/performance/caching/distributed) for more information.
@ -37,12 +37,12 @@ ABP defines the generic `IDistributedCache<TCacheItem>` interface in the [Volo.A
`IDistributedCache<TCacheItem>` solves the difficulties explained above;
* It internally **serializes/deserializes** the cached objects. Uses **JSON** serialization by default, but can be overridden by replacing the `IDistributedCacheSerializer` service in the [dependency injection](./dependency-injection.md) system.
* It automatically adds a **cache name** prefix to the cache keys based on the object type stored in the cache. Default cache name is the full name of the cache item class (`CacheItem` postfix is removed if your cache item class ends with it). You can use the **`CacheName` attribute** on the cache item class to set the cache name.
* It internally **serializes/deserializes** the cached objects. It uses **JSON** serialization by default but can be overridden by replacing the `IDistributedCacheSerializer` service in the [dependency injection](./dependency-injection.md) system.
* It automatically adds a **cache name** prefix to the cache keys based on the object type stored in the cache. The default cache name is the full name of the cache item class (`CacheItem` postfix is removed if your cache item class ends with it). You can use the **`CacheName` attribute** on the cache item class to set the cache name.
* It automatically adds the **current tenant id** to the cache key to distinguish cache items for different tenants (if your application is [multi-tenant](../architecture/multi-tenancy)). Define `IgnoreMultiTenancy` attribute on the cache item class to disable this if you want to share the cached objects among all tenants in a multi-tenant application.
* Allows to define a **global cache key prefix** per application, so different applications can use their isolated key pools in a shared distributed cache server.
* Allows defining a **global cache key prefix** per application so different applications can use their isolated key pools in a shared distributed cache server.
* It **can tolerate errors** wherever possible and bypasses the cache. This is useful when you have temporary problems on the cache server.
* It has methods like `GetManyAsync` and `SetManyAsync` which significantly improve the performance on **batch operations**.
* It has methods like `GetManyAsync` and `SetManyAsync` which significantly improve the performance of **batch operations**.
**Example: Store Book names and prices in the cache**
@ -167,7 +167,7 @@ namespace MyProject
````
* This sample service uses the `GetOrAddAsync()` method to get a book item from the cache.
* Since cache explicitly implemented as using `Guid` as cache key, `Guid` value passed to `_cache_GetOrAddAsync()` method.
* Since the cache is explicitly implemented as using `Guid` as the cache key, the `Guid` value is passed to the `_cache_GetOrAddAsync()` method.
#### Complex Types as the Cache Key
@ -228,29 +228,29 @@ Configure<AbpDistributedCacheOptions>(options =>
* `HideErrors` (`bool`, default: `true`): Enables/disables hiding the errors on writing/reading values from the cache server.
* `KeyPrefix` (`string`, default: `null`): If your cache server is shared by multiple applications, you can set a prefix for the cache keys for your application. In this case, different applications can not overwrite each other's cache items.
* `GlobalCacheEntryOptions` (`DistributedCacheEntryOptions`): Used to set default distributed cache options (like `AbsoluteExpiration` and `SlidingExpiration`) used when you don't specify the options while saving cache items. Default value uses the `SlidingExpiration` as 20 minutes.
* `GlobalCacheEntryOptions` (`DistributedCacheEntryOptions`): Used to set default distributed cache options (like `AbsoluteExpiration` and `SlidingExpiration`) used when you don't specify the options while saving cache items. The default value uses the `SlidingExpiration` as 20 minutes.
## Error Handling
When you design a cache for your objects, you typically try to get the value from cache first. If not found in the cache, you query the object from the **original source**. It may be located in a **database** or may require to perform an HTTP call to a remote server.
When you design a cache for your objects, you typically try to get the value from the cache first. If not found in the cache, you query the object from the **original source**. It may be located in a **database** or may require an HTTP call to a remote server to be performed.
In most cases, you want to **tolerate the cache errors**; If you get error from the cache server you don't want to cancel the operation. Instead, you silently hide (and log) the error and **query from the original source**. This is what the ABP does by default.
In most cases, you want to **tolerate the cache errors**; If you get an error from the cache server, you don't want to cancel the operation. Instead, you silently hide (and log) the error and **query from the original source**. This is what the ABP does by default.
ABP's Distributed Cache [handle](./exception-handling.md), log and hide errors by default. There is an option to change this globally (see the options below).
In addition, all of the `IDistributedCache<TCacheItem>` (and `IDistributedCache<TCacheItem, TCacheKey>`) methods have an optional `hideErrors` parameter, which is `null` by default. The global value is used if this parameter left as `null`, otherwise you can decide to hide or throw the exceptions for individual method calls.
In addition, all of the `IDistributedCache<TCacheItem>` (and `IDistributedCache<TCacheItem, TCacheKey>`) methods have an optional `hideErrors` parameter, which is `null` by default. The global value is used if this parameter is left as `null`; otherwise, you can decide to hide or throw the exceptions for individual method calls.
## Batch Operations
ABP's distributed cache interfaces provide methods to perform batch methods those improves the performance when you want to batch operation multiple cache items in a single method call.
ABP's distributed cache interfaces provide methods to perform batch operations that improve performance when you want to batch operation multiple cache items in a single method call.
* `SetManyAsync` and `SetMany` methods can be used to set multiple values to the cache.
* `GetManyAsync` and `GetMany` methods can be used to retrieve multiple values from the cache.
* `GetOrAddManyAsync` and `GetOrAddMany` methods can be used to retrieve multiple values and set missing values from the cache
* `RefreshManyAsync` and `RefreshMany` methods can be used to resets the sliding expiration timeout of multiple values from the cache
* `RefreshManyAsync` and `RefreshMany` methods can be used to reset the sliding expiration timeout of multiple values from the cache
* `RemoveManyAsync` and `RemoveMany` methods can be used to remove multiple values from the cache
> These are not standard methods of the ASP.NET Core caching. So, some providers may not support them. They are supported by the [ABP Redis Cache integration package](./redis-cache.md). If the provider doesn't support, it fallbacks to `SetAsync` and `GetAsync` ... methods (called once for each item).
> These are not standard methods of the ASP.NET Core caching. So, some providers may not support them. They are supported by the [ABP Redis Cache integration package](./redis-cache.md). If the provider doesn't support it, it falls back to `SetAsync` and `GetAsync` ... methods (called once for each item).
## Caching Entities
@ -266,17 +266,17 @@ It's designed as read-only and automatically invalidates a cached entity if the
Distributed cache service provides an interesting feature. Assume that you've updated the price of a book in the database, then set the new price to the cache, so you can use the cached value later. What if you have an exception after setting the cache and you **rollback the transaction** that updates the price of the book? In this case, cache value will be incorrect.
`IDistributedCache<..>` methods gets an optional parameter, named `considerUow`, which is `false` by default. If you set it to `true`, then the changes you made for the cache are not actually applied to the real cache store, but associated with the current [unit of work](../architecture/domain-driven-design/unit-of-work.md). You get the value you set in the same unit of work, but the changes are applied **only if the current unit of work succeed**.
`IDistributedCache<..>` methods gets an optional parameter, named `considerUow`, which is `false` by default. If you set it to `true`, then the changes you made for the cache are not actually applied to the real cache store, but associated with the current [unit of work](../architecture/domain-driven-design/unit-of-work.md). You get the value you set in the same unit of work, but the changes are applied **only if the current unit of work succeeds**.
### IDistributedCacheSerializer
`IDistributedCacheSerializer` service is used to serialize and deserialize the cache items. Default implementation is the `Utf8JsonDistributedCacheSerializer` class that uses `IJsonSerializer` service to convert objects to [JSON](../../json-serialization.md) and vice verse. Then it uses UTC8 encoding to convert the JSON string to a byte array which is accepted by the distributed cache.
`IDistributedCacheSerializer` service is used to serialize and deserialize the cache items. The default implementation is the `Utf8JsonDistributedCacheSerializer` class that uses `IJsonSerializer` service to convert objects to [JSON](../../json-serialization.md) and vice verse. Then it uses UTC8 encoding to convert the JSON string to a byte array which is accepted by the distributed cache.
You can [replace](./dependency-injection.md) this service by your own implementation if you want to implement your own serialization logic.
You can [replace](./dependency-injection.md) this service with your own implementation if you want to implement your own serialization logic.
### IDistributedCacheKeyNormalizer
`IDistributedCacheKeyNormalizer` is implemented by the `DistributedCacheKeyNormalizer` class by default. It adds cache name, application cache prefix and current tenant id to the cache key. If you need a more advanced key normalization, you can [replace](./dependency-injection.md) this service by your own implementation.
`IDistributedCacheKeyNormalizer` is implemented by the `DistributedCacheKeyNormalizer` class by default. It adds the cache name, application cache prefix and current tenant ID to the cache key. If you need a more advanced key normalization, you can [replace](./dependency-injection.md) this service with your own implementation.
## See Also

2
docs/en/framework/fundamentals/dependency-injection.md

@ -498,6 +498,8 @@ Use `ICachedServiceProvider` (instead of `ITransientCachedServiceProvider`) unle
> ABP also provides the `IAbpLazyServiceProvider` service. It does exists for backward compatibility and works exactly same with the `ITransientCachedServiceProvider` service. So, use the `ITransientCachedServiceProvider` since the `IAbpLazyServiceProvider` might be removed in future ABP versions.
> Another advantage of using `ICachedServiceProvider` is that, during an HTTP request, if a service's constructor requires injecting many dependencies, it can negatively impact performance, as the injected services may not all be used by the current request. By resolving services on-demand, performance degradation can be effectively avoided.
## Advanced Features
### IServiceCollection.OnRegistered Event

18
docs/en/framework/infrastructure/audit-logging.md

@ -106,6 +106,24 @@ Configure<AbpAspNetCoreAuditingOptions>(options =>
`IgnoredUrls` is the only option. It is a list of ignored URLs prefixes. In the preceding example, all URLs starting with `/products` will be ignored for audit logging.
## AbpAspNetCoreAuditingUrlOptions
`AbpAspNetCoreAuditingUrlOptions` is the [options object](../fundamentals/options.md) to configure audit logging in the ASP.NET Core layer. You can configure it in the `ConfigureServices` method of your [module](../architecture/modularity/basics.md):
````csharp
Configure<AbpAspNetCoreAuditingUrlOptions>(options =>
{
options.IncludeQuery = true;
});
````
Here, a list of the options you can configure:
* `IncludeSchema` (default: `false`): If you set to true, it will include the schema in the URL.
* `IncludeHost` (default: `false`): If you set to true, it will include the host in the URL.
* `IncludeQuery` (default: `false`): If you set to true, it will include the query string in the URL.
## Enabling/Disabling Audit Logging for Services
### Enable/Disable for Controllers & Actions

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

@ -221,6 +221,13 @@ public class MyModule : AbpModule
}
````
* `JobPollPeriod` is used to determine the interval between two job polling operations. Default is 5000 ms (5 seconds).
* `MaxJobFetchCount` is used to determine the maximum job count to fetch in a single polling operation. Default is 1000.
* `DefaultFirstWaitDuration` is used to determine the duration to wait before the first retry. Default is 60 seconds.
* `DefaultTimeout` is used to determine the timeout duration for a job. Default is 172800 seconds (2 days).
* `DefaultWaitFactor` is used to determine the factor to increase the wait duration between retries. Default is 2.0.
* `DistributedLockName` is used to determine the distributed lock name to use. Default is `AbpBackgroundJobWorker`.
### Data Store
The default background job manager needs a data store to save and read jobs. It defines `IBackgroundJobStore` as an abstraction to store the jobs.

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

@ -161,8 +161,16 @@ namespace FeaturesDemo
{
var myGroup = context.AddGroup("MyApp");
myGroup.AddFeature("MyApp.PdfReporting", defaultValue: "false");
myGroup.AddFeature("MyApp.MaxProductCount", defaultValue: "10");
myGroup.AddFeature(
"MyApp.PdfReporting",
defaultValue: "false"
);
myGroup.AddFeature(
"MyApp.MaxProductCount",
defaultValue: "10",
valueType: new FreeTextStringValueType(new NumericValueValidator())
);
}
}
}

2
docs/en/framework/ui/angular/quick-start.md

@ -6,7 +6,7 @@
Please follow the steps below to prepare your development environment for Angular.
1. **Install Node.js:** Please visit [Node.js downloads page](https://nodejs.org/en/download/) and download proper Node.js `v18.19+` installer for your OS. An alternative is to install [NVM](https://github.com/nvm-sh/nvm) and use it to have multiple versions of Node.js in your operating system.
1. **Install Node.js:** Please visit [Node.js downloads page](https://nodejs.org/en/download/) and download proper Node.js `v20.11+` installer for your OS. An alternative is to install [NVM](https://github.com/nvm-sh/nvm) and use it to have multiple versions of Node.js in your operating system.
2. **[Optional] Install Yarn:** You may install Yarn v1.22+ (not v2) following the instructions on [the installation page](https://classic.yarnpkg.com/en/docs/install). Yarn v1 delivers an arguably better developer experience compared to npm v10 and below. You may skip this step and work with npm, which is built-in in Node.js, instead.
3. **[Optional] Install VS Code:** [VS Code](https://code.visualstudio.com/) is a free, open-source IDE which works seamlessly with TypeScript. Although you can use any IDE including Visual Studio or Rider, VS Code will most likely deliver the best developer experience when it comes to Angular projects. ABP project templates even contain plugin recommendations for VS Code users, which VS Code will ask you to install when you open the Angular project folder. Here is a list of recommended extensions:
- [Angular Language Service](https://marketplace.visualstudio.com/items?itemName=angular.ng-template)

109
docs/en/framework/ui/blazor/global-scripts-styles.md

@ -1,83 +1,72 @@
# Blazor UI: Managing Global Scripts & Styles
Some modules may require additional styles or scripts that need to be referenced in **index.html** file. It's not easy to find and update these types of references in Blazor apps. ABP offers a simple, powerful, and modular way to manage global style and scripts in Blazor apps.
You can add your JavaScript and CSS files from your modules or applications to the Blazor global assets system. All the JavaScript and CSS files will be added to the `global.js` and `global.css` files. You can access these files via the following URL in a Blazor WASM project:
To update script & style references without worrying about dependencies, ordering, etc in a project, you can use the [bundle command](../../../cli#bundle).
- https://localhost/global.js
- https://localhost/global.css
You can also add custom styles and scripts and let ABP manage them for you. In your Blazor project, you can create a class implementing `IBundleContributor` interface.
## Add JavaScript and CSS to the global assets system in the module
`IBundleContributor` interface contains two methods.
Your module project solution will have two related Blazor projects:
* `AddScripts(...)`
* `AddStyles(...)`
* `MyModule.Blazor`:This project includes the JavaScript/CSS files required for your Blazor components. The `MyApp.Blazor.Client (Blazor WASM)` project will reference this project.
* `MyModule.Blazor.WebAssembly.Bundling`:This project is used to add your JavaScript/CSS files to the Blazor global resources. The `MyModule.Blazor (ASP.NET Core)` project will reference this project.
Both methods get `BundleContext` as a parameter. You can add scripts and styles to the `BundleContext` and run [bundle command](../../../cli#bundle). Bundle command detects custom styles and scripts with module dependencies and updates `index.html` file.
You need to define JavaScript and CSS contributor classes in the `MyModule.Blazor.WebAssembly.Bundling` project to add the files to the global assets system.
## Example Usage
```csharp
namespace MyProject.Blazor
> Please use `BlazorWebAssemblyStandardBundles.Scripts.Global` and `BlazorWebAssemblyStandardBundles.Styles.Global` for the bundle name.
```cs
public class MyModuleBundleScriptContributor : BundleContributor
{
public class MyProjectBundleContributor : IBundleContributor
public override void ConfigureBundle(BundleConfigurationContext context)
{
public void AddScripts(BundleContext context)
{
context.Add("site.js");
}
public void AddStyles(BundleContext context)
{
context.Add("main.css");
context.Add("custom-styles.css");
}
context.Files.AddIfNotContains("_content/MyModule.Blazor/libs/myscript.js");
}
}
```
> There is a BundleContributor class implementing `IBundleContributor` interface coming by default with the startup templates. So, most of the time, you don't need to add it manually.
## Bundling And Minification
`abp bundle` command offers bundling and minification support for client-side resources(JavaScript and CSS files). `abp bundle` command reads the `appsettings.json` file inside the Blazor project and bundles the resources according to the configuration. You can find the bundle configurations inside `AbpCli.Bundle` element.
Here are the options that you can control inside the `appsettings.json` file.
`Mode`: Bundling and minification mode. Possible values are
* `BundleAndMinify`: Bundle all the files into a single file and minify the content.
* `Bundle`: Bundle all files into a single file, but not minify.
* `None`: Add files individually, do not bundle.
`Name`: Bundle file name. Default value is `global`.
`Parameters`: You can define additional key/value pair parameters inside this section. `abp bundle` command automatically sends these parameters to the bundle contributors, and you can check these parameters inside the bundle contributor, take some actions according to these values.
Let's say that you want to exclude some resources from the bundle and control this action using the bundle parameters. You can add a parameter to the bundle section like below.
```json
"AbpCli": {
"Bundle": {
"Mode": "BundleAndMinify", /* Options: None, Bundle, BundleAndMinify */
"Name": "global",
"Parameters": {
"ExcludeThemeFromBundle":"true"
}
}
}
```
You can check this parameter and take action like below.
```csharp
public class MyProjectNameBundleContributor : IBundleContributor
```cs
public class MyModuleBundleStyleContributor : BundleContributor
{
public void AddScripts(BundleContext context)
public override void ConfigureBundle(BundleConfigurationContext context)
{
context.Files.AddIfNotContains("_content/MyModule.Blazor/libs/mystyle.css");
}
}
```
public void AddStyles(BundleContext context)
```cs
[DependsOn(
typeof(AbpAspNetCoreComponentsWebAssemblyThemingBundlingModule)
)]
public class MyBlazorWebAssemblyBundlingModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
var excludeThemeFromBundle = bool.Parse(context.Parameters.GetValueOrDefault("ExcludeThemeFromBundle"));
context.Add("mytheme.css", excludeFromBundle: excludeThemeFromBundle);
context.Add("main.css");
Configure<AbpBundlingOptions>(options =>
{
// Add script bundle
options.ScriptBundles.Get(BlazorWebAssemblyStandardBundles.Scripts.Global)
.AddContributors(typeof(MyModuleBundleScriptContributor));
// Add style bundle
options.StyleBundles.Get(BlazorWebAssemblyStandardBundles.Styles.Global)
.AddContributors(typeof(MyModuleBundleStyleContributor));
});
}
}
```
## Add JavaScript and CSS to the global assets system in the application
This is similar to the module. You need to define JavaScript and CSS contributor classes in the `MyApp.Blazor.Client` project to add the files to the global assets system.
## AbpBundlingGlobalAssetsOptions
You can configure the JavaScript and CSS file names in the `GlobalAssets` property of the `AbpBundlingOptions` class. The default values are `global.js` and `global.css`.
## Reference
- [ASP.NET Core MVC Bundling & Minification](../mvc-razor-pages/bundling-minification#bundle-contributorsg)
- [ABP Global Assets - New way to bundle JavaScript/CSS files in Blazor WebAssembly app](https://github.com/abpframework/abp/blob/dev/docs/en/Community-Articles/2024-11-25-Global-Assets/POST.md)

3
docs/en/framework/ui/maui/index.md

@ -40,6 +40,9 @@ Open a command line terminal and run the `adb reverse` command to expose a port
> You should replace "44305" with the real port.
> You should run the command after starting the emulator.
> If you don't have a separate installation of Android Debug Bridge, you can open it from **Visual Studio** by following toolbar menu `Tools` > `Android` > `Android Adb Command Prompt`. Android emulator has to be running for this operation.
### iOS
The iOS simulator uses the host machine network. Therefore, applications running in the simulator can connect to web services running on your local machine via the machines IP address or via the localhost hostname. For example, given a local secure web service that exposes a GET operation via the /api/todoitems/ relative URI, an application running on the iOS simulator can consume the operation by sending a GET request to https://localhost:<port>/api/todoitems/.

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

@ -41,7 +41,7 @@ After depending on a NPM package, all you should do is to run the **yarn** comma
yarn
```
Alternatively, you can use `npm install` but [Yarn](https://classic.yarnpkg.com/) is suggested as mentioned before.
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

6
docs/en/framework/ui/mvc-razor-pages/tag-helpers/dynamic-forms.md

@ -23,7 +23,7 @@ public class DynamicFormsModel : PageModel
new SelectListItem { Value = "CA", Text = "Canada"},
new SelectListItem { Value = "US", Text = "USA"},
new SelectListItem { Value = "UK", Text = "United Kingdom"},
new SelectListItem { Value = "RU", Text = "Russia"}
new SelectListItem { Value = "RU", Text = "Turkey"}
};
public void OnGet()
@ -217,7 +217,7 @@ public class DynamicFormsModel : PageModel
new SelectListItem { Value = "CA", Text = "Canada"},
new SelectListItem { Value = "US", Text = "USA"},
new SelectListItem { Value = "UK", Text = "United Kingdom"},
new SelectListItem { Value = "RU", Text = "Russia"}
new SelectListItem { Value = "RU", Text = "Turkey"}
};
public void OnGet()
@ -278,4 +278,4 @@ public string Name { get; set; }
## See Also
* [Form Elements](form-elements.md)
* [Form Elements](form-elements.md)

2
docs/en/framework/ui/react-native/index.md

@ -17,7 +17,7 @@ ABP platform provide basic [React Native](https://reactnative.dev/) startup temp
Please follow the steps below to prepare your development environment for React Native.
1. **Install Node.js:** Please visit [Node.js downloads page](https://nodejs.org/en/download/) and download proper Node.js v16 or v18 installer for your OS. An alternative is to install [NVM](https://github.com/nvm-sh/nvm) and use it to have multiple versions of Node.js in your operating system.
1. **Install Node.js:** Please visit [Node.js downloads page](https://nodejs.org/en/download/) and download proper Node.js v20.11+ installer for your OS. An alternative is to install [NVM](https://github.com/nvm-sh/nvm) and use it to have multiple versions of Node.js in your operating system.
2. **[Optional] Install Yarn:** You may install Yarn v1 (not v2) following the instructions on [the installation page](https://classic.yarnpkg.com/en/docs/install). Yarn v1 delivers an arguably better developer experience compared to npm v6 and below. You may skip this step and work with npm, which is built-in in Node.js, instead.
3. **[Optional] Install VS Code:** [VS Code](https://code.visualstudio.com/) is a free, open-source IDE which works seamlessly with TypeScript. Although you can use any IDE including Visual Studio or Rider, VS Code will most likely deliver the best developer experience when it comes to React Native projects.
4. **Install an Emulator:** React Native applications need an Android emulator or an iOS simulator to run on your OS. See the [Android Studio Emulator](https://docs.expo.io/workflow/android-simulator/) or [iOS Simulator](https://docs.expo.io/workflow/ios-simulator/) on expo.io documentation to learn how to set up an emulator.

BIN
docs/en/get-started/images/abp-studio-microservice-solution-runner-docker-dependencies.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.5 KiB

BIN
docs/en/get-started/images/abp-studio-microservice-solution-runner-enable-watch-1.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

BIN
docs/en/get-started/images/abp-studio-microservice-solution-runner-enable-watch-2.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

BIN
docs/en/get-started/images/abp-studio-microservice-solution-runner-enable-watch.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 86 KiB

BIN
docs/en/get-started/images/abp-studio-no-layers-new-solution-dialog-database-configurations-efcore-0.9.13.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

BIN
docs/en/get-started/images/abp-studio-no-layers-new-solution-dialog-database-configurations-mongo-0.9.13.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

BIN
docs/en/get-started/images/abp-studio-no-layers-new-solution-dialog-database-provider-efcore-0.9.13.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 75 KiB

BIN
docs/en/get-started/images/abp-studio-no-layers-new-solution-dialog-database-provider-mongo-0.9.13.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 117 KiB

BIN
docs/en/get-started/images/abp-studio-nolayers-new-solution-dialog-ui-theme-0.9.13.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

2
docs/en/get-started/index.md

@ -5,7 +5,7 @@ Great that you've decided to create a new application with ABP. ABP provides mul
Please select one of the following documents best fits for your application:
- **[Single-Layer Solution](single-layer-web-application.md)**: Creates a single-project solution. Recommended for building an application with a **simpler and easy to understand** architecture.
- **[Layered Solution](layered-web-application.md)**: A fully layered (multiple projects) solution based on [Domain Driven Design](../framework/architecture/domain-driven-design) practices. Recommended for long-term projects that need a **maintainable and extensible** codebase.
- **[Application (Layered)](layered-web-application.md)**: A fully layered (multiple projects) solution based on [Domain Driven Design](../framework/architecture/domain-driven-design) practices. Recommended for long-term projects that need a **maintainable and extensible** codebase.
- **[Microservice Solution](microservice.md)**: A **distributed solution** to build **microservice systems**. It includes pre-built services, API gateways, web and mobile applications, Kubernetes and Helm configuration, and everything you need to start your large-scale microservice solution.
- **Others**
- [Empty ASP.NET Core Application](empty-aspnet-core-application.md)

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

@ -13,31 +13,15 @@ In this quick start guide, you will learn how to create and run a layered (and p
## Setup your development environment
First things first! Let's setup your development environment before creating the first project.
First things first! Let's setup your development environment before creating the first project. The following tools should be installed on your development machine:
### Pre-requirements
* [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" }}
* [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){{ end }}
* [Docker Desktop](https://www.docker.com/products/docker-desktop/)
The following tools should be installed on your development machine:
* [Visual Studio 2022](https://visualstudio.microsoft.com/vs/) (v17.3+) for Windows / [Visual Studio for Mac](https://visualstudio.microsoft.com/vs/mac/). <sup id="a-editor">[1](#f-editor)</sup>
* [.NET 8.0+](https://dotnet.microsoft.com/en-us/download/dotnet)
{{ if UI != "Blazor" }}
* [Node v18.19+](https://nodejs.org/)
* [Yarn v1.22+ (not v2)](https://classic.yarnpkg.com/en/docs/install) <sup id="a-yarn">[2](#f-yarn)</sup> or npm v10+ (already installed with Node)
{{ end }}
{{ if Tiered == "Yes" }}
* [Redis](https://redis.io/) (as the [distributed cache](../framework/fundamentals/caching.md)).
{{ else }}
* [Redis](https://redis.io/) (as the [distributed cache](../framework/fundamentals/caching.md)) is required if you select the Public website option.
{{ end }}
<sup id="f-editor"><b>1</b></sup> _You can use another editor instead of Visual Studio as long as it supports .NET Core and ASP.NET Core._ <sup>[↩](#a-editor)</sup>
{{ if UI != "Blazor" }}
<sup id="f-yarn"><b>2</b></sup> _Yarn v2 works differently and is not supported._ <sup>[↩](#a-yarn)</sup>
{{ end }}
> Check the [Pre-requirements document](pre-requirements.md) for more detailed information about these tools.
## Creating a New Solution
@ -147,7 +131,7 @@ In the Solution Runner section (on the left side) you can see all the runnable a
You can run all the applications or start them one by one. To start an application, either click the *Play* icon near to the application or right-click and select the *Run* -> *Start* context menu item.
> For the first run, you'll need to build the application. You can achieve this by selecting *Run* -> *Build & Start* from the context menu.
> ABP Studio builds the application by default. So, you don't need to manually build the application before running it.
You can start the following application(s):
@ -229,7 +213,7 @@ You can start the following application(s):
{{ else }}
- `Acme.BookStore.Web`
{{ end }}
Before starting the mobile application, ensure that you configure it for [react-native](../framework/ui/react-native) or [MAUI](../framework/ui/maui).
![mobile-sample](images/abp-studio-mobile-sample.gif)

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

@ -4,6 +4,21 @@
In this quick start guide, you will learn how to create and run a microservice solution using [ABP Studio](../studio/index.md).
## Setup your development environment
First things first! Let's setup your development environment before creating the first project. The following tools should be installed on your development machine:
* [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)
* [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)
* [Docker Desktop (with Kubernetes enabled)](https://www.docker.com/products/docker-desktop/)
* [Helm](https://helm.sh/docs/intro/install/)
* [NGINX Ingress Controller](https://kubernetes.github.io/ingress-nginx/deploy/)
* [mkcert](https://github.com/FiloSottile/mkcert#installation)
> Check the [Pre-requirements document](pre-requirements.md) for more detailed information about these tools.
## 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.
@ -73,11 +88,11 @@ Click the Next button to see *Additional Options* selection:
If you unchecked the *Kubernetes Configuration* option, the solution will not include the Kubernetes configuration files which include the 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 the test projects in the solution.
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-microservice-solution](images/abp-studio-created-new-microservice-solution.png)
You can explore the solution, but you need to wait for background tasks to be completed before running any application in the solution (it can take up to a few minutes to set up all).
You can explore the solution, but you need to **wait for background tasks to be completed** before running any application in the solution (it can take up to a few minutes to set up all).
> The solution structure can be different in your case based on the options you've selected.
@ -123,28 +138,22 @@ In the *Solution Runner* section (on the left side) you can see all the runnable
![abp-studio-microservice-solution-runner-applications](images/abp-studio-microservice-solution-runner-applications.png)
> All the leaf items in the *Solution Runner* is called as an *Application* as they are executable applications.
> For a faster start process, first start the *Docker-Dependencies*, then you can start all applications.
> A leaf item in the *Solution Runner* is called as an *Application* as it is an executable application.
As shown in the figure above, the executable applications are grouped into folders like `apps`, `gateways`, `infrastructure`, and `services`. You can start/stop them all, a group (folder) of them, or one by one.
Before running the applications, it is good to be sure that all applications are built. To do that, right-click the root item in the *Solution Runner* and select *Build* -> *Build All* action.
![abp-studio-microservice-solution-runner-build-all](images/abp-studio-microservice-solution-runner-build-all.png)
> *Solution Runner* doesn't build an application before running it. That provides a great performance gain because most of the time you will work on one or a few services and you don't need to build all of the other applications in every run. However, if you want to build before running, you can right-click an item in the *Solution Runner* tree and select *Run* -> *Build & Start* command.
It will take some time to build all. Once all is done, you can start the system.
Before running the applications, you can run the all application by right-clicking the root item in the *Solution Runner* and select *Build* -> *Build All* action. However, you don't need to do that, because ABP Studio builds the applications before running them by default.
You can click the *Play* button on the root item in Solution Runner to start all the applications. Or you can start `Docker-Dependencies` first, so the database and other infrastructure services get ready before the other applications:
> If you want to change this behavior, and don't want ABP Studio to build before running the applications, you can click the *Manage start actions* button in the *Solution Runner*, which you can see from the root item or per folder.
![abp-studio-microservice-solution-runner-docker-dependencies](images/abp-studio-microservice-solution-runner-docker-dependencies.png)
You can click the *Play* button on the root item in *Solution Runner* to start all the applications.
> **About the Docker Containers**
>
> Docker will fetch the docker images before starting the containers in your first run (if they were not fetched before) and that process may take a few minutes depending on your internet connection speed. So, please wait for it to completely start. If the process takes more time than you expect, you can right-click on `Docker-Dependencies` and select the *Logs* command to see what's happening.
Once `Docker-Dependencies` is ready, you can click the *Play* button on the root item in Solution Runner to start all the applications.
> **About Failing Services on Startup**
>
> Some applications/services may fail on the first run. That may be because of service and database dependencies were not satisfied and an error occurs on the application startup. ABP Studio automatically restarts failing services until it is successfully started. Being completely ready for such a distributed solution may take a while, but it will be eventually started.
Once all the applications are ready, you can right-click the `Web` application and select the *Browse* command:
@ -175,9 +184,11 @@ Once you run the `IdentityService` in Visual Studio, it will be completely integ
As an alternative approach, especially if you don't need to debug your service, you can enable the watching feature of ABP Studio to automatically re-build and re-start when there is change in your application/service.
To enable watching, right-click the application/service you want to watch, select the *Run* -> *Enable Watch* command as shown in the following figure:
To enable watching, right-click the application/service you want to watch, select the *Properties* -> *Watch changes while running* option as shown in the following figure:
![abp-studio-microservice-solution-runner-enable-watch-1](images/abp-studio-microservice-solution-runner-enable-watch-1.png)
![abp-studio-microservice-solution-runner-enable-watch](images/abp-studio-microservice-solution-runner-enable-watch.png)
![abp-studio-microservice-solution-runner-enable-watch-2](images/abp-studio-microservice-solution-runner-enable-watch-2.png)
Now, you can make your development on the `IdentityService`. Whenever you save a code file, it is automatically rebuilt and restarted by ABP Studio, so any change will be effective on the running solution in a few seconds.
@ -185,8 +196,6 @@ When you enable watch for an application an *eye* icon is added near to the appl
![abp-studio-microservice-solution-runner-watch-enabled-icon](images/abp-studio-microservice-solution-runner-watch-enabled-icon.png)
You can disable watching by right-clicking an application and selecting *Run* -> *Disable Watch* command.
## Kubernetes Integration: Working with Helm Charts
Solution Runner is a great way to locally run all the applications and services of your solution. However, there are some drawbacks:
@ -222,6 +231,8 @@ Once the solution is ready in Kubernetes, you can open a browser and visit the f
![abp-studio-microservice-web-application-home-page](images/abp-studio-microservice-web-application-home-page.png)
> We could use `cloudcrm-local-web` as the host name since ABP Studio has added an entry to the host file for us.
Click the *Login* link in the application UI, it will redirect you to the *Authentication Server* application, enter `admin` as username and `1q2w3E*` as password to login to the application.
> The services run independently from each other and perform some initial data seed logic on their startups. So, they may fail in their first run. In that case, Kubernetes will re-start them. So, it may initially get some time to make the solution fully ready and working.
@ -248,11 +259,11 @@ Clicking the *Connect* button will start a process that establishes the VPN conn
![abp-studio-microservice-kubernetes-services](images/abp-studio-microservice-kubernetes-services.png)
Now, you can access all the services inside the Kubernetes cluster, including the services those are not exposes out of the cluster. You can use the service name as DNS. For example, you can directly visit `http://cloudcrm-local-identity` in your Browser. You can also right-click to a service or application and select the Browse command to open it's UI in the built-in browser of ABP Studio:
Now, you can access all the services inside the Kubernetes cluster, including the services those are not exposed out of the cluster. You can use the service name as DNS. For example, you can directly visit `http://cloudcrm-local-identity` in your Browser. You can also right-click to a service or application and select the Browse command to open it's UI in the built-in browser of ABP Studio:
![abp-studio-microservice-kubernetes-services-browse](images/abp-studio-microservice-kubernetes-services-browse.png)
You can even use the other services (e.g. SQL Server or RabbitMQ) from your local computer (even if they were not exposed out of cluster) with their service names. `sa` password for the SQL server is `myPassw@rd` by default, you can use your SQL Server management studio to connect to it and see the databases:
You can even use the other services (e.g. SQL Server or RabbitMQ) from your local computer (even if they were not exposed out of cluster) with their service names. `sa` password for the SQL server is `myPassw@rd` by default, you can use your SQL Server management studio to connect to it and see the databases (*Server name* is `cloudcrm-local-sqlserver`):
![abp-studio-microservice-sql-server-connection](images/abp-studio-microservice-sql-server-connection.png)
@ -266,6 +277,8 @@ When you connect to Kubernetes, ABP Studio automatically connects to the applica
In this way, you can easily track HTTP requests, distributed events, exceptions, logs and other details of your applications.
> If you want to browse a web application in the integrated browser of ABP Studio, right-click to a service in the *Kubernetes* tab of the *Kubernetes* panel and select the *Browse* command.
## Kubernetes Integration: Intercepting Services
The next step is to intercept a service to forward the traffic (coming to that service) to your local computer, so you can run the same service in your local computer to test, debug and develop it. This is the way of connecting two environments (your local machine and the Kubernetes cluster) to develop your services integrated to Kubernetes.
@ -306,3 +319,7 @@ To re-deploy a service to Kubernetes, right-click the service and select *Comman
![abp-studio-microservice-kubernetes-redeploy](images/abp-studio-microservice-kubernetes-redeploy.png)
ABP Studio will re-build the Docker image and re-install it using the related Helm chart.
## See Also
* [Microservice Development Tutorial](../tutorials/microservice/index.md)

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

@ -0,0 +1,107 @@
# Prerequisites for Developing ABP Applications
This document will guide you through preparing your development environment for ABP based application development.
## Notices
The prerequisites mentioned in this document are not necessary for every project type;
* You don't need to install the EF Core CLI if your application uses MongoDB instead of EF Core.
* You don't need to install Helm, NGINX Ingress, or mkcert if you are developing a non-microservice application.
`README.MD` files in new solutions contain specific requirements for your solution. Please refer to the `README.MD` file of your solution.
## IDE
You need to use an IDE that supports .NET development. The following IDEs are the most popular ones for .NET development.
### Visual Studio
Visual Studio is Microsoft's IDE and is the de facto tool for developing .NET projects. You can download Visual Studio from the [Visual Studio official website](https://visualstudio.microsoft.com/). It also has a **free Community edition** which is more than enough for ABP projects.
### Visual Studio Code
Visual Studio Code is a **free and cross-platform** lightweight code editor that supports .NET development. You can [download from here](https://code.visualstudio.com/download).
### JetBrains Rider
[JetBrains Rider](https://www.jetbrains.com/rider/download) is a cross-platform IDE by [JetBrains](https://www.jetbrains.com/) that supports .NET development. It is **[free for non-commercial use](https://blog.jetbrains.com/blog/2024/10/24/webstorm-and-rider-are-now-free-for-non-commercial-use/)**.
## .NET SDK
ABP is based on NET, so you need to install the .NET SDK. You can download the .NET SDK from the [.NET official website](https://dotnet.microsoft.com/en-us/download/dotnet/9.0).
> Installing Visual Studio or JetBrains Rider may automatically install the .NET SDK.
### EF Core CLI
If you are using [Entity Framework Core](https://learn.microsoft.com/en-us/ef/core/) as your database access provider, you need to install the [EF Core CLI](https://learn.microsoft.com/en-us/ef/core/cli/dotnet). You can install it by running the following command:
```bash
dotnet tool install --global dotnet-ef
```
If you have already installed the `EF Core CLI`, you can update it by running the following command:
```bash
dotnet tool update --global dotnet-ef
```
## Node.js and Yarn
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+.
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+).
To install Yarn using npm, run the following command:
```bash
npm install --global yarn
```
## Docker Engine or Docker Desktop
ABP's [Layered Solution](../solution-templates/layered-web-application/index.md) and [Microservice Solution](../solution-templates/microservice/index.md) use Docker to run infrastructure services (e.g. SQL Server, Redis, RabbitMQ) required by your application. You can install Docker Engine or Docker Desktop (recommended) on Windows, macOS and Linux.
* [Docker Desktop](https://www.docker.com/products/docker-desktop/) (recommended)
* [Docker Engine](https://docs.docker.com/engine/install/)
### Is Docker Engine or Docker Desktop Free?
Docker Engine is an open-source and free containerization technology for building and containerizing your applications. [`Docker Engine` follows the Apache License 2.0](https://docs.docker.com/engine/#licensing).
Docker Desktop is free [for small businesses (fewer than 250 employees and less than $10 million in annual revenue), personal use, education, and non-commercial open-source projects](https://docs.docker.com/subscription/desktop-license/).
## PowerShell
ABP startup solution templates and tools use some PowerShell scripts (`*.ps1`) to perform certain tasks. You can refer to the [PowerShell documentation](https://learn.microsoft.com/en-us/powershell/scripting/install/installing-powershell) for guidance on how to install PowerShell on Windows, macOS, and Linux.
* [Install PowerShell on Windows](https://learn.microsoft.com/en-us/powershell/scripting/install/installing-powershell-on-windows)
* [Install PowerShell on macOS](https://learn.microsoft.com/en-us/powershell/scripting/install/installing-powershell-on-macos)
* [Install PowerShell on Linux](https://learn.microsoft.com/en-us/powershell/scripting/install/installing-powershell-on-linux)
## MicroService Solution
The following tools are only required to develop ABP's [microservice solution](../solution-templates/microservice/index.md)
### Helm
[Helm](https://helm.sh/) is a package manager for Kubernetes. You can install Helm by following the [Helm installation guide](https://helm.sh/docs/intro/install/).
See [Helm Deployment on Local Kubernetes Cluster](../solution-templates/microservice/helm-charts-and-kubernetes.md) for more information.
### NGINX Ingress or NGINX Ingress using Helm
[NGINX Ingress](https://kubernetes.github.io/ingress-nginx/deploy/) is an Ingress controller for Kubernetes. You can install NGINX Ingress by following the [NGINX Ingress installation guide](https://kubernetes.github.io/ingress-nginx/deploy/).
If you are using Helm, you can install NGINX Ingress using the following commands:
```cs
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm repo update
helm upgrade --install --version=4.0.19 ingress-nginx ingress-nginx/ingress-nginx
```
### mkcert
Use mkcert to generate trusted certificates for local development. You can install mkcert by following the [official mkcert installation guide](https://github.com/FiloSottile/mkcert#installation).

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

@ -12,31 +12,14 @@ In this quick start guide, you will learn how to create and run a single layer w
## Setup your development environment
First things first! Let's setup your development environment before creating the first project.
First things first! Let's setup your development environment before creating the first project. The following tools should be installed on your development machine:
### Pre-requirements
* [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" }}
* [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){{ end }}
The following tools should be installed on your development machine:
* [Visual Studio 2022](https://visualstudio.microsoft.com/vs/) (v17.3+) for Windows / [Visual Studio for Mac](https://visualstudio.microsoft.com/vs/mac/). <sup id="a-editor">[1](#f-editor)</sup>
* [.NET 8.0+](https://dotnet.microsoft.com/en-us/download/dotnet)
{{ if UI != "Blazor" }}
* [Node v18.19+](https://nodejs.org/)
* [Yarn v1.22+ (not v2)](https://classic.yarnpkg.com/en/docs/install) <sup id="a-yarn">[2](#f-yarn)</sup> or npm v10+ (already installed with Node)
{{ end }}
{{ if Tiered == "Yes" }}
* [Redis](https://redis.io/) (as the [distributed cache](../framework/fundamentals/caching.md)).
{{ else }}
* [Redis](https://redis.io/) (as the [distributed cache](../framework/fundamentals/caching.md)) is required if you select the Public website option.
{{ end }}
<sup id="f-editor"><b>1</b></sup> _You can use another editor instead of Visual Studio as long as it supports .NET Core and ASP.NET Core._ <sup>[↩](#a-editor)</sup>
{{ if UI != "Blazor" }}
<sup id="f-yarn"><b>2</b></sup> _Yarn v2 works differently and is not supported._ <sup>[↩](#a-yarn)</sup>
{{ end }}
> Check the [Pre-requirements document](pre-requirements.md) for more detailed information about these tools.
## Creating a New Solution
@ -50,11 +33,11 @@ Assuming that you have [installed and logged in](../studio/installation.md) to t
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.png)
![abp-studio-new-solution-dialog](images/abp-studio-no-layers-new-solution-dialog-0.9.13.png)
We will use the *Application (Single Layer)* solution template for this tutorial, so pick it and click the *Next* button:
![abp-studio-new-solution-dialog-solution-properties](images/abp-studio-no-layers-new-solution-dialog-solution-properties.png)
![abp-studio-new-solution-dialog-solution-properties](images/abp-studio-no-layers-new-solution-dialog-solution-properties-0.9.13.png)
On that screen, you choose a name for your solution. You can use different levels of namespaces; e.g. `BookStore`, `Acme.BookStore` or `Acme.Retail.BookStore`.
@ -62,31 +45,35 @@ Then select an *output folder* to create your solution. The *Create solution fol
Once your configuration is done, click the *Next* button to navigate to the *UI Framework* selection:
![abp-studio-new-solution-dialog-ui-framework](images/abp-studio-no-layers-new-solution-dialog-ui-framework.png)
![abp-studio-new-solution-dialog-ui-framework](images/abp-studio-no-layers-new-solution-dialog-ui-framework-0.9.13.png)
Here, you see all the possible UI options supported by that startup solution template. Pick the **{{ UI_Value }}**.
Notice that; Once you select a UI type, some additional options will be available under the UI Framework list. You can further configure the options or leave them as default and click the *Next* button for the *UI Theme* selection screen:
![abp-studio-new-solution-dialog-ui-theme](images/abp-studio-nolayers-new-solution-dialog-ui-theme.png)
![abp-studio-new-solution-dialog-ui-theme](images/abp-studio-nolayers-new-solution-dialog-ui-theme-0.9.13.png)
LeptonX is the suggested UI theme that is proper for production usage. Select one of the themes, configure the additional options, and click the *Next* button for the *Database Provider* selection:
{{ if DB == "EF" }}
![abp-studio-new-solution-dialog-database-provider](images/abp-studio-no-layers-new-solution-dialog-database-provider-efcore.png)
![abp-studio-new-solution-dialog-database-provider](images/abp-studio-no-layers-new-solution-dialog-database-provider-efcore-0.9.13.png)
{{ else }}
![abp-studio-new-solution-dialog-database-provider](images/abp-studio-no-layers-new-solution-dialog-database-provider-mongo.png)
![abp-studio-new-solution-dialog-database-provider](images/abp-studio-no-layers-new-solution-dialog-database-provider-mongo-0.9.13.png)
{{ end }}
On that screen, you can decide on your database provider by selecting one of the provided options. There are some additional options for each database provider. Leave them as default or change them based on your preferences, then click the *Next* button for additional *Database Configurations*:
{{ if DB == "EF" }}
![abp-studio-new-solution-dialog-database-configurations](images/abp-studio-no-layers-new-solution-dialog-database-configurations-efcore.png)
![abp-studio-new-solution-dialog-database-configurations](images/abp-studio-no-layers-new-solution-dialog-database-configurations-efcore-0.9.13.png)
{{ else }}
![abp-studio-new-solution-dialog-database-configurations](images/abp-studio-no-layers-new-solution-dialog-database-configurations-mongo.png)
![abp-studio-new-solution-dialog-database-configurations](images/abp-studio-no-layers-new-solution-dialog-database-configurations-mongo-0.9.13.png)
{{ end }}
Here, you can select the database management systems (DBMS){{ if DB == "EF" }} and the connection string{{ end }}. 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.
Here, you can select the database management systems (DBMS){{ if DB == "EF" }} and the connection string{{ end }}. Then, you can select optional modules and enable additional options according to your preferences.
![abp-studio-no-layers-new-solution-additional-options](images/abp-studio-no-layers-new-solution-additional-options-0.9.13.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:
@ -112,8 +99,6 @@ In the Solution Runner section (on the left side) you can see all the runnable a
To start an application, either click the *Play* icon near to the application or right-click and select the *Run* -> *Start* context menu item.
> For the first run, you'll need to build the application. You can achieve this by selecting *Run* -> *Build & Start* from the context menu.
You can start the `Acme.BookStore`{{ if UI == "NG" }} and `Acme.BookStore.Angular`{{ end }}.
Once the `Acme.BookStore{{ if UI == "NG" }}.Angular{{ end }}` application started, you can right-click it and select the *Browse* command:

BIN
docs/en/images/generic-repositories.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 163 KiB

After

Width:  |  Height:  |  Size: 165 KiB

BIN
docs/en/images/idle-message.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 112 KiB

BIN
docs/en/images/idle-setting.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 656 KiB

BIN
docs/en/images/pen-test-alert-list-9.0.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

BIN
docs/en/images/suite-registry.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

5
docs/en/kb/can-not-login-with-admin-user.md

@ -0,0 +1,5 @@
# KB#0003: Can not login with the admin user
* Try username `admin` and Password `1q2w3E*`.
* Try to migrate database. If you have a `DbMigrator` application in your solution, use it. It will seed initial data and create the admin user for you.
* If not works, read the README.MD file in your solution, or check the [Getting Started](https://abp.io/docs/latest/get-started) document.

7
docs/en/kb/index.md

@ -0,0 +1,7 @@
# ABP Knowledge Base
The following documents provide useful information about several topics you might need to know.
* KB#0001: ["Filename too long" error on Windows](windows-path-too-long-fix.md)
* KB#0002: [When to use a distributed cache server](when-to-use-a-distributed-cache-server.md)
* KB#0003: [Can not login with the admin user](can-not-login-with-admin-user.md)

49
docs/en/kb/when-to-use-a-distributed-cache-server.md

@ -0,0 +1,49 @@
# KB#0002: When to Use a Distributed Cache Server
ABP provides a [distributed cache service](../framework/fundamentals/caching.md) that is based on [ASP.NET Core's distributed cache](https://docs.microsoft.com/en-us/aspnet/core/performance/caching/distributed). This document explains when you need to have a separate cache server for your applications.
## Understanding the Default Cache Service
**Default implementation of the cache service works in-memory**. Memory cache is only useful if you are building a monolith application and you run a single instance of your application. For other cases, **you should use a real distributed cache server**.
Here are a few example cases where you should use a distributed cache server:
* You have a **monolith application**, but you run **multiple instances** of that application concurrently, for example, in a [clustered environment](../deployment/clustered-environment.md)
* You build a **microservice** or any kind of **distributed** system
* You have web **multiple applications** in your solution and they should share the same cache
The problem is obvious: If each application instance uses its internal in-memory cache, and if two or more applications cache the same data, it is probable that they will cache different copies of the data. In that case, there is no way to **invalidate/refresh** that data in every application's memory when the data changes.
## What is a Distributed Cache Server
A **distributed cache server** (e.g. [Redis](../framework/fundamentals/redis-cache.md)) stores cache objects in a separate server application and allows multiple applications/processes to share the same cache objects. In that way;
* All applications/services and all their instances use the same cache store and share the same cached objects. Once an application instance refreshes a cached object, all others use the new object.
* Even if your applications stop and restart, the cached objects are not lost, since they are managed by a separate cache server.
## How to Use a Distributed Cache Server
ABP [solution templates](../solution-templates/index.md) come with Redis configured when it is certainly necessary. For example;
* The [microservice startup template](../solution-templates/microservice/index.md) always comes with [Redis configured](../solution-templates/microservice/distributed-cache.md) and also included as a docker container.
* The application startup template comes with Redis configured when you select multiple applications, tiered architecture, or some other configuration that requires a distributed cache server.
In other cases, to keep the dependencies minimal, they come with the default (in-memory) cache configuration. In those cases, if you need a distributed cache server, you should manually switch to a distributed cache provider for your application.
See the *[Redis Cache](../framework/fundamentals/redis-cache.md)* document if you need to use Redis as the distributed cache server. See [ASP.NET Core's documentation](https://docs.microsoft.com/en-us/aspnet/core/performance/caching/distributed) to see how to switch to another cache provider.
### Installing a Redis Server to Your Local Environment
If you want to use Redis as your distributed cache provider in your development environment, you can simply use the [official Redis docker image](https://hub.docker.com/_/redis). Once you have [Docker](https://www.docker.com/products/docker-desktop/) in your local machine, you can use the following command to run a Redis container and map the default Redis port:
````bash
docker run -p 6379:6379 --name RedisServer -d redis
````
You can check the [official Redis docker image](https://hub.docker.com/_/redis) document for more options.
## See Also
* [ABP Distributed Cache](../framework/fundamentals/caching.md)
* [ASP.NET Core Distributed Cache](https://docs.microsoft.com/en-us/aspnet/core/performance/caching/distributed)

2
docs/en/kb/windows-path-too-long-fix.md

@ -1,4 +1,4 @@
# How to Fix "Filename too long" Error on Windows
# KB#0001: How to Fix "Filename too long" Error on Windows
If you encounter the "filename too long" or "unzip" error on Windows, it's probably related to the Windows maximum file path limitation. Windows has a maximum file path limitation of 255 characters.

1
docs/en/modules/account-pro.md

@ -358,3 +358,4 @@ This module doesn't define any additional distributed event. See the [standard d
* [Impersonation](./account/impersonation.md)
* [Linked Accounts](./account/linkedaccounts.md)
* [Session Management](./account/session-management.md)
* [Idle Session Timeout](./account/idle-session-timeout.md)]

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

@ -0,0 +1,19 @@
# Idle Session Timeout
The `Idle Session Timeout` feature allows you to automatically log out users after a certain period of inactivity.
## Configure Idle Session Timeout
You can enable/disable the `Idle Session Timeout` feature in the `Setting > Account > Idle Session Timeout` 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).
![idle-setting](../../images/idle-setting.png)
Once the idle session timeout is reached, the user will see a warning modal before being logged out. if user does not respond for 60 seconds, the user will be logged out automatically.
![idle-setting](../../images/idle-message.png)
## How it works
There is JavaScript code running in the background to detect user activity. such as mouse movement, key press, click, etc. If there is no activity detected for setting time, The warning modal will be shown to the user.

36
docs/en/modules/docs.md

@ -490,9 +490,6 @@ Since not every single document in your projects may not have sections or may no
For example [Getting-Started.md](https://github.com/abpio/abp-commercial-docs/blob/master/en/getting-started.md):
```
.....
​```json
//[doc-params]
{
@ -502,9 +499,6 @@ For example [Getting-Started.md](https://github.com/abpio/abp-commercial-docs/bl
}
​```
........
```
This section will be automatically deleted during render. And f course, those key values must match with the ones in **Parameter document**.
![Interface](../images/docs-section-ui.png)
@ -513,7 +507,7 @@ Now you can use **Scriban** syntax to create sections in your document.
For example:
````
````text
{{ if UI == "NG" }}
* `-u` argument specifies the UI framework, `angular` in this case.
@ -672,22 +666,18 @@ The **Docs Module** supports referencing previous and next documents. It's usefu
To reference the previous and next documents from a document, you should specify the documentation titles and their paths as follows:
```
````json
//[doc-nav]
{
"Previous": {
"Name": "Overall",
"Path": "testing/overall"
},
"Next": {
"Name": "Integration tests",
"Path": "testing/integration-tests"
}
}
````
```json
//[doc-nav]
{
"Previous": {
"Name": "Overall",
"Path": "testing/overall"
},
"Next": {
"Name": "Integration tests",
"Path": "testing/integration-tests"
}
}
```
After you specify the next & previous documents, they will appear at the end of the current documentation like in the following figure:

46
docs/en/others/penetration-test-report.md

@ -1,6 +1,6 @@
# ABP Penetration Test Report
The ABP Commercial MVC `v8.3.0` application template has been tested against security vulnerabilities by the [OWASP ZAP v2.14.0](https://www.zaproxy.org/) tool. The demo web application was started on the `https://localhost:44349` address. The below alerts have been reported by the pentest tool. These alerts are sorted by the risk level as high, medium, and low. The informational alerts are not mentioned in this document.
The ABP Commercial MVC `v9.0.0` application template has been tested against security vulnerabilities by the [OWASP ZAP v2.14.0](https://www.zaproxy.org/) tool. The demo web application was started on the `https://localhost:44349` address. The below alerts have been reported by the pentest tool. These alerts are sorted by the risk level as high, medium, and low. The informational alerts are not mentioned in this document.
Many of these alerts are **false-positive**, meaning the vulnerability scanner detected these issues, but they are not exploitable. It's clearly explained for each false-positive alert why this alert is a false-positive.
@ -10,14 +10,14 @@ In the next sections, you will find the affected URLs, attack parameters (reques
There are high _(red flag)_, medium _(orange flag)_, low _(yellow flag)_, and informational _(blue flag)_ alerts.
![penetration-test-8.3.0](../images/pen-test-alert-list-8.3.png)
![penetration-test-9.0.0](../images/pen-test-alert-list-9.0.png)
> The informational alerts are not mentioned in this document. These alerts are not raising any risks on your application and they are optional.
### Path Traversal [Risk: High] - False Positive
- *[GET] - https://localhost:44349/api/audit-logging/audit-logs?startTime=&endTime=&url=&userName=&applicationName=&clientIpAddress=&correlationId=&httpMethod=audit-logs&httpStatusCode=&maxExecutionDuration=&minExecutionDuration=&hasException=true&sorting=executionTime+desc&skipCount=0&maxResultCount=10* (attack: **httpMethod=audit-logs**)
- *[POST] - https://localhost:44349/Account/Login* (attack: **\Login**)
- *[POST] - https://localhost:44349/Account/LinkLogin* (attack: **\LinkLogin**)
- *[POST] - https://localhost:44349/Account/Register* (attack: **\Register**)
- *[POST] - https://localhost:44349/Account/SecurityLogs* (attack: **\SecurityLogs**)
- *[POST] - https://localhost:44349/Identity/SecurityLogs* (attack: **\SecurityLogs**)
@ -28,19 +28,15 @@ The Path Traversal attack technique allows an attacker access to files, director
**Solution**:
This is a **false-positive** alert since ABP does all related checks for this kind of attack on the backend side for these endpoints.
This is a **false-positive** alert since ABP does all related checks for this kind of attacks on the backend side for these endpoints.
### SQL Injection [Risk: High] - False Positive
* *[POST] — https://localhost:44349/Account/Login* (attack: **1q2w3E* AND 1=1 --**)
* *[POST] — https://localhost:44349/AuditLogs* (attack: **GET' AND '1'='1' --**)
* *[POST] — https://localhost:44349/Identity/SecurityLogs* (attack: **admin' AND '1'='1**)
* *[POST] — https://localhost:44349/api/account/verify-authenticator-code* (attack: **AND '1'='1**)
* *[POST] — https://localhost:44349/Identity/ClaimTypes/CreateModal* (attack: **aaaa AND '1'='1**)
* *[POST] — https://localhost:44349/Account/ImpersonateUser* (attack: **CfDJ8Pyqeg0vtHtJpnK-9eLaft7-JxLJfJ6WHKPOdBZVxz14BDo061qpJ2NLplgAn2Hw16ec0IR38_wWAUkJGxP8hL6PcLfH0bh-ATNTspWyWYTGGbiH-zeKWiS5vWX-br2BA1hE7Dc45eWGUZNcVc_vm2s AND 1=1 --**)
* *[POST] — https://localhost:44349/Abp/MultiTenancy/TenantSwitchModal* (attack: **CfDJ8Pyqeg0vtHtJpnK-9eLaft7-JxLJfJ6WHKPOdBZVxz14BDo061qpJ2NLplgAn2Hw16ec0IR38_wWAUkJGxP8hL6PcLfH0bh-ATNTspWyWYTGGbiH-zeKWiS5vWX-br2BA1hE7Dc45eWGUZNcVc_vm2s AND 1=1 --**)
* *[POST] — https://localhost:44349/Identity/OrganizationUnits/\** (attack: **6f4cd0ab-f4eb-7ce0-8b26-3a138af1840d" AND '1'='1**) (also, several other URLs...)
* *[POST] — https://localhost:44349/Identity/ClaimTypes/EditModal* (attack: **aaaa AND '1'='1**)
* *[POST] — https://localhost:44349/LanguageManagement/Texts* (attack: **true" AND "1"="1" --**)
* *[POST] — https://localhost:44349/Account/Manage?CurrentPassword=ZAP%27+AND+%271%27%3D%271%27+--+&NewPassword=ZAP&NewPasswordConfirm=ZAP*
* *[POST] — https://localhost:44349/Identity/ClaimTypes/CreateModal* (attack: **aaaad AND '1'='1**)
**Description**:
@ -95,11 +91,17 @@ There are only one URL that is reported as exposing error messages. This is a **
### Content Security Policy (CSP) Header Not Set [Risk: Medium] — Positive (Fixed)
- *[GET] — https://localhost:44349*
- *[GET] — https://localhost:44349/AuditLogs*
- *[GET] — https://localhost:44349/CookiePolicy*
- *[GET] — https://localhost:44349/Gdpr/PersonalData*
- *[GET] — https://localhost:44349/Identity/ClaimTypes/{0}* (create & edit modal URLs - also there are other modal related URLs...)
- *[GET] — https://localhost:44349/AbpPermissionManagement/PermissionManagementModal?providerName=R&providerKey=role&providerKeyDisplayName=role*
- *[GET] — https://localhost:44349/Abp/MultiTenancy/TenantSwitchModal*
- *[GET] — https://localhost:44349/Account/AuthorityDelegation/AuthorityDelegationModal*
- *[GET] — https://localhost:44349/Account/AuthorityDelegation/DelegateNewUserModal*
- *[GET] — https://localhost:44349/Account/ForgotPassword _(other several account URLS)_*
- *[GET] — https://localhost:44349/Account/ExternalLogins _(other several account URLS)_*
- *[GET] — https://localhost:44349/Account/SecurityLogs _(other several account URLS)_*
- *[GET] — https://localhost:44349/Account/Login _(other several account URLS)_*
- *[GET] — https://localhost:44349/Account/Register _(other several account URLS)_*
- *[GET] — https://localhost:44349/Account/Manage _(other several account URLS)_*
@ -143,12 +145,13 @@ The first affected URL is a **false-positive** alert since it's already fixed an
The second URL is also a **false-positive** alert because there is no bad character string in the response.
> **Note**: However, it might be possible if you had any sensitive localization key-value pair in your localization entries, because this endpoint returns all localization values to be able to be used in the application. Therefore, keep that in mind while defining new localization entries.
> **Note**: However, it might be possible if you had any sensitive localization key-value pair in your localization entries, because this endpoint returns all localization values to be able to be used in the application. Therefore, keep that in mind while defining new localization entries. Pass the critical values in your code while using the localization entry as a parameter.
### XSLT Injection [Risk: Medium] - False Positive
- *[GET] — https://localhost:44349/Abp/Languages/Switch?culture=%3Cxsl%3Avalue-of+select%3D%22system-property%28%27xsl%3Avendor%27%29%22%2F%3E&returnUrl=%2F&uiCulture=ar*
- *[POST] — https://localhost:44349/Account/Login _(same URL with different parameters...)_*
- *[POST] — https://localhost:44349/Account/ImpersonateUser _(same URL with different parameters...)_*
- *[POST] — https://localhost:44349/Account/Register _(same URL with different parameters...)_*
- *[POST] — https://localhost:44349/Account/Manage _(same URL with different parameters...)_*
- *[POST] — https://localhost:44349/Account/ForgotPassword _(same URL with different parameters...)_*
@ -161,13 +164,14 @@ Injection using XSL transformations may be possible and may allow an attacker to
**Explanation**:
This is a **false-positive** alert. v8.3.0 uses .NET 8 and the XSLT transformation is not possible on .NET5 or higher.
This is a **false-positive** alert. v9.0 uses .NET 9 and the XSLT transformation is not possible on .NET5 or higher.
### Application Error Disclosure [Risk: Low] — False Positive
- *[GET] — https://localhost:44349/Abp/Languages/Switch*
- *[POST] — https://localhost:44349/Account/ImpersonateUser*
- *[POST] — https://localhost:44349/Saas/Host/Editions*
- *[POST] — https://localhost:44349/Saas/Host/Tenants*
- *[GET] — https://localhost:44349/Account/ExternalLogins*
- *[GET] — https://localhost:44349/Account/Logout*
**Description:**
@ -304,6 +308,7 @@ This vulnerability was reported as a positive alert because the application ran
### Timestamp Disclosure - Unix [Risk: Low] - False Positive
- *[GET] — https://localhost:44349/libs/zxcvbn/zxcvbn.js?=*
- *[GET] — https://localhost:44349/libs/sweetalert2/sweetalert2.all.min.js?=*
**Description**:
@ -319,8 +324,9 @@ This vulnerability was reported as a positive alert, because ABP uses the [zxcvb
### X-Content-Type-Options Header Missing [Risk: Low] - Positive (Fixed)
- *[GET] — https://localhost:44349/client-proxies/account-proxy.js?_v=638550091940000000 (and other client-proxies related URLs)*
- *[GET] — https://localhost:44349/client-proxies/account-proxy.js?_v=638550091940000000 (and other client-proxies related URLs...)*
- *[GET] — https://localhost:44349/favicon.svg*
- *[GET] — https://localhost:44349/images/getting-started/bg-01.png* (and other image URLs...)
- *[GET] — https://localhost:44349/global-styles.css?_v=638556076064360335*
- *[GET] — https://localhost:44349/libs/@fortawesome/fontawesome-free/css/all.css?_v=%5CWEB-INF%5Cweb.xml (other several URLs...)*
- other URLs...
@ -340,11 +346,3 @@ If possible, ensure that the end user uses a standards-compliant and modern web
The `X-Content-Type-Options` header allows you to avoid MIME type sniffing by saying that the MIME types are deliberately configured. This headeer is not strictly required, but it is highly recommended for security reasons. While modern browsers have improved security features, you can still set this header for ensuring the security of web applications.
You can add the [ABP's Security Header Middleware](../framework/ui/mvc-razor-pages/security-headers.md#security-headers-middleware) into the request pipeline to set the `X-Content-Type-Options` as *no-sniff*. Also, this middleware adds other pre-defined security headers to your application, including `X-XSS-Protection`, `X-Frame-Options` and `Content-Security-Policy` (if it's enabled). Read [Security Headers](../framework/ui/mvc-razor-pages/security-headers.md) documentation for more info.
## Other Alerts (Fixed)
The following alerts were reported by the community or our customers in v8.2 and fixed:
* https://github.com/abpframework/abp/issues/19576
* https://github.com/abpframework/abp/issues/19588
* https://github.com/abpframework/abp/issues/19589

28
docs/en/release-info/migration-guides/openiddict5-to-6.md

@ -0,0 +1,28 @@
# OpenIddict 5.x to 6.x Migration Guide
The 6.0 release of OpenIddict is a major release that introduces breaking changes.
Check this blog [OpenIddict 6.0 general availability](https://kevinchalet.com/2024/12/17/openiddict-6-0-general-availability/) for the new features introduced in OpenIddict 6.0. and the [Migrate to OpenIddict 6.0](https://documentation.openiddict.com/guides/migration/50-to-60) for more information about the changes.
In this guide, we will explain the changes you need to make to your ABP application.
## Constant changes
The following constants have been renamed:
| Old Constant Name | New Constant Name |
|---------------------------------------------------------------|-----------------------------------------------------------------|
| `OpenIddictConstants.Permissions.Endpoints.Logout` | `OpenIddictConstants.Permissions.Endpoints.EndSession` |
| `OpenIddictConstants.Permissions.Endpoints.Device` | `OpenIddictConstants.Permissions.Endpoints.DeviceAuthorization` |
## IdentityModel packages
If you have a reference to `IdentityModel` directly, please upgrade the necessary package versions to the latest stable version, which is currently 8.3.0:
* [System.IdentityModel.Tokens.Jwt](https://www.nuget.org/packages/System.IdentityModel.Tokens.Jwt/)
* [Microsoft.IdentityModel.Protocols.OpenIdConnect](https://www.nuget.org/packages/Microsoft.IdentityModel.Protocols.OpenIdConnect/)
* [Microsoft.IdentityModel.Tokens](https://www.nuget.org/packages/Microsoft.IdentityModel.Tokens/)
* [Microsoft.IdentityModel.JsonWebTokens](https://www.nuget.org/packages/Microsoft.IdentityModel.JsonWebTokens/)
That's all, it's a simple migration! If you have advanced usage of OpenIddict, please check the [official migration guide](https://documentation.openiddict.com/guides/migration/50-to-60) for more information.

2
docs/en/samples/easy-crm.md

@ -35,7 +35,7 @@ When you download and open the zip file, you will see two folders:
* First, follow all the steps above to run the server side and seed the sample data.
* Open a command prompt in the angular folder.
* Run the `yarn` command to install NPM packages (requires the [Yarn](https://yarnpkg.com/) package manager).
* Run the `yarn` command to install NPM packages (requires the [Yarn v1.22+ (not v2)](https://classic.yarnpkg.com/en/docs/install) package manager).
* Run the `yarn start` command to run the Angular application. It will automatically open the `localhost://4200` in your default browser once the application initialized.
### Blazor UI

5
docs/en/samples/eshop-on-abp/index.md

@ -1,3 +1,8 @@
# eShopOnAbp
> ⚠️ **Important Notice**
> This project, "eshoponabp," is outdated. It served as a reference project for microservice architecture using the ABP Framework, but we now recommend using the [ABP Microservice Solution Template](https://abp.io/docs/latest/solution-templates/microservice) for new projects.
>
> The new template offers a modernized and officially supported starting point for building microservices with ABP. Please consider transitioning to the new template for the latest features and improvements.
This document is in progress. Please see the source code for now: https://github.com/abpframework/eShopOnAbp

4
docs/en/samples/index.md

@ -13,9 +13,11 @@ A reference application built with ABP. It implements the Domain Driven Design w
Reference microservice solution built with ABP and .NET.
* [Live demo](https://www.eshoponabp.com/)
* [Source code](https://github.com/abpframework/eShopOnAbp)
> ⚠️ **Important Notice**
> This project, "eShopOnAbp," is outdated. It served as a reference project for microservice architecture using the ABP Framework, but we now recommend using the [ABP Microservice Solution Template](https://abp.io/docs/latest/solution-templates/microservice) for new projects.
## CMS Kit Demo
A minimal example website built with the [CMS Kit module](../modules/cms-kit/index.md).

BIN
docs/en/solution-templates/application-module/images/additional-options.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

BIN
docs/en/solution-templates/application-module/images/create-new-module.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

BIN
docs/en/solution-templates/application-module/images/issuemanagement-module-solution.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

BIN
docs/en/solution-templates/application-module/images/new-module.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

BIN
docs/en/solution-templates/application-module/images/new-solution.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 112 KiB

BIN
docs/en/solution-templates/application-module/images/select-database-provider.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

BIN
docs/en/solution-templates/application-module/images/select-user-interface.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 99 KiB

BIN
docs/en/solution-templates/application-module/images/solution-properties.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

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

Loading…
Cancel
Save