diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en-GB.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en-GB.json
index 48cba301a9..7e2642e88b 100644
--- a/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en-GB.json
+++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en-GB.json
@@ -33,12 +33,15 @@
"Name": "Name",
"DisplayName": "Display name",
"ShortDescription": "Short description",
+ "LongDescription": "Long description",
"NameFilter": "Name",
"CreationTime": "Creation time",
- "IsPro": "Is pro",
+ "IsPro": "Pro package",
"ShowOnModuleList": "Show in module list",
"EfCoreConfigureMethodName": "Configure method name",
"IsProFilter": "Is pro",
+ "ShowOnModuleFilter": "Show on module list",
+ "ShowOnModuleListFilter": "Show on module list",
"ApplicationType": "Application type",
"Target": "Target",
"TargetFilter": "Target",
@@ -57,8 +60,10 @@
"Refresh": "Refresh",
"NpmPackages": "NPM Packages",
"NugetPackages": "Nuget Packages",
+ "NuGetPackages": "NuGet Packages",
"NpmPackageCount": "NPM Package Count",
"NugetPackageCount": "Nuget Package Count",
+ "NuGetPackageCount": "NuGet Package Count",
"Module": "Modules",
"ModuleInfo": "Module info",
"CreateANpmPackage": "Create a NPM package",
diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json
index 703c158dea..9fb30d3fda 100644
--- a/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json
+++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json
@@ -28,17 +28,21 @@
"Menu:DiscountRequests": "Discount Requests",
"NpmPackageDeletionWarningMessage": "This NPM Package will be deleted. Do you confirm that?",
"NugetPackageDeletionWarningMessage": "This Nuget Package will be deleted. Do you confirm that?",
+ "NuGetPackages": "NuGet Packages",
"ModuleDeletionWarningMessage": "This Module will be deleted. Do you confirm that?",
"Name": "Name",
"DisplayName": "Display name",
"ShortDescription": "Short description",
+ "LongDescription": "Long description",
"NameFilter": "Name",
"CreationTime": "Creation time",
- "IsPro": "Is pro",
+ "IsPro": "Pro package",
"IsFreeToActiveLicenseOwners": "Free to license owners",
"ShowOnModuleList": "Show on module list",
"EfCoreConfigureMethodName": "Configure method name",
- "IsProFilter": "Is pro",
+ "IsProFilter": "Pro package",
+ "ShowOnModuleFilter": "Show on module list",
+ "ShowOnModuleListFilter": "Show on module list",
"ApplicationType": "Application type",
"Target": "Target",
"TargetFilter": "Target",
@@ -59,6 +63,7 @@
"NugetPackages": "Nuget Packages",
"NpmPackageCount": "NPM Package Count",
"NugetPackageCount": "Nuget Package Count",
+ "NuGetPackageCount": "NuGet Package Count",
"Module": "Modules",
"ModuleInfo": "Module info",
"CreateANpmPackage": "Create a NPM package",
diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/en.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/en.json
index 927d9ad1cc..ddf9d1e4fc 100644
--- a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/en.json
+++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/en.json
@@ -258,6 +258,8 @@
"Name": "Name",
"Surname": "Surname",
"CompanyName": "Company name",
+ "CompanyAddress" : "Company Address",
+ "TaxNumber" : "Tax Number",
"Free": "Free",
"DDDEBook": "DDD E-Book",
"PracticalGuideForImplementingDDD": "This book is a practical guide for implementing the Domain Driven Design with the ABP Framework.",
@@ -1835,6 +1837,8 @@
"ConcurrencyCheckExplanation": "ABP provides an optimistic concurrency check mechanism to ensure data consistency in your application and prevents users access or change the same data in a database at the same time.",
"NewsletterEmailFooterCreateTemplateMessage": "
Thank you for subscribing! We're thrilled to have you on board.
As a subscriber, you'll receive the latest updates on:- Promotional Offers:Benefit from exclusive discounts, seasonal campaigns, and special offers.
- Events:Stay informed about our Community Talks, Webinars, and the ABP DOTNET Conferences.
- Release Notes:Get the latest on ABP Platform releases and new products.
- Newsletter:Enjoy our blog posts, community news, and more.
We look forward to keeping you informed and engaged. ",
"NewsletterDeleteSubscriptionDescription": "This is a confirmation that you have unsubscribed from the following email categories:- Promotional Offers:Discounts, seasonal campaigns, etc.
- Events:Community Talks, Webinars, ABP DOTNET Conference, etc.
- Release Notes:ABP Platform releases, new products, etc.
- Newsletter:Blog posts, community news, etc.
Please note that you will still receive important transactional emails related to your account. ",
- "NewsletterEmailFooterTemplateDeleteSubscription": "If you change your mind, you're always welcome to resubscribe!"
+ "NewsletterEmailFooterTemplateDeleteSubscription": "If you change your mind, you're always welcome to resubscribe!",
+ "GenerateQuote" : "Generate Quote" ,
+ "GeneratePriceQuote" : "Generate a Price Quote"
}
}
\ No newline at end of file
diff --git a/docs/en/Blog-Posts/2024-08-01-switching-between-organization-units/0.png b/docs/en/Blog-Posts/2024-08-01-switching-between-organization-units/0.png
index de27c1bf4a..ccfe417544 100644
Binary files a/docs/en/Blog-Posts/2024-08-01-switching-between-organization-units/0.png and b/docs/en/Blog-Posts/2024-08-01-switching-between-organization-units/0.png differ
diff --git a/docs/en/Blog-Posts/2024-08-01-switching-between-organization-units/1.png b/docs/en/Blog-Posts/2024-08-01-switching-between-organization-units/1.png
index df10f1e70e..e6bb3f64b6 100644
Binary files a/docs/en/Blog-Posts/2024-08-01-switching-between-organization-units/1.png and b/docs/en/Blog-Posts/2024-08-01-switching-between-organization-units/1.png differ
diff --git a/docs/en/Blog-Posts/2024-08-01-switching-between-organization-units/2.png b/docs/en/Blog-Posts/2024-08-01-switching-between-organization-units/2.png
index 6df238e8f9..1bb1b0e9dd 100644
Binary files a/docs/en/Blog-Posts/2024-08-01-switching-between-organization-units/2.png and b/docs/en/Blog-Posts/2024-08-01-switching-between-organization-units/2.png differ
diff --git a/docs/en/Blog-Posts/2024-08-01-switching-between-organization-units/3.png b/docs/en/Blog-Posts/2024-08-01-switching-between-organization-units/3.png
index cff88fa288..5dd64da53e 100644
Binary files a/docs/en/Blog-Posts/2024-08-01-switching-between-organization-units/3.png and b/docs/en/Blog-Posts/2024-08-01-switching-between-organization-units/3.png differ
diff --git a/docs/en/Blog-Posts/2024-08-01-switching-between-organization-units/cover.jpg b/docs/en/Blog-Posts/2024-08-01-switching-between-organization-units/cover.jpg
index 9e0e080c56..3503744fbc 100644
Binary files a/docs/en/Blog-Posts/2024-08-01-switching-between-organization-units/cover.jpg and b/docs/en/Blog-Posts/2024-08-01-switching-between-organization-units/cover.jpg differ
diff --git a/docs/en/Blog-Posts/2024-09-06 v8_3_Release_Stable/POST.md b/docs/en/Blog-Posts/2024-09-06 v8_3_Release_Stable/POST.md
new file mode 100644
index 0000000000..e69fbb86ea
--- /dev/null
+++ b/docs/en/Blog-Posts/2024-09-06 v8_3_Release_Stable/POST.md
@@ -0,0 +1,77 @@
+# ABP.IO Platform 8.3 Final Has Been Released!
+
+
+
+[ABP](https://abp.io/) 8.3 stable version has been released today.
+
+## What's New With Version 8.3?
+
+All the new features were explained in detail in the [8.3 RC Announcement Post](https://blog.abp.io/abp/announcing-abp-8-3-release-candidate), so there is no need to review them again. You can check it out for more details.
+
+## Getting Started with 8.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.
+
+By default, ABP Studio uses stable versions to create solutions. Therefore, it will be creating the solution with the latest stable version, which is v8.3 for now, so you don't need to specify the version.
+
+### How to Upgrade an Existing Solution
+
+You can upgrade your existing solutions with either ABP Studio or ABP CLI. In the following sections, both approaches are explained:
+
+### Upgrading via ABP Studio
+
+If you are already using the ABP Studio, you can upgrade it to the latest version to align it with ABP v8.3. ABP Studio periodically checks for updates in the background, and when a new version of ABP Studio is available, you will be notified through a modal. Then, you can update it by confirming the opened modal. See [the documentation](https://abp.io/docs/latest/studio/installation#upgrading) for more info.
+
+After upgrading the ABP Studio, then you can open your solution in the application, and simply click the **Switch to stable** action button to instantly upgrade your solution:
+
+
+
+### 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.
+
+## Migration Guides
+
+There are a few breaking changes in this version that may affect your application. Please read the migration guide carefully, if you are upgrading from v8.2 or earlier: [ABP Version 8.3 Migration Guide](https://abp.io/docs/8.3/release-info/migration-guides/abp-8-3)
+
+## Community News
+
+### New ABP Community Posts
+
+As always, exciting articles have been contributed by the ABP community. I will highlight some of them here:
+
+* [Alper Ebicoglu](https://twitter.com/alperebicoglu) has created **three** new community articles:
+ * [Do You Really Need Multi-tenancy?](https://abp.io/community/articles/do-you-really-need-multitenancy-hpwn44r3)
+ * [What is Angular Schematics?](https://abp.io/community/articles/what-is-angular-schematics-2z4jusf5)
+ * [Understanding Angular AOT vs JIT Compilations](https://abp.io/community/articles/understanding-angular-aot-vs-jit-compilations-0r0a0a3f)
+* [Dynamic Widget Communication](https://abp.io/community/articles/dynamic-widget-communication-uvun7q23) by [Suhaib Mousa](https://suhaibmousa.com/)
+* [Introducing the Google Cloud Storage BLOB Provider](https://abp.io/community/articles/introducing-the-google-cloud-storage-blob-provider-yrt6azc0) by [Engincan Veske](https://twitter.com/EngincanVeske)
+* [Switching Between Organization Units](https://abp.io/community/articles/switching-between-organization-units-i5tokpzt) by [Liming Ma](https://github.com/maliming)
+
+Thanks to the ABP Community for all the content they have published. You can also [post your ABP-related (text or video) content](https://abp.io/community/posts/submit) to the ABP Community.
+
+## About the Next Version
+
+The next feature version will be 9.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.
\ No newline at end of file
diff --git a/docs/en/Blog-Posts/2024-09-06 v8_3_Release_Stable/cover-image.png b/docs/en/Blog-Posts/2024-09-06 v8_3_Release_Stable/cover-image.png
new file mode 100644
index 0000000000..875be518af
Binary files /dev/null and b/docs/en/Blog-Posts/2024-09-06 v8_3_Release_Stable/cover-image.png differ
diff --git a/docs/en/Blog-Posts/2024-09-06 v8_3_Release_Stable/switch-to-stable.png b/docs/en/Blog-Posts/2024-09-06 v8_3_Release_Stable/switch-to-stable.png
new file mode 100644
index 0000000000..30883ebf92
Binary files /dev/null and b/docs/en/Blog-Posts/2024-09-06 v8_3_Release_Stable/switch-to-stable.png differ
diff --git a/docs/en/Blog-Posts/2024-09-17-My-Impressions-at-DotNext-2024-Conference/banner.png b/docs/en/Blog-Posts/2024-09-17-My-Impressions-at-DotNext-2024-Conference/banner.png
new file mode 100644
index 0000000000..040e8470df
Binary files /dev/null and b/docs/en/Blog-Posts/2024-09-17-My-Impressions-at-DotNext-2024-Conference/banner.png differ
diff --git a/docs/en/Blog-Posts/2024-09-17-My-Impressions-at-DotNext-2024-Conference/boat-trip.jpg b/docs/en/Blog-Posts/2024-09-17-My-Impressions-at-DotNext-2024-Conference/boat-trip.jpg
new file mode 100644
index 0000000000..e8b25c8391
Binary files /dev/null and b/docs/en/Blog-Posts/2024-09-17-My-Impressions-at-DotNext-2024-Conference/boat-trip.jpg differ
diff --git a/docs/en/Blog-Posts/2024-09-17-My-Impressions-at-DotNext-2024-Conference/collage-moscow.jpg b/docs/en/Blog-Posts/2024-09-17-My-Impressions-at-DotNext-2024-Conference/collage-moscow.jpg
new file mode 100644
index 0000000000..1acfee01a3
Binary files /dev/null and b/docs/en/Blog-Posts/2024-09-17-My-Impressions-at-DotNext-2024-Conference/collage-moscow.jpg differ
diff --git a/docs/en/Blog-Posts/2024-09-17-My-Impressions-at-DotNext-2024-Conference/general-1.png b/docs/en/Blog-Posts/2024-09-17-My-Impressions-at-DotNext-2024-Conference/general-1.png
new file mode 100644
index 0000000000..20c9ef5b05
Binary files /dev/null and b/docs/en/Blog-Posts/2024-09-17-My-Impressions-at-DotNext-2024-Conference/general-1.png differ
diff --git a/docs/en/Blog-Posts/2024-09-17-My-Impressions-at-DotNext-2024-Conference/general-collage.jpg b/docs/en/Blog-Posts/2024-09-17-My-Impressions-at-DotNext-2024-Conference/general-collage.jpg
new file mode 100644
index 0000000000..9310e1312f
Binary files /dev/null and b/docs/en/Blog-Posts/2024-09-17-My-Impressions-at-DotNext-2024-Conference/general-collage.jpg differ
diff --git a/docs/en/Blog-Posts/2024-09-17-My-Impressions-at-DotNext-2024-Conference/halil-talk.jpg b/docs/en/Blog-Posts/2024-09-17-My-Impressions-at-DotNext-2024-Conference/halil-talk.jpg
new file mode 100644
index 0000000000..9f0e62bf77
Binary files /dev/null and b/docs/en/Blog-Posts/2024-09-17-My-Impressions-at-DotNext-2024-Conference/halil-talk.jpg differ
diff --git a/docs/en/Blog-Posts/2024-09-17-My-Impressions-at-DotNext-2024-Conference/my-talk-2.png b/docs/en/Blog-Posts/2024-09-17-My-Impressions-at-DotNext-2024-Conference/my-talk-2.png
new file mode 100644
index 0000000000..b2a0ae3581
Binary files /dev/null and b/docs/en/Blog-Posts/2024-09-17-My-Impressions-at-DotNext-2024-Conference/my-talk-2.png differ
diff --git a/docs/en/Blog-Posts/2024-09-17-My-Impressions-at-DotNext-2024-Conference/my-talk-pro-pictures.jpg b/docs/en/Blog-Posts/2024-09-17-My-Impressions-at-DotNext-2024-Conference/my-talk-pro-pictures.jpg
new file mode 100644
index 0000000000..20f411243b
Binary files /dev/null and b/docs/en/Blog-Posts/2024-09-17-My-Impressions-at-DotNext-2024-Conference/my-talk-pro-pictures.jpg differ
diff --git a/docs/en/Blog-Posts/2024-09-17-My-Impressions-at-DotNext-2024-Conference/my-talk.png b/docs/en/Blog-Posts/2024-09-17-My-Impressions-at-DotNext-2024-Conference/my-talk.png
new file mode 100644
index 0000000000..1206f5144c
Binary files /dev/null and b/docs/en/Blog-Posts/2024-09-17-My-Impressions-at-DotNext-2024-Conference/my-talk.png differ
diff --git a/docs/en/Blog-Posts/2024-09-17-My-Impressions-at-DotNext-2024-Conference/post.md b/docs/en/Blog-Posts/2024-09-17-My-Impressions-at-DotNext-2024-Conference/post.md
new file mode 100644
index 0000000000..c6ac51d273
--- /dev/null
+++ b/docs/en/Blog-Posts/2024-09-17-My-Impressions-at-DotNext-2024-Conference/post.md
@@ -0,0 +1,87 @@
+# DotNext 2024 Conference: A Speaker’s Impressions
+
+
+
+Last week, I had the chance of being a speaker at **DotNext 2024** in Moscow. [JUG Ru Group](https://jugru.org/en/) is arranging the DotNext Conferences since [2014](https://dotnext.ru/archive/). It's a specific conference for .NET developers held at the [MonArch Moscow Hotel](https://www.moscowmonarch.com/) on 10, 11 September 2024. This event brought together over **600 developers on-site, 200 developers online**, with around **35 speakers** delivering more than **30 talks**, making it one of the largest gatherings of the .NET community in Russia.
+
+
+
+---
+
+
+
+## Key Highlights & Popular Sessions
+
+One of the standout aspects of the conference was its strong technical focus, particularly on deep-dive .NET topics. Talks covered subjects like **low-level optimizations**, architecture, performance, and platform internals.
+
+The conference started with Sergei Benzenko's talk "What's New in .NET 9". There are important topics like ".NET Aspire in Action", "AI-Driven Software Development", "DDD and Strategic Design" and "OAuth 2.0 User-Managed Access in ASP.NET Core with Keycloak".
+
+
+
+There were two international speakers: me and Halil Ibrahim Kalkan from ABP Core Team. Halil's topic was **Implementing Domain-Driven Design as a Pragmatic Developer**. In his session, he gave practical real world examples of bad and best practices of DDD development.
+
+
+
+
+---
+
+
+
+## My Talk
+
+My presentation topic was **Building Multi-Tenant ASP.NET Core Applications** was part of this technical deep dive, and I was thrilled to see so much interest in scalable multi-tenant solutions. I generally talked about meta data in SaaS development and explained how to identify the active tenant, how to isolate the data in the same database, how to set `TenantId` automatically for new entities, how to select DB connection for the active tenant, how to change the active tenant when needed, how to disable multi-tenancy temporarily, how to handle database migrations and lastly feature system. These features are major multi-tenancy features, and you'll learn how they are implemented in an open-source web app framework.
+
+
+
+
+
+- My presentation 🌐https://github.com/ebicoglu/presentations/tree/main.
+
+- My conf profile🌐 https://dotnext.ru/en/persons/cbe6e4b2cc214a47bfc3752cdb0b1f88/
+
+
+
+
+---
+
+
+
+## Venue and Atmosphere
+
+The MonArch Moscow Hotel provided a great venue, combining spacious halls for sessions with cozy areas for networking. There were also afterparty events, which added a fun, informal touch to the otherwise highly technical environment. The setup allowed plenty of opportunities for spontaneous discussions with attendees and experts, both during and after the sessions.
+
+
+
+
+---
+
+
+
+## Boat Tour on Moscow River
+
+After the conference ended, the organizing team took all the speakers on a boat tour on the Moscow River. It was a great open buffet dinner in a nice boat. We had a chance to chat with other speakers.
+
+
+
+---
+
+
+
+## Networking and Community
+
+DotNext 2024 provided an excellent platform for connecting with fellow developers and industry leaders. In addition to presentations, there were plenty of opportunities to interact with other participants, including representatives from Microsoft, Volosoft, and local Russian tech giants like Ozon and beeline. The exhibition hall was filled with partner stands, including those from PVS-Studio, Kontur, Eremex and OzonTech which offered interactive displays and demos.
+
+---
+
+
+
+## Conclusion
+
+Overall, DotNext 2024 lived up to its reputation as a key event for .NET developers. From highly technical talks to networking opportunities, it was a fantastic experience, and I came away with new insights into both the technical and community aspects of the .NET ecosystem. If you’re a .NET developer looking to stay ahead in your field, DotNext is definitely a conference worth attending!
+
+Looking forward to come again!
+
+
+Lastly, I took some beautiful photos of Moscow, here are a few...
+
+
\ No newline at end of file
diff --git a/docs/en/Blog-Posts/2024-09-17-My-Impressions-at-DotNext-2024-Conference/speakers.png b/docs/en/Blog-Posts/2024-09-17-My-Impressions-at-DotNext-2024-Conference/speakers.png
new file mode 100644
index 0000000000..eccc1bd0b4
Binary files /dev/null and b/docs/en/Blog-Posts/2024-09-17-My-Impressions-at-DotNext-2024-Conference/speakers.png differ
diff --git a/docs/en/Community-Articles/2024-08-28-Understanding-AOT-vs-JIT/images/book.jpg b/docs/en/Community-Articles/2024-08-28-Understanding-AOT-vs-JIT/images/book.jpg
index bb1b8e86dc..a34fd1ff87 100644
Binary files a/docs/en/Community-Articles/2024-08-28-Understanding-AOT-vs-JIT/images/book.jpg and b/docs/en/Community-Articles/2024-08-28-Understanding-AOT-vs-JIT/images/book.jpg differ
diff --git a/docs/en/Community-Articles/2024-08-28-Understanding-AOT-vs-JIT/images/cover.png b/docs/en/Community-Articles/2024-08-28-Understanding-AOT-vs-JIT/images/cover.png
index 236eddc965..418eb5ff22 100644
Binary files a/docs/en/Community-Articles/2024-08-28-Understanding-AOT-vs-JIT/images/cover.png and b/docs/en/Community-Articles/2024-08-28-Understanding-AOT-vs-JIT/images/cover.png differ
diff --git a/docs/en/framework/ui/angular/how-replaceable-components-work-with-extensions.md b/docs/en/framework/ui/angular/how-replaceable-components-work-with-extensions.md
index 39c1f00cfe..11a7f6dfb8 100644
--- a/docs/en/framework/ui/angular/how-replaceable-components-work-with-extensions.md
+++ b/docs/en/framework/ui/angular/how-replaceable-components-work-with-extensions.md
@@ -18,7 +18,8 @@ Open the generated `src/app/my-roles/my-roles.component.ts` file and replace its
```js
import { ListService, PagedAndSortedResultRequestDto, PagedResultDto } from '@abp/ng.core';
-import { eIdentityComponents, IdentityRoleDto, IdentityRoleService, RolesComponent } from '@abp/ng.identity';
+import { eIdentityComponents, RolesComponent } from '@abp/ng.identity';
+import { IdentityRoleDto, IdentityRoleService } from '@abp/ng.identity/proxy';
import { ePermissionManagementComponents } from '@abp/ng.permission-management';
import { Confirmation, ConfirmationService } from '@abp/ng.theme.shared';
import {
@@ -232,7 +233,7 @@ We have added the `abp-page-toolbar`, `abp-extensible-table`, and `abp-extensibl
You should import the required modules for the `MyRolesComponent` to `MyRolesModule`. Open the `src/my-roles/my-roles.module.ts` file and replace the content with the following:
```js
-import { UiExtensionsModule } from '@abp/ng.theme.shared/extensions';
+import { ExtensibleModule } from '@abp/ng.components/extensible';
import { NgModule } from '@angular/core';
import { SharedModule } from '../shared/shared.module';
import { MyRolesComponent } from './my-roles.component';
@@ -240,13 +241,13 @@ import { PermissionManagementModule } from '@abp/ng.permission-management';
@NgModule({
declarations: [MyRolesComponent],
- imports: [SharedModule, UiExtensionsModule, PermissionManagementModule],
+ imports: [SharedModule, ExtensibleModule, PermissionManagementModule],
exports: [MyRolesComponent],
})
export class MyRolesModule {}
```
-- `UiExtensionsModule` imported to be able to use the extension components in your component.
+- `ExtensionsModule` imported to be able to use the extension components in your component.
- `PermissionManagementModule` imported to be able to use the `abp-permission-*management` in your component.
As the last step, it is needs to be replaced the `RolesComponent` with the `MyRolesComponent`. Open the `app.component.ts` and modify its content as shown below:
diff --git a/docs/en/get-started/images/abp-studio-created-new-solution.png b/docs/en/get-started/images/abp-studio-created-new-solution.png
index 4a7d4f0b01..c089c276f6 100644
Binary files a/docs/en/get-started/images/abp-studio-created-new-solution.png and b/docs/en/get-started/images/abp-studio-created-new-solution.png differ
diff --git a/docs/en/get-started/images/abp-studio-new-solution-dialog-additional-options-microservice.png b/docs/en/get-started/images/abp-studio-new-solution-dialog-additional-options-microservice.png
index 87bd86755c..9f9df8991f 100644
Binary files a/docs/en/get-started/images/abp-studio-new-solution-dialog-additional-options-microservice.png and b/docs/en/get-started/images/abp-studio-new-solution-dialog-additional-options-microservice.png differ
diff --git a/docs/en/get-started/images/abp-studio-new-solution-dialog-additional-options.png b/docs/en/get-started/images/abp-studio-new-solution-dialog-additional-options.png
new file mode 100644
index 0000000000..4a2d3c2dd2
Binary files /dev/null and b/docs/en/get-started/images/abp-studio-new-solution-dialog-additional-options.png differ
diff --git a/docs/en/get-started/images/abp-studio-new-solution-dialog-database-configurations-efcore.png b/docs/en/get-started/images/abp-studio-new-solution-dialog-database-configurations-efcore.png
index e71cbb7036..e9a5bcee19 100644
Binary files a/docs/en/get-started/images/abp-studio-new-solution-dialog-database-configurations-efcore.png and b/docs/en/get-started/images/abp-studio-new-solution-dialog-database-configurations-efcore.png differ
diff --git a/docs/en/get-started/images/abp-studio-new-solution-dialog-database-configurations-mongo.png b/docs/en/get-started/images/abp-studio-new-solution-dialog-database-configurations-mongo.png
index f0b0ed136b..4b00156e3f 100644
Binary files a/docs/en/get-started/images/abp-studio-new-solution-dialog-database-configurations-mongo.png and b/docs/en/get-started/images/abp-studio-new-solution-dialog-database-configurations-mongo.png differ
diff --git a/docs/en/get-started/images/abp-studio-new-solution-dialog-database-provider-efcore.png b/docs/en/get-started/images/abp-studio-new-solution-dialog-database-provider-efcore.png
index 6f8e937b09..138d1904f5 100644
Binary files a/docs/en/get-started/images/abp-studio-new-solution-dialog-database-provider-efcore.png and b/docs/en/get-started/images/abp-studio-new-solution-dialog-database-provider-efcore.png differ
diff --git a/docs/en/get-started/images/abp-studio-new-solution-dialog-database-provider-mongo.png b/docs/en/get-started/images/abp-studio-new-solution-dialog-database-provider-mongo.png
index a1175b81bf..1e3f54a9d8 100644
Binary files a/docs/en/get-started/images/abp-studio-new-solution-dialog-database-provider-mongo.png and b/docs/en/get-started/images/abp-studio-new-solution-dialog-database-provider-mongo.png differ
diff --git a/docs/en/get-started/images/abp-studio-new-solution-dialog-mobile-framework-microservice.png b/docs/en/get-started/images/abp-studio-new-solution-dialog-mobile-framework-microservice.png
index b7ccfb2976..7e43e784f3 100644
Binary files a/docs/en/get-started/images/abp-studio-new-solution-dialog-mobile-framework-microservice.png and b/docs/en/get-started/images/abp-studio-new-solution-dialog-mobile-framework-microservice.png differ
diff --git a/docs/en/get-started/images/abp-studio-new-solution-dialog-mobile-framework.png b/docs/en/get-started/images/abp-studio-new-solution-dialog-mobile-framework.png
index 20b89c059d..f773d887d8 100644
Binary files a/docs/en/get-started/images/abp-studio-new-solution-dialog-mobile-framework.png and b/docs/en/get-started/images/abp-studio-new-solution-dialog-mobile-framework.png differ
diff --git a/docs/en/get-started/images/abp-studio-new-solution-dialog-optional-modules.png b/docs/en/get-started/images/abp-studio-new-solution-dialog-optional-modules.png
new file mode 100644
index 0000000000..992760e3fc
Binary files /dev/null and b/docs/en/get-started/images/abp-studio-new-solution-dialog-optional-modules.png differ
diff --git a/docs/en/get-started/images/abp-studio-new-solution-dialog-public-website.png b/docs/en/get-started/images/abp-studio-new-solution-dialog-public-website.png
new file mode 100644
index 0000000000..e10d4a965c
Binary files /dev/null and b/docs/en/get-started/images/abp-studio-new-solution-dialog-public-website.png differ
diff --git a/docs/en/get-started/images/abp-studio-new-solution-dialog-solution-properties.png b/docs/en/get-started/images/abp-studio-new-solution-dialog-solution-properties.png
index 93b3154e7c..7412b4b6e1 100644
Binary files a/docs/en/get-started/images/abp-studio-new-solution-dialog-solution-properties.png and b/docs/en/get-started/images/abp-studio-new-solution-dialog-solution-properties.png differ
diff --git a/docs/en/get-started/images/abp-studio-new-solution-dialog-solution-structure.png b/docs/en/get-started/images/abp-studio-new-solution-dialog-solution-structure.png
index 3cdd22f555..310488c1bc 100644
Binary files a/docs/en/get-started/images/abp-studio-new-solution-dialog-solution-structure.png and b/docs/en/get-started/images/abp-studio-new-solution-dialog-solution-structure.png differ
diff --git a/docs/en/get-started/images/abp-studio-new-solution-dialog-ui-framework.png b/docs/en/get-started/images/abp-studio-new-solution-dialog-ui-framework.png
index 228c711a1a..d373a55344 100644
Binary files a/docs/en/get-started/images/abp-studio-new-solution-dialog-ui-framework.png and b/docs/en/get-started/images/abp-studio-new-solution-dialog-ui-framework.png differ
diff --git a/docs/en/get-started/images/abp-studio-new-solution-dialog-ui-theme.png b/docs/en/get-started/images/abp-studio-new-solution-dialog-ui-theme.png
index d17d1d766d..8594f02d58 100644
Binary files a/docs/en/get-started/images/abp-studio-new-solution-dialog-ui-theme.png and b/docs/en/get-started/images/abp-studio-new-solution-dialog-ui-theme.png differ
diff --git a/docs/en/get-started/images/abp-studio-quick-start-application-solution-runner.png b/docs/en/get-started/images/abp-studio-quick-start-application-solution-runner.png
index 2e4a9aa583..f5ca4c97e7 100644
Binary files a/docs/en/get-started/images/abp-studio-quick-start-application-solution-runner.png and b/docs/en/get-started/images/abp-studio-quick-start-application-solution-runner.png differ
diff --git a/docs/en/get-started/images/abp-studio-quick-start-browse-command.png b/docs/en/get-started/images/abp-studio-quick-start-browse-command.png
index 186ff2d55d..c97b3c9700 100644
Binary files a/docs/en/get-started/images/abp-studio-quick-start-browse-command.png and b/docs/en/get-started/images/abp-studio-quick-start-browse-command.png differ
diff --git a/docs/en/get-started/images/abp-studio-quick-start-browse.png b/docs/en/get-started/images/abp-studio-quick-start-browse.png
index d63c20c8ac..47b4bf29cf 100644
Binary files a/docs/en/get-started/images/abp-studio-quick-start-browse.png and b/docs/en/get-started/images/abp-studio-quick-start-browse.png differ
diff --git a/docs/en/get-started/images/abp-studio-quick-start-example-applications-in-solution-runner.png b/docs/en/get-started/images/abp-studio-quick-start-example-applications-in-solution-runner.png
index 46adf8bfc0..44cef603fb 100644
Binary files a/docs/en/get-started/images/abp-studio-quick-start-example-applications-in-solution-runner.png and b/docs/en/get-started/images/abp-studio-quick-start-example-applications-in-solution-runner.png differ
diff --git a/docs/en/get-started/images/solution-runner-public-website.png b/docs/en/get-started/images/solution-runner-public-website.png
index a00368ee79..b1e76a4ce6 100644
Binary files a/docs/en/get-started/images/solution-runner-public-website.png and b/docs/en/get-started/images/solution-runner-public-website.png differ
diff --git a/docs/en/get-started/layered-web-application.md b/docs/en/get-started/layered-web-application.md
index e1c00fd336..0b051b9681 100644
--- a/docs/en/get-started/layered-web-application.md
+++ b/docs/en/get-started/layered-web-application.md
@@ -77,17 +77,25 @@ LeptonX is the suggested UI theme that is proper for production usage. Select on
Here, you see all the mobile applications available in that startup solution template. These mobile applications are well-integrated into your solution and can use the same backend with your web application. They are simple (do not have pre-built features as much as the web application) but a very good starting point to build your mobile application.
-Pick the one best for you, or select the *None* if you don't want a mobile application in your solution, then click Next to navigate to the *Additional UI options* screen:
+Pick the one best for you, or select the *None* if you don't want a mobile application in your solution, then click Next to navigate to the *Public website* screen:
-
+
That startup solution template also provides an option to create a second web application inside the solution. The second application is called the Public website, an ASP.NET Core MVC / Razor Page application. It can be used to create a public landing/promotion for your product. It is well integrated into the solution (can share the same services, entities, database, and the same authentication logic, for example). If you want, you can also include the [CMS Kit module](../modules/cms-kit) to your solution to add dynamic content features to your web application.
-So, either select the *Public website* or skip it and click the Next button for the *Solution Structure* selection:
+So, either select the *Public website* or skip it and click the Next button for the *Optional Modules* selection:
+
+
+
+Each item in that list is a pre-built application module. You can click the blue icon near to the module name to get more information about the module. You can leave the list as is (so, it installs the most common and used modules for you) or customize based on your preference.
+
+Installing a module after creating the solution may require manual steps. So, it is better to decide the modules in the beginning. You can create an example solutions before your real solution to explore the solution and modules.
+
+Once you select the desired modules, click the *Next* button for the *Solution Structure* screen:

-The *Tiered* option is used to physically separate the web application (the UI part) from the backend HTTP APIs. It creates a separate host application that only serves the HTTP (REST) APIs. The web application then performs remote HTTP calls to that application for every operation. If the *Tiered* option is not selected, then the web and HTTP APIs are hosted in a single application, and the calls from the UI layer to the API layer are performed in-process.
+It creates a separate host application that only serves the HTTP (REST) APIs. The web application then performs remote HTTP calls to that application for every operation. If the *Tiered* option is not selected, then the web and HTTP APIs are hosted in a single application, and the calls from the UI layer to the API layer are performed in-process.
The tiered architecture allows you to host the web (UI) application in a server that can not access to your database server. However, it brings a slight loss of performance (because of the HTTP calls between UI and HTTP API applications) and makes your architecture, development, and deployment more complex. If you don't understand the tiered structure, just skip it.
@@ -107,9 +115,13 @@ On that screen, you can decide on your database provider by selecting one of the

{{ end }}
-Here, you can select the database management systems (DBMS){{ if DB == "EF" }} and the connection string{{ end }}. Now, we are ready to allow ABP Studio to create our solution. Just click the *Create* button and let the ABP Studio do the rest for you.
+Here, you can select the database management systems (DBMS){{ if DB == "EF" }} and the connection string{{ end }}. Click *Next* button to see the *Additional Options*.
+
+
+
+If you uncheck the *Kubernetes Configuration* option, the solution will not include the Kubernetes configuration files, such as Helm charts and other Kubernetes-related files. You can also specify *Social Logins*; if you uncheck this option, the solution will not be configured for social login.
-After clicking the Create button, the dialog is closed and your solution is loaded into ABP Studio:
+Now, we are ready to allow ABP Studio to create our solution. Just click the *Create* button and let the ABP Studio do the rest for you. After clicking the Create button, the dialog is closed and your solution is loaded into ABP Studio:

@@ -129,7 +141,7 @@ Open the [Solution Runner](../studio/running-applications.md) section on the lef
Once you click the *Play* icon on the left side, the section is open in the same place as the Solution Explorer section. ABP Studio also opens the *Application Monitor* view on the main content area. *Application Monitor* shows useful insights for your applications (e.g. *HTTP Request*, *Events* and *Exceptions*) in real-time. You can use it to see the happenings in your applications, so you can easily track errors and many helpful details.
-In the Solution Runner section (on the left side) you can see all the runnable applications in the current solution. For the MVC with public website example, we have three applications:
+In the Solution Runner section (on the left side) you can see all the runnable applications in the current solution. For the MVC with public website and MAUI mobile example, we have four applications:

@@ -230,4 +242,4 @@ Before starting the mobile application, ensure that you configure it for [react-
> For example in non-tiered MVC with public website application:
-
+
\ No newline at end of file
diff --git a/docs/en/get-started/microservice.md b/docs/en/get-started/microservice.md
index 82db8dcc62..47f1091b14 100644
--- a/docs/en/get-started/microservice.md
+++ b/docs/en/get-started/microservice.md
@@ -71,7 +71,7 @@ Click the Next button to see *Additional Options* selection:

-If you unchecked the *Kubernetes Configuration* option, the solution will not include the Kubernetes configuration files which include the Helm charts and other Kubernetes related files.
+If you unchecked the *Kubernetes Configuration* option, the solution will not include the Kubernetes configuration files which include the Helm charts and other Kubernetes related files. You can also specify *Social Logins*; if you uncheck this option, the solution will not be configured for social login.
Now, we are ready to allow ABP Studio to create our solution. Just click the *Create* button and let the ABP Studio do the rest for you. After clicking the Create button, the dialog is closed and your solution is loaded into ABP Studio:
diff --git a/docs/en/guides/migrating-from-open-source.md b/docs/en/guides/migrating-from-open-source.md
index 5340e4212a..35ba91df7a 100644
--- a/docs/en/guides/migrating-from-open-source.md
+++ b/docs/en/guides/migrating-from-open-source.md
@@ -1,6 +1,6 @@
# Migrating from Open Source Templates
-ABP Studio provides a way for users, who already started the development before purchasing a license, to auto-upgrade their solutions with Pro modules. You can use this functionality through ABP Studio UI or ABP Studio CLI:
+[ABP Studio](https://abp.io/studio) provides a way for the users who already started the development before purchasing a license to auto-upgrade their solutions with Pro modules. You can use this functionality through ABP Studio UI or ABP Studio CLI:
* A new button labeled `Upgrade to Pro` will be visible if you have a license but the current solution is created with open-source (free) license.
diff --git a/docs/en/images/issuemanagement-module-solution.png b/docs/en/images/issuemanagement-module-solution.png
index 3e01ff1b92..b224045596 100644
Binary files a/docs/en/images/issuemanagement-module-solution.png and b/docs/en/images/issuemanagement-module-solution.png differ
diff --git a/docs/en/images/module-layers-and-packages.png b/docs/en/images/module-layers-and-packages.png
index 0635172fc1..f99d95cd83 100644
Binary files a/docs/en/images/module-layers-and-packages.png and b/docs/en/images/module-layers-and-packages.png differ
diff --git a/docs/en/solution-templates/application-module/index.md b/docs/en/solution-templates/application-module/index.md
index f8e2d7adb6..60f53a7018 100644
--- a/docs/en/solution-templates/application-module/index.md
+++ b/docs/en/solution-templates/application-module/index.md
@@ -15,17 +15,25 @@ dotnet tool install -g Volo.Abp.Studio.Cli
Then use the `abp new` command in an empty folder to create a new solution:
```bash
-abp new Acme.IssueManagement -t module
+abp new-module Acme.BookStore
```
- `Acme.IssueManagement` is the solution name, like *YourCompany.YourProduct*. You can use single level, two-levels or three-levels naming.
-### Without User Interface
+### Specifying the User Interface
-The template comes with MVC, Blazor & Angular user interfaces by default. You can use `--no-ui` option to not include any of these UI layers.
+The template comes without a user interface by default. You can use the `mvc`, `blazor`, `blazor-server`, or `angular` options to include any of these UI layers. You can also combine them. For example, you can use `mvc,angular` to include both MVC and Angular UI. To create a module without a user interface, don't specify any value.
````bash
-abp new Acme.IssueManagement -t module --no-ui
+abp new-module Acme.IssueManagement -u mvc,angular
+````
+
+#### Specifying the Database Provider
+
+The template comes with the *EntityFrameworkCore* database provider by default. You can use the `ef` or `mongodb` options to include either of these providers. You can also combine them. For example, you can use `ef,mongodb` to include both EntityFrameworkCore and MongoDB.
+
+````bash
+abp new-module Acme.IssueManagement -d ef,mongodb
````
## Solution Structure
@@ -34,11 +42,10 @@ Based on the options you've specified, you will get a slightly different solutio

-Projects are organized as `src`, `test` and `host` folders:
+Projects are organized as `src` and`test` folders:
* `src` folder contains the actual module which is layered based on [DDD](../../framework/architecture/domain-driven-design) principles.
* `test` folder contains unit & integration tests.
-* `host` folder contains applications with different configurations to demonstrate how to host the module in an application. These are not a part of the module, but useful on development.
The diagram below shows the layers & project dependencies of the module:
@@ -105,8 +112,6 @@ The solution has multiple test projects, one for each layer:
- `.MongoDB.Tests` is used to test MongoDB configuration and custom repositories.
- `.TestBase` is a base (shared) project for all tests.
-In addition, `.HttpApi.Client.ConsoleTestApp` is a console application (not an automated test project) which demonstrate the usage of HTTP APIs from a Dotnet application.
-
Test projects are prepared for integration testing;
- It is fully integrated to ABP and all services in your application.
@@ -117,49 +122,9 @@ You can still create unit tests for your classes which will be harder to write (
> Domain & Application tests are using EF Core. If you remove EF Core integration or you want to use MongoDB for testing these layers, you should manually change project references & module dependencies.
-### Host Projects
-
-The solution has a few host applications to run your module. Host applications are used to run your module in a fully configured application. It is useful on development. Host applications includes some other modules in addition to the module being developed:
-
-Host applications support two types of scenarios.
-
-#### Single (Unified) Application Scenario
-
-If your module has a UI, then `.Web.Unified` application is used to host the UI and API on a single point. It has its own `appsettings.json` file (that includes the database connection string) and EF Core database migrations.
-
-For the `.Web.Unified` application, there is a single database, named `YourProjectName_Unified` (like *IssueManagement_Unified* for this sample).
-
-> If you've selected the `--no-ui` option, this project will not be in your solution.
-
-##### How to Run?
-
-Set `host/YourProjectName.Web.Unified` as the startup project, run `Update-Database` command for the EF Core from Package Manager Console and run your application. Default username is `admin` and password is `1q2w3E*`.
-
-#### Separated Deployment & Databases Scenario
-
-In this scenario, there are three applications;
-
-* `.AuthServer` application is an authentication server used by other applications. It has its own `appsettings.json` that contains database connection and other configurations.
-* `.HttpApi.Host` hosts the HTTP API of the module. It has its own `appsettings.json` that contains database connections and other configurations.
-* `.Web.Host` host the UI of the module. This project contains an `appsettings.json` file, but it does not have a connection string because it never connects to the database. Instead, it mainly contains endpoint of the remote API server and the authentication server.
-
-The diagram below shows the relation of the applications:
-
-
-
-`.Web.Host` project uses OpenId Connect Authentication to get identity and access tokens for the current user from the `.AuthServer`. Then uses the access token to call the `.HttpApi.Host`. HTTP API server uses bearer token authentication to obtain claims from the access token to authorize the current user.
-
-##### Pre-requirements
-
-* [Redis](https://redis.io/): The applications use Redis as as distributed cache. So, you need to have Redis installed & running.
-
-##### How to Run?
-
-You should run the application with the given order:
+### Host Project
-- First, run the `.AuthServer` since other applications depends on it.
-- Then run the `.HttpApi.Host` since it is used by the `.Web.Host` application.
-- Finally, you can run the `.Web.Host` project and login to the application using `admin` as the username and `1q2w3E*` as the password.
+The solution doesn't have a host application to run your module. However, you can create a [single-layer](../../get-started/single-layer-web-application.md) or [layered](../../get-started/layered-web-application.md) application and [import](../../studio/solution-explorer.md#imports) the created module into the host application.
## UI
@@ -172,7 +137,7 @@ The solution will have a folder called `angular` in it. This is where the Angula
* _angular/projects/issue-management_ folder contains the Angular module project.
* _angular/projects/dev-app_ folder contains a development application that runs your module.
-The server-side is similar to the solution described above. `*.HttpApi.Host` project serves the API and the `Angular` demo application consumes it. You will not need to run the `.Web.Host` project though.
+The server-side is similar to the solution described above. After you create a *Host* application, the API and the `Angular` demo application consume it.
#### How to Run the Angular Development App
@@ -195,9 +160,10 @@ The module you will develop depends on two of these ABP packages: _@abp/ng.core_
Once all dependencies are installed, follow the steps below to serve your development app:
-1. Make sure `.AuthServer` and `*.HttpApi.Host` projects are up and running.
-2. Open your terminal at the root folder, i.e. `angular`.
-3. Run `yarn start` or `npm start`.
+1. Make sure *Host* application project is up and running.
+2. Change the `environment.ts` file in the `angular/projects/dev-app/src/environments` folder to match your *Host* application URL.
+3. Open your terminal at the root folder, i.e. `angular`.
+4. Run `yarn start` or `npm start`.

diff --git a/docs/en/solution-templates/microservice/adding-new-microservices.md b/docs/en/solution-templates/microservice/adding-new-microservices.md
index 4a82ee6a55..9cb482c552 100644
--- a/docs/en/solution-templates/microservice/adding-new-microservices.md
+++ b/docs/en/solution-templates/microservice/adding-new-microservices.md
@@ -34,6 +34,11 @@ Select the database provider and click the `Create` button.

+When you create a new microservice, you can choose to enable integration with the current solution. If you check *Enable integration*, the new microservice is added to the solution, and the necessary configurations are made automatically, so no manual configuration is needed. If you uncheck the *Enable integration* option, you will need to manually configure the new microservice. You can follow the steps in this documentation, starting from the [Configuring the appsettings.json](#configuring-the-appsettingsjson) section.
+
+
+
+
The new microservice is created and added to the solution. You can see the new microservice in the `services` folder.

diff --git a/docs/en/solution-templates/microservice/images/create-new-microservice-nolayers-enable-integration.png b/docs/en/solution-templates/microservice/images/create-new-microservice-nolayers-enable-integration.png
new file mode 100644
index 0000000000..a1aa31887f
Binary files /dev/null and b/docs/en/solution-templates/microservice/images/create-new-microservice-nolayers-enable-integration.png differ
diff --git a/docs/en/studio/images/solution-explorer/abp-solution.png b/docs/en/studio/images/solution-explorer/abp-solution.png
index 8348e71778..b15e7f46f0 100644
Binary files a/docs/en/studio/images/solution-explorer/abp-solution.png and b/docs/en/studio/images/solution-explorer/abp-solution.png differ
diff --git a/docs/en/studio/images/solution-explorer/create-new-microservice-nolayers-enable-integration.png b/docs/en/studio/images/solution-explorer/create-new-microservice-nolayers-enable-integration.png
new file mode 100644
index 0000000000..a1aa31887f
Binary files /dev/null and b/docs/en/studio/images/solution-explorer/create-new-microservice-nolayers-enable-integration.png differ
diff --git a/docs/en/studio/kubernetes.md b/docs/en/studio/kubernetes.md
index c6722dfc37..f05a30ee04 100644
--- a/docs/en/studio/kubernetes.md
+++ b/docs/en/studio/kubernetes.md
@@ -25,6 +25,11 @@ The *Kubernetes* panel is available only in the [business and enterprise](https:
* [Docker Desktop](https://www.docker.com/products/docker-desktop) (Enable Kubernetes option if not working with a real cluster)
* [NGINX Ingress Controller](https://kubernetes.github.io/ingress-nginx/deploy)
* [mkcert](https://www.ibm.com/docs/en/fsmmn?topic=commands-mkcert)
+ * When you are installing the `mkcert` to allow ABP Studio to generate certificates for you, please ensure that `mkcert` is installed on the **Trusted Certificate Store** by running the following command (on **Windows**, this command must be executed with *Administrator* priviliges):
+
+ ```bash
+ mkcert -install
+ ```
## Profile
@@ -145,9 +150,9 @@ Upon disconnection from the cluster, we clean up the hosts file, excluding ingre

-> When you list the services in the Kubernetes cluster with the `kubectl get svc` command, you should see the *abp-wg-easy* and *abp-wg-easy-vpn* services. After a while, if the *EXTERNAL-IP* is still *pending*, then it can't connect to the cluster. This could be caused by if you try to install the WireGuard VPN to a Docker Desktop Kubernetes cluster more than once. You can delete the previous WireGuard VPN by running the `helm uninstall abp-wg-easy` command in the previous namespace.
+> When you list the services in the Kubernetes cluster with the `kubectl get svc` command, you should see the *abp-wg-easy* and *abp-wg-easy-vpn* services. Each WireGuard installation has a unique port number for the related services. If you have multiple WireGuard installations for different Kubernetes profiles or solutions, you can see the port numbers in the *PORT(S)* field when you list them with the `kubectl get svc` command.
-> Connecting to the Kubernetes cluster is limited to one instance of ABP Studio at a time. Trying to connect with another instance simultaneously won't work as expected.
+> Connecting to the Kubernetes cluster is limited to one instance of ABP Studio at the same time. Trying to connect with another instance simultaneously won't work as expected.
### Intercept a Service
diff --git a/docs/en/studio/release-notes.md b/docs/en/studio/release-notes.md
index e2bbddf2eb..211786cacb 100644
--- a/docs/en/studio/release-notes.md
+++ b/docs/en/studio/release-notes.md
@@ -2,6 +2,20 @@
This document contains **brief release notes** for each ABP Studio release. Release notes only include **major features** and **visible enhancements**. Therefore, they don't include all the development done in the related version.
+## 0.8.1 (2024-09-12)
+
+* Fixed MySQL connection problem for nolayers template
+* Ignored failed solution runner profiles while loading
+* Added required ModalBuilder extensions for the imported/installed modules for EF Core
+
+## 0.8.0 (2024-09-11)
+
+* Added `Blazor WebApp UI` to **app-nolayers** and **microservice** templates
+* Fixed version problem for bundle command
+* Fixed optional module integrations
+* Added **LeptonX Theme** to module-list
+* Fixed bug related to Kubernetes user-specified connection
+
## 0.7.9 (2024-08-29)
* Opened Readme.md file after module creation or opening a solution
diff --git a/docs/en/studio/solution-explorer.md b/docs/en/studio/solution-explorer.md
index 76e3543269..8aa0ea4404 100644
--- a/docs/en/studio/solution-explorer.md
+++ b/docs/en/studio/solution-explorer.md
@@ -47,6 +47,8 @@ It is the main solution that you can open with ABP Studio, an ABP solution can c
- `Open With`
- `Terminal`: Opens the terminal in the solution directory.
- `Explorer`: Opens the file explorer in the solution directory.
+- `Solution Configuration`: You can see the project creation options in this menu. It opens the *Solution Configuration* window.
+- `Open Readme`: Opens the README file in the solution if available. If there is no README file, this option will not be visible.
## Folder
@@ -143,6 +145,10 @@ You can choose the database provider for your microservice module. Select one of

+When you create a microservice, you must edit some [configurations](../solution-templates/microservice/adding-new-microservices.md#configuring-the-appsettingsjson). If you select the *Enable integration* option, it automatically configures the required settings for the microservice to work with the gateway, web, and other modules.
+
+
+
After creating the *Microservice (service-nolayers)* module, it will be added to the solution, and you should see the following structure in the solution explorer.

@@ -157,7 +163,7 @@ ABP modules have their own file extension `.abpmdl`, and they are located in the
### Difference Between ABP Module Template and ABP Studio Module Approach
-In ABP, creating a module solution using the [CLI](../cli/index.md) results in a solution with numerous projects, some of which may not be necessary for a specific use case. The ABP Studio module approach differs from the ABP module template, offering greater flexibility. With ABP Studio, we can create a module containing only the required projects; for example, an empty module with only the `Domain` and `Application` projects. In this approach, the term [Package](./concepts.md#package) is used for module projects.
+In ABP, creating a module solution using the [old CLI](../cli/differences-between-old-and-new-cli.md) results in a solution with numerous projects, some of which may not be necessary for a specific use case. The ABP Studio new module approach differs from the ABP old module template, offering greater flexibility. With ABP Studio, we can create a module containing only the required projects; for example, an empty module with only the `Domain` and `Application` projects. In this approach, the term [Package](./concepts.md#package) is used for module projects.
Furthermore, it's important to mention that we can create not just DDD-principled modules. The [Modularity](../framework/architecture/modularity/basics.md) document clarifies the difference between *Framework* and *Application* modules. Basically, every C# project refers to the `Volo.Abp.Core` package and defines the *Module* class as an ABP Class Library. We have the option to develop an infrastructure module using only the *ABP Class Library* packages and provide a module reference to other modules.
diff --git a/docs/en/studio/version-compatibility.md b/docs/en/studio/version-compatibility.md
index b8142f8cc0..bd19eb563d 100644
--- a/docs/en/studio/version-compatibility.md
+++ b/docs/en/studio/version-compatibility.md
@@ -2,9 +2,11 @@
This document provides an overview of the compatibility between various versions of ABP Studio and [ABP Solution Templates](../solution-templates/index.md). Use this reference to ensure that you are using the correct versions of ABP Studio and ABP for your projects.
-| **ABP Studio Version** | **ABP Version** |
+| **ABP Studio Version** | **ABP Version** |
|------------------------|---------------------------|
-| 0.7.8 | 8.2.2 |
+| 0.8.1 | 8.3.0 |
+| 0.8.0 | 8.2.3 |
+| 0.7.8 - 0.7.9 | 8.2.2 |
| 0.7.4 to 0.7.7 | 8.2.1 |
| 0.7.0 to 0.7.3 | 8.2.0 |
| 0.6.8 - 0.6.9 | 8.1.3 |
diff --git a/docs/en/ui-themes/lepton-x/index.md b/docs/en/ui-themes/lepton-x/index.md
index 5fc1ee4fb1..3bfc769409 100644
--- a/docs/en/ui-themes/lepton-x/index.md
+++ b/docs/en/ui-themes/lepton-x/index.md
@@ -85,13 +85,13 @@ LeptonX Module doesn't define any permissions.
You can use the following CLI command to download the source-code:
```bash
-abp get-source Volo.Abp.LeptonXTheme.Pro
+abp get-source Volo.Abp.LeptonXTheme
```
If you want to download the source code of the preview version, you can use the following command:
```bash
-abp get-source Volo.Abp.LeptonXTheme.Pro --preview
+abp get-source Volo.Abp.LeptonXTheme --preview
```
> You can download the source code of a certain version by using the `--version` parameter. See the [ABP CLI documentation](../../cli/index#get-source) for other possible options.
diff --git a/framework/Volo.Abp.sln b/framework/Volo.Abp.sln
index 19fbf05df8..ca1a85fd8d 100644
--- a/framework/Volo.Abp.sln
+++ b/framework/Volo.Abp.sln
@@ -471,6 +471,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.BlobStoring.Google
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.BlobStoring.Google.Tests", "test\Volo.Abp.BlobStoring.Google.Tests\Volo.Abp.BlobStoring.Google.Tests.csproj", "{40FB8907-9CF7-44D0-8B5F-538AC6DAF8B9}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.ExceptionHandling.Tests", "test\Volo.Abp.ExceptionHandling.Tests\Volo.Abp.ExceptionHandling.Tests.csproj", "{E50739A7-5E2F-4EB5-AEA9-554115CB9613}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -1405,6 +1407,10 @@ Global
{40FB8907-9CF7-44D0-8B5F-538AC6DAF8B9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{40FB8907-9CF7-44D0-8B5F-538AC6DAF8B9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{40FB8907-9CF7-44D0-8B5F-538AC6DAF8B9}.Release|Any CPU.Build.0 = Release|Any CPU
+ {E50739A7-5E2F-4EB5-AEA9-554115CB9613}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {E50739A7-5E2F-4EB5-AEA9-554115CB9613}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {E50739A7-5E2F-4EB5-AEA9-554115CB9613}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {E50739A7-5E2F-4EB5-AEA9-554115CB9613}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -1642,6 +1648,7 @@ Global
{E1051CD0-9262-4869-832D-B951723F4DDE} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}
{DEEB5200-BBF9-464D-9B7E-8FC035A27E94} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}
{40FB8907-9CF7-44D0-8B5F-538AC6DAF8B9} = {447C8A77-E5F0-4538-8687-7383196D04EA}
+ {E50739A7-5E2F-4EB5-AEA9-554115CB9613} = {447C8A77-E5F0-4538-8687-7383196D04EA}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {BB97ECF4-9A84-433F-A80B-2A3285BDD1D5}
diff --git a/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/ExceptionHandling/UserExceptionInformer.cs b/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/ExceptionHandling/UserExceptionInformer.cs
index 6773e4ff37..a8b0f71dea 100644
--- a/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/ExceptionHandling/UserExceptionInformer.cs
+++ b/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/ExceptionHandling/UserExceptionInformer.cs
@@ -67,6 +67,7 @@ public class UserExceptionInformer : IUserExceptionInformer, IScopedDependency
{
options.SendExceptionsDetailsToClients = Options.SendExceptionsDetailsToClients;
options.SendStackTraceToClients = Options.SendStackTraceToClients;
+ options.SendExceptionDataToClientTypes = Options.SendExceptionDataToClientTypes;
});
}
}
diff --git a/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/Messages/UiMessageOptions.cs b/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/Messages/UiMessageOptions.cs
index a13029a580..93faa51b4e 100644
--- a/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/Messages/UiMessageOptions.cs
+++ b/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/Messages/UiMessageOptions.cs
@@ -49,4 +49,9 @@ public class UiMessageOptions
/// Custom icon for the Cancel button.
///
public object? CancelButtonIcon { get; set; }
+
+ ///
+ /// Whether the message is html (true) or plain text (false)
+ ///
+ public bool IsMessageHtmlMarkup { get; set; }
}
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/Controllers/ErrorController.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/Controllers/ErrorController.cs
index e38995a685..e9800c8788 100644
--- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/Controllers/ErrorController.cs
+++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/Controllers/ErrorController.cs
@@ -51,6 +51,7 @@ public class ErrorController : AbpController
{
options.SendExceptionsDetailsToClients = ExceptionHandlingOptions.SendExceptionsDetailsToClients;
options.SendStackTraceToClients = ExceptionHandlingOptions.SendStackTraceToClients;
+ options.SendExceptionDataToClientTypes = ExceptionHandlingOptions.SendExceptionDataToClientTypes;
});
if (httpStatusCode == 0)
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ExceptionHandling/AbpExceptionFilter.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ExceptionHandling/AbpExceptionFilter.cs
index 3b60e74d78..03684b063d 100644
--- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ExceptionHandling/AbpExceptionFilter.cs
+++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ExceptionHandling/AbpExceptionFilter.cs
@@ -102,6 +102,7 @@ public class AbpExceptionFilter : IAsyncExceptionFilter, IAbpFilter, ITransientD
{
options.SendExceptionsDetailsToClients = exceptionHandlingOptions.SendExceptionsDetailsToClients;
options.SendStackTraceToClients = exceptionHandlingOptions.SendStackTraceToClients;
+ options.SendExceptionDataToClientTypes = exceptionHandlingOptions.SendExceptionDataToClientTypes;
});
var remoteServiceErrorInfoBuilder = new StringBuilder();
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ExceptionHandling/AbpExceptionPageFilter.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ExceptionHandling/AbpExceptionPageFilter.cs
index 56814718b6..8869293c7a 100644
--- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ExceptionHandling/AbpExceptionPageFilter.cs
+++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ExceptionHandling/AbpExceptionPageFilter.cs
@@ -81,6 +81,7 @@ public class AbpExceptionPageFilter : IAsyncPageFilter, IAbpFilter, ITransientDe
{
options.SendExceptionsDetailsToClients = exceptionHandlingOptions.SendExceptionsDetailsToClients;
options.SendStackTraceToClients = exceptionHandlingOptions.SendStackTraceToClients;
+ options.SendExceptionDataToClientTypes = exceptionHandlingOptions.SendExceptionDataToClientTypes;
});
var logLevel = context.Exception!.GetLogLevel();
diff --git a/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/ExceptionHandling/AbpExceptionHandlingMiddleware.cs b/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/ExceptionHandling/AbpExceptionHandlingMiddleware.cs
index 7d5ef610e5..e144812753 100644
--- a/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/ExceptionHandling/AbpExceptionHandlingMiddleware.cs
+++ b/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/ExceptionHandling/AbpExceptionHandlingMiddleware.cs
@@ -92,6 +92,7 @@ public class AbpExceptionHandlingMiddleware : AbpMiddlewareBase, ITransientDepen
{
options.SendExceptionsDetailsToClients = exceptionHandlingOptions.SendExceptionsDetailsToClients;
options.SendStackTraceToClients = exceptionHandlingOptions.SendStackTraceToClients;
+ options.SendExceptionDataToClientTypes = exceptionHandlingOptions.SendExceptionDataToClientTypes;
})
)
)
diff --git a/framework/src/Volo.Abp.BlazoriseUI/Components/UiMessageAlert.razor b/framework/src/Volo.Abp.BlazoriseUI/Components/UiMessageAlert.razor
index 629317aea6..9e0d86c112 100644
--- a/framework/src/Volo.Abp.BlazoriseUI/Components/UiMessageAlert.razor
+++ b/framework/src/Volo.Abp.BlazoriseUI/Components/UiMessageAlert.razor
@@ -16,7 +16,14 @@
}
- @Message
+ @if (!IsMessageHtmlMarkup)
+ {
+ @Message
+ }
+ else
+ {
+ @((MarkupString)Message)
+ }
diff --git a/framework/src/Volo.Abp.BlazoriseUI/Components/UiMessageAlert.razor.cs b/framework/src/Volo.Abp.BlazoriseUI/Components/UiMessageAlert.razor.cs
index 60ba8e8dd7..1bedfea916 100644
--- a/framework/src/Volo.Abp.BlazoriseUI/Components/UiMessageAlert.razor.cs
+++ b/framework/src/Volo.Abp.BlazoriseUI/Components/UiMessageAlert.razor.cs
@@ -21,6 +21,9 @@ public partial class UiMessageAlert : ComponentBase, IDisposable
protected virtual bool ShowMessageIcon
=> Options?.ShowMessageIcon ?? true;
+ protected virtual bool IsMessageHtmlMarkup
+ => Options?.IsMessageHtmlMarkup ?? false;
+
protected virtual object? MessageIcon => Options?.MessageIcon ?? MessageType switch
{
UiMessageType.Info => IconName.Info,
diff --git a/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/AspNetCore/ExceptionHandling/AbpExceptionHandlingOptions.cs b/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/AspNetCore/ExceptionHandling/AbpExceptionHandlingOptions.cs
index 1905c70e69..e3bde2e813 100644
--- a/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/AspNetCore/ExceptionHandling/AbpExceptionHandlingOptions.cs
+++ b/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/AspNetCore/ExceptionHandling/AbpExceptionHandlingOptions.cs
@@ -1,8 +1,23 @@
-namespace Volo.Abp.AspNetCore.ExceptionHandling;
+using System;
+using System.Collections.Generic;
+
+namespace Volo.Abp.AspNetCore.ExceptionHandling;
public class AbpExceptionHandlingOptions
{
- public bool SendExceptionsDetailsToClients { get; set; } = false;
+ public bool SendExceptionsDetailsToClients { get; set; }
+
+ public bool SendStackTraceToClients { get; set; }
+
+ public List SendExceptionDataToClientTypes { get; set; }
- public bool SendStackTraceToClients { get; set; } = true;
+ public AbpExceptionHandlingOptions()
+ {
+ SendExceptionsDetailsToClients = false;
+ SendStackTraceToClients = true;
+ SendExceptionDataToClientTypes =
+ [
+ typeof(IBusinessException)
+ ];
+ }
}
diff --git a/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/AspNetCore/ExceptionHandling/DefaultExceptionToErrorInfoConverter.cs b/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/AspNetCore/ExceptionHandling/DefaultExceptionToErrorInfoConverter.cs
index 82ed962a4f..63d6aa82ad 100644
--- a/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/AspNetCore/ExceptionHandling/DefaultExceptionToErrorInfoConverter.cs
+++ b/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/AspNetCore/ExceptionHandling/DefaultExceptionToErrorInfoConverter.cs
@@ -132,7 +132,10 @@ public class DefaultExceptionToErrorInfoConverter : IExceptionToErrorInfoConvert
errorInfo.Message = L["InternalServerErrorMessage"];
}
- errorInfo.Data = exception.Data;
+ if (options.SendExceptionDataToClientTypes.Any(t => t.IsInstanceOfType(exception)))
+ {
+ errorInfo.Data = exception.Data;
+ }
return errorInfo;
}
diff --git a/framework/test/Volo.Abp.ExceptionHandling.Tests/Volo.Abp.ExceptionHandling.Tests.csproj b/framework/test/Volo.Abp.ExceptionHandling.Tests/Volo.Abp.ExceptionHandling.Tests.csproj
new file mode 100644
index 0000000000..0c56c7190c
--- /dev/null
+++ b/framework/test/Volo.Abp.ExceptionHandling.Tests/Volo.Abp.ExceptionHandling.Tests.csproj
@@ -0,0 +1,17 @@
+
+
+
+
+
+ net8.0
+
+
+
+
+
+
+
+
+
+
+
diff --git a/framework/test/Volo.Abp.ExceptionHandling.Tests/Volo/Abp/ExceptionHandling/AbpExceptionHandlingTestBase.cs b/framework/test/Volo.Abp.ExceptionHandling.Tests/Volo/Abp/ExceptionHandling/AbpExceptionHandlingTestBase.cs
new file mode 100644
index 0000000000..aa384cf782
--- /dev/null
+++ b/framework/test/Volo.Abp.ExceptionHandling.Tests/Volo/Abp/ExceptionHandling/AbpExceptionHandlingTestBase.cs
@@ -0,0 +1,11 @@
+using Volo.Abp.Testing;
+
+namespace Volo.Abp.ExceptionHandling;
+
+public class AbpExceptionHandlingTestBase : AbpIntegratedTest
+{
+ protected override void SetAbpApplicationCreationOptions(AbpApplicationCreationOptions options)
+ {
+ options.UseAutofac();
+ }
+}
diff --git a/framework/test/Volo.Abp.ExceptionHandling.Tests/Volo/Abp/ExceptionHandling/AbpExceptionHandlingTestModule.cs b/framework/test/Volo.Abp.ExceptionHandling.Tests/Volo/Abp/ExceptionHandling/AbpExceptionHandlingTestModule.cs
new file mode 100644
index 0000000000..4f19b0bcfe
--- /dev/null
+++ b/framework/test/Volo.Abp.ExceptionHandling.Tests/Volo/Abp/ExceptionHandling/AbpExceptionHandlingTestModule.cs
@@ -0,0 +1,14 @@
+using Volo.Abp.Autofac;
+using Volo.Abp.Modularity;
+
+namespace Volo.Abp.ExceptionHandling;
+
+[DependsOn(
+ typeof(AbpExceptionHandlingModule),
+ typeof(AbpTestBaseModule),
+ typeof(AbpAutofacModule)
+ )]
+public class AbpExceptionHandlingTestModule : AbpModule
+{
+
+}
diff --git a/framework/test/Volo.Abp.ExceptionHandling.Tests/Volo/Abp/ExceptionHandling/ExceptionToErrorInfoConverter_Tests.cs b/framework/test/Volo.Abp.ExceptionHandling.Tests/Volo/Abp/ExceptionHandling/ExceptionToErrorInfoConverter_Tests.cs
new file mode 100644
index 0000000000..7ca93d7ee9
--- /dev/null
+++ b/framework/test/Volo.Abp.ExceptionHandling.Tests/Volo/Abp/ExceptionHandling/ExceptionToErrorInfoConverter_Tests.cs
@@ -0,0 +1,53 @@
+using Shouldly;
+using Volo.Abp.AspNetCore.ExceptionHandling;
+using Xunit;
+
+namespace Volo.Abp.ExceptionHandling;
+
+public class ExceptionToErrorInfoConverter_Tests : AbpExceptionHandlingTestBase
+{
+ private readonly IExceptionToErrorInfoConverter _exceptionToErrorInfoConverter;
+
+ public ExceptionToErrorInfoConverter_Tests()
+ {
+ _exceptionToErrorInfoConverter = GetRequiredService();
+ }
+
+ [Fact]
+ public void SendExceptionDataToClientTypes_Test()
+ {
+ var exception = new AbpException("test message")
+ {
+ Data =
+ {
+ ["my_data"] = "my_data_value",
+ ["my_data2"] = 42
+ }
+ };
+ var errorInfo = _exceptionToErrorInfoConverter.Convert(exception);
+ errorInfo.Data.ShouldBeNull();
+
+ errorInfo = _exceptionToErrorInfoConverter.Convert(exception, options =>
+ {
+ options.SendExceptionDataToClientTypes.Add(typeof(AbpException));
+ });
+ errorInfo.Data.ShouldNotBeNull();
+ errorInfo.Data.Keys.Count.ShouldBe(2);
+ errorInfo.Data["my_data"].ShouldBe("my_data_value");
+ errorInfo.Data["my_data2"].ShouldBe(42);
+
+ var businessException = new BusinessException("test message")
+ {
+ Data =
+ {
+ ["my_data"] = "my_data_value",
+ ["my_data2"] = 42
+ }
+ };
+ errorInfo = _exceptionToErrorInfoConverter.Convert(businessException);
+ errorInfo.Data.ShouldNotBeNull();
+ errorInfo.Data.Keys.Count.ShouldBe(2);
+ errorInfo.Data["my_data"].ShouldBe("my_data_value");
+ errorInfo.Data["my_data2"].ShouldBe(42);
+ }
+}
diff --git a/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain/Volo/Abp/AuditLogging/AuditLogInfoToAuditLogConverter.cs b/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain/Volo/Abp/AuditLogging/AuditLogInfoToAuditLogConverter.cs
index fccc5b65fe..94f0622714 100644
--- a/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain/Volo/Abp/AuditLogging/AuditLogInfoToAuditLogConverter.cs
+++ b/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain/Volo/Abp/AuditLogging/AuditLogInfoToAuditLogConverter.cs
@@ -57,6 +57,7 @@ public class AuditLogInfoToAuditLogConverter : IAuditLogInfoToAuditLogConverter,
{
options.SendExceptionsDetailsToClients = ExceptionHandlingOptions.SendExceptionsDetailsToClients;
options.SendStackTraceToClients = ExceptionHandlingOptions.SendStackTraceToClients;
+ options.SendExceptionDataToClientTypes = ExceptionHandlingOptions.SendExceptionDataToClientTypes;
}))
?? new List();
diff --git a/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/DynamicPermissionDefinitionsChangedEto.cs b/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/DynamicPermissionDefinitionsChangedEto.cs
new file mode 100644
index 0000000000..f1e27aad1e
--- /dev/null
+++ b/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/DynamicPermissionDefinitionsChangedEto.cs
@@ -0,0 +1,12 @@
+using System;
+using System.Collections.Generic;
+using Volo.Abp.EventBus;
+
+namespace Volo.Abp.PermissionManagement;
+
+[Serializable]
+[EventName("abp.permission-management.dynamic-permission-definitions-changed")]
+public class DynamicPermissionDefinitionsChangedEto
+{
+ public List Permissions { get; set; }
+}
diff --git a/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain/Volo/Abp/PermissionManagement/StaticPermissionSaver.cs b/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain/Volo/Abp/PermissionManagement/StaticPermissionSaver.cs
index 1ef851dac3..4fe6e63e3f 100644
--- a/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain/Volo/Abp/PermissionManagement/StaticPermissionSaver.cs
+++ b/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain/Volo/Abp/PermissionManagement/StaticPermissionSaver.cs
@@ -11,6 +11,7 @@ using Volo.Abp.Authorization.Permissions;
using Volo.Abp.Caching;
using Volo.Abp.DependencyInjection;
using Volo.Abp.DistributedLocking;
+using Volo.Abp.EventBus.Distributed;
using Volo.Abp.Json.SystemTextJson.Modifiers;
using Volo.Abp.Threading;
using Volo.Abp.Uow;
@@ -29,8 +30,8 @@ public class StaticPermissionSaver : IStaticPermissionSaver, ITransientDependenc
protected AbpPermissionOptions PermissionOptions { get; }
protected ICancellationTokenProvider CancellationTokenProvider { get; }
protected AbpDistributedCacheOptions CacheOptions { get; }
-
protected IUnitOfWorkManager UnitOfWorkManager { get; }
+ protected IDistributedEventBus DistributedEventBus { get; }
public StaticPermissionSaver(
IStaticPermissionDefinitionStore staticStore,
@@ -43,9 +44,11 @@ public class StaticPermissionSaver : IStaticPermissionSaver, ITransientDependenc
IAbpDistributedLock distributedLock,
IOptions permissionOptions,
ICancellationTokenProvider cancellationTokenProvider,
- IUnitOfWorkManager unitOfWorkManager)
+ IUnitOfWorkManager unitOfWorkManager,
+ IDistributedEventBus distributedEventBus)
{
UnitOfWorkManager = unitOfWorkManager;
+ DistributedEventBus = distributedEventBus;
StaticStore = staticStore;
PermissionGroupRepository = permissionGroupRepository;
PermissionRepository = permissionRepository;
@@ -104,12 +107,13 @@ public class StaticPermissionSaver : IStaticPermissionSaver, ITransientDependenc
throw new AbpException("Could not acquire distributed lock for saving static permissions!");
}
+ var newOrChangedPermissions = new List();
using (var unitOfWork = UnitOfWorkManager.Begin(requiresNew: true, isTransactional: true))
{
try
{
var hasChangesInGroups = await UpdateChangedPermissionGroupsAsync(permissionGroupRecords);
- var hasChangesInPermissions = await UpdateChangedPermissionsAsync(permissionRecords);
+ var hasChangesInPermissions = await UpdateChangedPermissionsAsync(permissionRecords, newOrChangedPermissions);
if (hasChangesInGroups || hasChangesInPermissions)
{
@@ -133,12 +137,20 @@ public class StaticPermissionSaver : IStaticPermissionSaver, ITransientDependenc
{
/* ignored */
}
-
+
throw;
}
await unitOfWork.CompleteAsync();
}
+
+ if (newOrChangedPermissions.Any())
+ {
+ await DistributedEventBus.PublishAsync(new DynamicPermissionDefinitionsChangedEto
+ {
+ Permissions = newOrChangedPermissions.Distinct().ToList()
+ });
+ }
}
await Cache.SetStringAsync(
@@ -207,8 +219,7 @@ public class StaticPermissionSaver : IStaticPermissionSaver, ITransientDependenc
return newRecords.Any() || changedRecords.Any() || deletedRecords.Any();
}
- private async Task UpdateChangedPermissionsAsync(
- IEnumerable permissionRecords)
+ private async Task UpdateChangedPermissionsAsync(IEnumerable permissionRecords, List newOrChangedPermissions)
{
var newRecords = new List();
var changedRecords = new List();
@@ -221,7 +232,7 @@ public class StaticPermissionSaver : IStaticPermissionSaver, ITransientDependenc
var permissionRecordInDatabase = permissionRecordsInDatabase.GetOrDefault(permissionRecord.Name);
if (permissionRecordInDatabase == null)
{
- /* New group */
+ /* New permission */
newRecords.Add(permissionRecord);
continue;
}
@@ -258,11 +269,13 @@ public class StaticPermissionSaver : IStaticPermissionSaver, ITransientDependenc
if (newRecords.Any())
{
+ newOrChangedPermissions.AddRange(newRecords.Select(x => x.Name));
await PermissionRepository.InsertManyAsync(newRecords);
}
if (changedRecords.Any())
{
+ newOrChangedPermissions.AddRange(newRecords.Select(x => x.Name));
await PermissionRepository.UpdateManyAsync(changedRecords);
}
@@ -330,4 +343,4 @@ public class StaticPermissionSaver : IStaticPermissionSaver, ITransientDependenc
.ToString()
.ToMd5();
}
-}
\ No newline at end of file
+}
diff --git a/npm/ng-packs/packages/account/config/src/providers/route.provider.ts b/npm/ng-packs/packages/account/config/src/providers/route.provider.ts
index 6b2f016c66..2708d1d2f7 100644
--- a/npm/ng-packs/packages/account/config/src/providers/route.provider.ts
+++ b/npm/ng-packs/packages/account/config/src/providers/route.provider.ts
@@ -14,6 +14,8 @@ export function configureRoutes(routes: RoutesService) {
name: eAccountRouteNames.Account,
invisible: true,
layout: eLayoutType.account,
+ breadcrumbText: eAccountRouteNames.Account,
+ iconClass: 'bi bi-person-fill-gear',
order: 1,
},
{
@@ -33,6 +35,8 @@ export function configureRoutes(routes: RoutesService) {
name: eAccountRouteNames.ManageProfile,
parentName: eAccountRouteNames.Account,
layout: eLayoutType.application,
+ breadcrumbText: 'AbpAccount::Manage',
+ iconClass: 'bi bi-kanban-fill',
order: 3,
},
{