Browse Source

Merge branch 'dev' into EngincanV/searching

abp-searching
EngincanV 6 months ago
parent
commit
171ec10d20
  1. 7
      Directory.Packages.props
  2. 18
      abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/en.json
  3. BIN
      docs/en/Blog-Posts/2025-07-22-My-Impressionf-at-WeAreDevelopers/1752664190317-min.jpeg
  4. BIN
      docs/en/Blog-Posts/2025-07-22-My-Impressionf-at-WeAreDevelopers/IMG_15941-min.jpg
  5. BIN
      docs/en/Blog-Posts/2025-07-22-My-Impressionf-at-WeAreDevelopers/IMG_15944-min.jpg
  6. BIN
      docs/en/Blog-Posts/2025-07-22-My-Impressionf-at-WeAreDevelopers/IMG_15947-min.jpg
  7. BIN
      docs/en/Blog-Posts/2025-07-22-My-Impressionf-at-WeAreDevelopers/IMG_15948-min.jpg
  8. BIN
      docs/en/Blog-Posts/2025-07-22-My-Impressionf-at-WeAreDevelopers/IMG_15949-min.jpg
  9. BIN
      docs/en/Blog-Posts/2025-07-22-My-Impressionf-at-WeAreDevelopers/IMG_15959-min.jpg
  10. BIN
      docs/en/Blog-Posts/2025-07-22-My-Impressionf-at-WeAreDevelopers/IMG_15963-min.jpg
  11. BIN
      docs/en/Blog-Posts/2025-07-22-My-Impressionf-at-WeAreDevelopers/IMG_15995-min.jpg
  12. BIN
      docs/en/Blog-Posts/2025-07-22-My-Impressionf-at-WeAreDevelopers/IMG_15996-min.jpg
  13. BIN
      docs/en/Blog-Posts/2025-07-22-My-Impressionf-at-WeAreDevelopers/IMG_15998-min.jpg
  14. BIN
      docs/en/Blog-Posts/2025-07-22-My-Impressionf-at-WeAreDevelopers/IMG_15999-min.jpg
  15. BIN
      docs/en/Blog-Posts/2025-07-22-My-Impressionf-at-WeAreDevelopers/IMG_16011-min.jpg
  16. BIN
      docs/en/Blog-Posts/2025-07-22-My-Impressionf-at-WeAreDevelopers/IMG_16012-min.jpg
  17. BIN
      docs/en/Blog-Posts/2025-07-22-My-Impressionf-at-WeAreDevelopers/cover.png
  18. BIN
      docs/en/Blog-Posts/2025-07-22-My-Impressionf-at-WeAreDevelopers/image-20250722203102576.png
  19. 79
      docs/en/Blog-Posts/2025-08-08 v9_3_Release_Stable/POST.md
  20. BIN
      docs/en/Blog-Posts/2025-08-08 v9_3_Release_Stable/cover-image.png
  21. BIN
      docs/en/Blog-Posts/2025-08-08 v9_3_Release_Stable/upgrade-abp-packages.png
  22. 2
      docs/en/Community-Articles/2022-04-18-abp-community-talks-20223/post.md
  23. 10
      docs/en/Community-Articles/2022-04-19-official-abp-discord-server-is-here/post.md
  24. 2
      docs/en/Community-Articles/2022-05-10-abpio-platform-53-rc-has-been-published/post.md
  25. 300
      docs/en/Community-Articles/2023-02-21-abp-year-review-2022-wrap-up/post.md
  26. 2
      docs/en/Community-Articles/2025-07-26-Separate-Tenant-Schema/POST.md
  27. BIN
      docs/en/Community-Articles/2025-07-26-Separate-Tenant-Schema/abp-saas-tenants-page.png
  28. BIN
      docs/en/Community-Articles/2025-07-26-Separate-Tenant-Schema/abp-studio-add-migration-select-dbcontext.png
  29. BIN
      docs/en/Community-Articles/2025-07-26-Separate-Tenant-Schema/abp-studio-add-migration-set-name.png
  30. BIN
      docs/en/Community-Articles/2025-07-26-Separate-Tenant-Schema/abp-studio-add-migration.png
  31. BIN
      docs/en/Community-Articles/2025-07-26-Separate-Tenant-Schema/abp-studio-browse.png
  32. BIN
      docs/en/Community-Articles/2025-07-26-Separate-Tenant-Schema/abp-studio-context-selection.png
  33. BIN
      docs/en/Community-Articles/2025-07-26-Separate-Tenant-Schema/abp-studio-open-with-terminal.png
  34. BIN
      docs/en/Community-Articles/2025-07-26-Separate-Tenant-Schema/abp-studio-solution-runner.png
  35. BIN
      docs/en/Community-Articles/2025-07-26-Separate-Tenant-Schema/acme-tenant-screen.png
  36. BIN
      docs/en/Community-Articles/2025-07-26-Separate-Tenant-Schema/added-product-entity-migration-main-context.png
  37. BIN
      docs/en/Community-Articles/2025-07-26-Separate-Tenant-Schema/added-product-entity-migration-tenant-context.png
  38. BIN
      docs/en/Community-Articles/2025-07-26-Separate-Tenant-Schema/builder-check-tenant-side.png
  39. BIN
      docs/en/Community-Articles/2025-07-26-Separate-Tenant-Schema/dbcontext-factories.png
  40. BIN
      docs/en/Community-Articles/2025-07-26-Separate-Tenant-Schema/dbmigrator-logs.png
  41. BIN
      docs/en/Community-Articles/2025-07-26-Separate-Tenant-Schema/hybrid-database-multi-tenancy.png
  42. BIN
      docs/en/Community-Articles/2025-07-26-Separate-Tenant-Schema/multi-tenancy-dbcontext-structure.png
  43. BIN
      docs/en/Community-Articles/2025-07-26-Separate-Tenant-Schema/new-tenant-dialog-1.png
  44. BIN
      docs/en/Community-Articles/2025-07-26-Separate-Tenant-Schema/new-tenant-dialog-2.png
  45. BIN
      docs/en/Community-Articles/2025-07-26-Separate-Tenant-Schema/new-tenant-dialog-conn-string-1.png
  46. BIN
      docs/en/Community-Articles/2025-07-26-Separate-Tenant-Schema/new-tenant-dialog-conn-string-2.png
  47. BIN
      docs/en/Community-Articles/2025-07-26-Separate-Tenant-Schema/product-database-table.png
  48. BIN
      docs/en/Community-Articles/2025-07-26-Separate-Tenant-Schema/separate-database.png
  49. BIN
      docs/en/Community-Articles/2025-07-26-Separate-Tenant-Schema/separate-tenant-database-multi-tenancy.png
  50. BIN
      docs/en/Community-Articles/2025-07-26-Separate-Tenant-Schema/separate-tenant-schema-option.png
  51. BIN
      docs/en/Community-Articles/2025-07-26-Separate-Tenant-Schema/single-shared-database.png
  52. BIN
      docs/en/Community-Articles/2025-07-26-Separate-Tenant-Schema/switch-host-side.png
  53. BIN
      docs/en/Community-Articles/2025-07-26-Separate-Tenant-Schema/switch-tenant-dialog.png
  54. BIN
      docs/en/Community-Articles/2025-07-26-Separate-Tenant-Schema/tenant-acme-name.png
  55. BIN
      docs/en/Community-Articles/2025-07-26-Separate-Tenant-Schema/tenant-database.png
  56. BIN
      docs/en/Community-Articles/2025-07-26-Separate-Tenant-Schema/user-login.png
  57. BIN
      docs/en/Community-Articles/2025-07-26-Separate-Tenant-Schema/user-logout.png
  58. BIN
      docs/en/Community-Articles/2025-07-26-Separate-Tenant-Schema/users-table-new-tenant.png
  59. 548
      docs/en/Community-Articles/2025-07-31-How-to-build-persistent-background-jobs-with-abp-framework-and-quartz/Post.md
  60. BIN
      docs/en/Community-Articles/2025-08-12-Integration-Services-Explained/integration-services.jpeg
  61. 138
      docs/en/Community-Articles/2025-08-12-Integration-Services-Explained/post.md
  62. 5
      docs/en/framework/architecture/multi-tenancy/index.md
  63. 16
      docs/en/framework/fundamentals/object-extensions.md
  64. 129
      docs/en/framework/infrastructure/object-to-object-mapping.md
  65. 4
      docs/en/framework/ui/angular/quick-start.md
  66. 32
      docs/en/framework/ui/blazor/layout-hooks.md
  67. BIN
      docs/en/get-started/images/abp-studio-created-new-solution_dark.png
  68. BIN
      docs/en/get-started/images/abp-studio-new-solution-dialog-additional-options_dark.png
  69. BIN
      docs/en/get-started/images/abp-studio-new-solution-dialog-database-configurations-efcore_dark.png
  70. BIN
      docs/en/get-started/images/abp-studio-new-solution-dialog-database-configurations-mongo_dark.png
  71. BIN
      docs/en/get-started/images/abp-studio-new-solution-dialog-database-provider-efcore_dark.png
  72. BIN
      docs/en/get-started/images/abp-studio-new-solution-dialog-database-provider-mongo_dark.png
  73. BIN
      docs/en/get-started/images/abp-studio-new-solution-dialog-mobile-framework_dark.png
  74. BIN
      docs/en/get-started/images/abp-studio-new-solution-dialog-modularity_dark.png
  75. BIN
      docs/en/get-started/images/abp-studio-new-solution-dialog-multi-tenancy_dark.png
  76. BIN
      docs/en/get-started/images/abp-studio-new-solution-dialog-optional-modules_dark.png
  77. BIN
      docs/en/get-started/images/abp-studio-new-solution-dialog-public-website_dark.png
  78. BIN
      docs/en/get-started/images/abp-studio-new-solution-dialog-solution-properties_dark.png
  79. BIN
      docs/en/get-started/images/abp-studio-new-solution-dialog-solution-structure-tiered_dark.png
  80. BIN
      docs/en/get-started/images/abp-studio-new-solution-dialog-solution-structure_dark.png
  81. BIN
      docs/en/get-started/images/abp-studio-new-solution-dialog-ui-framework-blazor-server_dark.png
  82. BIN
      docs/en/get-started/images/abp-studio-new-solution-dialog-ui-framework-blazor-wasm_dark.png
  83. BIN
      docs/en/get-started/images/abp-studio-new-solution-dialog-ui-framework-blazor-webapp_dark.png
  84. BIN
      docs/en/get-started/images/abp-studio-new-solution-dialog-ui-framework-mvc_dark.png
  85. BIN
      docs/en/get-started/images/abp-studio-new-solution-dialog-ui-framework-ng_dark.png
  86. BIN
      docs/en/get-started/images/abp-studio-new-solution-dialog-ui-theme_dark.png
  87. BIN
      docs/en/get-started/images/abp-studio-new-solution-dialog_dark.png
  88. BIN
      docs/en/get-started/images/abp-studio-new-solution-language-selection_dark.png
  89. BIN
      docs/en/get-started/images/abp-studio-no-layers-created-new-solution_dark.png
  90. BIN
      docs/en/get-started/images/abp-studio-no-layers-new-solution-additional-options_dark.png
  91. BIN
      docs/en/get-started/images/abp-studio-no-layers-new-solution-dialog-database-configurations-efcore_dark.png
  92. BIN
      docs/en/get-started/images/abp-studio-no-layers-new-solution-dialog-database-configurations-mongo_dark.png
  93. BIN
      docs/en/get-started/images/abp-studio-no-layers-new-solution-dialog-database-provider-efcore_dark.png
  94. BIN
      docs/en/get-started/images/abp-studio-no-layers-new-solution-dialog-database-provider-mongo_dark.png
  95. BIN
      docs/en/get-started/images/abp-studio-no-layers-new-solution-dialog-multi-tenancy_dark.png
  96. BIN
      docs/en/get-started/images/abp-studio-no-layers-new-solution-dialog-solution-properties_dark.png
  97. BIN
      docs/en/get-started/images/abp-studio-no-layers-new-solution-dialog-ui-framework-blazor-server_dark.png
  98. BIN
      docs/en/get-started/images/abp-studio-no-layers-new-solution-dialog-ui-framework-blazor-wasm_dark.png
  99. BIN
      docs/en/get-started/images/abp-studio-no-layers-new-solution-dialog-ui-framework-blazor-webapp_dark.png
  100. BIN
      docs/en/get-started/images/abp-studio-no-layers-new-solution-dialog-ui-framework-mvc_dark.png

7
Directory.Packages.props

@ -46,7 +46,7 @@
<PackageVersion Include="Hangfire.AspNetCore" Version="1.8.18" />
<PackageVersion Include="Hangfire.SqlServer" Version="1.8.18" />
<PackageVersion Include="HtmlSanitizer" Version="9.0.884" />
<PackageVersion Include="IdentityModel" Version="7.0.0" />
<PackageVersion Include="Duende.IdentityModel" Version="7.1.0" />
<PackageVersion Include="IdentityServer4" Version="4.1.2" />
<PackageVersion Include="IdentityServer4.AspNetIdentity" Version="4.1.2" />
<PackageVersion Include="JetBrains.Annotations" Version="2024.3.0" />
@ -145,6 +145,7 @@
<PackageVersion Include="RabbitMQ.Client" Version="7.1.2" />
<PackageVersion Include="Rebus" Version="8.8.0" />
<PackageVersion Include="Rebus.ServiceProvider" Version="10.3.0" />
<PackageVersion Include="Riok.Mapperly" Version="4.2.1" />
<PackageVersion Include="Scriban" Version="6.2.1" />
<PackageVersion Include="Serilog" Version="4.2.0" />
<PackageVersion Include="Serilog.AspNetCore" Version="9.0.0" />
@ -155,8 +156,8 @@
<PackageVersion Include="Serilog.Sinks.File" Version="7.0.0" />
<PackageVersion Include="SharpZipLib" Version="1.4.2" />
<PackageVersion Include="Shouldly" Version="4.3.0" />
<PackageVersion Include="SixLabors.ImageSharp" Version="3.1.8" />
<PackageVersion Include="SixLabors.ImageSharp.Drawing" Version="2.1.6" />
<PackageVersion Include="SixLabors.ImageSharp" Version="3.1.1" />
<PackageVersion Include="SixLabors.ImageSharp.Drawing" Version="2.1.7" />
<PackageVersion Include="SkiaSharp" Version="2.88.8" />
<PackageVersion Include="SkiaSharp.NativeAssets.Linux" Version="2.88.8" />
<PackageVersion Include="SkiaSharp.NativeAssets.macOS" Version="2.88.8" />

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

@ -431,6 +431,9 @@
"WhoWeAre_Expert": "About Me",
"CreateSolutionFolder": "Create Solution Folder",
"CreateSolutionFolderOption": "Specifies if the project will be in a new folder in the output folder or directly the output folder.",
"CreateCrudPage": "Create CRUD Page",
"CreateCrudPageOption": "Generates a sample CRUD page with a Book entity to demonstrate basic operations (Create, Read, Update, Delete).",
"ConnectionString": "Connection string",
"BooksPageTitle": "ABP Books",
"BooksPageDescription": "Explore ABP books to deepen your understanding and mastery of ABP.",
"PackageDetailPage_NuGetPackageInstallationOptions": "There are three ways to install <code>{0}</code> NuGet package to your project",
@ -907,6 +910,7 @@
"ProudToWorkWith": "Proud to Work With",
"JoinOurConsumers": "Join them and build amazing products fast.",
"AdditionalServicesExplanation": "Do you need additional or custom services? <strong>We and our partners can provide;</strong>",
"CustomLicense": "Custom License",
"CustomProjectDevelopment": "Custom Project Development",
"CustomProjectDevelopmentExplanation": "Dedicated developers for your custom projects.",
"PortingExistingProjects": "Porting Existing Projects",
@ -1894,6 +1898,18 @@
"SelectAnOption": "Select an option",
"MostPopular": "Most Popular",
"AnnouncmentsPageTitle": "ABP Community Announcements | Stay Updated with the Latest News",
"AnnouncmentsPageDescription": "Get the latest news, feature updates, release notes, and important announcements about the ABP framework and .NET ecosystem. Stay ahead with timely information directly from the ABP team."
"AnnouncmentsPageDescription": "Get the latest news, feature updates, release notes, and important announcements about the ABP framework and .NET ecosystem. Stay ahead with timely information directly from the ABP team.",
"CanIUseABPProductsOnMoreThanOneComputer": "Can I use ABP products on more than one computer?",
"ABPProductsOnMoreThanOneComputerExplanation": "Yes. Each developer can install the software on up to two machines. A third machine requires approval via email. When you stop using one of your computers, the system understands and automatically invalidates that computer from your paired computer list.",
"CanIShareTheLicensedABPCommercialProducts": "Can I share the licensed ABP commercial products publicly or make them open source?",
"ShareTheLicensedABPCommercialProductsExplanation": "No! Sharing or sublicensing a Commercial (PRO) ABP package is strictly prohibited.",
"AreSubscriptionRenewalsAutomatic": "Are subscription renewals automatic?",
"SubscriptionRenewalsAutomaticExplanation": "By default, no, the renewals are manual. On the other hand, when you purchase a new license and use the payment gateway 'Iyzico' with your credit card, you will see a checkbox called 'Automatic Renewal' in the purchase steps which allows ABP system automatically renew your license. When you check that checkbox, the auto-renewal process lets you renew your license without losing this discount, and your development will never be interrupted. ABP does not save your credit card information, but our payment gateway does secure savings. You can disable auto-renewal at any time by accessing your Organization Management page.",
"DoYouProvideSupportForThird-partyLibraries": "Do you provide support for third-party libraries?",
"ProvideSupportForThird-partyExplanation": "No. Support only covers ABP Framework, ABP commercial packages and products which have been created by Volosoft.",
"DoYouSupportCustomABPArchitectures": "Do you support custom ABP architectures?",
"SupportCustomABPArchitecturesExplanation": "No. Support is only provided for standard ABP solution structures. On the other hand, you can always get support for your custom needs with a paid consultancy from the ABP Team.",
"DoesABPCollectAnyPersonalOrTechnicalData": "Does ABP collect any personal or technical data?",
"ABPCollectAnyDataExplanation": "The software may collect information about you and your use of the software, and send that to Volosoft. Volosoft as the software and service provider may use this information to provide services and improve its products & services. You may opt-out of these scenarios, as described in the <a href=\"{0}\">EULA</a> under PRIVACY AND COLLECTION OF PERSONAL DATA topic ."
}
}

BIN
docs/en/Blog-Posts/2025-07-22-My-Impressionf-at-WeAreDevelopers/1752664190317-min.jpeg

Binary file not shown.

Before

Width:  |  Height:  |  Size: 214 KiB

After

Width:  |  Height:  |  Size: 180 KiB

BIN
docs/en/Blog-Posts/2025-07-22-My-Impressionf-at-WeAreDevelopers/IMG_15941-min.jpg

Binary file not shown.

Before

Width:  |  Height:  |  Size: 749 KiB

After

Width:  |  Height:  |  Size: 712 KiB

BIN
docs/en/Blog-Posts/2025-07-22-My-Impressionf-at-WeAreDevelopers/IMG_15944-min.jpg

Binary file not shown.

Before

Width:  |  Height:  |  Size: 779 KiB

After

Width:  |  Height:  |  Size: 709 KiB

BIN
docs/en/Blog-Posts/2025-07-22-My-Impressionf-at-WeAreDevelopers/IMG_15947-min.jpg

Binary file not shown.

Before

Width:  |  Height:  |  Size: 697 KiB

After

Width:  |  Height:  |  Size: 667 KiB

BIN
docs/en/Blog-Posts/2025-07-22-My-Impressionf-at-WeAreDevelopers/IMG_15948-min.jpg

Binary file not shown.

Before

Width:  |  Height:  |  Size: 852 KiB

After

Width:  |  Height:  |  Size: 825 KiB

BIN
docs/en/Blog-Posts/2025-07-22-My-Impressionf-at-WeAreDevelopers/IMG_15949-min.jpg

Binary file not shown.

Before

Width:  |  Height:  |  Size: 738 KiB

After

Width:  |  Height:  |  Size: 714 KiB

BIN
docs/en/Blog-Posts/2025-07-22-My-Impressionf-at-WeAreDevelopers/IMG_15959-min.jpg

Binary file not shown.

Before

Width:  |  Height:  |  Size: 802 KiB

After

Width:  |  Height:  |  Size: 742 KiB

BIN
docs/en/Blog-Posts/2025-07-22-My-Impressionf-at-WeAreDevelopers/IMG_15963-min.jpg

Binary file not shown.

Before

Width:  |  Height:  |  Size: 633 KiB

After

Width:  |  Height:  |  Size: 620 KiB

BIN
docs/en/Blog-Posts/2025-07-22-My-Impressionf-at-WeAreDevelopers/IMG_15995-min.jpg

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 MiB

After

Width:  |  Height:  |  Size: 1.0 MiB

BIN
docs/en/Blog-Posts/2025-07-22-My-Impressionf-at-WeAreDevelopers/IMG_15996-min.jpg

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 MiB

After

Width:  |  Height:  |  Size: 1.2 MiB

BIN
docs/en/Blog-Posts/2025-07-22-My-Impressionf-at-WeAreDevelopers/IMG_15998-min.jpg

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 MiB

After

Width:  |  Height:  |  Size: 1.3 MiB

BIN
docs/en/Blog-Posts/2025-07-22-My-Impressionf-at-WeAreDevelopers/IMG_15999-min.jpg

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

After

Width:  |  Height:  |  Size: 1.4 MiB

BIN
docs/en/Blog-Posts/2025-07-22-My-Impressionf-at-WeAreDevelopers/IMG_16011-min.jpg

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 MiB

After

Width:  |  Height:  |  Size: 1.2 MiB

BIN
docs/en/Blog-Posts/2025-07-22-My-Impressionf-at-WeAreDevelopers/IMG_16012-min.jpg

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 MiB

After

Width:  |  Height:  |  Size: 2.1 MiB

BIN
docs/en/Blog-Posts/2025-07-22-My-Impressionf-at-WeAreDevelopers/cover.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 602 KiB

After

Width:  |  Height:  |  Size: 594 KiB

BIN
docs/en/Blog-Posts/2025-07-22-My-Impressionf-at-WeAreDevelopers/image-20250722203102576.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 78 KiB

After

Width:  |  Height:  |  Size: 44 KiB

79
docs/en/Blog-Posts/2025-08-08 v9_3_Release_Stable/POST.md

@ -0,0 +1,79 @@
# ABP.IO Platform 9.3 Final Has Been Released!
We are glad to announce that [ABP](https://abp.io/) 9.3 stable version has been released today.
## What's New With Version 9.3?
All the new features were explained in detail in the [9.3 RC Announcement Post](https://abp.io/community/announcements/announcing-abp-9-3-release-candidate-4dqgiryf), so there is no need to review them again. You can check it out for more details.
## Getting Started with 9.3
### 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.
> **Note**: ABP Studio **v1.2.1** has been released with support for **ABP 9.3**. If you already have ABP Studio installed, update it to v1.2.1 (or later, if available) to create new applications targeting 9.3. ABP Studio checks for updates automatically and will prompt you in-app modal to update to the latest version, or you can download the latest installer from the [Studio](https://abp.io/studio) page. See the [upgrading guide](https://abp.io/docs/latest/studio/installation#upgrading) for details. After updating, the New Solution wizard will create applications with ABP 9.3 by default. You can check the [ABP Studio and ABP Startup Template Version Mappings](https://abp.io/docs/latest/studio/version-mapping) documentation to see the corresponding ABP versions for other versions of Studio.
### How to Upgrade an Existing Solution
You can upgrade your existing solutions with either ABP Studio or ABP CLI. In the following sections, both approaches are explained:
### Upgrading via ABP Studio
If you are already using the ABP Studio, you can upgrade it to the latest version. ABP Studio periodically checks for updates in the background, and when a new version of ABP Studio is available, you will be notified through a modal. Then, you can update it by confirming the opened modal. See [the documentation](https://abp.io/docs/latest/studio/installation#upgrading) for more info.
After upgrading the ABP Studio, then you can open your solution in the application, and simply click the **Upgrade ABP Packages** action button to instantly upgrade your solution:
![](upgrade-abp-packages.png)
### Upgrading via ABP CLI
Alternatively, you can upgrade your existing solution via ABP CLI. First, you need to install the ABP CLI or upgrade it to the latest version.
If you haven't installed it yet, you can run the following command:
```bash
dotnet tool install -g Volo.Abp.Studio.Cli
```
Or to update the existing CLI, you can run the following command:
```bash
dotnet tool update -g Volo.Abp.Studio.Cli
```
After installing/updating the ABP CLI, you can use the [`update` command](https://abp.io/docs/latest/CLI#update) to update all the ABP related NuGet and NPM packages in your solution as follows:
```bash
abp update
```
You can run this command in the root folder of your solution to update all ABP related packages.
## Migration Guides
There are a few breaking changes in this version that may affect your application. Please read the migration guide carefully, if you are upgrading from v9.2: [ABP Version 9.3 Migration Guide](https://abp.io/docs/9.3/release-info/migration-guides/abp-9-3)
## Community News
### New ABP Community Articles
As always, exciting articles have been contributed by the ABP community. I will highlight some of them here:
* [Fahri Gedik](https://abp.io/community/members/fahrigedik) has published 2 new articles:
* [A Modern Approach to Angular Dependency Injection using inject function](https://abp.io/community/articles/a-modern-approach-to-angular-dependency-injection-using-8np4o1ap)
* [Angular Application Builder: Transitioning from Webpack to Esbuild](https://abp.io/community/articles/angular-application-builder-transitioning-from-webpack-to-3yzhzfl0)
* [Benjamin Fadina](https://abp.io/community/members/benjaminsqlserver@gmail.com) has published several videos on various topics such as **Blazor Web Assembly Using ABP.IO**, **CQRS Implementation with MediatR in ABP** and more. You can see all his videos [here](https://abp.io/community/members/benjaminsqlserver@gmail.com).
* [Mansur Besleney](https://abp.io/community/members/mansur.besleney) has published [How to Build Persistent Background Jobs with ABP Framework and Quartz](https://abp.io/community/articles/how-to-build-persistent-background-jobs-with-abp-framework-n9aloh93)
* [Halil Ibrahim Kalkan](https://x.com/hibrahimkalkan) has published [Multitenancy with Separate Databases in .NET and ABP](https://abp.io/community/articles/multitenancy-with-separate-databases-in-dotnet-and-abp-51nvl4u9)
* [Alex Maiereanu](https://abp.io/community/members/alex.maiereanu@3sstudio.com) has published [ABP-Hangfire-AzurePostgreSQL](https://abp.io/community/articles/abphangfireazurepostgresql-s1jnf3yg)
* [Jack Fistelmann](https://abp.io/community/members/jfistelmann) has published [ABP and maildev](https://abp.io/community/articles/abp-and-maildev-gy13cr1p)
* [Harsh Gupta](https://abp.io/community/members/harshgupta) has published [How to Add a Module in the ABP.io Application?](https://abp.io/community/articles/how-to-add-a-module-in-the-abp.io-application-sdeajkn6)
* [Tarık Özdemir](https://abp.io/community/members/mtozdemir) has published [AI-First Architecture for .NET Projects: A Modern Blueprint Inspired by McKinsey](https://abp.io/community/articles/AI-First%20Architecture%20for%20.NET%20Projects%3A%20A%20Modern%20Blueprint-h2wgcoq3)
* [Liming Ma](https://github.com/maliming) has published [Using Hangfire Dashboard in ABP API Website](https://abp.io/community/articles/using-hangfire-dashboard-in-abp-api-website--r32ox497)
Thanks to the ABP Community for all the content they have published. You can also [post your ABP related (text or video) content](https://abp.io/community/posts/create) to the ABP Community.
## About the Next Version
The next feature version will be 10.0. You can follow the [release planning here](https://github.com/abpframework/abp/milestones). Please [submit an issue](https://github.com/abpframework/abp/issues/new) if you have any problems with this version.

BIN
docs/en/Blog-Posts/2025-08-08 v9_3_Release_Stable/cover-image.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 676 KiB

BIN
docs/en/Blog-Posts/2025-08-08 v9_3_Release_Stable/upgrade-abp-packages.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

2
docs/en/Community-Articles/2022-04-18-abp-community-talks-20223/post.md

@ -6,7 +6,7 @@
* ABP Community Talks are scheduled to be held on a monthly basis.
* ABP Community Talks are and always will be completely free to attend. Everyone is welcome to join, ask questions and make suggestions before, during and after the event.
* ABP Community Talks are created and announced on [Kommunity](https://kommunity.com/volosoft/events).
* ABP Community Talks are announced regularly on [ABP Framework Twitter Account](https://twitter.com/abpframework), [Volosoft LinkedIn account](https://www.linkedin.com/company/volosoft), [Volosoft Facebook Account](https://www.facebook.com/volosoftcompany), [ABP Community Discord Server](https://discord.gg/CrYrd5vcGh). We highly encourage everyone to follow us and make suggestions.
* ABP Community Talks are announced regularly on [ABP Framework Twitter Account](https://twitter.com/abpframework), [Volosoft LinkedIn account](https://www.linkedin.com/company/volosoft), [Volosoft Facebook Account](https://www.facebook.com/volosoftcompany), [ABP Community Discord Server](https://abp.io/join-discord). We highly encourage everyone to follow us and make suggestions.
* ABP Community Talks are available to watch after the event on YouTube. See [ABP Community Talks YouTube Playlist](https://www.youtube.com/playlist?list=PLsNclT2aHJcOsPustEkzG6DywiO8eh0lB).
# ABP Community Talks 2022.3

10
docs/en/Community-Articles/2022-04-19-official-abp-discord-server-is-here/post.md

@ -1,9 +1,9 @@
We are excited to announce Official ABP Discord Server is created! You can join the ABP Discord Community by clicking [here](https://discord.gg/wbcQAsUrs9).
We are excited to announce Official ABP Discord Server is created! You can join the ABP Discord Community by clicking [here](https://abp.io/join-discord).
In the first week of opening ABP Discord Server, member amount reached more than 500. We are grateful to and blessed by your interest. Thanks to all of you! This also made us sure that an ABP Discord Server was actually a need for the community members to interact with each other.
ABP Community is growing by the second, and we are grateful for all your contributions towards ABP Framework. We noticed that ABP Community’s communication were significant on ABP Framework’s GitHub, we wanted to take it to the next level and have an area where all of us can easily chat with each other.
> [Join ABP Discord Server Now](https://discord.gg/wbcQAsUrs9)
> [Join ABP Discord Server Now](https://abp.io/join-discord)
# What Can You Do on ABP Community Discord Server?
@ -42,11 +42,11 @@
# How Can You Join To ABP Discord Server?
You can join ABP Discord Server by simply clicking to [https://discord.gg/abp](https://discord.gg/wbcQAsUrs9).
You can join ABP Discord Server by simply clicking to [https://abp.io/join-discord](https://abp.io/join-discord).
We are excited to welcome you in ABP Discord Server!
> [Click Here to Join ABP Discord Server Now](https://discord.gg/wbcQAsUrs9)
> [Click Here to Join ABP Discord Server Now](https://abp.io/join-discord)
### What is Discord?
@ -62,4 +62,4 @@
In Discord Servers, users communicate with each other in a way that is convenient for them. Discord allows people to make voice calls, video chats, or simply text messages. Communities are created by wether fans of a specific topic(games, open-source frameworks, NFT, etc.) or by the official authorities of that specific topic(game creator, framework core team, creator of a token, etc).
In ABP Community Discord Server’s case, it is a server created by official authorities with core team being present in the server along with the community members. Even though it is created for the framework community members to communicate with each other easily, everyone who is interested in following the latest news about ABP Platform are welcome to [join ABP Discord Server](https://discord.gg/wbcQAsUrs9)!
In ABP Community Discord Server’s case, it is a server created by official authorities with core team being present in the server along with the community members. Even though it is created for the framework community members to communicate with each other easily, everyone who is interested in following the latest news about ABP Platform are welcome to [join ABP Discord Server](https://abp.io/join-discord)!

2
docs/en/Community-Articles/2022-05-10-abpio-platform-53-rc-has-been-published/post.md

@ -254,4 +254,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.

300
docs/en/Community-Articles/2023-02-21-abp-year-review-2022-wrap-up/post.md

@ -1,100 +1,200 @@
<p> ABP Framework is an open source infrastructure that enables developers to create modern web applications by following the best practices and conventions of software development. In 2022, ABP Framework continued to thrive, achieving significant milestones and making waves in the software development community. With more than 9K GitHub stars and over 10 millions of downloads on NuGet, ABP Framework has become a go-to framework for developers seeking a reliable and efficient way to build web applications.</p>
<p>As ABP Team, we owe our success to our vibrant community, and we are immensely grateful for the support and contributions of each and every member. With your help, we achieved a lot in 2022. We remained committed to our values of transparency, openness, and collaboration, engaging with our community members as much as possible to ensure that we are creating a framework that meets their needs.</p>
<p>One of the major highlights of 2022 was the release of .NET Core 7, which provided a powerful platform for ABP Framework to build upon. Additionally, ABP Commercial and our training programs continued to help developers and businesses to leverage the power of the ABP Framework, enabling them to build modern web applications more efficiently and effectively than ever before.</p>
<p>In this article, we'll take a closer look at the key highlights of 2022 for ABP Framework, from major updates to achivements and the community insights. We are excited to share our progress with you and provide insights into how ABP Framework is continuing to shape the future of software development. So, let's dive in!</p>
</ br>
<img src="https://i.ibb.co/qjgK7Dj/2022-Highlights.png">
<h2> NuGet Downloads </h2>
<p> NuGet is a package manager designed specifically for the .NET ecosystem. It simplifies the process of creating and consuming packages, thanks to the NuGet client tools. By using these tools, developers can easily manage their project dependencies and improve their workflow.</p>
<p> In 2022, <a href="https://www.nuget.org/packages/Volo.Abp.Core/7.0.1" target="_blank" rel="nofollow">ABP Core NuGet package</a> reached more than <b>10 million</b> of downloads! </p>
<p> On the other hand, overall <a href="https://www.nuget.org/profiles/volosoft" target="_blank" rel="nofollow">Volosoft NuGet Packages</a> reached <b> more than half a billion</b> downloads!</p>
<p> Thank you all for your interest and support towards Volosoft and ABP packages.</p>
<h2> E-Books </h2>
<p> Our published e-book amount is reached <b>3</b>! This year, with our founder <a href="https://github.com/hikalkan" target="_blank" rel="nofollow">Halil İbrahim Kalkan</a>'s contributions we now have <b>3 published e-books</b>. </p>
<ul>
<li> <b>Mastering ABP Framework Book</b>: You can learn more details about it from <a href="https://abp.io/books/mastering-abp-framework" target="_blank">here</a> or <a href="https://www.amazon.com/gp/product/B097Z2DM8Q" target="_blank" rel="nofollow">purchase from Amazon</a> or <a href="https://www.packtpub.com/product/mastering-abp-framework/9781801079242" target="_blank" rel="nofollow"> purchase from Packt Publishing's website</a>.</li>
<li> <b>Implementing Domain Driven Design</b>: You can download it for free from <a href="https://abp.io/books/implementing-domain-driven-design" target="_blank"> here</a>. </li>
<li> <b>Building Microservice Solutions</b>: You can download it for free from <a href="https://abp.io/books/building-microservice-solutions" target="_blank">here</a>. </li>
</ul>
<h2> Tutorial Videos </h2>
<p> In 2022, we tried to be as much active as we could. To give you more insight and let you understand ABP Framework with short videos according to your interests, we published 48 tutorial videos. Though the videos were created by overall team members of ABP Framework, someone deserves a special mention here. Shout out to our ABP Core Team member <a href="https://github.com/braim23" target="_blank" rel="nofollow">Hamza Albreem</a> for his hard work.</p>
<ul>
<li> 6 videos have been published on How to Build a To Do App in a Single Layer which can be found in <a href="https://www.youtube.com/playlist?list=PLsNclT2aHJcPqZxk7D4tU8LtTeCFcN_ci" target="_blank"> ABP To-Do Application [Single Layer] Playlist</a>. </li>
<li> 8 videos have been published on How to Build a To-Do App in Multi Layers which can be found in <a href="https://www.youtube.com/playlist?list=PLsNclT2aHJcM8LFSBnmmoNYBGwJ9-H8dG" target="_blank" rel="nofollow"> ABP To Do Application [Multi-Layers] Playlist</a>. </li>
<li> 1 video has been published on ABP Framework Essentials which can be found in <a href="https://www.youtube.com/playlist?list=PLsNclT2aHJcNupH2wz83y7htugpLoUZ_B" target="_blank" rel="nofollow"> ABP Framework Essentials Playlist</a>. </li>
<li> 13 videos have been published to introduce ABP Modules which can be found in <a href="https://www.youtube.com/playlist?list=PLsNclT2aHJcNQC8t7vighWWX6aDR5ZYbc" target="_blank" rel="nofollow"> ABP Modules Playlist</a>.</li>
<li> And many other videos can be found on <a href="https://www.youtube.com/c/@volosoft" target="_blank" rel="nofollow">Volosoft YouTube Channel</a>.</li>
</ul>
<h2> GitHub Stars </h2>
<p> ABP Framework GitHub repository reached <b>more than 9K stars</b>. We appreciate your interest and support for <a href="https://github.com/abpframework/abp" target="_blank" rel="nofollow">ABP Framework GitHub repository</a>. We are working hard to be worthy of your interest and reach out to more people to simplify and streamline their development processes.</p>
<h2> Community Talks </h2>
<p><a href="https://community.abp.io/events" target="_blank">ABP Community Talks</a> is our monthly event that brings together members of the ABP Framework community to discuss and exchange ideas. Prior to each event, we collect suggestions from our contributors, monitor trending topics in the industry, and review updates and news related to the ABP Platform to curate the topics for discussion. Once the topics are finalized, we announce them through our social media and community channels to ensure everyone is aware and can join in on the conversation.</p>
<p> We did 10 <a href="https://www.youtube.com/playlist?list=PLsNclT2aHJcOsPustEkzG6DywiO8eh0lB" target="_blank" rel="nofollow">ABP Community Talks Episodes</a> of and 1 <a href="https://www.youtube.com/watch?v=RFArBh60RSA" target="_blank" rel="nofollow"> ABP Suite webinar</a>. You can take a look at them and check out our videos we have on <a href="https://www.youtube.com/c/@volosoft" target="_blank" rel="nofollow">Volosoft YouTube Channel</a>. </p>
<h2> ABP Community Contributions </h2>
<p> The ABP Community is a hub that offers resources such as articles, video tutorials, and updates on ABP's development progress and events for ABP Framework, .NET, and software development. Developers can also connect with others, help each other, and share their expertise in <a href="https://community.abp.io/">ABP Community</a>.</p>
<ul> You can check out each source from the list below.
<li>ABP Community Events: You can reach them from <a href="https://community.abp.io/events" target="_blank"> here</a>.</li>
<li>ABP Community Posts: You can reach them from <a href="https://community.abp.io/posts" target="_blank"> here</a></li>
<li>ABP Community Videos: You can reach them from <a href="https://community.abp.io/videos" target="_blank"> here</a>. </li>
<li>ABP Community Stackoverflow: You can reach them from <a href="https://stackoverflow.com/questions/tagged/abp" target="_blank"> here</a>. </li>
</ul>
<p> In 2022, the community's contribution reached a point where <b>more than 100 resources</b>. Thank you for all your effort! Please keep it going! It is becoming a more and more rich resource thanks to your variety of contributions and help.</p>
<h2> ABP Community Discord Server</h2>
<p> To take community interaction to the next level, we created the official <a href="https://community.abp.io/discord" target="_blank"> ABP Discord server</a>, providing a platform for the ABP Community to connect and communicate instantly through chatting.</p>
<p> We were so excited <a href="https://blog.abp.io/abp/Official-ABP-Discord-Server-is-Here" target="_blank">announcing the official ABP Discord Server</a>. In the first week of announcing it, the server quickly attracted over 500 members. We're grateful for your interest and support, which confirms the need for a dedicated platform for community interaction.</p>
> <a href="https://discord.gg/wbcQAsUrs9" target="_blank" rel="nofollow">Join ABP Discord Server Now</a>
<h2> ABP Framework GitHub Contributions</h2>
<p> In 2022, ABP Core Team worked hard to achieve milestones and give the best value with ABP Framework so users can benefit from its features. Additional to our team's work, ABP Framework is perfected in 2022 with <a href="https://github.com/abpframework/abp/graphs/contributors" target="_blank" rel="nofollow"> ABP Community members' contributions</a>, <b>3157 commits</b> pushed from <b> 48 different contributors</b>.</p>
<p> We appreciate your hard work and effort you put into making ABP Framework better and improved.</p>
<h2> Events/Summits</h2>
<p> We try to contribute to the developers community as much as we can since day 1. This year was no different. We tried to give value through sponsorships for developer communities. Especially with us leaving the pandemic behind every day, we try to keep up with the in-person events as well as online events. We plan to do more in next year. So, stay tuned!</p>
<p> This year, we sponsored to 4 events. They were, <a href="https://kommunity.com/devnot/events/designing-monolith-first-for-microservice-architecture-e74fec40" target="_blank" rel="nofollow"> DevNot
Designing Monolith First for Microservice Architecture event</a>, <a href="https://www.dnfsummit.org/" target="_blank" rel="nofollow"> DNF Summit 2022</a>, <a href="https://summit.devnot.com/" target="_blank" rel="nofollow"> Developer Summit 2022</a>, and <a href="https://www.dotnetconf.net/" target="_blank" rel="nofollow"> .NET Conference 2022</a>.
<h2> ABP Releases </h2>
<p> ABP Framework released 4 versions from 5.1 to 7.1 in 2022. You can check the release logs from <a href="https://github.com/abpframework/abp/releases" target="_blank" rel="nofollow"> ABP Framework Release Logs</a>. </p>
<p> The most important milestone in these releases is that we upgraded ABP Framework to .NET 7.0 in <a href="https://blog.abp.io/abp/ABP.IO-Platform-7.0-RC-Has-Been-Published" target="_blank"> ABP v7.0</a>.</p>
<p> Additionally, we switched to OpenIddict for the startup templates in <a href="https://blog.abp.io/abp/ABP.IO-Platform-6.0-RC-Has-Been-Published" target="_blank"> ABP v6.0</a>.</p>
<h2> ABP Commercial</h2>
<p> It has been a successful year for ABP Commercial as well as ABP Framework. We have already reached to more than 100 countries over the years of ABP Commercial's release. This year, we continued to be streamline businesses' development processes with ABP Commercial. </p>
<ul>
<li> We have served to different sizes of businesses from <b> more than 50 countries</b> and <b> more than 40 industries </b>.</a></li>
<li> We performed <b>286 hours of training</b> to simplify users' learning curve of ABP Framework. </li>
<li> 1771 support tickets resolved in the premium support forum in which ABP Commercial users can ask their questions directly to ABP Core Team members via <a href="https://support.abp.io/" target="_blank"> ABP Commercial Support Center</a> in addition to community support we provide for ABP Framework users/developers. </li>
<li> We received 39 new testimonials, all from satisfied customers which led us to the other headline, Gartner Badges.</li>
</ul>
<h2> LeptonX Theme </h2>
<p>The Lepton Theme is a module that offers a theme for abp.io-based applications, featuring an Admin Dashboard designed by the ABP Platform. We released a version we called LeptonX Theme which is an upgraded version of Lepton Theme. You can view a live preview of the <a href="https://leptontheme.com/" target="_blank"> LeptonX Theme</a>. While the LeptonX theme is currently exclusive to ABP Commercial users, ABP Framework users can still access the Lite version. You can see the documentation for ABP LeptonX Theme light from <a href="https://docs.abp.io/en/abp/7.0/Themes/Index" target="_blank"> here</a>.</p>
<h2> Gartner Badges </h2>
<p> Gartner badges are given as an award to the listed softwares within their software review/suggestion platforms. To be able to get these awards, certain criterias have to be met such as ease of use, likelihood of recommend, functionality, etc. and they are calculated completely according to the users' real reviews. </p>
<p> In 2022, ABP Commercial reached to such success thanks to its users' support on Gartner, it has been recognized with 2 badges in Application Development category. </p>
<ul> ABP Commercial was selected in the following platforms of Gartner:
<li> <b>Software Advice's Front Runner:</b> <a href="https://www.softwareadvice.com/app-development/abp-commercial-profile/" target="_blank" rel="nofollow"> ABP Commercial's Software Advice profile</a> was given 2022 Front Runners badge according to its high success in terms of usability and customer satisfaction. <a href="https://blog.abp.io/abp/abpcommercial-2022-front-runner-in-app-development-category" target="_blank"> You can learn more about it from here</a>. </li>
<li> <b>GetApp's Category Leader</b>: <a href="https://www.getapp.com/development-tools-software/a/abp-commercial/" target="_blank" rel="nofollow"> ABP Commercial's GetApp profile</a> was given 2022 Category Leader badge among 368 other softwares in its category. <a href="https://blog.abp.io/abp/abpcommercial-2022-category-leader-in-app-development-category"> You can learn more about it from here</a>. </li>
</ul>
<p> Thank you all for all these recognition you deemed us worthy of. </p>
<p> ABP Framework is an open source infrastructure that enables developers to create modern web applications by following the best practices and conventions of software development. In 2022, ABP Framework continued to thrive, achieving significant milestones and making waves in the software development community. With more than 9K GitHub stars and over 10 millions of downloads on NuGet, ABP Framework has become a go-to framework for developers seeking a reliable and efficient way to build web applications.</p>
<p>As ABP Team, we owe our success to our vibrant community, and we are immensely grateful for the support and contributions of each and every member. With your help, we achieved a lot in 2022. We remained committed to our values of transparency, openness, and collaboration, engaging with our community members as much as possible to ensure that we are creating a framework that meets their needs.</p>
<p>One of the major highlights of 2022 was the release of .NET Core 7, which provided a powerful platform for ABP Framework to build upon. Additionally, ABP Commercial and our training programs continued to help developers and businesses to leverage the power of the ABP Framework, enabling them to build modern web applications more efficiently and effectively than ever before.</p>
<p>In this article, we'll take a closer look at the key highlights of 2022 for ABP Framework, from major updates to achivements and the community insights. We are excited to share our progress with you and provide insights into how ABP Framework is continuing to shape the future of software development. So, let's dive in!</p>
</ br>
<img src="https://i.ibb.co/qjgK7Dj/2022-Highlights.png">
<h2> NuGet Downloads </h2>
<p> NuGet is a package manager designed specifically for the .NET ecosystem. It simplifies the process of creating and consuming packages, thanks to the NuGet client tools. By using these tools, developers can easily manage their project dependencies and improve their workflow.</p>
<p> In 2022, <a href="https://www.nuget.org/packages/Volo.Abp.Core/7.0.1" target="_blank" rel="nofollow">ABP Core NuGet package</a> reached more than <b>10 million</b> of downloads! </p>
<p> On the other hand, overall <a href="https://www.nuget.org/profiles/volosoft" target="_blank" rel="nofollow">Volosoft NuGet Packages</a> reached <b> more than half a billion</b> downloads!</p>
<p> Thank you all for your interest and support towards Volosoft and ABP packages.</p>
<h2> E-Books </h2>
<p> Our published e-book amount is reached <b>3</b>! This year, with our founder <a href="https://github.com/hikalkan" target="_blank" rel="nofollow">Halil İbrahim Kalkan</a>'s contributions we now have <b>3 published e-books</b>. </p>
<ul>
<li> <b>Mastering ABP Framework Book</b>: You can learn more details about it from <a href="https://abp.io/books/mastering-abp-framework" target="_blank">here</a> or <a href="https://www.amazon.com/gp/product/B097Z2DM8Q" target="_blank" rel="nofollow">purchase from Amazon</a> or <a href="https://www.packtpub.com/product/mastering-abp-framework/9781801079242" target="_blank" rel="nofollow"> purchase from Packt Publishing's website</a>.</li>
<li> <b>Implementing Domain Driven Design</b>: You can download it for free from <a href="https://abp.io/books/implementing-domain-driven-design" target="_blank"> here</a>. </li>
<li> <b>Building Microservice Solutions</b>: You can download it for free from <a href="https://abp.io/books/building-microservice-solutions" target="_blank">here</a>. </li>
</ul>
<h2> Tutorial Videos </h2>
<p> In 2022, we tried to be as much active as we could. To give you more insight and let you understand ABP Framework with short videos according to your interests, we published 48 tutorial videos. Though the videos were created by overall team members of ABP Framework, someone deserves a special mention here. Shout out to our ABP Core Team member <a href="https://github.com/braim23" target="_blank" rel="nofollow">Hamza Albreem</a> for his hard work.</p>
<ul>
<li> 6 videos have been published on How to Build a To Do App in a Single Layer which can be found in <a href="https://www.youtube.com/playlist?list=PLsNclT2aHJcPqZxk7D4tU8LtTeCFcN_ci" target="_blank"> ABP To-Do Application [Single Layer] Playlist</a>. </li>
<li> 8 videos have been published on How to Build a To-Do App in Multi Layers which can be found in <a href="https://www.youtube.com/playlist?list=PLsNclT2aHJcM8LFSBnmmoNYBGwJ9-H8dG" target="_blank" rel="nofollow"> ABP To Do Application [Multi-Layers] Playlist</a>. </li>
<li> 1 video has been published on ABP Framework Essentials which can be found in <a href="https://www.youtube.com/playlist?list=PLsNclT2aHJcNupH2wz83y7htugpLoUZ_B" target="_blank" rel="nofollow"> ABP Framework Essentials Playlist</a>. </li>
<li> 13 videos have been published to introduce ABP Modules which can be found in <a href="https://www.youtube.com/playlist?list=PLsNclT2aHJcNQC8t7vighWWX6aDR5ZYbc" target="_blank" rel="nofollow"> ABP Modules Playlist</a>.</li>
<li> And many other videos can be found on <a href="https://www.youtube.com/c/@volosoft" target="_blank" rel="nofollow">Volosoft YouTube Channel</a>.</li>
</ul>
<h2> GitHub Stars </h2>
<p> ABP Framework GitHub repository reached <b>more than 9K stars</b>. We appreciate your interest and support for <a href="https://github.com/abpframework/abp" target="_blank" rel="nofollow">ABP Framework GitHub repository</a>. We are working hard to be worthy of your interest and reach out to more people to simplify and streamline their development processes.</p>
<h2> Community Talks </h2>
<p><a href="https://community.abp.io/events" target="_blank">ABP Community Talks</a> is our monthly event that brings together members of the ABP Framework community to discuss and exchange ideas. Prior to each event, we collect suggestions from our contributors, monitor trending topics in the industry, and review updates and news related to the ABP Platform to curate the topics for discussion. Once the topics are finalized, we announce them through our social media and community channels to ensure everyone is aware and can join in on the conversation.</p>
<p> We did 10 <a href="https://www.youtube.com/playlist?list=PLsNclT2aHJcOsPustEkzG6DywiO8eh0lB" target="_blank" rel="nofollow">ABP Community Talks Episodes</a> of and 1 <a href="https://www.youtube.com/watch?v=RFArBh60RSA" target="_blank" rel="nofollow"> ABP Suite webinar</a>. You can take a look at them and check out our videos we have on <a href="https://www.youtube.com/c/@volosoft" target="_blank" rel="nofollow">Volosoft YouTube Channel</a>. </p>
<h2> ABP Community Contributions </h2>
<p> The ABP Community is a hub that offers resources such as articles, video tutorials, and updates on ABP's development progress and events for ABP Framework, .NET, and software development. Developers can also connect with others, help each other, and share their expertise in <a href="https://community.abp.io/">ABP Community</a>.</p>
<ul> You can check out each source from the list below.
<li>ABP Community Events: You can reach them from <a href="https://community.abp.io/events" target="_blank"> here</a>.</li>
<li>ABP Community Posts: You can reach them from <a href="https://community.abp.io/posts" target="_blank"> here</a></li>
<li>ABP Community Videos: You can reach them from <a href="https://community.abp.io/videos" target="_blank"> here</a>. </li>
<li>ABP Community Stackoverflow: You can reach them from <a href="https://stackoverflow.com/questions/tagged/abp" target="_blank"> here</a>. </li>
</ul>
<p> In 2022, the community's contribution reached a point where <b>more than 100 resources</b>. Thank you for all your effort! Please keep it going! It is becoming a more and more rich resource thanks to your variety of contributions and help.</p>
<h2> ABP Community Discord Server</h2>
<p> To take community interaction to the next level, we created the official <a href="https://community.abp.io/discord" target="_blank"> ABP Discord server</a>, providing a platform for the ABP Community to connect and communicate instantly through chatting.</p>
<p> We were so excited <a href="https://blog.abp.io/abp/Official-ABP-Discord-Server-is-Here" target="_blank">announcing the official ABP Discord Server</a>. In the first week of announcing it, the server quickly attracted over 500 members. We're grateful for your interest and support, which confirms the need for a dedicated platform for community interaction.</p>
> <a href="https://abp.io/join-discord" target="_blank" rel="nofollow">Join ABP Discord Server Now</a>
<h2> ABP Framework GitHub Contributions</h2>
<p> In 2022, ABP Core Team worked hard to achieve milestones and give the best value with ABP Framework so users can benefit from its features. Additional to our team's work, ABP Framework is perfected in 2022 with <a href="https://github.com/abpframework/abp/graphs/contributors" target="_blank" rel="nofollow"> ABP Community members' contributions</a>, <b>3157 commits</b> pushed from <b> 48 different contributors</b>.</p>
<p> We appreciate your hard work and effort you put into making ABP Framework better and improved.</p>
<h2> Events/Summits</h2>
<p> We try to contribute to the developers community as much as we can since day 1. This year was no different. We tried to give value through sponsorships for developer communities. Especially with us leaving the pandemic behind every day, we try to keep up with the in-person events as well as online events. We plan to do more in next year. So, stay tuned!</p>
<p> This year, we sponsored to 4 events. They were, <a href="https://kommunity.com/devnot/events/designing-monolith-first-for-microservice-architecture-e74fec40" target="_blank" rel="nofollow"> DevNot
Designing Monolith First for Microservice Architecture event</a>, <a href="https://www.dnfsummit.org/" target="_blank" rel="nofollow"> DNF Summit 2022</a>, <a href="https://summit.devnot.com/" target="_blank" rel="nofollow"> Developer Summit 2022</a>, and <a href="https://www.dotnetconf.net/" target="_blank" rel="nofollow"> .NET Conference 2022</a>.
<h2> ABP Releases </h2>
<p> ABP Framework released 4 versions from 5.1 to 7.1 in 2022. You can check the release logs from <a href="https://github.com/abpframework/abp/releases" target="_blank" rel="nofollow"> ABP Framework Release Logs</a>. </p>
<p> The most important milestone in these releases is that we upgraded ABP Framework to .NET 7.0 in <a href="https://blog.abp.io/abp/ABP.IO-Platform-7.0-RC-Has-Been-Published" target="_blank"> ABP v7.0</a>.</p>
<p> Additionally, we switched to OpenIddict for the startup templates in <a href="https://blog.abp.io/abp/ABP.IO-Platform-6.0-RC-Has-Been-Published" target="_blank"> ABP v6.0</a>.</p>
<h2> ABP Commercial</h2>
<p> It has been a successful year for ABP Commercial as well as ABP Framework. We have already reached to more than 100 countries over the years of ABP Commercial's release. This year, we continued to be streamline businesses' development processes with ABP Commercial. </p>
<ul>
<li> We have served to different sizes of businesses from <b> more than 50 countries</b> and <b> more than 40 industries </b>.</a></li>
<li> We performed <b>286 hours of training</b> to simplify users' learning curve of ABP Framework. </li>
<li> 1771 support tickets resolved in the premium support forum in which ABP Commercial users can ask their questions directly to ABP Core Team members via <a href="https://support.abp.io/" target="_blank"> ABP Commercial Support Center</a> in addition to community support we provide for ABP Framework users/developers. </li>
<li> We received 39 new testimonials, all from satisfied customers which led us to the other headline, Gartner Badges.</li>
</ul>
<h2> LeptonX Theme </h2>
<p>The Lepton Theme is a module that offers a theme for abp.io-based applications, featuring an Admin Dashboard designed by the ABP Platform. We released a version we called LeptonX Theme which is an upgraded version of Lepton Theme. You can view a live preview of the <a href="https://leptontheme.com/" target="_blank"> LeptonX Theme</a>. While the LeptonX theme is currently exclusive to ABP Commercial users, ABP Framework users can still access the Lite version. You can see the documentation for ABP LeptonX Theme light from <a href="https://docs.abp.io/en/abp/7.0/Themes/Index" target="_blank"> here</a>.</p>
<h2> Gartner Badges </h2>
<p> Gartner badges are given as an award to the listed softwares within their software review/suggestion platforms. To be able to get these awards, certain criterias have to be met such as ease of use, likelihood of recommend, functionality, etc. and they are calculated completely according to the users' real reviews. </p>
<p> In 2022, ABP Commercial reached to such success thanks to its users' support on Gartner, it has been recognized with 2 badges in Application Development category. </p>
<ul> ABP Commercial was selected in the following platforms of Gartner:
<li> <b>Software Advice's Front Runner:</b> <a href="https://www.softwareadvice.com/app-development/abp-commercial-profile/" target="_blank" rel="nofollow"> ABP Commercial's Software Advice profile</a> was given 2022 Front Runners badge according to its high success in terms of usability and customer satisfaction. <a href="https://blog.abp.io/abp/abpcommercial-2022-front-runner-in-app-development-category" target="_blank"> You can learn more about it from here</a>. </li>
<li> <b>GetApp's Category Leader</b>: <a href="https://www.getapp.com/development-tools-software/a/abp-commercial/" target="_blank" rel="nofollow"> ABP Commercial's GetApp profile</a> was given 2022 Category Leader badge among 368 other softwares in its category. <a href="https://blog.abp.io/abp/abpcommercial-2022-category-leader-in-app-development-category"> You can learn more about it from here</a>. </li>
</ul>
<p> Thank you all for all these recognition you deemed us worthy of. </p>

2
docs/en/Community-Articles/2025-07-26-Separate-Tenant-Schema/POST.md

@ -22,7 +22,7 @@ In the shared database model, all the application data stored in a single physic
![single-shared-database](single-shared-database.png)
This is the default behavior when you [create a new ABP application](https://abp.io/docs/latest/get-started), because it is simple to begin with and proper for must applications.
This is the default behavior when you [create a new ABP application](https://abp.io/docs/latest/get-started), because it is simple to begin with and proper for most applications.
In this model, a single database table may contain data of multiple tenants. Each row in these tables have a `TenantId` field which is used to distinguish the tenant data and isolate a tenant's data from other tenant users. To make your entities multi-tenant aware, all you have to do is to implement the `IMultiTenant` interface provided by the ABP Framework.

BIN
docs/en/Community-Articles/2025-07-26-Separate-Tenant-Schema/abp-saas-tenants-page.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

After

Width:  |  Height:  |  Size: 26 KiB

BIN
docs/en/Community-Articles/2025-07-26-Separate-Tenant-Schema/abp-studio-add-migration-select-dbcontext.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 16 KiB

BIN
docs/en/Community-Articles/2025-07-26-Separate-Tenant-Schema/abp-studio-add-migration-set-name.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 9.2 KiB

BIN
docs/en/Community-Articles/2025-07-26-Separate-Tenant-Schema/abp-studio-add-migration.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 63 KiB

After

Width:  |  Height:  |  Size: 41 KiB

BIN
docs/en/Community-Articles/2025-07-26-Separate-Tenant-Schema/abp-studio-browse.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 9.6 KiB

BIN
docs/en/Community-Articles/2025-07-26-Separate-Tenant-Schema/abp-studio-context-selection.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 17 KiB

BIN
docs/en/Community-Articles/2025-07-26-Separate-Tenant-Schema/abp-studio-open-with-terminal.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 63 KiB

After

Width:  |  Height:  |  Size: 40 KiB

BIN
docs/en/Community-Articles/2025-07-26-Separate-Tenant-Schema/abp-studio-solution-runner.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 11 KiB

BIN
docs/en/Community-Articles/2025-07-26-Separate-Tenant-Schema/acme-tenant-screen.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 66 KiB

After

Width:  |  Height:  |  Size: 48 KiB

BIN
docs/en/Community-Articles/2025-07-26-Separate-Tenant-Schema/added-product-entity-migration-main-context.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 8.5 KiB

BIN
docs/en/Community-Articles/2025-07-26-Separate-Tenant-Schema/added-product-entity-migration-tenant-context.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 6.8 KiB

BIN
docs/en/Community-Articles/2025-07-26-Separate-Tenant-Schema/builder-check-tenant-side.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 17 KiB

BIN
docs/en/Community-Articles/2025-07-26-Separate-Tenant-Schema/dbcontext-factories.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 8.8 KiB

BIN
docs/en/Community-Articles/2025-07-26-Separate-Tenant-Schema/dbmigrator-logs.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 79 KiB

After

Width:  |  Height:  |  Size: 62 KiB

BIN
docs/en/Community-Articles/2025-07-26-Separate-Tenant-Schema/hybrid-database-multi-tenancy.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 11 KiB

BIN
docs/en/Community-Articles/2025-07-26-Separate-Tenant-Schema/multi-tenancy-dbcontext-structure.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 16 KiB

BIN
docs/en/Community-Articles/2025-07-26-Separate-Tenant-Schema/new-tenant-dialog-1.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

After

Width:  |  Height:  |  Size: 24 KiB

BIN
docs/en/Community-Articles/2025-07-26-Separate-Tenant-Schema/new-tenant-dialog-2.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

After

Width:  |  Height:  |  Size: 24 KiB

BIN
docs/en/Community-Articles/2025-07-26-Separate-Tenant-Schema/new-tenant-dialog-conn-string-1.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 9.9 KiB

BIN
docs/en/Community-Articles/2025-07-26-Separate-Tenant-Schema/new-tenant-dialog-conn-string-2.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 18 KiB

BIN
docs/en/Community-Articles/2025-07-26-Separate-Tenant-Schema/product-database-table.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 40 KiB

After

Width:  |  Height:  |  Size: 25 KiB

BIN
docs/en/Community-Articles/2025-07-26-Separate-Tenant-Schema/separate-database.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.8 KiB

After

Width:  |  Height:  |  Size: 5.7 KiB

BIN
docs/en/Community-Articles/2025-07-26-Separate-Tenant-Schema/separate-tenant-database-multi-tenancy.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 9.4 KiB

BIN
docs/en/Community-Articles/2025-07-26-Separate-Tenant-Schema/separate-tenant-schema-option.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 70 KiB

After

Width:  |  Height:  |  Size: 48 KiB

BIN
docs/en/Community-Articles/2025-07-26-Separate-Tenant-Schema/single-shared-database.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 9.2 KiB

BIN
docs/en/Community-Articles/2025-07-26-Separate-Tenant-Schema/switch-host-side.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 8.0 KiB

BIN
docs/en/Community-Articles/2025-07-26-Separate-Tenant-Schema/switch-tenant-dialog.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 8.6 KiB

BIN
docs/en/Community-Articles/2025-07-26-Separate-Tenant-Schema/tenant-acme-name.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

BIN
docs/en/Community-Articles/2025-07-26-Separate-Tenant-Schema/tenant-database.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 11 KiB

BIN
docs/en/Community-Articles/2025-07-26-Separate-Tenant-Schema/user-login.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 63 KiB

After

Width:  |  Height:  |  Size: 62 KiB

BIN
docs/en/Community-Articles/2025-07-26-Separate-Tenant-Schema/user-logout.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 18 KiB

BIN
docs/en/Community-Articles/2025-07-26-Separate-Tenant-Schema/users-table-new-tenant.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

After

Width:  |  Height:  |  Size: 27 KiB

548
docs/en/Community-Articles/2025-07-31-How-to-build-persistent-background-jobs-with-abp-framework-and-quartz/Post.md

@ -0,0 +1,548 @@
# How to Build Persistent Background Jobs with ABP Framework and Quartz
## Introduction
In modern SaaS applications, automated background processing is essential for delivering reliable user experiences. Whether you're sending subscription reminders, processing payments, or generating reports, background jobs ensure critical tasks happen on schedule without blocking your main application flow.
### What is `Quartz.NET`?
`Quartz.NET` is a powerful, open-source job scheduling library for .NET applications that provides cron-based scheduling for complex time patterns, job persistence across application restarts, clustering support for high-availability scenarios, flexible trigger types, and the ability to pass parameters to jobs through job data maps. It's the de facto standard for enterprise-grade job scheduling in the .NET ecosystem.
### Quartz Storage Options: In-Memory vs Persistent
When configuring **Quartz**, you have two primary storage options, each with significant implications for how your application behaves:
### 🧠 In-Memory Storage (`RAMJobStore`)
- Keeps all job information in application memory.
- **Very fast** – no database overhead.
- **Volatile** – all jobs, triggers, and schedules are lost when the application stops or restarts.
- Best suited for:
- Development environments.
- Scenarios where job loss is acceptable.
### 🗃️ Persistent Storage (`JobStoreTX` or similar)
- Stores all job information in a database.
- **Reliable** – schedules persist across:
- Application restarts
- Server crashes
- Deployments
- **Supports horizontal scaling** – multiple application instances can share the same job queue.
- **Slight performance overhead** due to database I/O.
- Best choice for:
- Production systems.
- Any scenario where **business continuity and reliability** are critical.
### How ABP Simplifies Quartz Integration
ABP handles Quartz configuration, dependency injection, and lifecycle management automatically. Developers define jobs using `QuartzBackgroundWorkerBase` and access services via `ICachedServiceProvider`, following ABP's standard conventions and leveraging optimal service caching for background job scenarios.
### Benefits of the Integration
- Full support for ABP’s cross-cutting concerns (e.g., multi-tenancy, localization)
- Robust scheduling powered by Quartz
- Built-in logging, error handling, and performance monitoring
- Scales easily without modifying business logic
### Real-World Use Case: Subscription Reminders
In this tutorial, we'll build a subscription reminder system that monitors client subscriptions, identifies those nearing expiration, sends professional email reminders seven days before expiration, tracks reminder history to prevent duplicates, and runs automatically every day at 9:00 AM using Quartz scheduling with PostgreSQL persistence. This system demonstrates how ABP and Quartz work together to solve real business problems with clean, maintainable code that follows enterprise-grade patterns.
## Installing and Configuring Quartz
Getting Quartz up and running in an ABP application is straightforward thanks to ABP's dedicated integration package. We'll replace the default background job system with Quartz for persistent job storage and robust scheduling capabilities.
### Adding the Quartz Package
The easiest way to add Quartz support to your ABP application is using the ABP CLI. Open a terminal in your project directory and run:
```bash
abp add-package Volo.Abp.BackgroundWorkers.Quartz
```
This command automatically adds the necessary NuGet package reference and updates your module dependencies. The ABP CLI handles all the heavy lifting, ensuring you get the correct version that matches your ABP Framework version.
### Configuring Quartz for Persistent Storage
Once the package is installed, you need to configure Quartz to use your database (in my case it is PostgreSQL) for job persistence. This configuration goes in your main module's `PreConfigureServices` method:
```csharp
[DependsOn(
// ... other dependencies
typeof(AbpBackgroundJobsQuartzModule),
typeof(AbpBackgroundWorkersQuartzModule)
)]
public class MySaaSApplicationModule : AbpModule
{
public override void PreConfigureServices(ServiceConfigurationContext context)
{
var hostingEnvironment = context.Services.GetHostingEnvironment();
var configuration = context.Services.GetConfiguration();
ConfigureAuthentication(context, configuration);
ConfigureUrls(configuration);
ConfigureImpersonation(context, configuration);
ConfigureQuartz(); // Add this line
}
private void ConfigureQuartz()
{
PreConfigure<AbpQuartzOptions>(options =>
{
options.Properties = new NameValueCollection
{
["quartz.scheduler.instanceName"] = "QuartzScheduler",
["quartz.jobStore.type"] = "Quartz.Impl.AdoJobStore.JobStoreTX, Quartz",
["quartz.jobStore.tablePrefix"] = "qrtz_",
["quartz.jobStore.dataSource"] = "myDS",
["quartz.dataSource.myDS.connectionString"] = _configuration.GetConnectionString("Default"),
["quartz.dataSource.myDS.provider"] = "Npgsql",
["quartz.serializer.type"] = "json"
};
});
}
}
```
This configuration tells Quartz to store all job information in your PostgreSQL database using tables prefixed with "qrtz_". The key points are:
- **Job Store Type**: Uses ADO.NET with transaction support for reliable job persistence
- **Connection String**: Shares your application's existing database connection
- **Table Prefix**: Keeps Quartz tables separate with the "qrtz_" prefix
- **JSON Serialization**: Makes job data readable and debuggable
- **PostgreSQL Provider**: Uses Npgsql for optimal PostgreSQL integration
When your application starts, ABP automatically initializes the Quartz scheduler with these settings. Any background workers you create will be registered and scheduled automatically, with their state persisted to the database for reliability across application restarts.
For detailed installation options and advanced configuration scenarios, check the official [ABP documentation.](https://abp.io/docs/latest/framework/infrastructure/background-workers/quartz)
## Database Setup for Quartz
With Quartz configured for persistent storage, we need to create the necessary database tables where Quartz will store job definitions, triggers, and execution history. Rather than running SQL scripts directly against the database, we'll use Entity Framework migrations to maintain consistency with ABP's database management approach.
### Creating an Empty Migration for Quartz Tables
Instead of executing raw SQL scripts against the database, we created an empty Entity Framework migration and populated it with the required Quartz table definitions. This approach keeps all database changes within the migration system, ensuring they're version-controlled, repeatable, and consistent across different environments.
To create the empty migration, we used the standard Entity Framework CLI command:
```bash
dotnet ef migrations add AddQuartzTables
```
This generates a new migration file with empty `Up` and `Down` methods that we can populate with the Quartz table creation scripts.
### Adding Quartz SQL Schema to Migration
Once the empty migration was created, we populated it with the PostgreSQL-specific SQL needed to create all Quartz tables. The SQL scripts were obtained from the official Quartz repository, which provides database schema scripts for various database providers:
```csharp
public partial class AddQuartzTables : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.Sql(@"
CREATE TABLE qrtz_job_details (
sched_name VARCHAR(120) NOT NULL,
job_name VARCHAR(200) NOT NULL,
job_group VARCHAR(200) NOT NULL,
description VARCHAR(250) NULL,
job_class_name VARCHAR(250) NOT NULL,
is_durable BOOLEAN NOT NULL,
is_nonconcurrent BOOLEAN NOT NULL,
is_update_data BOOLEAN NOT NULL,
requests_recovery BOOLEAN NOT NULL,
job_data BYTEA NULL,
PRIMARY KEY (sched_name, job_name, job_group)
);
CREATE TABLE qrtz_triggers (
sched_name VARCHAR(120) NOT NULL,
trigger_name VARCHAR(200) NOT NULL,
trigger_group VARCHAR(200) NOT NULL,
job_name VARCHAR(200) NOT NULL,
job_group VARCHAR(200) NOT NULL,
-- ... additional columns and constraints
PRIMARY KEY (sched_name, trigger_name, trigger_group),
FOREIGN KEY (sched_name, job_name, job_group) REFERENCES qrtz_job_details(sched_name, job_name, job_group)
);
-- Additional tables: qrtz_simple_triggers, qrtz_cron_triggers,
-- qrtz_simprop_triggers, qrtz_blob_triggers, qrtz_calendars,
-- qrtz_paused_trigger_grps, qrtz_fired_triggers, qrtz_scheduler_state, qrtz_locks
");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.Sql(@"
DROP TABLE IF EXISTS qrtz_locks;
DROP TABLE IF EXISTS qrtz_scheduler_state;
-- ... drop all other Quartz tables in reverse order
DROP TABLE IF EXISTS qrtz_triggers;
DROP TABLE IF EXISTS qrtz_job_details;
");
}
}
```
The complete SQL scripts for all supported database providers, including PostgreSQL, MySQL, SQL Server, and others, can be found in the official `Quartz.NET` repository. You should use the script that matches your specific database provider and version requirements.
### Why Use Migrations Instead of Direct SQL Scripts?
This migration-based approach offers several important advantages over running SQL scripts directly:
**Version Control Integration**: The migration becomes part of your codebase, tracked in source control alongside your application changes. This means every developer and deployment environment gets the exact same database schema.
**Rollback Capability**: The `Down` method provides a clean way to remove Quartz tables if needed, something that's much harder to manage with standalone SQL scripts.
**Environment Consistency**: Whether you're setting up a development machine, staging server, or production deployment, running DBMigrator or `dotnet ef database update` command ensures the same schema is created everywhere.
**Integration with ABP's Database Management**: This approach aligns perfectly with how ABP manages all other database changes, keeping your database evolution strategy consistent.
The Quartz tables created by this migration handle all aspects of job persistence - from storing job definitions and triggers to tracking execution history and managing scheduler state. With these tables in place, your Quartz scheduler can reliably persist jobs across application restarts and coordinate work across multiple application instances if needed.
After creating this migration, running DBMigrator `dotnet ef database update` will create all the necessary Quartz infrastructure in your PostgreSQL database, ready to store and manage your background jobs.
For complete SQL scripts for your specific database provider, visit the official [Quartz documentation.](https://www.quartz-scheduler.net/documentation/quartz-3.x/quick-start.html#creating-and-initializing-database)
## Building the Business Logic
Before implementing our Quartz background job, we needed to create the essential business entities and services that our subscription reminder system would work with. Since this article focuses on Quartz integration rather than general ABP development patterns, we'll keep this section brief and move quickly to the background job implementation.
### Core Entities and Services
For our subscription reminder system, we created the following core components:
**Entities:**
- **`Client`**: Represents customers with subscription information (Name, Email, SubscriptionEnd, IsActive)
- **`ReminderLog`**: Tracks when reminder emails have been sent to prevent duplicates
**Application Services:**
- **`ClientAppService`**: Handles CRUD operations and provides methods to find clients with expiring subscriptions
- **`ReminderLogAppService`**: Manages reminder history and prevents duplicate notifications
- **`EmailService`**: Sends professional HTML reminder emails via SMTP
**Data Transfer Objects (DTOs):**
- Complete set of DTOs for both entities following ABP conventions
- Input/output DTOs for all service operations
### Business Logic Overview
The system follows standard ABP patterns with entities inheriting from `FullAuditedAggregateRoot`, services implementing `ICrudAppService` interfaces, and proper AutoMapper configurations for entity-DTO mapping. We also included a data seeder to create sample clients for testing purposes.
The key business methods our background job will use are:
- `GetExpiringClientsAsync()` - Finds clients whose subscriptions expire in the next 7 days
- `CreateAsync()` - Logs when a reminder has been sent
- `SendSubscriptionExpiryReminderAsync()` - Sends professional email reminders
### Focus on Background Operations
Rather than diving deep into ABP entity creation, repository patterns, or service layer implementation details, we'll move directly to the heart of this article: implementing robust background jobs with Quartz. The entities and services we created simply provide the business context for our background job to operate within.
The real value of this tutorial lies in showing how ABP's `QuartzBackgroundWorkerBase` integrates seamlessly with your business logic to create reliable, persistent background operations that survive application restarts and scale across multiple instances.
Let's now implement the background job that ties everything together and demonstrates the power of ABP + Quartz integration.
## Implementing the Background Job (The ABP Way)
This is where the magic happens. ABP's integration with Quartz provides a clean, powerful way to create background jobs that follow framework conventions while leveraging Quartz's robust scheduling capabilities. Let's dive into how we implemented our subscription reminder job and explore the advanced features ABP provides.
### Creating a QuartzBackgroundWorkerBase Job
Instead of implementing Quartz's raw `IJob` interface, ABP provides `QuartzBackgroundWorkerBase`, which integrates seamlessly with ABP's dependency injection, logging, and lifecycle management systems:
```csharp
public class SubscriptionExpiryNotifierJob : QuartzBackgroundWorkerBase
{
public SubscriptionExpiryNotifierJob()
{
// Configure the job to run daily at 9:00 AM
JobDetail = JobBuilder.Create<SubscriptionExpiryNotifierJob>()
.WithIdentity(nameof(SubscriptionExpiryNotifierJob))
.Build();
Trigger = TriggerBuilder.Create()
.WithIdentity(nameof(SubscriptionExpiryNotifierJob))
.WithCronSchedule("0 0 9 * * ?") // Every day at 9:00 AM
.Build();
ScheduleJob = async scheduler =>
{
if (!await scheduler.CheckExists(JobDetail.Key))
{
await scheduler.ScheduleJob(JobDetail, Trigger);
}
};
}
public override async Task Execute(IJobExecutionContext context)
{
// Use ICachedServiceProvider for better performance and proper scoping
var serviceProvider = ServiceProvider.GetRequiredService<ICachedServiceProvider>();
// These services will be cached and reused throughout the job execution
var clientAppService = serviceProvider.GetRequiredService<IClientAppService>();
var reminderLogAppService = serviceProvider.GetRequiredService<IReminderLogAppService>();
var emailService = serviceProvider.GetRequiredService<IEmailService>();
Logger.LogInformation("🔄 Starting subscription expiry notification job...");
// 1. Get clients expiring in 7 days
var expiringClients = await clientAppService.GetExpiringClientsAsync(7);
Logger.LogInformation("📋 Found {Count} clients with expiring subscriptions", expiringClients.Count);
// 2. Process each client
foreach (var client in expiringClients)
{
await ProcessClientAsync(client, emailService, reminderLogAppService);
}
Logger.LogInformation("✅ Job completed successfully");
}
}
```
### Key Implementation Features
**Constructor-Based Configuration**: Unlike traditional Quartz jobs that require external scheduling code, ABP's approach lets you define both the job and its schedule directly in the constructor. This keeps related configuration together and makes the job self-contained.
**ABP Service Integration**: The `ICachedServiceProvider` gives you access to any service in ABP's dependency injection container, enabling you to use application services, repositories, domain services, or any other ABP component with optimized caching and proper scoping.
**Built-in Logging**: The `Logger` property provides access to ABP's logging infrastructure, automatically including context like correlation IDs and tenant information in multi-tenant applications.
**Custom Scheduling Logic**: The `ScheduleJob` property allows you to customize how the job gets registered with Quartz. In our example, we check if the job already exists before scheduling it, preventing duplicate registrations during application restarts.
### Understanding Quartz Trigger Types
Quartz provides several trigger types to handle different scheduling requirements. Choosing the right trigger type is crucial for your job's behavior and performance.
#### CronTrigger - Complex Time-Based Scheduling
CronTrigger uses cron expressions for sophisticated scheduling patterns. This is what we used for our daily subscription reminders:
```csharp
// Daily at 9:00 AM
Trigger = TriggerBuilder.Create()
.WithIdentity("DailyReminder")
.WithCronSchedule("0 0 9 * * ?")
.Build();
// Every weekday at 2:30 PM
Trigger = TriggerBuilder.Create()
.WithIdentity("WeekdayReport")
.WithCronSchedule("0 30 14 ? * MON-FRI")
.Build();
// First day of every month at midnight
Trigger = TriggerBuilder.Create()
.WithIdentity("MonthlyCleanup")
.WithCronSchedule("0 0 0 1 * ?")
.Build();
```
**Cron Expression Format**: `Seconds Minutes Hours Day-of-Month Month Day-of-Week Year(optional)`
- `0 0 9 * * ?` = 9:00 AM every day
- `0 */15 * * * ?` = Every 15 minutes
- `0 0 12 ? * SUN` = Every Sunday at noon
#### SimpleTrigger - Interval-Based Scheduling
SimpleTrigger is perfect for jobs that need to run at regular intervals or a specific number of times:
```csharp
// Run every 30 seconds indefinitely
Trigger = TriggerBuilder.Create()
.WithIdentity("HealthCheck")
.StartNow()
.WithSimpleSchedule(x => x
.WithIntervalInSeconds(30)
.RepeatForever())
.Build();
// Run every 5 minutes, but only 10 times
Trigger = TriggerBuilder.Create()
.WithIdentity("LimitedRetry")
.StartNow()
.WithSimpleSchedule(x => x
.WithIntervalInMinutes(5)
.WithRepeatCount(9)) // 0-based, so 9 = 10 executions
.Build();
// One-time execution after 1 hour delay
Trigger = TriggerBuilder.Create()
.WithIdentity("DelayedCleanup")
.StartAt(DateTimeOffset.UtcNow.AddHours(1))
.Build();
```
#### CalendarIntervalTrigger - Calendar-Aware Intervals
CalendarIntervalTrigger handles intervals that need to respect calendar boundaries:
```csharp
// Every month on the same day (handles varying month lengths)
Trigger = TriggerBuilder.Create()
.WithIdentity("MonthlyBilling")
.WithCalendarIntervalSchedule(x => x
.WithIntervalInMonths(1))
.Build();
// Every week, starting Monday
Trigger = TriggerBuilder.Create()
.WithIdentity("WeeklyReport")
.WithCalendarIntervalSchedule(x => x
.WithIntervalInWeeks(1))
.Build();
```
#### DailyTimeIntervalTrigger - Time Windows
DailyTimeIntervalTrigger runs jobs within specific time windows on certain days:
```csharp
// Every 2 hours between 8 AM and 6 PM, Monday through Friday
Trigger = TriggerBuilder.Create()
.WithIdentity("BusinessHoursSync")
.WithDailyTimeIntervalSchedule(x => x
.OnMondayThroughFriday()
.StartingDailyAt(TimeOfDay.HourAndMinuteOfDay(8, 0))
.EndingDailyAt(TimeOfDay.HourAndMinuteOfDay(18, 0))
.WithIntervalInHours(2))
.Build();
```
### Choosing the Right Trigger Type
For different scenarios, you'd choose different trigger types:
- **Daily/Weekly/Monthly Operations**: Use **CronTrigger** for maximum flexibility
- **High-Frequency Tasks**: Use **SimpleTrigger** for performance (every few seconds/minutes)
- **Business Calendar Operations**: Use **CalendarIntervalTrigger** for month-end reports, quarterly tasks
- **Business Hours Operations**: Use **DailyTimeIntervalTrigger** for operations that should only run during specific hours
### Automatic Job Registration
One of ABP's most powerful features is automatic job discovery and registration. When your application starts, ABP automatically:
1. **Scans for Background Workers**: ABP discovers all classes inheriting from `QuartzBackgroundWorkerBase`
2. **Registers with DI Container**: Each job is registered as a service in the dependency injection container
3. **Schedules with Quartz**: ABP calls the `ScheduleJob` delegate to register the job with the Quartz scheduler
4. **Handles Lifecycle**: ABP manages starting and stopping jobs with the application lifecycle
This means you simply create your job class, and ABP handles everything else. No manual registration, no startup code, no configuration files - it just works.
### Understanding Misfire Handling
Misfires occur when a scheduled job cannot execute at its intended time, typically due to system downtime, resource constraints, or the scheduler being paused. Quartz provides several misfire instructions to handle these scenarios:
#### CronTrigger Misfire Instructions
For cron-based schedules like our daily reminder job, Quartz offers these misfire behaviors:
**`MisfireInstruction.DoNothing`** (Default):
```csharp
Trigger = TriggerBuilder.Create()
.WithIdentity(nameof(SubscriptionExpiryNotifierJob))
.WithCronSchedule("0 0 9 * * ?", x => x.WithMisfireHandlingInstructionDoNothing())
.Build();
```
- Skips all missed executions
- Waits for the next naturally scheduled time
- Best for jobs where missing executions is acceptable
**`MisfireInstruction.FireOnceNow`**:
```csharp
.WithCronSchedule("0 0 9 * * ?", x => x.WithMisfireHandlingInstructionFireAndProceed())
```
- Immediately executes one missed job upon recovery
- Then continues with the normal schedule
- Useful when you need to catch up on missed work
**`MisfireInstruction.IgnoreMisfires`**:
```csharp
.WithCronSchedule("0 0 9 * * ?", x => x.WithMisfireHandlingInstructionIgnoreMisfires())
```
- Executes all missed jobs immediately upon recovery
- Can cause a burst of executions after extended downtime
- Use carefully to avoid overwhelming the system
#### SimpleTrigger Misfire Instructions
Simple triggers have their own set of misfire behaviors:
**`MisfireInstruction.FireNow`**: Execute immediately when recovered
**`MisfireInstruction.RescheduleNowWithExistingRepeatCount`**: Start over with remaining repeat count
**`MisfireInstruction.RescheduleNowWithRemainingRepeatCount`**: Continue as if no misfire occurred
**`MisfireInstruction.RescheduleNextWithExistingCount`**: Wait for next interval, keep original repeat count
### Real-World Misfire Considerations
For our subscription reminder system, we chose the default `DoNothing` behavior because:
- **Business Logic**: Sending yesterday's reminder today might confuse customers
- **Duplicate Prevention**: Our job checks for existing reminders, so running late won't cause duplicate emails
- **Resource Management**: We avoid overwhelming the email system after extended downtime
However, for other scenarios you might choose differently:
- **Financial reporting**: Use `FireOnceNow` to ensure reports are always generated
- **Data synchronization**: Use `IgnoreMisfires` to process all missed sync operations
- **Cache warming**: Use `DoNothing` since stale cache warming provides no value
### Advanced Job Features
**Error Handling and Resilience**: Our job implementation includes comprehensive error handling for individual client processing, ensuring one failed email doesn't stop the entire batch:
```csharp
try
{
await emailService.SendSubscriptionExpiryReminderAsync(/*...*/);
await LogReminderAsync(client.Id, client.SubscriptionEnd, "Email sent successfully", reminderLogAppService);
}
catch (Exception ex)
{
Logger.LogError(ex, "❌ Failed to send reminder to {ClientName}", client.Name);
await LogReminderAsync(client.Id, client.SubscriptionEnd, $"Failed: {ex.Message}", reminderLogAppService);
}
```
**Duplicate Prevention**: The job checks for existing reminders to prevent sending multiple emails on the same day, even if the job runs multiple times:
```csharp
private async Task<bool> AlreadySentTodayAsync(Guid clientId, IReminderLogAppService reminderLogAppService)
{
var todayReminders = await reminderLogAppService.GetByClientIdAsync(clientId);
var today = DateTime.UtcNow.Date;
return todayReminders.Any(r => r.ReminderDate.Date == today);
}
```
This implementation demonstrates how ABP's `QuartzBackgroundWorkerBase` provides a clean, powerful foundation for building robust background jobs that integrate seamlessly with your business logic while leveraging Quartz's enterprise-grade scheduling capabilities.
## Conclusion
You've successfully built a production-ready subscription reminder system that demonstrates the powerful synergy between ABP Framework and `Quartz.NET`. This isn't just a tutorial example - it's a robust, enterprise-grade solution that handles real business requirements.
### What We Accomplished
**✅ Enterprise-Grade Reliability**: PostgreSQL persistence ensures jobs survive restarts and deployments
**✅ ABP Best Practices**: Used `QuartzBackgroundWorkerBase`, `ICachedServiceProvider`, and ABP's logging infrastructure
**✅ Real Business Value**: Automated subscription reminders with duplicate prevention and audit logging
**✅ Flexible Scheduling**: Explored cron expressions, trigger types, and misfire handling strategies
### The Power of ABP + Quartz Integration
The combination delivers exceptional value through automatic job discovery, persistent scheduling, built-in dependency injection, and seamless framework integration. You get enterprise reliability with developer-friendly simplicity.
### Final Thoughts
Complex background processing doesn't have to be complicated to implement. ABP's thoughtful abstractions combined with Quartz's proven engine create a development experience that's both powerful and enjoyable.
Whether you're building subscription management, financial reporting, or data synchronization, these patterns provide a solid foundation for reliable, maintainable solutions.
You can reach sample project's source code from [here](https://github.com/MansurBesleney/MySaaSApplication)
**Happy coding, and may your background jobs never miss a beat!** 🚀

BIN
docs/en/Community-Articles/2025-08-12-Integration-Services-Explained/integration-services.jpeg

Binary file not shown.

After

Width:  |  Height:  |  Size: 126 KiB

138
docs/en/Community-Articles/2025-08-12-Integration-Services-Explained/post.md

@ -0,0 +1,138 @@
# Integration Services in ABP — What they are, when to use them, and how they behave 🚦
If you’ve been building with ABP for a while, you’ve probably used Application Services for your UI and APIs in your .NET and ASP.NET Core apps. Integration Services are similar—but with a different mission: they exist for service-to-service or module-to-module communication, not for end users.
If you want the formal spec, see the official doc: [Integration Services](../../framework/api-development/integration-services.md). This post is the practical, no-fluff guide.
## What is an Integration Service?
An Integration Service is an application service or ASP.NET Core MVC controller marked with the `[IntegrationService]` attribute. That marker tells ABP “this endpoint is for internal communication.”
- They are not exposed by default (safer for reusable modules and monoliths).
- When exposed, their route prefix is `/integration-api` (so you can easily protect them at your gateway or firewall).
- Auditing is disabled by default for them (less noise for machine-to-machine calls).
Quick look:
```csharp
[IntegrationService]
public interface IProductIntegrationService : IApplicationService
{
Task<List<ProductDto>> GetProductsByIdsAsync(List<Guid> ids);
}
public class ProductIntegrationService : ApplicationService, IProductIntegrationService
{
public Task<List<ProductDto>> GetProductsByIdsAsync(List<Guid> ids)
{
// fetch and return minimal product info for other services/modules
}
}
```
## Are they HTTP endpoints?
- By default: no (they won’t be reachable over HTTP in the ASP.NET Core routing pipeline).
- If you need them over HTTP (typically for microservices), explicitly enable:
```csharp
Configure<AbpAspNetCoreMvcOptions>(options =>
{
options.ExposeIntegrationServices = true;
});
```
Once exposed, ABP puts them under `/integration-api/...` instead of `/api/...` in the ASP.NET Core routing pipeline. That’s your hint to restrict them from public internet access.
## Enable auditing (optional)
If you want audit logs for integration calls, enable it explicitly:
```csharp
Configure<AbpAuditingOptions>(options =>
{
options.IsEnabledForIntegrationServices = true;
});
```
## When should you use Integration Services?
- Internal, synchronous operations between services or modules.
- You need a “thin” API designed for other services (not for UI): minimal DTOs, no view concerns, predictable contracts.
- You want to hide these endpoints from public clients, or only allow them inside your private network or k8s cluster.
- You’re packaging a reusable module that might be used in both monolith and microservice deployments.
## When NOT to use them
- Public APIs or anything intended for browsers/mobile apps → use regular application services/controllers.
- Asynchronous cross-service workflows → consider domain events + outbox/inbox; use Integration Services for sync calls.
- Complex, chatty UI endpoints → those belong to your external API surface, not internal integration.
## Common use-cases and examples
- Identity lookups across services: an Ordering service needs basic user info from the Identity service.
- Permission checks from another module: a CMS module asks a Permission service for access decisions.
- Product data hydrations: a Cart service needs minimal product details (price, name) from Catalog.
- Internal admin/maintenance operations that aren’t meant for end users but are needed by other services.
## Example: microservice-to-microservice call
1) Mark and expose the integration service in the target service:
```csharp
[IntegrationService]
public interface IUserIntegrationService : IApplicationService
{
Task<UserBriefDto?> FindByIdAsync(Guid id);
}
Configure<AbpAspNetCoreMvcOptions>(o => o.ExposeIntegrationServices = true);
```
2) In the caller service, add an HTTP client proxy only for Integration Services if you like to keep things clean:
```csharp
services.AddHttpClientProxies(
typeof(TargetServiceApplicationModule).Assembly,
remoteServiceConfigurationName: "TargetService",
asDefaultServices: true,
applicationServiceTypes: ApplicationServiceTypes.IntegrationServices);
```
3) Call it just like a local service (ABP’s HTTP proxy handles the wire):
```csharp
public class OrderAppService : ApplicationService
{
private readonly IUserIntegrationService _userIntegrationService;
public OrderAppService(IUserIntegrationService userIntegrationService)
{
_userIntegrationService = userIntegrationService;
}
public async Task PlaceOrderAsync(CreateOrderDto input)
{
var user = await _userIntegrationService.FindByIdAsync(CurrentUser.GetId());
// validate user status, continue placing order...
}
}
```
## Monolith vs. Microservices
- Monolith: keep them unexposed and call via DI in-process. You get the same clear contract with zero network overhead.
- Microservices: expose them and route behind your gateway. The `/integration-api` prefix makes it easy to firewall/gateway-restrict.
## Practical tips
- Keep integration DTOs lean and stable. These are machine contracts—don’t mix UI concerns.
- Name them clearly (e.g., `UserIntegrationService`) so intent is obvious.
- Guard your ASP.NET Core gateway application: block `/integration-api/*` from public traffic.
- Enable auditing only if you truly need the logs for these calls.
## Further reading
- Official docs: [Integration Services](../../framework/api-development/integration-services.md)
That’s it! Integration Services give you a clean, intentional way to design internal APIs—great in monoliths, essential in microservices.

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

@ -42,6 +42,8 @@ ABP supports all the following approaches to store the tenant data in the databa
[Saas module (PRO)](../../../modules/saas.md) allows you to set a connection string for any tenant (as optional), so you can achieve any of the approaches.
> You can see the community article *[Multi-Tenancy with Separate Databases in .NET and ABP Framework](https://abp.io/community/articles/multitenancy-with-separate-databases-in-dotnet-and-abp-51nvl4u9)* for more details about different database architectures with practical implementation details.
## Usage
Multi-tenancy system is designed to **work seamlessly** and make your application code **multi-tenancy unaware** as much as possible.
@ -456,8 +458,9 @@ The [Tenant Management module](../../../modules/tenant-management.md) provides a
### A note about separate database per tenant approach in open source version
While ABP fully supports this option, managing connection strings of tenants from the UI is not available in open source version. You need to have [Saas module (PRO)](../../../modules/saas.md).
Alternatively you can implement this feature yourself by customizing the tenant management module and tenant application service to create and migrate the database on the fly.
Alternatively, you can implement this feature yourself by customizing the tenant management module and tenant application service to create and migrate the database on the fly.
## See Also
* [Features](../../infrastructure/features.md)
* [Article: Multi-Tenancy with Separate Databases in .NET and ABP Framework](https://abp.io/community/articles/multitenancy-with-separate-databases-in-dotnet-and-abp-51nvl4u9)

16
docs/en/framework/fundamentals/object-extensions.md

@ -394,6 +394,22 @@ public class MyProfile : Profile
It has the same parameters with the `MapExtraPropertiesTo` method.
#### Mapperly Integration
If you're using the [Mapperly](https://github.com/riok/mapperly) library, the ABP also provides an extension method to utilize the `MapExtraPropertiesTo` method defined above.
You can use the `MapExtraProperties` attribute to Mapperly class:
````csharp
[Mapper]
[MapExtraProperties]
public partial class IdentityUserToProfileDtoMapper : MapperBase<IdentityUser, IdentityUserDto>
{
public override partial IdentityUserDto Map(IdentityUser source);
public override partial void Map(IdentityUser source, IdentityUserDto destination);
}
````
## Entity Framework Core Database Mapping
If you're using the EF Core, you can map an extra property to a table field in the database. Example:

129
docs/en/framework/infrastructure/object-to-object-mapping.md

@ -84,7 +84,7 @@ public class UserAppService : ApplicationService
}
````
You should have defined the mappings before to be able to map objects. See the AutoMapper integration section to learn how to define mappings.
You should have defined the mappings before to be able to map objects. See the AutoMapper/Mapperly integration section to learn how to define mappings.
## AutoMapper Integration
@ -217,13 +217,120 @@ public class MyProfile : Profile
}
````
## Mapperly Integration
[Mapperly](https://github.com/riok/mapperly) is a .NET source generator for generating object mappings. [Volo.Abp.Mapperly](https://www.nuget.org/packages/Volo.Abp.Mapperly) package defines the Mapperly integration for the `IObjectMapper`.
Once you define mappings class as below, you can use the `IObjectMapper` interface just like explained before.
### Define Mapping Classes
You can define a mapper class by using the `Mapper` attribute. The class and methods must be `partial` to allow the Mapperly to generate the implementation during the build process:
````csharp
[Mapper]
public partial class UserToUserDtoMapper : MapperBase<User, UserDto>
{
public override partial UserDto Map(User source);
public override partial void Map(User source, UserDto destination);
}
````
If you also want to map `UserDto` to `User`, you can inherit from the `TwoWayMapperBase<User, UserDto>` class:
````csharp
[Mapper]
public partial class UserToUserDtoMapper : TwoWayMapperBase<User, UserDto>
{
public override partial UserDto Map(User source);
public override partial void Map(User source, UserDto destination);
public override partial User ReverseMap(UserDto destination);
public override partial void ReverseMap(UserDto destination, User source);
}
````
### Before and After Mapping Methods
The base class provides `BeforeMap` and `AfterMap` methods that can be overridden to perform actions before and after the mapping:
````csharp
[Mapper]
public partial class UserToUserDtoMapper : TwoWayMapperBase<User, UserDto>
{
public override partial UserDto Map(User source);
public override partial void Map(User source, UserDto destination);
public override partial void BeforeMap(User source)
{
//TODO: Perform actions before the mapping
}
public override partial void AfterMap(User source, UserDto destination)
{
//TODO: Perform actions after the mapping
}
public override partial User ReverseMap(UserDto destination);
public override partial void ReverseMap(UserDto destination, User source);
public override partial void BeforeReverseMap(UserDto destination)
{
//TODO: Perform actions before the reverse mapping
}
public override partial void AfterReverseMap(UserDto destination, User source)
{
//TODO: Perform actions after the reverse mapping
}
}
````
### Mapping the Object Extensions
[Object extension system](../fundamentals/object-extensions.md) allows to define extra properties for existing classes. ABP provides a mapping definition extension to properly map extra properties of two objects:
````csharp
[Mapper]
[MapExtraProperties]
public partial class UserToUserDtoMapper : MapperBase<User, UserDto>
{
public override partial UserDto Map(User source);
public override partial void Map(User source, UserDto destination);
}
````
It is suggested to use the `MapExtraPropertiesAttribute` attribute if both classes are extensible objects (implement the `IHasExtraProperties` interface). See the [object extension document](../fundamentals/object-extensions.md) for more.
### Lists and Arrays Support
ABP Mapperly integration also supports mapping lists and arrays as explained in the [IObjectMapper<TSource, TDestination> Interface](#iobjectmappertsource-tdestination-interface) section.
**Example**:
````csharp
[Mapper]
public partial class UserToUserDtoMapper : MapperBase<User, UserDto>
{
public override partial UserDto Map(User source);
public override partial void Map(User source, UserDto destination);
}
var users = await _userRepository.GetListAsync(); // returns List<User>
var dtos = ObjectMapper.Map<List<User>, List<UserDto>>(users); // creates List<UserDto>
````
### More Mapperly Features
Most of Mapperly's features such as `Ignore` can be configured through its attributes. See the [Mapperly documentation](https://mapperly.riok.app/docs/intro/) for more details.
## Advanced Topics
### IObjectMapper<TContext> Interface
Assume that you have created a **reusable module** which defines AutoMapper profiles and uses `IObjectMapper` when it needs to map objects. Your module then can be used in different applications, by nature of the [modularity](../architecture/modularity/basics.md).
Assume that you have created a **reusable module** which defines AutoMapper/Mapperly profiles and uses `IObjectMapper` when it needs to map objects. Your module then can be used in different applications, by nature of the [modularity](../architecture/modularity/basics.md).
`IObjectMapper` is an abstraction and can be replaced by the final application to use another mapping library. The problem here that your reusable module is designed to use the AutoMapper library, because it only defines mappings for it. In such a case, you will want to guarantee that your module always uses AutoMapper even if the final application uses another default object mapping library.
`IObjectMapper` is an abstraction and can be replaced by the final application to use another mapping library. The problem here that your reusable module is designed to use the AutoMapper/Mapperly library, because it only defines mappings for it. In such a case, you will want to guarantee that your module always uses AutoMapper/Mapperly even if the final application uses another default object mapping library.
`IObjectMapper<TContext>` is used to contextualize the object mapper, so you can use different libraries for different modules/contexts.
@ -281,6 +388,8 @@ public class UserAppService : ApplicationService
While using the contextualized object mapper is same as the normal object mapper, you should register the contextualized mapper in your module's `ConfigureServices` method:
When using AutoMapper:
````csharp
[DependsOn(typeof(AbpAutoMapperModule))]
public class MyModule : AbpModule
@ -298,6 +407,20 @@ public class MyModule : AbpModule
}
````
When using Mapperly:
````csharp
[DependsOn(typeof(AbpMapperlyModule))]
public class MyModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
//Use Mapperly for MyModule
context.Services.AddMapperlyObjectMapper<MyModule>();
}
}
````
`IObjectMapper<MyModule>` is an essential feature for a reusable module where it can be used in multiple applications each may use a different library for object to object mapping. All pre-built ABP modules are using it. But, for the final application, you can ignore this interface and always use the default `IObjectMapper` interface.
### IObjectMapper<TSource, TDestination> Interface

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

@ -1,12 +1,12 @@
# ABP Angular Quick Start
**In this version ABP uses Angular [17.3.x](https://github.com/angular/angular/tree/17.3.x) version. You don't have to install Angular CLI globally**
**In this version ABP uses Angular [20.0.x](https://github.com/angular/angular/tree/20.0.x) version. You don't have to install Angular CLI globally**
## How to Prepare Development Environment
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 `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.
1. **Install Node.js:** Please visit [Node.js downloads page](https://nodejs.org/en/download/) and download proper Node.js `v20.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.
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)

32
docs/en/framework/ui/blazor/layout-hooks.md

@ -2,7 +2,7 @@
ABP theming system places the page layout into the [theme](theming.md) NuGet packages. That means the final application doesn't include a layout, so you can't directly change the layout code to customize it.
> If you create a Blazor WASM project, the `index.html` file will be included within the template. You can also customize it to your needs.
> If you created your Blazor application with ABP templates, then you'll have an `App.razor` file in your project. You can customize it to your needs and even extend it with layout hooks.
You can copy the theme code into your solution. In this case, you are completely free to customize it. However, then you won't be able to get automatic updates of the theme (by upgrading the theme NuGet package).
@ -101,11 +101,41 @@ See the *Layouts* section below to learn more about the layout system.
There are some pre-defined layout hook points. The standard hook points are:
* `LayoutHooks.Head.First`: Used to add a component as the first item in the HTML head tag.
* `LayoutHooks.Head.Last`: Used to add a component as the last item in the HTML head tag.
* `LayoutHooks.Body.First`: Used to add a component as the first item in the HTML body tag.
* `LayoutHooks.Body.Last`: Used to add a component as the last item in the HTML body tag.
> You (or the modules you are using) can add **multiple items to the same hook point**. All of them will be added to the layout in the order they were added.
### Render LayoutHooks.Head in App.razor
In your Blazor application, there is an `App.razor` file, which acts as the entry point of your application. If you need to render layout hooks between the **head** tags, then you should manually register the layout hooks as below:
```csharp
@using Volo.Abp.AspNetCore.Components.Web.Theming.Components.LayoutHooks;
@using Volo.Abp.Ui.LayoutHooks;
@using Volo.Abp.AspNetCore.Components.Web.Theming.Layout;
<!DOCTYPE html>
<html>
<head>
<LayoutHook Name="@LayoutHooks.Head.First" Layout="@StandardLayouts.Application" />
// Your head content
// ...
<LayoutHook Name="@LayoutHooks.Head.Last" Layout="@StandardLayouts.Application" />
</head>
<body>
// Your body content
// ...
</body>
</html>
```
After registering the related layout hooks, you can define components to render in the specific place accordingly as mentioned above.
## Layouts
The layout system allows themes to define the standard named layouts and allows any page to select a proper layout for its purpose. There is one pre-defined layout:

BIN
docs/en/get-started/images/abp-studio-created-new-solution_dark.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 118 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

BIN
docs/en/get-started/images/abp-studio-new-solution-dialog-database-configurations-efcore_dark.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

BIN
docs/en/get-started/images/abp-studio-new-solution-dialog-database-configurations-mongo_dark.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

BIN
docs/en/get-started/images/abp-studio-new-solution-dialog-database-provider-efcore_dark.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

BIN
docs/en/get-started/images/abp-studio-new-solution-dialog-database-provider-mongo_dark.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

BIN
docs/en/get-started/images/abp-studio-new-solution-dialog-ui-framework-blazor-server_dark.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 81 KiB

BIN
docs/en/get-started/images/abp-studio-new-solution-dialog-ui-framework-blazor-wasm_dark.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

BIN
docs/en/get-started/images/abp-studio-new-solution-dialog-ui-framework-blazor-webapp_dark.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

BIN
docs/en/get-started/images/abp-studio-new-solution-language-selection_dark.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 67 KiB

BIN
docs/en/get-started/images/abp-studio-no-layers-created-new-solution_dark.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

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

Loading…
Cancel
Save