@ -0,0 +1,203 @@ |
|||
# ABP Platform 9.3 RC Has Been Released |
|||
|
|||
We are happy to release [ABP](https://abp.io) version **9.3 RC** (Release Candidate). This blog post introduces the new features and important changes in this new version. |
|||
|
|||
Try this version and provide feedback for a more stable version of ABP v9.3! Thanks to you in advance. |
|||
|
|||
## Get Started with the 9.3 RC |
|||
|
|||
You can check the [Get Started page](https://abp.io/get-started) to see how to get started with ABP. You can either download [ABP Studio](https://abp.io/get-started#abp-studio-tab) (**recommended**, if you prefer a user-friendly GUI application - desktop application) or use the [ABP CLI](https://abp.io/docs/latest/cli). |
|||
|
|||
By default, ABP Studio uses stable versions to create solutions. Therefore, if you want to create a solution with a preview version, first you need to create a solution and then switch your solution to the preview version from the ABP Studio UI: |
|||
|
|||
 |
|||
|
|||
## Migration Guide |
|||
|
|||
There are a few breaking changes in this version that may affect your application. Please read the migration guide carefully, if you are upgrading from v9.2 or earlier: [ABP Version 9.3 Migration Guide](https://abp.io/docs/9.3/release-info/migration-guides/abp-9-3) |
|||
|
|||
## What's New with ABP v9.3? |
|||
|
|||
In this section, I will introduce some major features released in this version. |
|||
Here is a brief list of titles explained in the next sections: |
|||
|
|||
* Cron Expression Support for Background Workers |
|||
* Docs Module: PDF Export |
|||
* Angular UI: Standalone Package Structure |
|||
* Upgraded to Blazorise v1.7.7 |
|||
* Audit Logging Module: Excel Export |
|||
|
|||
### Cron Expression Support for Background Workers |
|||
|
|||
We've enhanced the [Background Workers System](https://abp.io/docs/9.3/framework/infrastructure/background-workers) by adding support for Cron expressions when using [Hangfire](https://abp.io/docs/9.3/framework/infrastructure/background-workers/hangfire) or [Quartz](https://abp.io/docs/9.3/framework/infrastructure/background-workers/quartz) as the background worker manager. This new feature provides more flexibility in scheduling background tasks compared to the simple period-based timing system. |
|||
|
|||
Now you can define complex scheduling patterns using standard Cron expressions. For example, you can schedule a task to run: "Every day at midnight", "Every Monday at 9 AM", or "First day of every month". |
|||
|
|||
Here's how you can use it in your background worker: |
|||
|
|||
```csharp |
|||
public class MyPeriodicBackgroundWorker : AsyncPeriodicBackgroundWorkerBase |
|||
{ |
|||
public MyPeriodicBackgroundWorker( |
|||
AbpAsyncTimer timer, |
|||
IServiceScopeFactory serviceScopeFactory) |
|||
: base(timer, serviceScopeFactory) |
|||
{ |
|||
// You can either use Period for simple intervals |
|||
Timer.Period = 600000; //10 minutes |
|||
|
|||
// 👇 or use CronExpression for more complex scheduling 👇 |
|||
CronExpression = "0 0/10 * * * ?"; //Run every 10 minutes |
|||
} |
|||
|
|||
protected async override Task DoWorkAsync( |
|||
PeriodicBackgroundWorkerContext context) |
|||
{ |
|||
// Your background work... |
|||
} |
|||
} |
|||
``` |
|||
|
|||
The `CronExpression` property takes precedence over the `Period` property when both are set. This feature is available when you use either the [Hangfire](https://abp.io/docs/9.3/framework/infrastructure/background-workers/hangfire) or [Quartz](https://abp.io/docs/9.3/framework/infrastructure/background-workers/quartz) background worker managers. |
|||
|
|||
> See the [Background Workers documentation](https://abp.io/docs/9.3/framework/infrastructure/background-workers) for more information about configuring and using background workers with Cron expressions. |
|||
|
|||
### Docs Module: PDF Export |
|||
|
|||
We're excited to introduce a new feature in the Docs Module that allows users to export documentation as PDF files. This feature makes it easier for users to access documentation offline or share it with team members who might not have immediate access to the online documentation system. |
|||
|
|||
**Administrators can generate PDF files from the back-office side**: |
|||
|
|||
 |
|||
|
|||
and **then a "Download PDF" button appears in the document system** (as shown in the image below - the bottom right of the navigation menu -), allowing users to download the compiled documentation as a PDF file: |
|||
|
|||
 |
|||
|
|||
The feature supports multiple versions of documentation, different language variants, and ensures proper formatting of all content including code blocks and technical documentation. |
|||
|
|||
### Angular UI: Standalone Package Structure |
|||
|
|||
ABP v9.3 introduces support for Angular's standalone components architecture while maintaining **full compatibility with existing module-based applications**. This update aligns with Angular's strategic direction toward standalone components as the recommended approach for building Angular applications. |
|||
|
|||
The key improvements include: |
|||
|
|||
* **Dual-support routing configurations** that work seamlessly with both module-based and standalone approaches |
|||
* **ABP Suite integration** for generating code that supports standalone components |
|||
* **Updated schematics** that provide templates for both development patterns |
|||
|
|||
This enhancement gives developers the flexibility to choose their preferred Angular architecture. Existing module-based applications **continue to work without modifications**, while new projects can leverage the standalone approach for simplified dependency management, reduced boilerplate code, and better lazy-loading capabilities. |
|||
|
|||
> For developers interested in migrating to standalone components or starting new projects, we'll be publishing a comprehensive blog post with detailed guidance and best practices. In the meantime, you can check [#22829](https://github.com/abpframework/abp/pull/22829) for implementation details of the standalone package structure and make the necessary changes to your project. |
|||
|
|||
### Upgraded to Blazorise v1.7.7 |
|||
|
|||
Upgraded the [Blazorise](https://blazorise.com/) library to v1.7.7 for Blazor UI. If you are upgrading your project to v9.3.0, please ensure that all the Blazorise-related packages are using v1.7.7 in your application. Otherwise, you might get errors due to incompatible versions. |
|||
|
|||
> See [#23013](https://github.com/abpframework/abp/pull/23013) for the updated NuGet packages. |
|||
|
|||
### Audit Logging Module: Excel Export |
|||
|
|||
In this version, we've added Excel export capabilities to the [Audit Logging Module](https://abp.io/docs/latest/modules/audit-logging-pro), allowing administrators to export audit logs and entity changes to Excel files for further analysis or reporting purposes. |
|||
|
|||
 |
|||
|
|||
This feature enables users to: |
|||
|
|||
- Export audit logs with filtering options |
|||
- Export entity changes with detailed information |
|||
- Receive email notifications when exports are completed or fail |
|||
- Download exported files via secure links |
|||
|
|||
The export process runs in the background, and once completed, users receive an email with a download link. This approach ensures that even large audit log exports don't block the UI or time out during processing. |
|||
|
|||
You can configure various aspects of this feature using the `AuditLogExcelFileOptions` in your module's configuration: |
|||
|
|||
```csharp |
|||
Configure<AuditLogExcelFileOptions>(options => |
|||
{ |
|||
// How long to keep exported files before cleanup |
|||
options.FileRetentionHours = 48; |
|||
|
|||
// Base URL for download links in notification emails |
|||
options.DownloadBaseUrl = "https://yourdomain.com"; |
|||
|
|||
// Configure the cleanup worker schedule |
|||
options.ExcelFileCleanupOptions.Period = (int)TimeSpan.FromHours(24).TotalMilliseconds; |
|||
|
|||
// Use cron expression for more advanced scheduling (requires Hangfire or Quartz) |
|||
options.ExcelFileCleanupOptions.CronExpression = "0 2 * * *"; // Run at 2 AM daily |
|||
}); |
|||
``` |
|||
|
|||
The module includes pre-configured email templates for notifications about completed or failed exports, ensuring users are always informed about the status of their export requests. |
|||
|
|||
> **Note**: This feature requires a configured BLOB storage provider to store the generated Excel files. See the [BLOB Storing documentation](https://abp.io/docs/9.3/framework/infrastructure/blob-storing) for more information. |
|||
|
|||
For more details about the Audit Logging Module and its Excel export capabilities, please refer to the [official documentation](https://abp.io/docs/9.3/modules/audit-logging-pro). |
|||
|
|||
## Community News |
|||
|
|||
### Announcing ABP Studio 1.0 General Availability 🚀 |
|||
|
|||
 |
|||
|
|||
We are thrilled to announce that ABP Studio has reached version 1.0 and is now generally available! This marks a significant milestone for our integrated development environment designed specifically for ABP developers. The stable release brings several powerful features including: |
|||
|
|||
* Enhanced Solution Runner with health monitoring capabilities |
|||
* Theme style selection during project creation (Basic, LeptonX Lite, and LeptonX Themes) |
|||
* New "Container" application type for better Docker container management |
|||
* Improved handling of multiple DbContexts for migration operations |
|||
|
|||
> For a detailed overview of these features and to learn more about what's coming next, check out our [announcement post](https://abp.io/community/articles/announcing-abp-studio-1-0-general-availability-82yw62bt). |
|||
|
|||
### ABP Community Talks 2025.05: Empower Elsa Workflows with AI in .NET + ABP Framework |
|||
|
|||
In this episode of ABP Community Talks, 2025.05, we are thrilled to host [**Sipke Schoorstra**](https://github.com/sfmskywalker), the creator of the [Elsa Workflows](https://docs.elsaworkflows.io/) library! This month's session is all about **"Empower Elsa Workflows with AI in .NET + ABP Framework"**. |
|||
|
|||
 |
|||
|
|||
Sipke will join us to demonstrate how you can leverage AI within Elsa Workflows using .NET and the ABP Framework. The session will explore practical techniques and showcase how to integrate AI capabilities to enhance and automate your business processes within the Elsa workflow engine. |
|||
|
|||
> 👉 Don't miss this opportunity to learn directly from the creator of Elsa and see real-world examples of building intelligent, automated workflows! You can register from [here](https://kommunity.com/volosoft/events/abp-community-talks-202505empower-elsa-workflows-with-ai-in-netabp-framework-3965dd32). |
|||
|
|||
### ABP Bootcamp: Mastering Infrastructure & Features |
|||
|
|||
We are excited to announce the very first **ABP Bootcamp: Mastering Infrastructure & Features**! This is a live training program designed to give you hands-on, practical experience with ABP's core infrastructure and features. |
|||
|
|||
 |
|||
|
|||
Join the ABP Bootcamp to learn directly from the core team in a focused, hands-on program designed for busy developers. Over four days, you'll gain a deep understanding of ABP's infrastructure, best practices, and practical skills you can immediately apply to your projects. |
|||
|
|||
> **Seats are limited!** Don't miss this opportunity to level up your ABP skills with direct guidance from the experts. |
|||
> |
|||
> 👉 [See full details and reserve your seat!](https://abp.io/bootcamp) |
|||
|
|||
### New ABP Community Articles |
|||
|
|||
There are exciting articles contributed by the ABP community as always. I will highlight some of them here: |
|||
|
|||
* [Prabhjot Singh](https://abp.io/community/members/prabhjot) has published 3 new articles: |
|||
* [Accessing Multiple Remote ABP based Backends Using HttpApi.Client](https://abp.io/community/articles/consume-multi-backends-using-clients-6f4vcggh) |
|||
* [Adopting the new .slnx format to organize applications and services](https://abp.io/community/articles/adopting-the-new-.slnx-format-to-organize-applications-6cm3vl8k) |
|||
* [Replacing Dynamic client proxies with Static client proxies](https://abp.io/community/articles/replacing-dynamic-client-proxies-with-static-client-proxies-g30lf0vx) |
|||
* [Liming Ma](https://github.com/maliming) has published 2 new articles: |
|||
* [Resolving Tenant from Route in ABP Framework](https://abp.io/community/articles/resolving-tenant-from-route-in-abp-framework-ah7oru97) |
|||
* [Integrating .NET AI Chat Template with ABP Framework](https://abp.io/community/articles/integrating-.net-ai-chat-template-with-abp-framework-qavb5p2j) |
|||
* [Engincan Veske](https://engincanveske.substack.com/) has published 2 new articles: |
|||
* [Understanding HttpApi.Client Project & Remote Services in an ABP Based Application](https://abp.io/community/articles/http-api-client-and-remote-services-in-abp-based-application-xkknsp6m) |
|||
* [Using Elsa 3 with the ABP Framework: A Comprehensive Guide](https://abp.io/community/articles/using-elsa-3-workflow-with-abp-framework-usqk8afg) |
|||
* [Enis Necipoğlu](https://github.com/enisn) has published 2 new articles: |
|||
* [White Labeling in ABP Framework](https://abp.io/community/articles/white-labeling-in-abp-framework-5trwmrfm) by [Enis Necipoğlu](https://github.com/enisn) |
|||
* [You do it wrong! Customizing ABP Login Page Correctly](https://abp.io/community/articles/you-do-it-wrong-customizing-abp-login-page-correctly-bna7wzt5) |
|||
* [New in ABP Studio: Docker Container Management](https://abp.io/community/articles/abp-studio-docker-container-management-ex7r27y8) by [Yunus Emre Kalkan](https://github.com/yekalkan) |
|||
* [Solving MongoDB GUID Issues After an ABP Framework Upgrade](https://abp.io/community/articles/solving-mongodb-guid-issues-after-an-abp-framework-upgrade-tv8waw1n) by [Burak Demir](https://abp.io/community/members/burakdemir) |
|||
|
|||
|
|||
Thanks to the ABP Community for all the content they have published. You can also [post your ABP-related (text or video) content](https://abp.io/community/posts/create) to the ABP Community. |
|||
|
|||
## Conclusion |
|||
|
|||
This version comes with some new features and a lot of enhancements to the existing features. You can see the [Road Map](https://abp.io/docs/9.3/release-info/road-map) documentation to learn about the release schedule and planned features for the next releases. Please try ABP v9.3 RC and provide feedback to help us release a more stable version. |
|||
|
|||
Thanks for being a part of this community! |
|||
|
After Width: | Height: | Size: 455 KiB |
|
After Width: | Height: | Size: 147 KiB |
|
After Width: | Height: | Size: 300 KiB |
|
After Width: | Height: | Size: 239 KiB |
|
After Width: | Height: | Size: 676 KiB |
|
After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 23 KiB |
|
After Width: | Height: | Size: 34 KiB |
|
After Width: | Height: | Size: 180 KiB |
|
After Width: | Height: | Size: 852 KiB |
|
After Width: | Height: | Size: 1.4 MiB |
|
After Width: | Height: | Size: 1.4 MiB |
|
After Width: | Height: | Size: 712 KiB |
|
After Width: | Height: | Size: 709 KiB |
|
After Width: | Height: | Size: 1.1 MiB |
|
After Width: | Height: | Size: 667 KiB |
|
After Width: | Height: | Size: 825 KiB |
|
After Width: | Height: | Size: 714 KiB |
|
After Width: | Height: | Size: 993 KiB |
|
After Width: | Height: | Size: 742 KiB |
|
After Width: | Height: | Size: 620 KiB |
|
After Width: | Height: | Size: 970 KiB |
|
After Width: | Height: | Size: 779 KiB |
|
After Width: | Height: | Size: 518 KiB |
|
After Width: | Height: | Size: 630 KiB |
|
After Width: | Height: | Size: 674 KiB |
|
After Width: | Height: | Size: 228 KiB |
|
After Width: | Height: | Size: 267 KiB |
|
After Width: | Height: | Size: 156 KiB |
|
After Width: | Height: | Size: 230 KiB |
|
After Width: | Height: | Size: 206 KiB |
|
After Width: | Height: | Size: 206 KiB |
|
After Width: | Height: | Size: 241 KiB |
|
After Width: | Height: | Size: 156 KiB |
|
After Width: | Height: | Size: 347 KiB |
|
After Width: | Height: | Size: 210 KiB |
|
After Width: | Height: | Size: 174 KiB |
|
After Width: | Height: | Size: 182 KiB |
|
After Width: | Height: | Size: 925 KiB |
|
After Width: | Height: | Size: 220 KiB |
|
After Width: | Height: | Size: 200 KiB |
|
After Width: | Height: | Size: 163 KiB |
|
After Width: | Height: | Size: 968 KiB |
|
After Width: | Height: | Size: 1.1 MiB |
|
After Width: | Height: | Size: 1.0 MiB |
|
After Width: | Height: | Size: 1.2 MiB |
|
After Width: | Height: | Size: 1.3 MiB |
|
After Width: | Height: | Size: 1.4 MiB |
|
After Width: | Height: | Size: 859 KiB |
|
After Width: | Height: | Size: 604 KiB |
|
After Width: | Height: | Size: 984 KiB |
|
After Width: | Height: | Size: 201 KiB |
|
After Width: | Height: | Size: 994 KiB |
|
After Width: | Height: | Size: 983 KiB |
|
After Width: | Height: | Size: 788 KiB |
|
After Width: | Height: | Size: 1.2 MiB |
|
After Width: | Height: | Size: 2.1 MiB |
|
After Width: | Height: | Size: 980 KiB |
|
After Width: | Height: | Size: 269 KiB |
|
After Width: | Height: | Size: 259 KiB |
|
After Width: | Height: | Size: 248 KiB |
|
After Width: | Height: | Size: 259 KiB |
|
After Width: | Height: | Size: 472 KiB |
|
After Width: | Height: | Size: 354 KiB |
|
After Width: | Height: | Size: 217 KiB |
|
After Width: | Height: | Size: 254 KiB |
|
After Width: | Height: | Size: 307 KiB |
|
After Width: | Height: | Size: 307 KiB |
|
After Width: | Height: | Size: 248 KiB |
|
After Width: | Height: | Size: 265 KiB |
|
After Width: | Height: | Size: 1.2 MiB |
|
After Width: | Height: | Size: 355 KiB |
|
After Width: | Height: | Size: 346 KiB |
|
After Width: | Height: | Size: 594 KiB |
|
After Width: | Height: | Size: 44 KiB |
|
After Width: | Height: | Size: 516 KiB |
|
After Width: | Height: | Size: 1.3 MiB |
|
After Width: | Height: | Size: 1.3 MiB |
@ -0,0 +1,101 @@ |
|||
# WeAreDevelopers 2025: A Speaker’s Impressions |
|||
|
|||
 |
|||
|
|||
After speaking at DotNext Moscow, I had high expectations for WeAreDevelopers 2025—and the event delivered on all fronts. Held in Berlin / Germany, it brought together a truly global crowd of developers, tech leaders, and innovators. As a speaker and software architect , I’m sharing my first-hand highlights, favorite moments, and candid scenes from this 2025’s conference. |
|||
|
|||
## 🗣 My Talk |
|||
|
|||
We have a good experience on multi-tenancy topic in SaaS development. My talk's topic was "Building Multi-Tenant ASP.NET Core Applications: Best Practices and Real-World Solutions". It was on the stage 4, 11 July Friday 10:20 am - 10:50 am and [this my presentation file](https://github.com/ebicoglu/presentations/blob/main/multi-tenancy-wearedevelopers-2025_30mins.pptx). |
|||
|
|||
 |
|||
|
|||
 |
|||
 |
|||
 |
|||
|
|||
|
|||
## 🏛 Huge Venue |
|||
|
|||
 |
|||
*The image is credited to WeAreDevelopers organization* |
|||
|
|||
First of all, I had been in numerous software conferences, I must say that I've never seen such a big software event. The event spanned **500+ sessions across 20+ stages**, including the HR Leaders Summit for **2 full days**. |
|||
|
|||
 |
|||
 |
|||
|
|||
------ |
|||
|
|||
## 🎤 Opening Keynote from GitHub |
|||
|
|||
GitHub CEO Thomas Dohmke initiated the conference on the main stage with a talk on *“Agents for the Sake of Happiness”*. Having introduced Copilot three years ago here, he now launched bold predictions about autonomous AI—a fascinating evolution... He demonstrated GitHub Co-Pilot's AI and created a snake game. Altough it didn't work as he planned, we're developers we know live coding is hard. Actually that's because we shouldn't rely on AI. AI is not deterministic even though we set all those temperature, TopP, TopK parameters to minimum. |
|||
|
|||
> AI is a good but not trustable friend! |
|||
|
|||
 |
|||
|
|||
------ |
|||
|
|||
## 🧭 11 Parallel Stages: Rush |
|||
|
|||
There were 11 stages where 11 different topics were being explained. And the sessions were 30 minutes. Actually that's the downside of this event. Because there were so nice talks that needs to be minimum 40 minutes. But anyway I understand the organization team because there are many smart speakers whose needs to be included in this event. So as a attendee I was on a hurry to pick the next talk even when I was listening to a talk :) |
|||
|
|||
The venue consists of 3 buildings. So if you pick a talk on another building, you have 10 mins to go to toilet or drink something and catch the next session on that far building... |
|||
|
|||
There was HR track with **3 stages and 2 full days** of HR/Talent Acquisition programming, it attracted a notable overlap of developers and HR pros. Themes included AI‑powered recruiting, remote work culture, mental health, diversity & inclusion, and building AI agents |
|||
|
|||
 |
|||
 |
|||
|
|||
|
|||
------ |
|||
|
|||
## 🤖 AI & AI & AI & Others... |
|||
|
|||
I'm one of those AI lovers. I love learning cutting-edge information. And as I see AI is being more trendy everyday. That's why most of the talks were about AI. Everything related to AI. I generaly attended AI related talks because I'm also working on some AI topics in Volosoft at the moment. |
|||
|
|||
|
|||
------ |
|||
|
|||
## 🤝 Expo Floor & Networking |
|||
|
|||
The expo was a developer’s playground—cloud services, open‑source tools, startups, and enterprise platforms. I found new partners and reconnected with peers in a buzzing atmosphere. Everywhere was full of talking's even outside. If you want to get fresh air and drink coffee, you can go out and listen to the outside talks. |
|||
|
|||
 |
|||
 |
|||
|
|||
|
|||
|
|||
Networking wasn't just daytime chatter—hallway meetups and evening socials were unforgettable. |
|||
|
|||
 |
|||
 |
|||
|
|||
------ |
|||
|
|||
## 😂 Candid & Fun Moments |
|||
|
|||
Swag stations, sponsor games, “developer selfies”—these lighter moments kept the vibe upbeat and human. |
|||
|
|||
 |
|||
 |
|||
|
|||
------ |
|||
|
|||
## ✅ Final Thoughts & Looking Ahead |
|||
|
|||
WeAreDevelopers 2025 was an unforgettable three-day ride: **15,000 tech minds**, **500+ sessions**, and a true **bridge between developers and HR** |
|||
I’m leaving with: |
|||
|
|||
- Fresh strategies in GenAI and SaaS growth |
|||
- Stronger HR-tech understanding and crossover potential |
|||
- New professional connections—and fun memories |
|||
|
|||
|
|||
------ |
|||
|
|||
 |
|||
|
|||
|
|||
|
|||
@ -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: |
|||
|
|||
 |
|||
|
|||
### 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. |
|||
|
After Width: | Height: | Size: 676 KiB |
|
After Width: | Height: | Size: 34 KiB |
@ -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> |
|||
|
|||
|
|||
@ -0,0 +1,250 @@ |
|||
# Using Hangfire Dashboard in ABP API Website 🚀 |
|||
|
|||
## Introduction |
|||
|
|||
In this article, I'll show you how to integrate and use the Hangfire Dashboard in an ABP API website. |
|||
|
|||
Typically, API websites use `JWT Bearer` authentication, but the Hangfire Dashboard isn't compatible with `JWT Bearer` authentication. Therefore, we need to implement `Cookies` and `OpenIdConnect` authentication for the Hangfire Dashboard access. |
|||
|
|||
## Creating a New ABP Demo Project 🛠️ |
|||
|
|||
We'll create a new ABP Demo `Tiered` project that includes `AuthServer`, `API`, and `Web` projects. |
|||
|
|||
```bash |
|||
abp new AbpHangfireDemoApp -t app --tiered |
|||
``` |
|||
|
|||
Now let's add the Hangfire Dashboard to the `API` project and configure it to use `Cookies` and `OpenIdConnect` authentication for accessing the dashboard. |
|||
|
|||
## Adding a New Hangfire Application 🔧 |
|||
|
|||
We need to add a new Hangfire application to the `appsettings.json` file in the `DbMigrator` project: |
|||
|
|||
> **Note:** Replace `44371` with your `API` project's port. |
|||
|
|||
```json |
|||
"OpenIddict": { |
|||
"Applications": { |
|||
//... |
|||
"AbpHangfireDemoApp_Hangfire": { |
|||
"ClientId": "AbpHangfireDemoApp_Hangfire", |
|||
"RootUrl": "https://localhost:44371/" |
|||
} |
|||
//... |
|||
} |
|||
} |
|||
``` |
|||
|
|||
2. Update the `OpenIddictDataSeedContributor`'s `CreateApplicationsAsync` method in the `Domain` project to seed the new Hangfire application. |
|||
|
|||
```csharp |
|||
//Hangfire Client |
|||
var hangfireClientId = configurationSection["AbpHangfireDemoApp_Hangfire:ClientId"]; |
|||
if (!hangfireClientId.IsNullOrWhiteSpace()) |
|||
{ |
|||
var hangfireClientRootUrl = configurationSection["AbpHangfireDemoApp_Hangfire:RootUrl"]!.EnsureEndsWith('/'); |
|||
|
|||
await CreateApplicationAsync( |
|||
applicationType: OpenIddictConstants.ApplicationTypes.Web, |
|||
name: hangfireClientId!, |
|||
type: OpenIddictConstants.ClientTypes.Confidential, |
|||
consentType: OpenIddictConstants.ConsentTypes.Implicit, |
|||
displayName: "Hangfire Application", |
|||
secret: configurationSection["AbpHangfireDemoApp_Hangfire:ClientSecret"] ?? "1q2w3e*", |
|||
grantTypes: new List<string> //Hybrid flow |
|||
{ |
|||
OpenIddictConstants.GrantTypes.AuthorizationCode, OpenIddictConstants.GrantTypes.Implicit |
|||
}, |
|||
scopes: commonScopes, |
|||
redirectUris: new List<string> { $"{hangfireClientRootUrl}signin-oidc" }, |
|||
postLogoutRedirectUris: new List<string> { $"{hangfireClientRootUrl}signout-callback-oidc" }, |
|||
clientUri: hangfireClientRootUrl, |
|||
logoUri: "/images/clients/aspnetcore.svg" |
|||
); |
|||
} |
|||
``` |
|||
|
|||
3. Run the `DbMigrator` project to seed the new Hangfire application. |
|||
|
|||
### Adding Hangfire Dashboard to the `API` Project 📦 |
|||
|
|||
1. Add the following packages and modules dependencies to the `API` project: |
|||
|
|||
```bash |
|||
<PackageReference Include="Volo.Abp.BackgroundJobs.HangFire" Version="9.2.0" /> |
|||
<PackageReference Include="Volo.Abp.AspNetCore.Authentication.OpenIdConnect" Version="9.2.0" /> |
|||
<PackageReference Include="Hangfire.SqlServer" Version="1.8.20" /> |
|||
``` |
|||
|
|||
```cs |
|||
typeof(AbpBackgroundJobsHangfireModule), |
|||
typeof(AbpAspNetCoreAuthenticationOpenIdConnectModule) |
|||
``` |
|||
|
|||
2. Add the `HangfireClientId` and `HangfireClientSecret` to the `appsettings.json` file in the `API` project: |
|||
|
|||
```csharp |
|||
"AuthServer": { |
|||
"Authority": "https://localhost:44358", |
|||
"RequireHttpsMetadata": true, |
|||
"MetaAddress": "https://localhost:44358", |
|||
"SwaggerClientId": "AbpHangfireDemoApp_Swagger", |
|||
"HangfireClientId": "AbpHangfireDemoApp_Hangfire", |
|||
"HangfireClientSecret": "1q2w3e*" |
|||
} |
|||
``` |
|||
|
|||
3. Add the `ConfigureHangfire` method to the `API` project to configure Hangfire: |
|||
|
|||
```csharp |
|||
public override void ConfigureServices(ServiceConfigurationContext context) |
|||
{ |
|||
var configuration = context.Services.GetConfiguration(); |
|||
var hostingEnvironment = context.Services.GetHostingEnvironment(); |
|||
|
|||
//... |
|||
|
|||
//Add Hangfire |
|||
ConfigureHangfire(context, configuration); |
|||
//... |
|||
} |
|||
|
|||
private void ConfigureHangfire(ServiceConfigurationContext context, IConfiguration configuration) |
|||
{ |
|||
context.Services.AddHangfire(config => |
|||
{ |
|||
config.UseSqlServerStorage(configuration.GetConnectionString("Default")); |
|||
}); |
|||
} |
|||
``` |
|||
|
|||
4. Modify the `ConfigureAuthentication` method to add new `Cookies` and `OpenIdConnect` authentication schemes: |
|||
|
|||
```csharp |
|||
private void ConfigureAuthentication(ServiceConfigurationContext context, IConfiguration configuration) |
|||
{ |
|||
context.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) |
|||
.AddAbpJwtBearer(options => |
|||
{ |
|||
options.Authority = configuration["AuthServer:Authority"]; |
|||
options.RequireHttpsMetadata = configuration.GetValue<bool>("AuthServer:RequireHttpsMetadata"); |
|||
options.Audience = "AbpHangfireDemoApp"; |
|||
|
|||
options.ForwardDefaultSelector = httpContext => httpContext.Request.Path.StartsWithSegments("/hangfire", StringComparison.OrdinalIgnoreCase) |
|||
? CookieAuthenticationDefaults.AuthenticationScheme |
|||
: null; |
|||
}) |
|||
.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme) |
|||
.AddAbpOpenIdConnect(OpenIdConnectDefaults.AuthenticationScheme, options => |
|||
{ |
|||
options.Authority = configuration["AuthServer:Authority"]; |
|||
options.RequireHttpsMetadata = Convert.ToBoolean(configuration["AuthServer:RequireHttpsMetadata"]); |
|||
options.ResponseType = OpenIdConnectResponseType.Code; |
|||
|
|||
options.ClientId = configuration["AuthServer:HangfireClientId"]; |
|||
options.ClientSecret = configuration["AuthServer:HangfireClientSecret"]; |
|||
|
|||
options.UsePkce = true; |
|||
options.SaveTokens = true; |
|||
options.GetClaimsFromUserInfoEndpoint = true; |
|||
|
|||
options.Scope.Add("roles"); |
|||
options.Scope.Add("email"); |
|||
options.Scope.Add("phone"); |
|||
options.Scope.Add("AbpHangfireDemoApp"); |
|||
|
|||
options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme; |
|||
}); |
|||
|
|||
//... |
|||
} |
|||
``` |
|||
|
|||
5. Add a custom middleware and `UseAbpHangfireDashboard` after `UseAuthorization` in the `OnApplicationInitialization` method: |
|||
|
|||
```csharp |
|||
//... |
|||
app.UseAuthorization(); |
|||
|
|||
app.Use(async (httpContext, next) => |
|||
{ |
|||
if (httpContext.Request.Path.StartsWithSegments("/hangfire", StringComparison.OrdinalIgnoreCase)) |
|||
{ |
|||
var authenticateResult = await httpContext.AuthenticateAsync(CookieAuthenticationDefaults.AuthenticationScheme); |
|||
if (!authenticateResult.Succeeded) |
|||
{ |
|||
await httpContext.ChallengeAsync( |
|||
OpenIdConnectDefaults.AuthenticationScheme, |
|||
new AuthenticationProperties |
|||
{ |
|||
RedirectUri = httpContext.Request.Path + httpContext.Request.QueryString |
|||
}); |
|||
return; |
|||
} |
|||
} |
|||
await next.Invoke(); |
|||
}); |
|||
app.UseAbpHangfireDashboard("/hangfire", options => |
|||
{ |
|||
options.AsyncAuthorization = new[] |
|||
{ |
|||
new AbpHangfireAuthorizationFilter() |
|||
}; |
|||
}); |
|||
|
|||
//... |
|||
``` |
|||
|
|||
Perfect! 🎉 Now you can run the `AuthServer` and `API` projects and access the Hangfire Dashboard at `https://localhost:44371/hangfire`. |
|||
|
|||
> **Note:** Replace `44371` with your `API` project's port. |
|||
|
|||
The first time you access the Hangfire Dashboard, you'll be redirected to the login page of the `AuthServer` project. After you log in, you'll be redirected back to the Hangfire Dashboard. |
|||
|
|||
 |
|||
|
|||
## Key Points 🔑 |
|||
|
|||
### 1. Authentication Scheme Selection |
|||
|
|||
The default authentication scheme in API websites is `JWT Bearer`. We've implemented `Cookies` and `OpenIdConnect` specifically for the Hangfire Dashboard. |
|||
|
|||
We've configured the `JwtBearerOptions`'s `ForwardDefaultSelector` to use `CookieAuthenticationDefaults.AuthenticationScheme` for Hangfire Dashboard requests. |
|||
|
|||
This means that if the request path starts with `/hangfire`, the request will be authenticated using the `Cookies` authentication scheme; otherwise, it will use the `JwtBearer` authentication scheme. |
|||
|
|||
```csharp |
|||
options.ForwardDefaultSelector = httpContext => httpContext.Request.Path.StartsWithSegments("/hangfire", StringComparison.OrdinalIgnoreCase) |
|||
? CookieAuthenticationDefaults.AuthenticationScheme |
|||
: null; |
|||
``` |
|||
|
|||
### 2. Custom Middleware for Authentication |
|||
|
|||
We've also implemented a custom middleware to handle `Cookies` authentication for the Hangfire Dashboard. If the current request isn't authenticated with the `Cookies` authentication scheme, it will be redirected to the login page. |
|||
|
|||
```csharp |
|||
app.Use(async (httpContext, next) => |
|||
{ |
|||
if (httpContext.Request.Path.StartsWithSegments("/hangfire", StringComparison.OrdinalIgnoreCase)) |
|||
{ |
|||
var authenticateResult = await httpContext.AuthenticateAsync(CookieAuthenticationDefaults.AuthenticationScheme); |
|||
if (!authenticateResult.Succeeded) |
|||
{ |
|||
await httpContext.ChallengeAsync( |
|||
OpenIdConnectDefaults.AuthenticationScheme, |
|||
new AuthenticationProperties |
|||
{ |
|||
RedirectUri = httpContext.Request.Path + httpContext.Request.QueryString |
|||
}); |
|||
return; |
|||
} |
|||
} |
|||
await next.Invoke(); |
|||
}); |
|||
``` |
|||
|
|||
## References 📚 |
|||
|
|||
- [ABP Hangfire Background Job Manager](https://abp.io/docs/latest/framework/infrastructure/background-jobs/hangfire) |
|||
- [Use cookie authentication in ASP.NET Core](https://learn.microsoft.com/en-us/aspnet/core/security/authentication/cookie?view=aspnetcore-9.0) |
|||
|
After Width: | Height: | Size: 4.9 MiB |
@ -0,0 +1,28 @@ |
|||
**It is going to get hotter with ABP’s Summer Campaign!** |
|||
|
|||
Since it’s summer time, we wanted to make it even hotter by announcing a summer campaign! From July 21 to 31 we are offering a 20% discount on all ABP licenses. Now is the best time to invest in ABP and start developing asp net applications faster without wasting your time with repetitive tasks. |
|||
|
|||
## Summer Campaign Terms |
|||
|
|||
Please review the following terms and conditions carefully. |
|||
|
|||
* This offer is available for extensions and new purchases. |
|||
* Developer seat purchases are also included to the campaign. |
|||
* Campaign is available from July 21st to July 31st. |
|||
* Discounts are valid on selected licenses only. |
|||
* This offer cannot be combined with other promotions or discounts. |
|||
|
|||
**Why Choose ABP?** |
|||
|
|||
ABP offers a powerful infrastructure, simplifying modern ASP.NET core development. It helps develop modern ASP.NET applications, including ASP.NET core MVC web applications, blazor front-end projects, and angular .NET Core solutions. |
|||
|
|||
-The core framework and pre-built modules are designed with microservice architecture in mind. |
|||
-ABP provides a module system that allows you to develop reusable application modules. |
|||
-Helps implement a DDD based layered architecture and build a maintainable code base. |
|||
-Easily manage SaaS applications with integrated multi-tenancy, from database to UI. |
|||
|
|||
**This Offer Ends July 31, So Hurry Up!** |
|||
|
|||
This summer campaign is running from July 21 to July 31, so don’t miss your chance. Now is the perfect opportunity to enhance your asp net web development with ABP and benefit from our exclusive features. |
|||
|
|||
Get Your Discount Now: [https://abp.io/pricing?utm_source=abpwebsite&utm_medium=referral&utm_campaign=summer25_blog](https://abp.io/pricing?utm_source=abpwebsite&utm_medium=referral&utm_campaign=summer25_blog) |
|||
@ -0,0 +1,480 @@ |
|||
# Multi-Tenancy with Separate Databases in .NET and ABP Framework |
|||
|
|||
[Multi-tenancy](https://abp.io/architecture/multi-tenancy) is a common architectural concept for modern SaaS applications, enabling a single application to serve multiple customers (each known as a tenant) while maintaining data isolation, scalability, and operational efficiency. The "Separate database per tenant" approach offers the highest level of data isolation, making it ideal for scenarios with strict data privacy, security, and performance requirements. |
|||
|
|||
In this article, we’ll explore how to use this advanced multi-tenancy model using the powerful capabilities of the ABP Framework and the .NET platform. |
|||
|
|||
> In this article, I will use [ABP Studio](https://abp.io/studio) for creating the application. ABP Studio allows to select "separate database per tenant" option only for [commercial licenses](https://abp.io/pricing). |
|||
|
|||
## Understanding Database Models for a Multi-Tenant Application |
|||
|
|||
In the next sections, I will explain various models for database models of a multi-tenant solution: |
|||
|
|||
* Single (shared) Database Model |
|||
* Separate Tenant Databases Model |
|||
* Hybrid Multi-Tenant Database Model |
|||
|
|||
Let's start with the first one... |
|||
|
|||
### Single (shared) Database Model |
|||
|
|||
In the shared database model, all the application data stored in a single physical database. In the following diagram, you see different kind of users use the application, and the application stored their data in a main database: |
|||
|
|||
 |
|||
|
|||
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. |
|||
|
|||
Here, is an example `Product` entity that should support multi-tenancy: |
|||
|
|||
````csharp |
|||
using System; |
|||
using Volo.Abp.Domain.Entities; |
|||
using Volo.Abp.MultiTenancy; |
|||
|
|||
namespace MtDemoApp |
|||
{ |
|||
public class Product : AggregateRoot<Guid>, IMultiTenant //Implementing the interface |
|||
{ |
|||
public Guid? TenantId { get; set; } //Defined by the IMultiTenant interface |
|||
public string Name { get; set; } |
|||
public float Price { get; set; } |
|||
} |
|||
} |
|||
```` |
|||
|
|||
In this way, ABP Framework automatically isolates data using the `TenantId` property. You don't need to care about how to set `TenantId` or filter data when you need to query from database - all automated. |
|||
|
|||
### Separate Tenant Databases Model |
|||
|
|||
In the separate tenant database model, each tenant has a dedicated physical database (with a separate connection string), as shown below: |
|||
|
|||
 |
|||
|
|||
ABP Framework can automatically select the right database from the current user's tenant context. Again, it is completely automated. You just need to set a connection string for a tenant, as we will do later in this article. |
|||
|
|||
Even each tenant has a separate database, we still need to a main database to store host-side data, like a table of tenants, their connection strings and some other management data for tenants. Also, tenant-independent (or tenant-shared) application data is stored in the main database. |
|||
|
|||
### Hybrid Multi-Tenant Database Model |
|||
|
|||
Lastly, you may want to have a hybrid model, where some tenants shares a single database (they don't have separate databases) but some of them have dedicated databases. In the following figure, Tenant C has its own physical database, but all other tenants data stored in the main database of the application. |
|||
|
|||
 |
|||
|
|||
ABP Framework handles the complexity: If a tenant has a separate database it uses that tenant's database, otherwise it filters the tenant data by the `TenantId` field in shared tables. |
|||
|
|||
## Understanding the Separate Tenant Schema Approach |
|||
|
|||
When you create a new ABP solution, it has a single `DbContext` class (for Entity Framework Core) by default. It also includes the necessary EF Core code-first database migrations to create and update the database. As a result of this approach, the main database schema (tables and their fields) will be identical with a tenant database schema. As a drawback of that, tenant databases have some tables that are not meaningful and not used. For example, Tenants table (a list of tenants) will be created in the tenant database, but will never be used (because tenant list is stored in the main database). |
|||
|
|||
As a solution to that problem, ABP Studio provides a "Use separate tenant schema" option on the Multi-Tenancy step of the solution creation wizard: |
|||
|
|||
 |
|||
|
|||
This option is only available for the [Layered Monolith (optionally Modular) Solution Template](https://abp.io/docs/latest/get-started/layered-web-application). We don't provide that option in other templates, because: |
|||
|
|||
* [Single-Layer](https://abp.io/docs/latest/get-started/single-layer-web-application) template is recommended for more simpler applications with an easy-to-understand architecture. We don't want to add these kind of complications in that template. |
|||
* [Microservice](https://abp.io/docs/latest/get-started/microservice) template already has a separate database for each service. Having multiple database schema (and multiple `DbContext` classes) for each service makes it over complicated without bringing much value. |
|||
|
|||
While you can manually convert your applications so they support separate database schema approach (ABP is flexible), it is not recommended to do it for these solution types. |
|||
|
|||
> Note that "Separate database per tenant" approach is already supported by default for the Single-Layer template too. "Separate tenant schema" is something different as I explained in this section. |
|||
|
|||
## Creating a new Application |
|||
|
|||
Follow the *[Get Started tutorial](https://abp.io/docs/latest/get-started/layered-web-application)* to create a new ABP application. Remember to select the "*Use separate tenant schema*" option since I want to demonstrate it in this article. |
|||
|
|||
## Understanding the DbContext Structure |
|||
|
|||
When you open the solution in your IDE, you will see the following structure under the `.EntityFrameworkCore` project: |
|||
|
|||
 |
|||
|
|||
There are 3 DbContext-related classes here (MtDemoApp is your application name): |
|||
|
|||
* `MtDemoAppDbContext` class is used to map entities for the main (host + shared) database. |
|||
* `MtDemoAppTenantDbContext` class is used to map entities for tenant that have separate physical databases. |
|||
* `MtDemoAppDbContextBase` is an abstract base class for the classes explained above. In this way, you can configure common mapping logic here. |
|||
|
|||
Let's see these classes a bit closer... |
|||
|
|||
### The Main `DbContext` Class |
|||
|
|||
Here the main `DbContext` class: |
|||
|
|||
````csharp |
|||
public class MtDemoAppDbContext : MtDemoAppDbContextBase<MtDemoAppDbContext> |
|||
{ |
|||
public MtDemoAppDbContext(DbContextOptions<MtDemoAppDbContext> options) |
|||
: base(options) |
|||
{ |
|||
} |
|||
|
|||
protected override void OnModelCreating(ModelBuilder builder) |
|||
{ |
|||
builder.SetMultiTenancySide(MultiTenancySides.Both); |
|||
|
|||
base.OnModelCreating(builder); |
|||
} |
|||
} |
|||
```` |
|||
|
|||
* It inherits from the `MtDemoAppDbContextBase` as I mentioned before. So, any configuration made in the base class is also valid here. |
|||
* `OnModelCreating` overrides the base method and sets the multi-tenancy side as `MultiTenancySides.Both`. `Both` means this database can store host data as well as tenant data. This is needed because we store data in this database for the tenants who don't have a separate database. |
|||
|
|||
### The Tenant `DbContext` class |
|||
|
|||
Here is the tenant-specific `DbContext` class: |
|||
|
|||
````csharp |
|||
public class MtDemoAppTenantDbContext : MtDemoAppDbContextBase<MtDemoAppTenantDbContext> |
|||
{ |
|||
public MtDemoAppTenantDbContext(DbContextOptions<MtDemoAppTenantDbContext> options) |
|||
: base(options) |
|||
{ |
|||
} |
|||
|
|||
protected override void OnModelCreating(ModelBuilder builder) |
|||
{ |
|||
builder.SetMultiTenancySide(MultiTenancySides.Tenant); |
|||
|
|||
base.OnModelCreating(builder); |
|||
} |
|||
} |
|||
```` |
|||
|
|||
The only difference is that we used `MultiTenancySides.Tenant` as the multi-tenancy side here, since this `DbContext` will only have entities/tables for tenants that have separate databases. |
|||
|
|||
### The Base `DbContext` Class |
|||
|
|||
Here is the base `DbContext` class: |
|||
|
|||
````csharp |
|||
public abstract class MtDemoAppDbContextBase<TDbContext> : AbpDbContext<TDbContext> |
|||
where TDbContext : DbContext |
|||
{ |
|||
|
|||
public MtDemoAppDbContextBase(DbContextOptions<TDbContext> options) |
|||
: base(options) |
|||
{ |
|||
|
|||
} |
|||
|
|||
protected override void OnModelCreating(ModelBuilder builder) |
|||
{ |
|||
base.OnModelCreating(builder); |
|||
|
|||
/* Include modules to your migration db context */ |
|||
|
|||
builder.ConfigurePermissionManagement(); |
|||
builder.ConfigureSettingManagement(); |
|||
builder.ConfigureBackgroundJobs(); |
|||
builder.ConfigureAuditLogging(); |
|||
builder.ConfigureIdentityPro(); |
|||
builder.ConfigureOpenIddictPro(); |
|||
builder.ConfigureFeatureManagement(); |
|||
builder.ConfigureLanguageManagement(); |
|||
builder.ConfigureSaas(); |
|||
builder.ConfigureTextTemplateManagement(); |
|||
builder.ConfigureBlobStoring(); |
|||
builder.ConfigureGdpr(); |
|||
|
|||
/* Configure your own tables/entities inside here */ |
|||
|
|||
//builder.Entity<YourEntity>(b => |
|||
//{ |
|||
// b.ToTable(MtDemoAppConsts.DbTablePrefix + "YourEntities", MtDemoAppConsts.DbSchema); |
|||
// b.ConfigureByConvention(); //auto configure for the base class props |
|||
// //... |
|||
//}); |
|||
|
|||
//if (builder.IsHostDatabase()) |
|||
//{ |
|||
// /* Tip: Configure mappings like that for the entities only |
|||
* available in the host side, |
|||
// * but should not be in the tenant databases. */ |
|||
//} |
|||
} |
|||
} |
|||
```` |
|||
|
|||
This `DbContext` class configures database mappings for all the [application modules](https://abp.io/docs/latest/modules) used by this application by calling their extension methods, like `builder.ConfigureBackgroundJobs()`. Each of these extension methods are defined as multi-tenancy aware and care about what you've set for the multi-tenancy side. |
|||
|
|||
### Where to Configure Your Entities? |
|||
|
|||
You can configure your entity mappings in the `OnModelCreating` method in any of the `DbContext` classes that was explained: |
|||
|
|||
* If you configure in the main `DbContext` class, these configuration will be valid only for the main database. So, don't configure tenant-related configuration here, otherwise, it won't be applied for the tenants who have separate databases. |
|||
* If you configure in the tenant `DbContext` class, it will be valid only for the tenants with separate databases. You rarely need to do that. You typically want to make same configuration in the base `DbContext` to support hybrid scenarios (some tenants use the main (shared) database and some tenants have separate databases). |
|||
* If you configure in the base `DbContext` class, it will be valid for the main database and tenant databases. You typically define tenant-related configuration here. That means, if you have a multi-tenant `Product` entity, then you should define its EF Core database mapping configuration here, so the Products table is created in the main database as well as in the tenant databases. |
|||
|
|||
The recommended approach is to configure all the mapping in the base class, but add controls like `builder.IsHostDatabase()` and `builder.IsTenantDatabase()` to conditionally configure the mappings: |
|||
|
|||
 |
|||
|
|||
## Adding Database Migrations |
|||
|
|||
In this section, I will show how to configure your entity mappings, generate database migrations and apply to the database. |
|||
|
|||
### Defining an Entity |
|||
|
|||
Let's define a `Product` entity in the `.Domain` layer of your application: |
|||
|
|||
````csharp |
|||
using System; |
|||
using Volo.Abp.Domain.Entities; |
|||
using Volo.Abp.MultiTenancy; |
|||
|
|||
namespace MtDemoApp |
|||
{ |
|||
public class Product : AggregateRoot<Guid>, IMultiTenant |
|||
{ |
|||
public Guid? TenantId { get; set; } |
|||
public string Name { get; set; } |
|||
public float Price { get; set; } |
|||
} |
|||
} |
|||
```` |
|||
|
|||
### Configuring the Database Mapping |
|||
|
|||
Open the `MtDemoAppDbContextBase` class and add the following property to the class: |
|||
|
|||
````csharp |
|||
public DbSet<Product> Products { get; set; } |
|||
```` |
|||
|
|||
Then add the following mapping code inside the `OnModelCreating` method (after all other existing code): |
|||
|
|||
````csharp |
|||
builder.Entity<Product>(b => |
|||
{ |
|||
b.ToTable(MtDemoAppConsts.DbTablePrefix + "Products", MtDemoAppConsts.DbSchema); |
|||
b.ConfigureByConvention(); //auto-configure for the base class props |
|||
b.Property(x => x.Name).IsRequired().HasMaxLength(100); |
|||
}); |
|||
```` |
|||
|
|||
We made the configuration in the base class since the `Products` table should be created in all databases, not only in the main database. |
|||
|
|||
>`DbTablePrefix` and `DbSchema` are optional and configurable in your application. You can change or remove them. |
|||
|
|||
### Add a New Database Migration for the Main Database |
|||
|
|||
To add a new EF Core database migration, we can use ABP Studio UI or EF Core command-line commands. I will show both of these approaches here. |
|||
|
|||
#### Using the ABP Studio "Add Migrations" UI |
|||
|
|||
You can right-click the `.EntityFrameworkCore` package in the ABP Studio's *Solution Explorer* panel and select *EF Core CLI* -> *Add Migration* command as shown below: |
|||
|
|||
 |
|||
|
|||
You set a migration name on the opened dialog: |
|||
|
|||
 |
|||
|
|||
If you select the *Update Database* checkbox it will apply changes to the database after generating the migration code. |
|||
|
|||
Lastly, select the main DbContext class for this migration: |
|||
|
|||
 |
|||
|
|||
This dialog is shown when your application has multiple `DbContext` classes. Once you click the *OK* button, a new migration class is added under the `Migrations` folder of the `.EntityFrameworkCore` project (you can see in your coding editor): |
|||
|
|||
 |
|||
|
|||
Since we selected the *Update Database* option, the database table is also created. The following screenshot shows the `AppProducts` table (`App` is the default prefix for your tables, but you can change or remove it) in Microsoft SQL Server Management Studio: |
|||
|
|||
 |
|||
|
|||
#### Using a Command-Line Terminal |
|||
|
|||
If you prefer to use the command-line terminal (instead of ABP Studio UI), open a command-line terminal in the directory of the `.EntityFrameworkCore` project. As a shortcut, you can right-click the `.EntityFrameworkCore` project in ABP Studio, then select *Open with* -> *Terminal* command as shown in the following figure: |
|||
|
|||
 |
|||
|
|||
Then you can use the [EF Core command-line tool](https://learn.microsoft.com/en-us/ef/core/cli/dotnet) to add a new database migration: |
|||
|
|||
````bash |
|||
dotnet ef migrations add "Added_Product_Entity" --context MtDemoAppDbContext |
|||
```` |
|||
|
|||
It is important to set the `--context` parameter since we have two DbContext classes in the same project. |
|||
|
|||
After adding the migration, you can update the database: |
|||
|
|||
````bash |
|||
dotnet ef database update "Added_Product_Entity" --context MtDemoAppDbContext |
|||
```` |
|||
|
|||
> If you are using Visual Studio, you can also use the [Package Manager Console](https://learn.microsoft.com/en-us/ef/core/cli/powershell) inside your IDE to add migrations and update the database. |
|||
|
|||
### Add a New Database Migration for the Tenant Database |
|||
|
|||
We added a database migration for the main (shared) database. We also need to add a new database migration for tenants who have separate databases. |
|||
|
|||
This time, no need to configure the DbContext since we did it in the base DbContext class, so it is valid for both of the DbContext classes. Just right-click the `.EntityFrameworkCore` package in the ABP Studio's *Solution Explorer* panel and select *EF Core CLI* -> *Add Migration* command as shown below: |
|||
|
|||
 |
|||
|
|||
You can set the same or a different migration name here: |
|||
|
|||
 |
|||
|
|||
The important part is to select the Tenant DbContext in the next dialog, because we want to change the tenant database this time: |
|||
|
|||
 |
|||
|
|||
After clicking the *OK* button, it will add a new database migration class, but this time to the `TenantMigrations` folder: |
|||
|
|||
 |
|||
|
|||
ABP Studio is smart enough to select the right folder name for the new migration by mapping with the DbContext name. However, you could manually type `TenantMigrations` in the *Output directory* textbox. |
|||
|
|||
Since we selected the *Update Database* option, it also applied changes to the database. But, which database? Interestingly, it automatically creates a second database for tenants with the project name + `_Tenant` suffix: |
|||
|
|||
 |
|||
|
|||
> This new database is never used on runtime or production. It is only created to allow you to see the schema (tables and their fields) on development time to be sure that everything is as expected. As you see, some tables (like `Saas*` and `OpenIddict*`) are not available in that database, since they are used on the host side and only necessary to be in the main database. |
|||
> |
|||
> So, where is the real tenant database? If a tenant's database is dedicated (separate), it is created on runtime as I will explain in the *Managing Tenant Databases and Connection Strings* section later. |
|||
|
|||
You can see that database's connection string in the `appsettings.development.json` file of the `.DbMigrator` project in the solution. If you want to understand how it works, you can check source code of the `DbContextFactory` classes in the `.EntityFrameworkCore` project: |
|||
|
|||
 |
|||
|
|||
These factory classes are used to create `DbContext` instances when you execute *Add Migration* and *Update Database* commands. |
|||
|
|||
## Managing Tenant Databases and Connection Strings |
|||
|
|||
Until now, we even didn't run the application. It is the time to do it. |
|||
|
|||
### Running the Application with ABP Studio |
|||
|
|||
You can run the `.Web` project in your IDE. But I prefer to use ABP Studio's *[Solution Runner](https://abp.io/docs/latest/studio/running-applications)* feature here. You can open the *Solution Runner* panel in *ABP Studio* and click the play icon near to the solution root (`MyDemoApp`): |
|||
|
|||
 |
|||
|
|||
Once the application runs (and you see the blue link icon near to it), right click and select the *Browse* command: |
|||
|
|||
 |
|||
|
|||
It will open the application's UI in the built-in browser of ABP Studio. You can Login the application (with `admin` as user name and `1q2w3E*` as the default password) and navigate to the *Saas* -> *Tenants* page. |
|||
|
|||
### Creating a New Tenant with the Shared Database |
|||
|
|||
The *Tenants* page of the [SaaS module](https://abp.io/modules/Volo.SaaS) is shown below: |
|||
|
|||
 |
|||
|
|||
As you see, there is no tenant at the beginning. I can click the *+ New tenant* button to create the first tenant: |
|||
|
|||
 |
|||
|
|||
On this screen, we can set the base tenant information. If you click the *Database connection strings* tab, you can see the following UI: |
|||
|
|||
 |
|||
|
|||
For this first tenant, I will keep it as default and use the shared (main) database for this tenant's data. After clicking the *Save* button, the tenant is created and an initial [data seed](https://abp.io/docs/latest/framework/infrastructure/data-seeding) operation is automatically performed for us. To see an example, you can open the database, show rows of the `AbpUsers` table: |
|||
|
|||
 |
|||
|
|||
As you see, a new `admin` user has been created with a `TenantId`. The first row is the `admin` user of the host side. So, ABP allows to define same user name in different tenants, because their data (users in this example) are completely isolated from each other. |
|||
|
|||
### Sign in with the new Tenant |
|||
|
|||
We created a new tenant. In this step, we will sign in with the new tenant's `admin` user to see the application UI by that new tenant. To do that, we should logout from the host admin user first. Click the user name (`admin`) on the top right area of the application and select the *Log out* command: |
|||
|
|||
 |
|||
|
|||
Click the *Login* button again, which redirects you to the *Login* page: |
|||
|
|||
 |
|||
|
|||
In this page, click the *switch* button near to the *TENANT* selection area and type `acme` as *Name*: |
|||
|
|||
 |
|||
|
|||
Once you click the *Save* button, you are now in the acme tenant's context. You can see it on the *TENANT* selection area: |
|||
|
|||
 |
|||
|
|||
> This kind of tenant switch feature is very useful in development to quickly change tenants to test your application. However, in production, you typically want to use subdomain/domain names or another mechanism to determine tenants automatically. When you configure domain based resolution, the tenant selection area is automatically disappears from the login page. You can check the [multi-tenant document](https://abp.io/docs/latest/framework/architecture/multi-tenancy) to learn how to configure it. |
|||
|
|||
After switching to the `acme` tenant, we can use `admin` as user name and the password you set during the tenant creation (I had set it as `1q2w3E*`) to login to the application. |
|||
|
|||
Here a screenshot from the *Roles* page after signing in as the `acme` tenant's `admin` user: |
|||
|
|||
 |
|||
|
|||
> Notice that each tenant has its own roles, users, permissions, and other data. If you change roles here, it doesn't affect other tenants or the host side. |
|||
> |
|||
> Also, you can see that there are less menu items compared to host side. For example, tenant management page is not available for tenants as you can expect. |
|||
|
|||
### Switch Back to the Host Side |
|||
|
|||
To switch back to the host side to add a new tenant, logout from the application, click the *Login* button again to open the login page and then again click the *switch* button to change the current tenant context: |
|||
|
|||
 |
|||
|
|||
In this dialog, clear the *Name* field and then *Save* the dialog to switch back to the host side. Then you can use the standard `admin` user name with `1q2w3E*` password to login to the application as the host administrator. |
|||
|
|||
### Creating a New Tenant with a Separate Database |
|||
|
|||
Finally, we came to the point that we will create a new tenant with a separate, dedicated database. Open the *Tenants* page of the SaaS module and click the *+ New tenant* button: |
|||
|
|||
 |
|||
|
|||
Just fill these information as you wish, then open the *Database connection strings* tab: |
|||
|
|||
 |
|||
|
|||
Uncheck the *Use the shared database* option and set a connection string to the *Default connection string* for this tenant. I used `Server=(LocalDb)\MSSQLLocalDB;Database=MtDemoApp_Volosoft;Trusted_Connection=True;TrustServerCertificate=true` as the connection string value. The database name is `MtDemoApp_Volosoft`. You can Test the connection string to be sure that it is a valid connection string. |
|||
|
|||
Once you click the *Save* button, the new tenant is created, a new database is created on the fly, all the database migrations are applied and the initial data seed is performed. You can open the SQL Server Management Studio to see the new database: |
|||
|
|||
 |
|||
|
|||
You can check the tables (e.g. `AbpUsers`) to see that only this new tenant's data is stored in this database. To test the application, switch to the Volosoft tenant (as like explained in the *Sign in with the new Tenant* section before), create a new role or user and check the database. |
|||
|
|||
## Migrating Existing Tenant Databases |
|||
|
|||
In the previous section, we've seen that a tenant database is automatically created on runtime if you set a connection string for that tenant. Also, all the current migrations are automatically applied to the database, so it becomes up to date. |
|||
|
|||
But what about existing tenant databases when a new migration is added to the application? Maybe you have a few tenants with their separate databases, or you may have thousands of tenants with separate databases. How will you apply database schema changes to all of these databases? |
|||
|
|||
The startup template comes with a solution to this problem. There is a `.DbMigrator` console application in the solution that is responsible to apply schema (table and their fields) changes to all of the databases in the system (the main database and all the separate tenant databases). It also executes the data seeding if seed data is available. All you need to do is to execute this application on your production environment while deploying a new version of your application (of course, it is also very useful in the development environment). It checks and upgrades all the databases before the new version of your application is deployed. |
|||
|
|||
Here is the console log screen when I run the `.DbMigrator` application on my development environment: |
|||
|
|||
 |
|||
|
|||
As you can see in the logs, it first migrates for the main (host) database, then migrates the tenant databases one by one. It doesn't make schema migration for the `acme` tenant since it has not a separate database, but uses the main database. |
|||
|
|||
In brief, when you make changes on your entity classes; |
|||
|
|||
1) Add a new migration for the main DbContext class as I explained in this article. |
|||
2) Add a new migration for the tenant DbContext class as I explained in this article. |
|||
3) Run the `.DbMigrator` application in your development environment to ensure all the databases are up to date. |
|||
4) When you deploy your application to production or test environments, remember to run the `.DbMigrator` application first, then update your application. Or better, setup a CI/CD pipeline that automates this process. You can run the `.DbMigrator` every time while deploying the application, regardless of whether there is a schema change or not. |
|||
|
|||
> If you have too many tenants with separate database, then the migration process may take too much time. `.DbMigrator` provides the fundamental solution. But for more advanced scenarios or bigger systems, you can always develop your own solution. Just check the `.DbMigrator` application to understand how it was implemented. All the necessary code located in your solution, so you can easily understand and freely customize. |
|||
|
|||
## Conclusion |
|||
|
|||
In this article, I covered two important aspects of multi-tenant application development: |
|||
|
|||
* How ABP startup templates provide a multi-tenant application setup, so some tenants may store their data in a single (main, shared) database while some others may have their own dedicated database. |
|||
* Demonstrate how it can manage database migration process on the fly for multiple databases. |
|||
|
|||
I started by defining different database models for multi-tenant applications (Single database, separate databases, and hybrid), showed how to create an ABP application that supports hybrid model, explained the DbContext structure that is coming with the solution template, demonstrated how to define entities, create and apply database migrations in such an application. |
|||
|
|||
I hope this article gives you a good understanding the problem and the solution provided by the ABP Framework. Please write your questions or comments under this article. |
|||
|
|||
Enjoy coding! :) |
|||
|
|||
## Further Reading |
|||
|
|||
* [ABP Multi-Tenancy document](https://abp.io/docs/latest/framework/architecture/multi-tenancy) |
|||
* [Multi-Tenancy Architecture with .NET](https://abp.io/architecture/multi-tenancy) |
|||
|
After Width: | Height: | Size: 26 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 9.2 KiB |