Browse Source

Merge branch 'dev' into openiddict6

pull/20979/head
maliming 1 year ago
parent
commit
a889e8fc2d
No known key found for this signature in database GPG Key ID: A646B9CB645ECEA4
  1. 5
      Directory.Packages.props
  2. 67
      docs/en/Blog-Posts/2024-12-15-ABP-Studio-R2R/POST.md
  3. 234
      docs/en/Community-Articles/2024-12-09-Unit-Test/POST.md
  4. 2
      docs/en/cli/index.md
  5. 2
      docs/en/cli/new-command-samples.md
  6. 6
      docs/en/contribution/index.md
  7. 4
      docs/en/deployment/configuring-openIddict.md
  8. 2
      docs/en/docs-nav.json
  9. 18
      docs/en/framework/infrastructure/audit-logging.md
  10. 7
      docs/en/framework/infrastructure/background-jobs/index.md
  11. 12
      docs/en/framework/infrastructure/features.md
  12. 6
      docs/en/framework/ui/mvc-razor-pages/tag-helpers/dynamic-forms.md
  13. 16
      docs/en/get-started/microservice.md
  14. BIN
      docs/en/images/suite-registry.png
  15. 36
      docs/en/modules/docs.md
  16. 465
      docs/en/solution-templates/layered-web-application/_index.md
  17. 56
      docs/en/solution-templates/layered-web-application/authentication.md
  18. 49
      docs/en/solution-templates/layered-web-application/blob-storing.md
  19. 25
      docs/en/solution-templates/layered-web-application/built-in-features.md
  20. 36
      docs/en/solution-templates/layered-web-application/cors-configuration.md
  21. 266
      docs/en/solution-templates/layered-web-application/database-configurations.md
  22. 41
      docs/en/solution-templates/layered-web-application/db-migrator.md
  23. 65
      docs/en/solution-templates/layered-web-application/helm-charts-and-kubernetes.md
  24. BIN
      docs/en/solution-templates/layered-web-application/images/account-external-provider.png
  25. BIN
      docs/en/solution-templates/layered-web-application/images/angular-folder-structure.png
  26. BIN
      docs/en/solution-templates/layered-web-application/images/angular-template-structure-diagram.png
  27. BIN
      docs/en/solution-templates/layered-web-application/images/apply-database-migrations.png
  28. BIN
      docs/en/solution-templates/layered-web-application/images/bookstore-solution-tiered.png
  29. BIN
      docs/en/solution-templates/layered-web-application/images/database-connection-strings-modal.png
  30. BIN
      docs/en/solution-templates/layered-web-application/images/database-connection-strings.png
  31. BIN
      docs/en/solution-templates/layered-web-application/images/file-management-index-page.png
  32. BIN
      docs/en/solution-templates/layered-web-application/images/helm-folder.png
  33. BIN
      docs/en/solution-templates/layered-web-application/images/kubernetes.png
  34. BIN
      docs/en/solution-templates/layered-web-application/images/layered-project-dependencies.png
  35. BIN
      docs/en/solution-templates/layered-web-application/images/layered-solution-in-explorer.png
  36. BIN
      docs/en/solution-templates/layered-web-application/images/mobile-applications.png
  37. BIN
      docs/en/solution-templates/layered-web-application/images/new-solution-openiddict-module.png
  38. BIN
      docs/en/solution-templates/layered-web-application/images/open-solution-with-explorer.png
  39. BIN
      docs/en/solution-templates/layered-web-application/images/openiddict-ui.png
  40. BIN
      docs/en/solution-templates/layered-web-application/images/run-solution-tiered.png
  41. BIN
      docs/en/solution-templates/layered-web-application/images/run-solution.png
  42. BIN
      docs/en/solution-templates/layered-web-application/images/saas-module-selection.png
  43. BIN
      docs/en/solution-templates/layered-web-application/images/solution-folders.png
  44. BIN
      docs/en/solution-templates/layered-web-application/images/solutionrunner-maui-targetframework.png
  45. BIN
      docs/en/solution-templates/layered-web-application/images/tiered-solution-applications-authserver.png
  46. BIN
      docs/en/solution-templates/layered-web-application/images/tiered-solution-servers.png
  47. BIN
      docs/en/solution-templates/layered-web-application/images/web-applications.png
  48. 492
      docs/en/solution-templates/layered-web-application/index.md
  49. 35
      docs/en/solution-templates/layered-web-application/logging.md
  50. 21
      docs/en/solution-templates/layered-web-application/main-components.md
  51. 122
      docs/en/solution-templates/layered-web-application/mobile-applications.md
  52. 74
      docs/en/solution-templates/layered-web-application/multi-tenancy.md
  53. 108
      docs/en/solution-templates/layered-web-application/overview.md
  54. 222
      docs/en/solution-templates/layered-web-application/solution-structure.md
  55. 19
      docs/en/solution-templates/layered-web-application/swagger-integration.md
  56. 178
      docs/en/solution-templates/layered-web-application/web-applications.md
  57. 4
      docs/en/solution-templates/microservice/microservices.md
  58. BIN
      docs/en/studio/images/solution-runner/cli-application-context-menu.png
  59. BIN
      docs/en/studio/images/solution-runner/csharp-application-context-menu-build.png
  60. BIN
      docs/en/studio/images/solution-runner/csharp-application-context-menu-monitor.png
  61. BIN
      docs/en/studio/images/solution-runner/csharp-application-context-menu.png
  62. BIN
      docs/en/studio/images/solution-runner/folder-context-menu-add.png
  63. BIN
      docs/en/studio/images/solution-runner/folder-context-menu-build.png
  64. BIN
      docs/en/studio/images/solution-runner/folder-context-menu.png
  65. BIN
      docs/en/studio/images/solution-runner/manage-start-actions.png
  66. BIN
      docs/en/studio/images/solution-runner/profile-root-context-menu-add.png
  67. BIN
      docs/en/studio/images/solution-runner/profile-root-context-menu-build.png
  68. BIN
      docs/en/studio/images/solution-runner/profile-root-context-menu.png
  69. BIN
      docs/en/studio/images/solution-runner/solutioın-runner-properties.png
  70. 10
      docs/en/studio/release-notes.md
  71. 67
      docs/en/studio/running-applications.md
  72. 2
      docs/en/studio/version-mapping.md
  73. 18
      docs/en/suite/how-to-start.md
  74. 7
      docs/en/tutorials/book-store-with-abp-suite/part-01.md
  75. 62
      docs/en/tutorials/book-store-with-abp-suite/part-02.md
  76. 4
      docs/en/tutorials/book-store-with-abp-suite/part-03.md
  77. 2
      docs/en/tutorials/book-store-with-abp-suite/part-04.md
  78. 12
      docs/en/tutorials/book-store/part-02.md
  79. 11
      docs/en/tutorials/book-store/part-03.md
  80. 28
      docs/en/tutorials/book-store/part-05.md
  81. 2
      docs/en/tutorials/book-store/part-06.md
  82. 7
      docs/en/tutorials/book-store/part-09.md
  83. 2
      docs/en/tutorials/book-store/part-10.md
  84. 2
      docs/en/tutorials/microservice/part-03.md
  85. 4
      docs/en/tutorials/microservice/part-05.md
  86. 33
      docs/en/tutorials/microservice/part-06.md
  87. 8
      docs/en/tutorials/microservice/part-07.md
  88. 2
      docs/en/tutorials/modular-crm/part-05.md
  89. 2
      docs/en/tutorials/modular-crm/part-06.md
  90. 6
      docs/en/tutorials/modular-crm/part-07.md
  91. 1
      docs/en/ui-themes/basic-theme/index.md
  92. 14
      framework/Volo.Abp.sln
  93. 4
      framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/Builder/AbpApplicationBuilderExtensions.cs
  94. 10
      framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Auditing/AbpAspNetCoreAuditingUrlOptions.cs
  95. 35
      framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Auditing/AspNetCoreAuditLogContributor.cs
  96. 7
      framework/src/Volo.Abp.BackgroundJobs/Volo/Abp/BackgroundJobs/AbpBackgroundJobWorkerOptions.cs
  97. 4
      framework/src/Volo.Abp.BackgroundJobs/Volo/Abp/BackgroundJobs/BackgroundJobWorker.cs
  98. 4
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/LIbs/InstallLibsService.cs
  99. 5
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Utils/NpmHelper.cs
  100. 2
      framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/Migrations/EfCoreRuntimeDatabaseMigratorBase.cs

5
Directory.Packages.props

@ -128,7 +128,7 @@
<PackageVersion Include="Oracle.EntityFrameworkCore" Version="9.23.60" />
<PackageVersion Include="Polly" Version="8.4.2" />
<PackageVersion Include="Polly.Extensions.Http" Version="3.0.0" />
<PackageVersion Include="Pomelo.EntityFrameworkCore.MySql" Version="9.0.0-preview.1" />
<PackageVersion Include="Pomelo.EntityFrameworkCore.MySql" Version="9.0.0-preview.2.efcore.9.0.0" />
<PackageVersion Include="Quartz" Version="3.13.0" />
<PackageVersion Include="Quartz.Extensions.DependencyInjection" Version="3.13.0" />
<PackageVersion Include="Quartz.Plugins.TimeZoneConverter" Version="3.13.0" />
@ -168,6 +168,7 @@
<PackageVersion Include="System.Text.Json" Version="9.0.0.0" />
<PackageVersion Include="System.Threading.Tasks.Extensions" Version="4.5.4" />
<PackageVersion Include="System.IdentityModel.Tokens.Jwt" Version="8.1.0" />
<PackageVersion Include="TencentCloudSDK.Sms" Version="3.0.1142" />
<PackageVersion Include="TimeZoneConverter" Version="6.1.0" />
<PackageVersion Include="Unidecode.NET" Version="2.1.0" />
<PackageVersion Include="xunit" Version="2.9.2" />
@ -177,4 +178,4 @@
<PackageVersion Include="ConfigureAwait.Fody" Version="3.3.2" />
<PackageVersion Include="Fody" Version="6.8.2" />
</ItemGroup>
</Project>
</Project>

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

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

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

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

2
docs/en/cli/index.md

@ -112,7 +112,7 @@ abp cli clear-cache
### new
Generates a new solution based on the ABP [startup templates](../solution-templates).
Generates a new solution based on the ABP [startup templates](../solution-templates). See [new solution create sample commands](new-command-samples.md)
Usage:

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

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

6
docs/en/contribution/index.md

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

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

@ -4,6 +4,8 @@ This document introduces how to configure `OpenIddict` in the `AuthServer` proje
There are different configurations in the `AuthServer` project for the `Development` and `Production` environments.
> If your solution does not include a project named `.AuthServer`, it means that you might have another project that depends on `AbpAccountPublicWebOpenIddictModule`. The project name can be `MyProject`, `MyProject.Web`, or `MyProject.HttpApi.Host`. They are both `Authentication Server` projects in that context.
````csharp
public override void PreConfigureServices(ServiceConfigurationContext context)
{
@ -38,6 +40,8 @@ To avoid that, consider creating self-signed certificates and storing them in th
You can use the `dotnet dev-certs https -v -ep openiddict.pfx -p 00000000-0000-0000-0000-000000000000` command to generate the `openiddict.pfx` certificate.
> `openiddict.pfx` is just an example of a filename. You can use any filename for the pfx file.
> `00000000-0000-0000-0000-000000000000` is the password of the certificate, you can change it to any password you want.
> Also, please remember to copy `openiddict.pfx` to the [Content Root Folder](https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.hosting.ihostingenvironment.contentrootpath?view=aspnetcore-7.0) of the `AuthServer` website.

2
docs/en/docs-nav.json

@ -1941,7 +1941,7 @@
},
{
"text": "The Basic Theme",
"path": "framework/ui/mvc-razor-pages/basic-theme.md"
"path": "ui-themes/basic-theme"
},
{
"text": "LeptonX Theme",

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

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

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

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

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

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

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

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

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

@ -4,6 +4,22 @@
In this quick start guide, you will learn how to create and run a microservice solution using [ABP Studio](../studio/index.md).
## Setup your development environment
First things first! Let's setup your development environment before creating the first project.
### Pre-requirements
The following tools should be installed on your development machine:
* [Visual Studio 2022](https://visualstudio.microsoft.com/vs/) or another IDE that supports .NET development
* [.NET 9.0+](https://dotnet.microsoft.com/en-us/download/dotnet)
* [Node v22.11+](https://nodejs.org/)
* [Docker Desktop with Kubernetes](https://www.docker.com/products/docker-desktop/)
* [helm](https://helm.sh/docs/intro/install/)
* [NGINX Ingress Controller](https://kubernetes.github.io/ingress-nginx/deploy/)
* [mkcert](https://github.com/FiloSottile/mkcert#installation)
## Creating a New Solution
> 🛈 This document uses [ABP Studio](../studio/index.md) to create new ABP solutions. **ABP Studio** is in the beta version now. If you have any issues, you can use the [ABP CLI](../cli/index.md) to create new solutions. You can also use the [getting started page](https://abp.io/get-started) to easily build ABP CLI commands for new project creations.

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

36
docs/en/modules/docs.md

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

465
docs/en/solution-templates/layered-web-application/_index.md

@ -0,0 +1,465 @@
# Layered Application Solution Template
This template provides a layered application structure based on the [Domain Driven Design](../../framework/architecture/domain-driven-design) (DDD) practices.
## Getting Started
This document explains **the solution structure** and projects in details. If you want to start quickly, follow the guides below:
* [The getting started document](../../get-started/layered-web-application.md) explains how to create a new application in a few minutes.
* [The application development tutorial](../../tutorials/book-store/part-01.md) explains step by step application development.
## How to Start With?
You can use the [ABP CLI](../../cli) to create a new project using this startup template. Alternatively, you can generate a CLI command from the [Get Started](https://abp.io/get-started) page. CLI approach is used here.
First, install the ABP CLI if you haven't installed it before:
````bash
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.BookStore -t app
````
* `Acme.BookStore` is the solution name, like *YourCompany.YourProduct*. You can use single-level, two-level or three-level naming.
* This example specified the template name (`-t` or `--template` option). However, `app` is already the default template if you didn't specify it.
### Specify the UI Framework
This template provides multiple UI frameworks:
* `mvc`: ASP.NET Core MVC UI with Razor Pages (default)
* `blazor`: Blazor UI
* `blazor-server`: Blazor Server UI
* `angular`: Angular UI
Use the `-u` or `--ui` option to specify the UI framework:
````bash
abp new Acme.BookStore -u angular
````
### Specify the Database Provider
This template supports the following database providers:
- `ef`: Entity Framework Core (default)
- `mongodb`: MongoDB
Use `-d` (or `--database-provider`) option to specify the database provider:
````bash
abp new Acme.BookStore -d mongodb
````
### Specify the Mobile Application Framework
This template supports the following mobile application frameworks:
- `react-native`: React Native (*Available for* ***Team*** *or higher licenses*)
Use the `-m` (or `--mobile`) option to specify the mobile application framework:
````bash
abp new Acme.BookStore -m react-native
````
* [The getting started document](../../get-started/layered-web-application.md) explains how to create a new application with this startup template.
* [The application development tutorial](../../tutorials/book-store/part-01.md) explains step by step application development with this startup template.
## Solution Structure
Based on the options you've specified, you will get a slightly different solution structure.
### Default Structure
If you don't specify any additional options, you will have a solution as shown below:
![bookstore-rider-solution-v6](../../images/solution-structure-solution-explorer-rider.png)
Projects are organized in `src` and `test` folders. `src` folder contains the actual application which is layered based on [DDD](../../framework/architecture/domain-driven-design) principles as mentioned before.
The diagram below shows the layers & project dependencies of the application:
![layered-project-dependencies](../../images/layered-project-dependencies.png)
Each section below will explain the related project & its dependencies.
#### .Domain.Shared Project
This project contains constants, enums and other objects these are actually a part of the domain layer, but needed to be used by all layers/projects in the solution.
A `BookType` enum and a `BookConsts` class (which may have some constant fields for the `Book` entity, like `MaxNameLength`) are good candidates for this project.
* This project has no dependency on other projects in the solution. All other projects depend on this one directly or indirectly.
#### .Domain Project
This is the domain layer of the solution. It mainly contains [entities, aggregate roots](../../framework/architecture/domain-driven-design/entities.md), [domain services](../../framework/architecture/domain-driven-design/domain-services.md), [value objects](../../framework/architecture/domain-driven-design/value-objects.md), [repository interfaces](../../framework/architecture/domain-driven-design/repositories.md) and other domain objects.
A `Book` entity, a `BookManager` domain service and an `IBookRepository` interface are good candidates for this project.
* Depends on the `.Domain.Shared` because it uses constants, enums and other objects defined in that project.
#### .Application.Contracts Project
This project mainly contains [application service](../../framework/architecture/domain-driven-design/application-services.md) **interfaces** and [Data Transfer Objects](../../framework/architecture/domain-driven-design/data-transfer-objects.md) (DTO) of the application layer. It exists to separate the interface & implementation of the application layer. In this way, the interface project can be shared to the clients as a contract package.
An `IBookAppService` interface and a `BookCreationDto` class are good candidates for this project.
* Depends on the `.Domain.Shared` because it may use constants, enums and other shared objects of this project in the application service interfaces and DTOs.
#### .Application Project
This project contains the [application service](../../framework/architecture/domain-driven-design/application-services.md) **implementations** of the interfaces defined in the `.Application.Contracts` project.
A `BookAppService` class is a good candidate for this project.
* Depends on the `.Application.Contracts` project to be able to implement the interfaces and use the DTOs.
* Depends on the `.Domain` project to be able to use domain objects (entities, repository interfaces... etc.) to perform the application logic.
#### .EntityFrameworkCore Project
This is the integration project for the EF Core. It defines the `DbContext` and implements repository interfaces defined in the `.Domain` project.
* Depends on the `.Domain` project to be able to reference to entities and repository interfaces.
> This project is available only if you are using EF Core as the database provider. If you select another database provider, its name will be different.
#### .DbMigrator Project
This is a console application that simplifies the execution of database migrations on development and production environments. When you run this application, it:
* Creates the database if necessary.
* Applies the pending database migrations.
* Seeds initial data if needed.
> This project has its own `appsettings.json` file. So, if you want to change the database connection string, remember to change this file too.
Especially, seeding initial data is important at this point. ABP has a modular data seed infrastructure. See [its documentation](../../framework/infrastructure/data-seeding.md) for more about the data seeding.
While creating database & applying migrations seem only necessary for relational databases, this project comes even if you choose a NoSQL database provider (like MongoDB). In that case, it still seeds the initial data which is necessary for the application.
* Depends on the `.EntityFrameworkCore` project (for EF Core) since it needs to access to the migrations.
* Depends on the `.Application.Contracts` project to be able to access permission definitions, because the initial data seeder grants all permissions to the admin role by default.
#### .HttpApi Project
This project is used to define your API Controllers.
Most of the time you don't need to manually define API Controllers since ABP's [Auto API Controllers](../../framework/api-development/auto-controllers.md) feature creates them automagically based on your application layer. However, in case of you need to write API controllers, this is the best place to do it.
* Depends on the `.Application.Contracts` project to be able to inject the application service interfaces.
#### .HttpApi.Client Project
This is a project that defines C# client proxies to use the HTTP APIs of the solution. You can share this library to 3rd-party clients, so they can easily consume your HTTP APIs in their Dotnet applications (For other types of applications, they can still use your APIs, either manually or using a tool in their own platform)
Most of the time you don't need to manually create C# client proxies, thanks to ABP's [Dynamic C# API Clients](../../framework/api-development/dynamic-csharp-clients.md) feature.
`.HttpApi.Client.ConsoleTestApp` project is a console application created to demonstrate the usage of the client proxies.
* Depends on the `.Application.Contracts` project to be able to share the same application service interfaces and DTOs with the remote service.
> You can delete this project & dependencies if you don't need to create C# client proxies for your APIs.
#### .Web Project
This project contains the User Interface (UI) of the application if you are using ASP.NET Core MVC UI. It contains Razor pages, JavaScript files, CSS files, images and so on...
This project contains the main `appsettings.json` file that contains the connection string and other configurations of the application.
* Depends on the `.HttpApi` project since the UI layer needs to use APIs and the application service interfaces of the solution.
> If you check the source code of the `.Web.csproj` file, you will see the references to the `.Application` and the `.EntityFrameworkCore` projects.
>
> These references are actually not needed while coding your UI layer, because the UI layer normally doesn't depend on the EF Core or the Application layer's implementation. These startup templates are ready for tiered deployment, where the API layer is hosted on a separate server than the UI layer.
>
> However, if you don't choose the `--tiered` option, these references will be in the .Web project to be able to host the Web, API and application layers in a single application endpoint.
>
> This gives you the ability to use domain entities & repositories in your presentation layer. However, this is considered as a bad practice according to DDD.
#### Test Projects
The solution has multiple test projects, one for each layer:
* `.Domain.Tests` is used to test the domain layer.
* `.Application.Tests` is used to test the application layer.
* `.EntityFrameworkCore.Tests` is used to test EF Core configuration and custom repositories.
* `.Web.Tests` is used to test the UI (if you are using ASP.NET Core MVC UI).
* `.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 .NET application.
Test projects are prepared for integration testing;
* It is fully integrated into the ABP and all services in your application.
* It uses SQLite in-memory database for EF Core. For MongoDB, it uses the [EphemeralMongo](https://github.com/asimmon/ephemeral-mongo) library.
* Authorization is disabled, so any application service can be easily used in tests.
You can still create unit tests for your classes which will be harder to write (because you will need to prepare mock/fake objects), but faster to run (because it only tests a single class and skips all the initialization processes).
#### How to Run?
Set `.Web` as the startup project and run the application. The default username is `admin` and the password is `1q2w3E*`.
See [Getting Started With the ASP.NET Core MVC Template](../../get-started/layered-web-application.md) for more information.
### Tiered Structure
If you have selected the ASP.NET Core UI and specified the `--tiered` option, the solution created will be a tiered solution. The purpose of the tiered structure is to be able to **deploy Web applications and HTTP API to different servers**:
![bookstore-visual-studio-solution-v3](../../images/tiered-solution-servers.png)
* Browser runs your UI by executing HTML, CSS & JavaScript.
* Web servers host static UI files (CSS, JavaScript, image... etc.) & dynamic components (e.g. Razor pages). It performs HTTP requests to the API server to execute the business logic of the application.
* The API Server hosts the HTTP APIs which then use the application & domain layers of the application to perform the business logic.
* Finally, database server hosts your database.
So, the resulting solution allows a 4-tiered deployment, by comparing to 3-tiered deployment of the default structure explained before.
> Unless you actually need such a 4-tiered deployment, it's suggested to go with the default structure which is simpler to develop, deploy and maintain.
The solution structure is shown below:
![bookstore-rider-solution-v6](../../images/bookstore-rider-solution-tiered.png)
As different from the default structure, two new projects come into play: `.AuthServer` & `.HttpApi.Host`.
#### .AuthServer Project
This project is used as an authentication server for other projects. `.Web` 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 HTTP API server. HTTP API server uses bearer token authentication to obtain claims from the access token to authorize the current user.
![tiered-solution-applications](../../images/tiered-solution-applications-authserver.png)
ABP uses the [OpenIddict Module](../../modules/openiddict.md) that uses the open-source [OpenIddict-core](https://github.com/openiddict/openiddict-core) library for the authentication between applications. See [OpenIddict documentation](https://documentation.openiddict.com/) for details about the OpenIddict and OpenID Connect protocol.
It has its own `appsettings.json` that contains database connection and other configurations.
#### .HttpApi.Host Project
This project is an application that hosts the API of the solution. It has its own `appsettings.json` that contains database connection and other configurations.
#### .Web Project
Just like the default structure, this project contains the User Interface (UI) of the application. It contains razor pages, JavaScript files, style files, images and so on...
This project contains an `appsettings.json` file, but this time it does not have a connection string because it never connects to the database. Instead, it mainly contains the endpoint of the remote API server and the authentication server.
#### Pre-requirements
* [Redis](https://redis.io/): The applications use Redis as a distributed cache. So, you need to have Redis installed & running.
#### How to Run?
You should run the application with the given order:
* First, run the `.AuthServer` since other applications depend on it.
* Then run the `.HttpApi.Host` since it is used by the `.Web` application.
* Finally, you can run the `.Web` project and login to the application (using `admin` as the username and `1q2w3E*` as the password).
### Blazor UI
If you choose `Blazor` as the UI Framework (using the `-u blazor` or `-u blazor-server` option), the solution will have a project named `.Blazor`. This project contains the Blazor UI application. According to your choice, it will be a Blazor WebAssembly or Blazor Server application. If Blazor WebAssembly is selected, the solution will also have a `.HttpApi.Host`. This project is an ASP.NET Core application that hosts the backend application for the Blazor single page application.
#### .Blazor Project (Server)
The Blazor Server project is similar to the ASP.NET Core MVC project. It replaces `.Web` project with `.Blazor` in the solution structure above. It has the same folder structure and the same application flow. Since it's an ASP.NET Core application, it can contain **.cshtml** files and **.razor** components at the same time. If routing matches a razor component, the Blazor UI will be used. Otherwise, the request will be handled by the MVC framework.
![abp solution structure blazor server](../../images/layered-project-dependencies-blazor-server.png)
#### .Blazor Project (WebAssembly)
The Blazor WebAssembly project is a single page application that runs on the browser. You'll see it as `.Blazor` project in the solution. It uses the `.HttpApi.Host` project to communicate with the backend. It can't be used without the backend application. It contains only **.razor** components. It's a pure client-side application. It doesn't have any server-side code. Everything in this layer will be for the client side.
![abp solution structure blazor wasm](../../images/layered-project-dependencies-blazor-wasm.png)
### Angular UI
If you choose `Angular` as the UI framework (using the `-u angular` option), the solution is being separated into two folders:
* `angular` folder contains the Angular UI application, the client-side code.
* `aspnet-core` folder contains the ASP.NET Core solution, the server-side code.
The server-side is similar to the solution described above. `*.HttpApi.Host` project serves the API, so the `Angular` application consumes it.
Angular application folder structure looks like below:
![angular-folder-structure](../../images/angular-folder-structure.png)
Each of ABP modules is an NPM package. Some ABP modules are added as a dependency in `package.json`. These modules install with their dependencies. To see all ABP packages, you can run the following command in the `angular` folder:
```bash
yarn list --pattern abp
```
Angular application module structure:
![Angular template structure diagram](../../images/angular-template-structure-diagram.png)
#### AppModule
`AppModule` is the root module of the application. Some of the ABP modules and some essential modules are imported to `AppModule`.
ABP Config modules have also been imported to `AppModule` for initial requirements of the lazy-loadable ABP modules.
#### AppRoutingModule
There are lazy-loadable ABP modules in the `AppRoutingModule` as routes.
> Paths of ABP Modules should not be changed.
You should add `routes` property in the `data` object to add a link on the menu to redirect to your custom pages.
```js
{
path: 'dashboard',
loadChildren: () => import('./dashboard/dashboard.module').then(m => m.DashboardModule),
canActivate: [authGuard, permissionGuard],
data: {
routes: {
name: 'ProjectName::Menu:Dashboard',
order: 2,
iconClass: 'fa fa-dashboard',
requiredPolicy: 'ProjectName.Dashboard.Host'
} as ABP.Route
}
}
```
In the above example;
* If the user is not logged in, authGuard blocks access and redirects to the login page.
* permissionGuard checks the user's permission with the `requiredPolicy` property of the `routes` object. If the user is not authorized to access the page, the 403 page appears.
* The `name` property of `routes` is the menu link label. A localization key can be defined.
* The `iconClass` property of the `routes` object is the menu link icon class.
* The `requiredPolicy` property of the `routes` object is the required policy key to access the page.
After the above `routes` definition, if the user is authorized, the dashboard link will appear on the menu.
#### Shared Module
The modules that may be required for all modules have been imported to the `SharedModule`. You should import `SharedModule` to all modules.
See the [Sharing Modules](https://angular.io/guide/sharing-ngmodules) document.
#### Environments
The files under the `src/environments` folder have the essential configuration of the application.
#### Home Module
Home module is an example lazy-loadable module that loads on the root address of the application.
#### Styles
The required style files are added to the `styles` array in `angular.json`. `AppComponent` loads some style files lazily via `LazyLoadService` after the main bundle is loaded to shorten the first rendering time.
#### Testing
You should create your tests in the same folder as the file you want to test.
See the [testing document](https://angular.io/guide/testing).
#### Depended Packages
* [NG Bootstrap](https://ng-bootstrap.github.io/) is used as UI component library.
* [NGXS](https://www.ngxs.io/) is used as state management library.
* [angular-oauth2-oidc](https://github.com/manfredsteyer/angular-oauth2-oidc) is used to support for OAuth 2 and OpenId Connect (OIDC).
* [Chart.js](https://www.chartjs.org/) is used to create widgets.
* [ngx-validate](https://github.com/ng-turkey/ngx-validate) is used for dynamic validation of reactive forms.
### React Native
If the `-m react-native` option is specified in the new project command, the solution includes the [React Native](https://reactnative.dev/) application in the `react-native` folder.
The server-side is similar to the solution described above. `*.HttpApi.Host` project serves the API, so the React Native application consumes it.
The React Native application was generated with [Expo](https://expo.io/). Expo is a set of tools built around React Native to help you quickly start an app and, while it has many features.
React Native application folder structure as like below:
![react-native-folder-structure](../../images/react-native-folder-structure.png)
* `App.js` is the bootstrap component of the application.
* `Environment.js` file has the essential configuration of the application. `prod` and `dev` configurations are defined in this file.
* [Contexts](https://reactjs.org/docs/context.html) are created in the `src/contexts` folder.
* [Higher order components](https://reactjs.org/docs/higher-order-components.html) are created in the `src/hocs` folder.
* [Custom hooks](https://reactjs.org/docs/hooks-custom.html#extracting-a-custom-hook) are created in `src/hooks`.
* [Axios interceptors](https://github.com/axios/axios#interceptors) are created in the `src/interceptors` folder.
* Utility functions are exported from `src/utils` folder.
#### Components
Components that can be used on all screens are created in the `src/components` folder. All components have been created as a function that is able to use [hooks](https://reactjs.org/docs/hooks-intro.html).
#### Screens
![react-native-navigation-structure](../../images/react-native-navigation-structure.png)
Screens are created by creating folders that separate their names in the `src/screens` folder. Certain parts of some screens can be split into components.
Each screen is used in a navigator in the `src/navigators` folder.
#### Navigation
[React Navigation](https://reactnavigation.org/) is used as a navigation library. Navigators are created in the `src/navigators`. A [drawer](https://reactnavigation.org/docs/drawer-based-navigation/) navigator and several [stack](https://reactnavigation.org/docs/hello-react-navigation/#installing-the-stack-navigator-library) navigators have been created in this folder. See the [above diagram](#screens) for the navigation structure.
#### State Management
[Redux](https://redux.js.org/) is used as a state management library. [Redux Toolkit](https://redux-toolkit.js.org/) library is used as a toolset for efficient Redux development.
Actions, reducers, sagas and selectors are created in the `src/store` folder. Store folder is as below:
![react-native-store-folder](../../images/react-native-store-folder.png)
* [**Store**](https://redux.js.org/basics/store) is defined in the `src/store/index.js` file.
* [**Actions**](https://redux.js.org/basics/actions/) are payloads of information that send data from your application to your store.
* [**Reducers**](https://redux.js.org/basics/reducers) specify how the application's state changes in response to actions sent to the store.
* [**Redux-Saga**](https://redux-saga.js.org/) is a library that aims to make application side effects (i.e. asynchronous things like data fetching and impure things like accessing the browser cache) easier to manage. Sagas are created in the `src/store/sagas` folder.
* [**Reselect**](https://github.com/reduxjs/reselect) library is used to create memoized selectors. Selectors are created in the `src/store/selectors` folder.
#### APIs
[Axios](https://github.com/axios/axios) is used as an HTTP client library. An Axios instance has exported from `src/api/API.js` file to make HTTP calls with the same config. `src/api` folder also has the API files that have been created for API calls.
#### Theming
[Native Base](https://nativebase.io/) is used as UI components library. Native Base components can customize easily. See the [Native Base customize](https://docs.nativebase.io/customizing-components) documentation. We followed the same way.
* Native Base theme variables are in the `src/theme/variables` folder.
* Native Base component styles are in the `src/theme/components` folder. These files have been generated with Native Base's `ejectTheme` script.
* Styles of components override with the files under the `src/theme/overrides` folder.
#### Testing
Unit tests will be created.
See the [Testing Overview](https://reactjs.org/docs/testing.html) document.
#### Depended Libraries
* [Native Base](https://nativebase.io/) is used as UI components library.
* [React Navigation](https://reactnavigation.org/) is used as navigation library.
* [Axios](https://github.com/axios/axios) is used as an HTTP client library.
* [Redux](https://redux.js.org/) is used as state management library.
* [Redux Toolkit](https://redux-toolkit.js.org/) library is used as a toolset for efficient Redux development.
* [Redux-Saga](https://redux-saga.js.org/) is used to manage asynchronous processes.
* [Redux Persist](https://github.com/rt2zz/redux-persist) is used as state persistence.
* [Reselect](https://github.com/reduxjs/reselect) is used to create memoized selectors.
* [i18n-js](https://github.com/fnando/i18n-js) is used as i18n library.
* [expo-font](https://docs.expo.io/versions/latest/sdk/font/) library allows loading fonts easily.
* [Formik](https://github.com/jaredpalmer/formik) is used to build forms.
* [Yup](https://github.com/jquense/yup) is used for form validations.
## Social / External Logins
If you want to configure social/external logins for your application, please follow the [Social/External Logins](../../social-external-logins.md) document.
## What's Next?
- [The getting started document](../../get-started) explains how to create a new application in a few minutes.
- [The application development tutorial](../../tutorials/book-store/part-01.md) explains step by step application development.
## See Also
* [Video tutorial](https://abp.io/video-courses/essentials/app-template)

56
docs/en/solution-templates/layered-web-application/authentication.md

@ -0,0 +1,56 @@
# Layered Solution: Authentication
```json
//[doc-nav]
{
"Previous": {
"Name": "Built-In Features",
"Path": "solution-templates/layered-web-application/built-in-features"
},
"Next": {
"Name": "Database configurations in the Layered solution",
"Path": "solution-templates/layered-web-application/database-configurations"
}
}
```
> Some of the features mentioned in this document may not be available in the free version. We're using the **\*** symbol to indicate that a feature is available in the **[Team](https://abp.io/pricing)** and **[Higher](https://abp.io/pricing)** licenses.
The [Layered solution template](index.md) is fully configured for authentication. All the services and applications are configured to use the [OpenIddict](https://documentation.openiddict.com) library for authentication. They are configured in a common way for authentication. This document explains that common authentication structure.
If you choose the *Tiered* option while [creating](../../get-started/layered-web-application.md#creating-a-new-solution) the solution, the solution will have the `*.AuthServer` project.
## OpenIddict
[OpenIddict](https://documentation.openiddict.com) is an open-source library that provides a simple and easy way to implement an OpenID Connect server in your application. ABP has built-in modules ([OpenIddict](../../modules/openiddict.md), [OpenIddict UI **\***](../../modules/openiddict-pro.md)) to integrate OpenIddict into the solution.
## Domain Layer
The layered solution template *Domain* layer is the responsible for the OpenIddict definitions (Applications, Scopes, etc.). Also, it provides the *OpenIddictDataSeedContributor* class to seed the initial data. It creates the default clients (applications) and scopes for the solution.
The [OpenIddict UI **\***](../../modules/openiddict-pro.md) module is added only if you choose the OpenIddict UI module while creating the solution.
![new-solution-openiddict-module](images/new-solution-openiddict-module.png)
The OpenIddict UI **\*** module provides a user interface to manage the OpenIddict entities such as applications, scopes, etc. You can manage these entities from the application UI.
![openiddict-ui](images/openiddict-ui.png)
## The Authentication Application
The solution may include an external authentication server (`auth-server`) application if you select the *Tiered* option during solution creation. Otherwise, the authentication server is integrated into one of the [Web Applications](web-applications.md).
The authentication server handles token generation, validation, and user account management (e.g., login, registration). It uses the [Account](../../modules/account.md) or [Account Pro **\***](../../modules/account-pro.md) module. The [Account Pro **\***](../../modules/account-pro.md) module additionally supports [social logins](../../modules/account-pro.md#social--external-logins) (e.g., Google, Facebook). Social logins can be enabled, disabled, and configured directly from the application's user interface.
![account-external-provider](images/account-external-provider.png)
## Authentication Flows
Applications in the solution use different authentication flows depending on the application type:
- **MVC UI Web Application**:
Uses the [Hybrid Flow](https://openid.net/specs/openid-connect-core-1_0.html#HybridFlowAuth) (OpenID Connect Authentication) for user authentication.
- **SPA and Swagger Applications**:
Use the [Authorization Code Flow](https://openid.net/specs/openid-connect-core-1_0.html#CodeFlowAuth) to authenticate users.
Once a user logs into the system and obtains a token from the authentication server, the `*.HttpApi.Host` application use [JWT Bearer Authentication](https://jwt.io/introduction/) to authorize the user's actions.

49
docs/en/solution-templates/layered-web-application/blob-storing.md

@ -0,0 +1,49 @@
# Layered Solution: BLOB Storing
```json
//[doc-nav]
{
"Previous": {
"Name": "Multi-Tenancy",
"Path": "solution-templates/layered-web-application/multi-tenancy"
},
"Next": {
"Name": "CORS Configuration",
"Path": "solution-templates/layered-web-application/cors-configuration"
}
}
```
> Some of the features mentioned in this document may not be available in the free version. We're using the **\*** symbol to indicate that a feature is available in the **[Team](https://abp.io/pricing)** and **[Higher](https://abp.io/pricing)** licenses.
This document explains how to store BLOBs (Binary Large Objects) in a layered solution. It is common to store files, images, videos, and other large objects in a distributed system. You can learn more about BLOB storage in the [BLOB Storing System](../../framework/infrastructure/blob-storing/index.md) documentation.
In the layered solution template, the [Database Provider](../../framework/infrastructure/blob-storing/database.md) is used to store BLOBs in the database. The `Volo.Abp.BlobStoring.Database.EntityFrameworkCore` or `Volo.Abp.BlobStoring.Database.MongoDB` package provides the necessary implementations to store and retrieve BLOBs in the database. This setup is integrated into the layered solution template and is used in all related projects. You can change the database configuration in the `appsettings.json` file of the related project.
You can use the `IBlobContainer` or `IBlobContainer<T>` service to store and retrieve BLOBs. Here is an example of storing a BLOB:
```csharp
public class MyService : ITransientDependency
{
private readonly IBlobContainer _blobContainer;
public MyService(IBlobContainer blobContainer)
{
_blobContainer = blobContainer;
}
public async Task SaveBytesAsync(byte[] bytes)
{
await _blobContainer.SaveAsync("my-blob-1", bytes);
}
public async Task<byte[]> GetBytesAsync()
{
return await _blobContainer.GetAllBytesOrNullAsync("my-blob-1");
}
}
```
The *File Management* module is optional and can be added to the solution during the creation process. It provides a user interface to manage folders and files. You can learn more about the module in the [File Management *](../../modules/file-management.md) document.
![file-management](images/file-management-index-page.png)

25
docs/en/solution-templates/layered-web-application/built-in-features.md

@ -0,0 +1,25 @@
# Layered Solution: Built-In Features
```json
//[doc-nav]
{
"Previous": {
"Name": "Mobile Applications",
"Path": "solution-templates/layered-web-application/mobile-applications"
},
"Next": {
"Name": "Authentication",
"Path": "solution-templates/layered-web-application/authentication"
}
}
```
The Layered solution template includes several built-in features to help you get started with your layered web application. These features are designed to provide a solid foundation for your application and help you focus on your business logic. This document provides an overview of the built-in features included in the Layered solution template. The following documents explains these features in details:
* [Authentication](authentication.md)
* [Database configurations](database-configurations.md)
* [Logging (with Serilog)](logging.md)
* [Swagger integration](swagger-integration.md)
* [Multi-Tenancy](multi-tenancy.md)
* [BLOB storing](blob-storing.md)
* [CORS configuration](cors-configuration.md)

36
docs/en/solution-templates/layered-web-application/cors-configuration.md

@ -0,0 +1,36 @@
# Layered Solution: CORS Configuration
```json
//[doc-nav]
{
"Previous": {
"Name": "BLOB Storing",
"Path": "solution-templates/layered-web-application/blob-storing"
},
"Next": {
"Name": "Helm Charts and Kubernetes",
"Path": "solution-templates/layered-web-application/helm-charts-and-kubernetes"
}
}
```
Cross-Origin Resource Sharing (CORS) is a security feature that allows web applications to make requests to a different domain than the one that served the web page.
In the layered solution template, CORS configuration is applied in the following cases:
- If you select the [Tiered solution](solution-structure.md#tiered-structure-).
- If you choose [Angular](web-applications.md#angular) as the web application type.
- If you choose [No UI](web-applications.md#no-ui) as the web application type.
The CORS settings are configured in the `appsettings.json` file of the corresponding project. Typically, the web application serves as the entry point for front-end applications, so it must be configured to accept requests from different origins.
The default configuration in `appsettings.json` is as follows:
```json
{
"App": {
"CorsOrigins": "https://*.MyProjectName.com"
}
}
```
You can modify the `CorsOrigins` property to include additional domains or wildcard subdomains as required by your application.

266
docs/en/solution-templates/layered-web-application/database-configurations.md

@ -0,0 +1,266 @@
# Layered Solution: Database configurations
```json
//[doc-nav]
{
"Previous": {
"Name": "Authentication",
"Path": "solution-templates/layered-web-application/authentication"
},
"Next": {
"Name": "Logging (with Serilog)",
"Path": "solution-templates/layered-web-application/logging"
}
}
```
> Some of the features mentioned in this document may not be available in the free version. We're using the **\*** symbol to indicate that a feature is available in the **[Team](https://abp.io/pricing)** and **[Higher](https://abp.io/pricing)** licenses.
ABP Studio's Layered Solution Template includes pre-configured database settings. This document explains how to manage database configurations in your solution.
## Connection Strings
Connection strings are stored in the `appsettings.json` file. You can customize them for different environments by modifying the respective `appsettings.json` files. The `*.DbMigrator` project and one of the [Web Application](web-applications.md) projects use the `Default` connection string by default.
To change the connection string for the `Default` key, update the `appsettings.json` file in your project. Connection strings are defined under the `ConnectionStrings` section, as shown below:
```json
{
"ConnectionStrings": {
"Default": "Server=(LocalDb)\\MSSQLLocalDB;Database=Bookstore;Trusted_Connection=True;TrustServerCertificate=true"
}
}
```
### The DbContext Class
In the `*.EntityFrameworkCore` project, the `DbContext` class is defined. The `DbContext` class is derived from the `AbpDbContext` class, which is a part of the ABP Framework.
```csharp
[ReplaceDbContext(typeof(IIdentityProDbContext))]
[ReplaceDbContext(typeof(ISaasDbContext))]
[ConnectionStringName("Default")]
public class BookstoreDbContext :
AbpDbContext<BookstoreDbContext>,
ISaasDbContext,
IIdentityProDbContext
{
#region Entities from the modules
// Identity
public DbSet<IdentityUser> Users { get; set; }
public DbSet<IdentityRole> Roles { get; set; }
public DbSet<IdentityClaimType> ClaimTypes { get; set; }
public DbSet<OrganizationUnit> OrganizationUnits { get; set; }
public DbSet<IdentitySecurityLog> SecurityLogs { get; set; }
public DbSet<IdentityLinkUser> LinkUsers { get; set; }
public DbSet<IdentityUserDelegation> UserDelegations { get; set; }
public DbSet<IdentitySession> Sessions { get; set; }
// SaaS
public DbSet<Tenant> Tenants { get; set; }
public DbSet<Edition> Editions { get; set; }
public DbSet<TenantConnectionString> TenantConnectionStrings { get; set; }
#endregion
public BookstoreDbContext(DbContextOptions<BookstoreDbContext> options)
: base(options)
{
}
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
builder.ConfigurePermissionManagement();
builder.ConfigureSettingManagement();
builder.ConfigureBackgroundJobs();
builder.ConfigureAuditLogging();
builder.ConfigureFeatureManagement();
builder.ConfigureIdentityPro();
builder.ConfigureOpenIddictPro();
builder.ConfigureLanguageManagement();
builder.ConfigureSaas();
builder.ConfigureTextTemplateManagement();
builder.ConfigureGdpr();
builder.ConfigureCmsKit();
builder.ConfigureCmsKitPro();
builder.ConfigureBlobStoring();
/* Configure your own tables/entities inside here */
//builder.Entity<YourEntity>(b =>
//{
// b.ToTable(BookstoreConsts.DbTablePrefix + "YourEntities", BookstoreConsts.DbSchema);
// b.ConfigureByConvention(); //auto configure for the base class props
// //...
//});
}
}
```
#### ConnectionStringName Attribute
We're using the *Default* connection string in the `BookstoreDbContext` class. You can change the connection string name by updating the `ConnectionStringName` attribute.
```csharp
[ConnectionStringName("Default")]
```
[The `ConnectionStringName` attribute](../../framework/fundamentals/connection-strings.md#set-the-connection-string-name) defines the unique name of the connection string that is being used by that `DbContext` class. It matches with the connection string defined in the `appsettings.json` file. That name is also used in database migrations to distinguish different database schemas, and used as the key while storing tenant connection strings for a multi-tenant system.
#### ReplaceDbContext Attribute
```csharp
[ReplaceDbContext(typeof(IIdentityProDbContext))]
[ReplaceDbContext(typeof(ISaasDbContext))]
```
The application DbContext utilizes the [Identity](../../modules/identity.md) and [Saas **\***](../../modules/saas.md) modules and creates a single database that contains these modules database schemas. These modules define their own `DbContext` class normally. But [the `ReplaceDbContext` attribute](../../framework/data/entity-framework-core/index.md#replace-other-dbcontextes) tells to ABP to use this (`BookstoreDbContext`) `DbContext` class instead of the `DbContext` classes defined by these modules. Technically, it replaces the given `DbContext` classes on runtime. We are doing that to ensure that we have a single (merged) database schema, single database migration path and a single database transaction operation when we work these multiple modules. When we replace a `DbContext`, we should implement its interface as done with the `BookstoreDbContext` class:
````csharp
public class BookstoreDbContext :
AbpDbContext<BookstoreDbContext>,
ISaasDbContext,
IIdentityProDbContext
````
* That class implements `ISaasDbContext` and `IIdentityProDbContext`, so these modules can use it.
As the next part, the `BookstoreDbContext` class defines the following properties those are forced by the implemented interfaces:
```csharp
// Identity
public DbSet<IdentityUser> Users { get; set; }
public DbSet<IdentityRole> Roles { get; set; }
public DbSet<IdentityClaimType> ClaimTypes { get; set; }
public DbSet<OrganizationUnit> OrganizationUnits { get; set; }
public DbSet<IdentitySecurityLog> SecurityLogs { get; set; }
public DbSet<IdentityLinkUser> LinkUsers { get; set; }
public DbSet<IdentityUserDelegation> UserDelegations { get; set; }
public DbSet<IdentitySession> Sessions { get; set; }
// SaaS
public DbSet<Tenant> Tenants { get; set; }
public DbSet<Edition> Editions { get; set; }
public DbSet<TenantConnectionString> TenantConnectionStrings { get; set; }
```
#### OnModelCreating Method
The `OnModelCreating` method is used to configure the database schema. It calls the `Configure*` methods of the ABP Framework to configure the database schema for the modules. You can also configure your own tables/entities inside this method.
```csharp
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
builder.ConfigurePermissionManagement();
builder.ConfigureSettingManagement();
builder.ConfigureBackgroundJobs();
builder.ConfigureAuditLogging();
builder.ConfigureFeatureManagement();
builder.ConfigureIdentityPro();
builder.ConfigureOpenIddictPro();
builder.ConfigureLanguageManagement();
builder.ConfigureSaas();
builder.ConfigureTextTemplateManagement();
builder.ConfigureGdpr();
builder.ConfigureCmsKit();
builder.ConfigureCmsKitPro();
builder.ConfigureBlobStoring();
/* Configure your own tables/entities inside here */
//builder.Entity<YourEntity>(b =>
//{
// b.ToTable(BookstoreConsts.DbTablePrefix + "YourEntities", BookstoreConsts.DbSchema);
// b.ConfigureByConvention(); //auto configure for the base class props
// //...
//});
}
```
> The `Configure*` methods are extension methods defined in each module's `EntityFrameworkCore` project. These methods are used to configure the database schema for their respective modules. At runtime, the `DbContext` class is replaced by the `BookstoreDbContext` class only for the `DbContext` classes that use the `ReplaceDbContext` attribute. For other modules, their own dedicated `DbContext` classes are used without replacement.
### The `IDesignTimeDbContextFactory` Implementation
The `IDesignTimeDbContextFactory` interface is used to create a `DbContext` instance at design time. It is used by EF Core tools to create migrations and update the database. The `BookstoreDbContextFactory` class implements the `IDesignTimeDbContextFactory` interface to create a `BookstoreMigrationsDbContext` instance.
```csharp
public class BookstoreDbContextFactory : IDesignTimeDbContextFactory<BookstoreDbContext>
{
public BookstoreDbContext CreateDbContext(string[] args)
{
var configuration = BuildConfiguration();
BookstoreEfCoreEntityExtensionMappings.Configure();
var builder = new DbContextOptionsBuilder<BookstoreDbContext>()
.UseSqlServer(configuration.GetConnectionString("Default"));
return new BookstoreDbContext(builder.Options);
}
private static IConfigurationRoot BuildConfiguration()
{
var builder = new ConfigurationBuilder()
.SetBasePath(Path.Combine(Directory.GetCurrentDirectory(), "../Acme.Bookstore.DbMigrator/"))
.AddJsonFile("appsettings.json", optional: false);
return builder.Build();
}
}
```
### Configuration
In the `*.EntityFrameworkCore` project, the `BookstoreEntityFrameworkCoreModule` class is used to configure the database context.
```csharp
public override void ConfigureServices(ServiceConfigurationContext context)
{
context.Services.AddAbpDbContext<BookstoreDbContext>(options =>
{
/* Remove "includeAllEntities: true" to create
* default repositories only for aggregate roots */
options.AddDefaultRepositories(includeAllEntities: true);
});
Configure<AbpDbContextOptions>(options =>
{
/* The main point to change your DBMS.
* See also BookstoreDbContextFactory for EF Core tooling. */
options.UseSqlServer();
});
}
```
We are basically setting the SQL Server as the default DBMS for this application. and registering the `BookstoreDbContext` class to the [dependency injection](../../framework/fundamentals/dependency-injection.md) system.
### SaaS Module: The Tenant Management UI **\***
SaaS module provides the necessary UI to set and change connection string for tenants and trigger the database migrations.
#### The Connection String Management Modal
You can click to the *Database Connection Strings* command in the *Actions* dropdown button for a tenant in the *Tenants* page of the SaaS module:
![Database Connection Strings](images/database-connection-strings.png)
It opens the *Database Connection Strings* modal as shown below:
![Database Connection Strings Modal](images/database-connection-strings-modal.png)
Here, we can set a *Default connection string* for the tenant.
When you make the changes and save the dialog, the database is automatically created and migrated. If you later update the connection string (for example if you change the database name), it will also trigger the database migration process again.
#### Manually Applying the Database Migrations
If you need to manually trigger the database migrations for a specific tenant, click the *Actions* dropdown for the related tenant and select the *Apply Database Migrations* command on the *Tenant Management* page of the SaaS module:
![Apply Database Migrations](images/apply-database-migrations.png)

41
docs/en/solution-templates/layered-web-application/db-migrator.md

@ -0,0 +1,41 @@
# Layered Solution: Db Migrator
````json
//[doc-nav]
{
"Previous": {
"Name": "Web Applications",
"Path": "solution-templates/layered-web-application/web-applications"
},
"Next": {
"Name": "Mobile Applications",
"Path": "solution-templates/layered-web-application/mobile-applications"
}
}
````
## Db Migrator Project
The Db Migrator project is a console application designed to handle database schema migrations and seed data population. It operates as a standalone application that can be executed on-demand or integrated into a CI/CD pipeline.
### Usage
You can run the Db Migrator application:
- From the command line.
- Directly from Visual Studio.
### Configuration
The Db Migrator project maintains its own configuration, separate from the main application. If you need to update the database connection string or any related settings, ensure that changes are applied consistently to both the main application and the Db Migrator to avoid discrepancies.
## Folder Structure
In the `*.DbMigrator` project, you will find the `DbMigratorHostedService` class, which is responsible for executing database migrations and seeding data. This class is registered in the `Program` class and starts running when the application is launched.
### Layers and Responsibilities
- **`*.Domain` Layer**:
Contains the `Data` folder, which holds the necessary classes for managing database migrations and seed data. However, since the `*.Domain` layer does not reference the `EntityFrameworkCore` package, it only defines the abstraction for data migration.
- **`*.EntityFrameworkCore` Layer**:
This layer is responsible for implementing database schema migrations. It includes the `EntityFrameworkCore[ProjectName]DbSchemaMigrator` class, which handles the actual migration logic using the `EntityFrameworkCore` package.

65
docs/en/solution-templates/layered-web-application/helm-charts-and-kubernetes.md

@ -0,0 +1,65 @@
# Layered Solution: Helm Charts and Kubernetes
````json
//[doc-nav]
{
"Previous": {
"Name": "CORS configuration",
"Path": "solution-templates/layered-web-application/cors-configuration"
}
}
````
> You must have an ABP Business or a higher license to be able to use the Kubernetes features.
This document explains how to deploy the layered solution to a Kubernetes cluster using [Helm](https://helm.sh/) charts. The layered solution template includes Helm charts for each application and infrastructure (Redis, RabbitMQ, etc). You can use these charts to deploy the solution to a Kubernetes cluster. You can see the Helm charts in the `etc/helm` folder of the solution.
## Folder Structure
The folder structure of the Helm charts is as follows:
![helm-folder](images/helm-folder.png)
> You might have different charts based on the solution template options you selected while creating the solution.
* **bookstore**: The Helm chart for the `Bookstore` solution. The folder name should be the same as your project name.
* **charts**: The sub-charts of the solution. Each application and infrastructure has its own chart.
* **templates**: The templates of the solution. It includes the ingress host URLs.
* **Chart.yaml**: The chart metadata.
* **values.bookstore-local.yaml**: The override values file for the [Kubernetes profile](../../studio/kubernetes.md#profile). It should follow the naming convention for your project name.
* **values.yaml**: The default values file for the chart.
* **build-all-images.ps1**: A PowerShell script to build all Docker images of the solution.
* **build-image.ps1**: A PowerShell script to build a Docker image of a specified project.
* **create-tls-secrets.ps1**: A PowerShell script to create local TLS secrets for the ingress controller. It's important when you try to [intercept a service](../../studio/kubernetes.md#intercept-a-service) and run it locally.
* **install.ps1**: A PowerShell script to install the solution to a Kubernetes cluster. You can override the default argument values.
* **uninstall.ps1**: A PowerShell script to uninstall the solution from a Kubernetes cluster. You can override the default argument values.
## Installing the Helm Charts
You can install the solution to a Kubernetes cluster using the `install.ps1` script. The script has the following arguments:
* **ChartName**: Default value is the project name. You can create different charts and specify the chart name. In ABP Studio [Kubernetes Main Chart](../../studio/kubernetes.md#main-chart) *Install Chart(s)* command automatically sets the chart name.
* **Namespace**: The namespace to install the Kubernetes resources. Default value is the project name with the `-local` suffix.
* **ReleaseName**: The release name of the Helm chart. Default value is the project name with the `-local` suffix.
* **DotnetEnvironment**: The environment to run the application. Default value is `Staging`.
* **User**: The user responsible for installing the Kubernetes resources. The application will automatically set the user name if you configure it under [Specify the User](../../studio/kubernetes.md#specify-the-user).
Before running the script, you need to build the Docker images of the solution. You can use the `build-all-images.ps1` script to build all Docker images of the solution. Afterwards, make sure that you have a Kubernetes TLS secret for the ingress controller. It is automatically created when you create the solution; however, if you clone the solution from a repository, you need to create it manually. You can use the `create-tls-secrets.ps1` script to create the TLS secret. Then you can run the `install.ps1` script to install the solution to a Kubernetes cluster.
## Uninstalling the Helm Charts
You can uninstall the solution from a Kubernetes cluster using the `uninstall.ps1` script. The script has the following arguments:
* **Namespace**: The namespace to uninstall the helm chart. Default value is the project name with the `-local` suffix.
* **ReleaseName**: The release name of the Helm chart. Default value is the project name with the `-local` suffix.
* **User**: The user responsible for uninstalling the Kubernetes resources. The application will automatically set the user name if you configure it under [Specify the User](../../studio/kubernetes.md#specify-the-user).
You can run the `uninstall.ps1` script to uninstall the solution from a Kubernetes cluster.
```bash
./uninstall.ps1
```
Additionally, in ABP Studio [Kubernetes](../../studio/kubernetes.md) feature, you can do the same operations more easily. You can use the Install Chart(s) and Uninstall Chart(s) commands to install and uninstall the solution to a Kubernetes cluster. Also, use the Build Docker Image(s) command to build the Docker images of the solution.
![kubernetes](images/kubernetes.png)

BIN
docs/en/solution-templates/layered-web-application/images/account-external-provider.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

BIN
docs/en/solution-templates/layered-web-application/images/angular-folder-structure.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 79 KiB

BIN
docs/en/solution-templates/layered-web-application/images/angular-template-structure-diagram.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

BIN
docs/en/solution-templates/layered-web-application/images/apply-database-migrations.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

BIN
docs/en/solution-templates/layered-web-application/images/bookstore-solution-tiered.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 88 KiB

BIN
docs/en/solution-templates/layered-web-application/images/database-connection-strings-modal.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

BIN
docs/en/solution-templates/layered-web-application/images/database-connection-strings.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

BIN
docs/en/solution-templates/layered-web-application/images/file-management-index-page.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

BIN
docs/en/solution-templates/layered-web-application/images/helm-folder.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

BIN
docs/en/solution-templates/layered-web-application/images/kubernetes.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

BIN
docs/en/solution-templates/layered-web-application/images/layered-project-dependencies.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

BIN
docs/en/solution-templates/layered-web-application/images/layered-solution-in-explorer.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

BIN
docs/en/solution-templates/layered-web-application/images/mobile-applications.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

BIN
docs/en/solution-templates/layered-web-application/images/open-solution-with-explorer.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

BIN
docs/en/solution-templates/layered-web-application/images/openiddict-ui.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 KiB

BIN
docs/en/solution-templates/layered-web-application/images/run-solution-tiered.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

BIN
docs/en/solution-templates/layered-web-application/images/run-solution.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

BIN
docs/en/solution-templates/layered-web-application/images/saas-module-selection.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 95 KiB

BIN
docs/en/solution-templates/layered-web-application/images/solution-folders.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

BIN
docs/en/solution-templates/layered-web-application/images/solutionrunner-maui-targetframework.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

BIN
docs/en/solution-templates/layered-web-application/images/tiered-solution-applications-authserver.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

BIN
docs/en/solution-templates/layered-web-application/images/tiered-solution-servers.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

BIN
docs/en/solution-templates/layered-web-application/images/web-applications.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 183 KiB

492
docs/en/solution-templates/layered-web-application/index.md

@ -1,465 +1,35 @@
# Layered Application Solution Template
# ABP Studio: Layered Solution Template
This template provides a layered application structure based on the [Domain Driven Design](../../framework/architecture/domain-driven-design) (DDD) practices.
## Getting Started
This document explains **the solution structure** and projects in details. If you want to start quickly, follow the guides below:
* [The getting started document](../../get-started/layered-web-application.md) explains how to create a new application in a few minutes.
* [The application development tutorial](../../tutorials/book-store/part-01.md) explains step by step application development.
## How to Start With?
You can use the [ABP CLI](../../cli) to create a new project using this startup template. Alternatively, you can generate a CLI command from the [Get Started](https://abp.io/get-started) page. CLI approach is used here.
First, install the ABP CLI if you haven't installed it before:
````bash
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.BookStore -t app
````
* `Acme.BookStore` is the solution name, like *YourCompany.YourProduct*. You can use single-level, two-level or three-level naming.
* This example specified the template name (`-t` or `--template` option). However, `app` is already the default template if you didn't specify it.
### Specify the UI Framework
This template provides multiple UI frameworks:
* `mvc`: ASP.NET Core MVC UI with Razor Pages (default)
* `blazor`: Blazor UI
* `blazor-server`: Blazor Server UI
* `angular`: Angular UI
Use the `-u` or `--ui` option to specify the UI framework:
````bash
abp new Acme.BookStore -u angular
````
### Specify the Database Provider
This template supports the following database providers:
- `ef`: Entity Framework Core (default)
- `mongodb`: MongoDB
Use `-d` (or `--database-provider`) option to specify the database provider:
````bash
abp new Acme.BookStore -d mongodb
````
### Specify the Mobile Application Framework
This template supports the following mobile application frameworks:
- `react-native`: React Native (*Available for* ***Team*** *or higher licenses*)
Use the `-m` (or `--mobile`) option to specify the mobile application framework:
````bash
abp new Acme.BookStore -m react-native
````
* [The getting started document](../../get-started/layered-web-application.md) explains how to create a new application with this startup template.
* [The application development tutorial](../../tutorials/book-store/part-01.md) explains step by step application development with this startup template.
## Solution Structure
Based on the options you've specified, you will get a slightly different solution structure.
### Default Structure
If you don't specify any additional options, you will have a solution as shown below:
![bookstore-rider-solution-v6](../../images/solution-structure-solution-explorer-rider.png)
Projects are organized in `src` and `test` folders. `src` folder contains the actual application which is layered based on [DDD](../../framework/architecture/domain-driven-design) principles as mentioned before.
The diagram below shows the layers & project dependencies of the application:
![layered-project-dependencies](../../images/layered-project-dependencies.png)
Each section below will explain the related project & its dependencies.
#### .Domain.Shared Project
This project contains constants, enums and other objects these are actually a part of the domain layer, but needed to be used by all layers/projects in the solution.
A `BookType` enum and a `BookConsts` class (which may have some constant fields for the `Book` entity, like `MaxNameLength`) are good candidates for this project.
* This project has no dependency on other projects in the solution. All other projects depend on this one directly or indirectly.
#### .Domain Project
This is the domain layer of the solution. It mainly contains [entities, aggregate roots](../../framework/architecture/domain-driven-design/entities.md), [domain services](../../framework/architecture/domain-driven-design/domain-services.md), [value objects](../../framework/architecture/domain-driven-design/value-objects.md), [repository interfaces](../../framework/architecture/domain-driven-design/repositories.md) and other domain objects.
A `Book` entity, a `BookManager` domain service and an `IBookRepository` interface are good candidates for this project.
* Depends on the `.Domain.Shared` because it uses constants, enums and other objects defined in that project.
#### .Application.Contracts Project
This project mainly contains [application service](../../framework/architecture/domain-driven-design/application-services.md) **interfaces** and [Data Transfer Objects](../../framework/architecture/domain-driven-design/data-transfer-objects.md) (DTO) of the application layer. It exists to separate the interface & implementation of the application layer. In this way, the interface project can be shared to the clients as a contract package.
An `IBookAppService` interface and a `BookCreationDto` class are good candidates for this project.
* Depends on the `.Domain.Shared` because it may use constants, enums and other shared objects of this project in the application service interfaces and DTOs.
#### .Application Project
This project contains the [application service](../../framework/architecture/domain-driven-design/application-services.md) **implementations** of the interfaces defined in the `.Application.Contracts` project.
A `BookAppService` class is a good candidate for this project.
* Depends on the `.Application.Contracts` project to be able to implement the interfaces and use the DTOs.
* Depends on the `.Domain` project to be able to use domain objects (entities, repository interfaces... etc.) to perform the application logic.
#### .EntityFrameworkCore Project
This is the integration project for the EF Core. It defines the `DbContext` and implements repository interfaces defined in the `.Domain` project.
* Depends on the `.Domain` project to be able to reference to entities and repository interfaces.
> This project is available only if you are using EF Core as the database provider. If you select another database provider, its name will be different.
#### .DbMigrator Project
This is a console application that simplifies the execution of database migrations on development and production environments. When you run this application, it:
* Creates the database if necessary.
* Applies the pending database migrations.
* Seeds initial data if needed.
> This project has its own `appsettings.json` file. So, if you want to change the database connection string, remember to change this file too.
Especially, seeding initial data is important at this point. ABP has a modular data seed infrastructure. See [its documentation](../../framework/infrastructure/data-seeding.md) for more about the data seeding.
While creating database & applying migrations seem only necessary for relational databases, this project comes even if you choose a NoSQL database provider (like MongoDB). In that case, it still seeds the initial data which is necessary for the application.
* Depends on the `.EntityFrameworkCore` project (for EF Core) since it needs to access to the migrations.
* Depends on the `.Application.Contracts` project to be able to access permission definitions, because the initial data seeder grants all permissions to the admin role by default.
#### .HttpApi Project
This project is used to define your API Controllers.
Most of the time you don't need to manually define API Controllers since ABP's [Auto API Controllers](../../framework/api-development/auto-controllers.md) feature creates them automagically based on your application layer. However, in case of you need to write API controllers, this is the best place to do it.
* Depends on the `.Application.Contracts` project to be able to inject the application service interfaces.
#### .HttpApi.Client Project
This is a project that defines C# client proxies to use the HTTP APIs of the solution. You can share this library to 3rd-party clients, so they can easily consume your HTTP APIs in their Dotnet applications (For other types of applications, they can still use your APIs, either manually or using a tool in their own platform)
Most of the time you don't need to manually create C# client proxies, thanks to ABP's [Dynamic C# API Clients](../../framework/api-development/dynamic-csharp-clients.md) feature.
`.HttpApi.Client.ConsoleTestApp` project is a console application created to demonstrate the usage of the client proxies.
* Depends on the `.Application.Contracts` project to be able to share the same application service interfaces and DTOs with the remote service.
> You can delete this project & dependencies if you don't need to create C# client proxies for your APIs.
#### .Web Project
This project contains the User Interface (UI) of the application if you are using ASP.NET Core MVC UI. It contains Razor pages, JavaScript files, CSS files, images and so on...
This project contains the main `appsettings.json` file that contains the connection string and other configurations of the application.
* Depends on the `.HttpApi` project since the UI layer needs to use APIs and the application service interfaces of the solution.
> If you check the source code of the `.Web.csproj` file, you will see the references to the `.Application` and the `.EntityFrameworkCore` projects.
>
> These references are actually not needed while coding your UI layer, because the UI layer normally doesn't depend on the EF Core or the Application layer's implementation. These startup templates are ready for tiered deployment, where the API layer is hosted on a separate server than the UI layer.
>
> However, if you don't choose the `--tiered` option, these references will be in the .Web project to be able to host the Web, API and application layers in a single application endpoint.
>
> This gives you the ability to use domain entities & repositories in your presentation layer. However, this is considered as a bad practice according to DDD.
#### Test Projects
The solution has multiple test projects, one for each layer:
* `.Domain.Tests` is used to test the domain layer.
* `.Application.Tests` is used to test the application layer.
* `.EntityFrameworkCore.Tests` is used to test EF Core configuration and custom repositories.
* `.Web.Tests` is used to test the UI (if you are using ASP.NET Core MVC UI).
* `.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 .NET application.
Test projects are prepared for integration testing;
* It is fully integrated into the ABP and all services in your application.
* It uses SQLite in-memory database for EF Core. For MongoDB, it uses the [EphemeralMongo](https://github.com/asimmon/ephemeral-mongo) library.
* Authorization is disabled, so any application service can be easily used in tests.
You can still create unit tests for your classes which will be harder to write (because you will need to prepare mock/fake objects), but faster to run (because it only tests a single class and skips all the initialization processes).
#### How to Run?
Set `.Web` as the startup project and run the application. The default username is `admin` and the password is `1q2w3E*`.
See [Getting Started With the ASP.NET Core MVC Template](../../get-started/layered-web-application.md) for more information.
### Tiered Structure
If you have selected the ASP.NET Core UI and specified the `--tiered` option, the solution created will be a tiered solution. The purpose of the tiered structure is to be able to **deploy Web applications and HTTP API to different servers**:
![bookstore-visual-studio-solution-v3](../../images/tiered-solution-servers.png)
* Browser runs your UI by executing HTML, CSS & JavaScript.
* Web servers host static UI files (CSS, JavaScript, image... etc.) & dynamic components (e.g. Razor pages). It performs HTTP requests to the API server to execute the business logic of the application.
* The API Server hosts the HTTP APIs which then use the application & domain layers of the application to perform the business logic.
* Finally, database server hosts your database.
So, the resulting solution allows a 4-tiered deployment, by comparing to 3-tiered deployment of the default structure explained before.
> Unless you actually need such a 4-tiered deployment, it's suggested to go with the default structure which is simpler to develop, deploy and maintain.
The solution structure is shown below:
![bookstore-rider-solution-v6](../../images/bookstore-rider-solution-tiered.png)
As different from the default structure, two new projects come into play: `.AuthServer` & `.HttpApi.Host`.
#### .AuthServer Project
This project is used as an authentication server for other projects. `.Web` 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 HTTP API server. HTTP API server uses bearer token authentication to obtain claims from the access token to authorize the current user.
![tiered-solution-applications](../../images/tiered-solution-applications-authserver.png)
ABP uses the [OpenIddict Module](../../modules/openiddict.md) that uses the open-source [OpenIddict-core](https://github.com/openiddict/openiddict-core) library for the authentication between applications. See [OpenIddict documentation](https://documentation.openiddict.com/) for details about the OpenIddict and OpenID Connect protocol.
It has its own `appsettings.json` that contains database connection and other configurations.
#### .HttpApi.Host Project
This project is an application that hosts the API of the solution. It has its own `appsettings.json` that contains database connection and other configurations.
#### .Web Project
Just like the default structure, this project contains the User Interface (UI) of the application. It contains razor pages, JavaScript files, style files, images and so on...
This project contains an `appsettings.json` file, but this time it does not have a connection string because it never connects to the database. Instead, it mainly contains the endpoint of the remote API server and the authentication server.
#### Pre-requirements
* [Redis](https://redis.io/): The applications use Redis as a distributed cache. So, you need to have Redis installed & running.
#### How to Run?
You should run the application with the given order:
* First, run the `.AuthServer` since other applications depend on it.
* Then run the `.HttpApi.Host` since it is used by the `.Web` application.
* Finally, you can run the `.Web` project and login to the application (using `admin` as the username and `1q2w3E*` as the password).
### Blazor UI
If you choose `Blazor` as the UI Framework (using the `-u blazor` or `-u blazor-server` option), the solution will have a project named `.Blazor`. This project contains the Blazor UI application. According to your choice, it will be a Blazor WebAssembly or Blazor Server application. If Blazor WebAssembly is selected, the solution will also have a `.HttpApi.Host`. This project is an ASP.NET Core application that hosts the backend application for the Blazor single page application.
#### .Blazor Project (Server)
The Blazor Server project is similar to the ASP.NET Core MVC project. It replaces `.Web` project with `.Blazor` in the solution structure above. It has the same folder structure and the same application flow. Since it's an ASP.NET Core application, it can contain **.cshtml** files and **.razor** components at the same time. If routing matches a razor component, the Blazor UI will be used. Otherwise, the request will be handled by the MVC framework.
![abp solution structure blazor server](../../images/layered-project-dependencies-blazor-server.png)
#### .Blazor Project (WebAssembly)
The Blazor WebAssembly project is a single page application that runs on the browser. You'll see it as `.Blazor` project in the solution. It uses the `.HttpApi.Host` project to communicate with the backend. It can't be used without the backend application. It contains only **.razor** components. It's a pure client-side application. It doesn't have any server-side code. Everything in this layer will be for the client side.
![abp solution structure blazor wasm](../../images/layered-project-dependencies-blazor-wasm.png)
### Angular UI
If you choose `Angular` as the UI framework (using the `-u angular` option), the solution is being separated into two folders:
* `angular` folder contains the Angular UI application, the client-side code.
* `aspnet-core` folder contains the ASP.NET Core solution, the server-side code.
The server-side is similar to the solution described above. `*.HttpApi.Host` project serves the API, so the `Angular` application consumes it.
Angular application folder structure looks like below:
![angular-folder-structure](../../images/angular-folder-structure.png)
Each of ABP modules is an NPM package. Some ABP modules are added as a dependency in `package.json`. These modules install with their dependencies. To see all ABP packages, you can run the following command in the `angular` folder:
```bash
yarn list --pattern abp
```
Angular application module structure:
![Angular template structure diagram](../../images/angular-template-structure-diagram.png)
#### AppModule
`AppModule` is the root module of the application. Some of the ABP modules and some essential modules are imported to `AppModule`.
ABP Config modules have also been imported to `AppModule` for initial requirements of the lazy-loadable ABP modules.
#### AppRoutingModule
There are lazy-loadable ABP modules in the `AppRoutingModule` as routes.
> Paths of ABP Modules should not be changed.
You should add `routes` property in the `data` object to add a link on the menu to redirect to your custom pages.
```js
````json
//[doc-nav]
{
path: 'dashboard',
loadChildren: () => import('./dashboard/dashboard.module').then(m => m.DashboardModule),
canActivate: [authGuard, permissionGuard],
data: {
routes: {
name: 'ProjectName::Menu:Dashboard',
order: 2,
iconClass: 'fa fa-dashboard',
requiredPolicy: 'ProjectName.Dashboard.Host'
} as ABP.Route
}
"Next": {
"Name": "Overview",
"Path": "solution-templates/layered-web-application/overview"
}
}
```
In the above example;
* If the user is not logged in, authGuard blocks access and redirects to the login page.
* permissionGuard checks the user's permission with the `requiredPolicy` property of the `routes` object. If the user is not authorized to access the page, the 403 page appears.
* The `name` property of `routes` is the menu link label. A localization key can be defined.
* The `iconClass` property of the `routes` object is the menu link icon class.
* The `requiredPolicy` property of the `routes` object is the required policy key to access the page.
After the above `routes` definition, if the user is authorized, the dashboard link will appear on the menu.
#### Shared Module
The modules that may be required for all modules have been imported to the `SharedModule`. You should import `SharedModule` to all modules.
See the [Sharing Modules](https://angular.io/guide/sharing-ngmodules) document.
#### Environments
The files under the `src/environments` folder have the essential configuration of the application.
#### Home Module
Home module is an example lazy-loadable module that loads on the root address of the application.
#### Styles
The required style files are added to the `styles` array in `angular.json`. `AppComponent` loads some style files lazily via `LazyLoadService` after the main bundle is loaded to shorten the first rendering time.
#### Testing
You should create your tests in the same folder as the file you want to test.
See the [testing document](https://angular.io/guide/testing).
#### Depended Packages
* [NG Bootstrap](https://ng-bootstrap.github.io/) is used as UI component library.
* [NGXS](https://www.ngxs.io/) is used as state management library.
* [angular-oauth2-oidc](https://github.com/manfredsteyer/angular-oauth2-oidc) is used to support for OAuth 2 and OpenId Connect (OIDC).
* [Chart.js](https://www.chartjs.org/) is used to create widgets.
* [ngx-validate](https://github.com/ng-turkey/ngx-validate) is used for dynamic validation of reactive forms.
### React Native
If the `-m react-native` option is specified in the new project command, the solution includes the [React Native](https://reactnative.dev/) application in the `react-native` folder.
The server-side is similar to the solution described above. `*.HttpApi.Host` project serves the API, so the React Native application consumes it.
The React Native application was generated with [Expo](https://expo.io/). Expo is a set of tools built around React Native to help you quickly start an app and, while it has many features.
React Native application folder structure as like below:
![react-native-folder-structure](../../images/react-native-folder-structure.png)
* `App.js` is the bootstrap component of the application.
* `Environment.js` file has the essential configuration of the application. `prod` and `dev` configurations are defined in this file.
* [Contexts](https://reactjs.org/docs/context.html) are created in the `src/contexts` folder.
* [Higher order components](https://reactjs.org/docs/higher-order-components.html) are created in the `src/hocs` folder.
* [Custom hooks](https://reactjs.org/docs/hooks-custom.html#extracting-a-custom-hook) are created in `src/hooks`.
* [Axios interceptors](https://github.com/axios/axios#interceptors) are created in the `src/interceptors` folder.
* Utility functions are exported from `src/utils` folder.
#### Components
Components that can be used on all screens are created in the `src/components` folder. All components have been created as a function that is able to use [hooks](https://reactjs.org/docs/hooks-intro.html).
#### Screens
![react-native-navigation-structure](../../images/react-native-navigation-structure.png)
Screens are created by creating folders that separate their names in the `src/screens` folder. Certain parts of some screens can be split into components.
Each screen is used in a navigator in the `src/navigators` folder.
#### Navigation
[React Navigation](https://reactnavigation.org/) is used as a navigation library. Navigators are created in the `src/navigators`. A [drawer](https://reactnavigation.org/docs/drawer-based-navigation/) navigator and several [stack](https://reactnavigation.org/docs/hello-react-navigation/#installing-the-stack-navigator-library) navigators have been created in this folder. See the [above diagram](#screens) for the navigation structure.
#### State Management
[Redux](https://redux.js.org/) is used as a state management library. [Redux Toolkit](https://redux-toolkit.js.org/) library is used as a toolset for efficient Redux development.
Actions, reducers, sagas and selectors are created in the `src/store` folder. Store folder is as below:
![react-native-store-folder](../../images/react-native-store-folder.png)
* [**Store**](https://redux.js.org/basics/store) is defined in the `src/store/index.js` file.
* [**Actions**](https://redux.js.org/basics/actions/) are payloads of information that send data from your application to your store.
* [**Reducers**](https://redux.js.org/basics/reducers) specify how the application's state changes in response to actions sent to the store.
* [**Redux-Saga**](https://redux-saga.js.org/) is a library that aims to make application side effects (i.e. asynchronous things like data fetching and impure things like accessing the browser cache) easier to manage. Sagas are created in the `src/store/sagas` folder.
* [**Reselect**](https://github.com/reduxjs/reselect) library is used to create memoized selectors. Selectors are created in the `src/store/selectors` folder.
#### APIs
[Axios](https://github.com/axios/axios) is used as an HTTP client library. An Axios instance has exported from `src/api/API.js` file to make HTTP calls with the same config. `src/api` folder also has the API files that have been created for API calls.
#### Theming
[Native Base](https://nativebase.io/) is used as UI components library. Native Base components can customize easily. See the [Native Base customize](https://docs.nativebase.io/customizing-components) documentation. We followed the same way.
* Native Base theme variables are in the `src/theme/variables` folder.
* Native Base component styles are in the `src/theme/components` folder. These files have been generated with Native Base's `ejectTheme` script.
* Styles of components override with the files under the `src/theme/overrides` folder.
#### Testing
Unit tests will be created.
See the [Testing Overview](https://reactjs.org/docs/testing.html) document.
#### Depended Libraries
* [Native Base](https://nativebase.io/) is used as UI components library.
* [React Navigation](https://reactnavigation.org/) is used as navigation library.
* [Axios](https://github.com/axios/axios) is used as an HTTP client library.
* [Redux](https://redux.js.org/) is used as state management library.
* [Redux Toolkit](https://redux-toolkit.js.org/) library is used as a toolset for efficient Redux development.
* [Redux-Saga](https://redux-saga.js.org/) is used to manage asynchronous processes.
* [Redux Persist](https://github.com/rt2zz/redux-persist) is used as state persistence.
* [Reselect](https://github.com/reduxjs/reselect) is used to create memoized selectors.
* [i18n-js](https://github.com/fnando/i18n-js) is used as i18n library.
* [expo-font](https://docs.expo.io/versions/latest/sdk/font/) library allows loading fonts easily.
* [Formik](https://github.com/jaredpalmer/formik) is used to build forms.
* [Yup](https://github.com/jquense/yup) is used for form validations.
## Social / External Logins
If you want to configure social/external logins for your application, please follow the [Social/External Logins](../../social-external-logins.md) document.
## What's Next?
- [The getting started document](../../get-started) explains how to create a new application in a few minutes.
- [The application development tutorial](../../tutorials/book-store/part-01.md) explains step by step application development.
````
## See Also
* [Video tutorial](https://abp.io/video-courses/essentials/app-template)
ABP Studio provides pre-architected, production-ready templates to jump-start a new solution. One of these templates is the Layered solution template. It is designed for building monolithic layered systems that follow common application patterns based on [Domain-Driven Design](../../framework/architecture/domain-driven-design) (DDD) principles. The template includes multiple layers, integrates existing modules, and provides host applications based on your selections, making it an excellent foundation for your layered system.
> **This document explains the Layered solution template in detail. It is a reference document to fully understand the solution and refer to when you have trouble.**
> **If you want to quickly create a layered solution, please refer to *[Quick Start: Creating a Layered Web Application with ABP Studio](../../get-started/layered-web-application.md)* document.**
## Contents
* [Overview](overview.md)
* [Solution structure](solution-structure.md)
* [Main Components](main-components.md)
* [Web Applications](web-applications.md)
* [Db Migrator](db-migrator.md)
* [Mobile Applications](mobile-applications.md)
* [Built-In Features](built-in-features.md)
* [Authentication](authentication.md)
* [Database configurations](database-configurations.md)
* [Logging (with Serilog)](logging.md)
* [Swagger integration](swagger-integration.md)
* [Multi-Tenancy](multi-tenancy.md)
* [BLOB storing](blob-storing.md)
* [CORS configuration](cors-configuration.md)
* [Helm Charts and Kubernetes](helm-charts-and-kubernetes.md)

35
docs/en/solution-templates/layered-web-application/logging.md

@ -0,0 +1,35 @@
# Layered Solution: Logging
```json
//[doc-nav]
{
"Previous": {
"Name": "Database configurations",
"Path": "solution-templates/layered-web-application/database-configurations"
},
"Next": {
"Name": "Swagger integration",
"Path": "solution-templates/layered-web-application/swagger-integration"
}
}
```
The ABP Studio [layered solution template](index.md) is fully configured for [logging](../../framework/fundamentals/logging.md). All the applications are configured to use the [Serilog](https://serilog.net/) library for structured logging. They are configured in a common way for logging. This document explains that common logging structure.
## The Serilog Sinks
The Serilog library is configured so it writes the logs to the following targets (a.k.a. [sinks](https://github.com/serilog/serilog/wiki/Provided-Sinks)) in parallel:
* **[Console](https://github.com/serilog/serilog-sinks-console)**: Logs are written to the standard output of the executing application. Logging to console is useful when you want to see logs easily while it is running in a container.
* **[File](https://github.com/serilog/serilog-sinks-file)**: Logs are written to a file named `logs.txt` located under the `Logs` folder of the executing application. File logging is useful when you run the application on your local computer. You can check logs easily when you have a trouble. This sinks is only configured for DEBUG mode. It won't be available in your production environment (you can change the behavior in your `Program.cs` file).
* **ABP Studio**: This is a Sink provided by ABP Studio. It sends all logs to ABP Studio, so you can easily monitor your logs in real-time on your ABP Studio Application Monitoring panel.
The solution can work with [any sink](https://github.com/serilog/serilog/wiki/Provided-Sinks) supported by Serilog. You can add more sinks, remove pre-installed sinks or fine tune their configuration for your solution.
## Program.cs
The `Program.cs` file is the main point that configures the logging system. It is done here, because we want to initialize and start the logging in the very beginning of the application.
## Additional Information
We are using ABP Serilog Enrichers in the module class of the application. It is done by the `app.UseAbpSerilogEnrichers();` line in the `OnApplicationInitialization` method of your module class. That ASP.NET Core middleware adds current [tenant](../../framework/architecture/multi-tenancy/index.md), [user](../../framework/infrastructure/current-user.md), client and correlation id information to the log records.

21
docs/en/solution-templates/layered-web-application/main-components.md

@ -0,0 +1,21 @@
# Layered Solution: Main Components
````json
//[doc-nav]
{
"Previous": {
"Name": "Solution structure",
"Path": "solution-templates/layered-web-application/solution-structure"
},
"Next": {
"Name": "Web Applications",
"Path": "solution-templates/layered-web-application/web-applications"
}
}
````
The solution consists of various applications; web applications, mobile applications, and a database migrator application. These applications are the main components of the solution and are designed to work together to provide a complete solution. The following documents explains these components in details:
* [Web Applications](web-applications.md)
* [Db Migrator](db-migrator.md)
* [Mobile Applications](mobile-applications.md)

122
docs/en/solution-templates/layered-web-application/mobile-applications.md

@ -0,0 +1,122 @@
# Layered Solution: Mobile Applications
```json
//[doc-nav]
{
"Previous": {
"Name": "Db Migrator",
"Path": "solution-templates/layered-web-application/db-migrator"
},
"Next": {
"Name": "Built-In Features",
"Path": "solution-templates/layered-web-application/built-in-features"
}
}
```
> You must have an ABP Team or a higher license to be able to create a mobile application project with ABP Studio.
Mobile applications are an essential part of modern software solutions. They provide a user-friendly interface to the end-users and allow them to access the system from anywhere. ABP Studio allows you to create mobile applications for your layered solution. You can create a new mobile application project, configure it, and run it on your device.
## Mobile Application Types
ABP Studio supports the following mobile application types:
- **None**: No mobile application project is created. It is the default option.
- **MAUI**: Cross-platform mobile applications with .NET MAUI (Multi-platform App UI). You can create MAUI projects with ABP Studio.
- **React Native**: Cross-platform mobile applications that share code between iOS and Android platforms. You can create React Native projects with ABP Studio.
You can select the mobile application type when creating a new layered application project during the *Mobile Framework* step.
![mobile-applications](images/mobile-applications.png)
### The MAUI Application
This is the mobile application that is built based on Microsoft's [MAUI framework](https://learn.microsoft.com/en-us/dotnet/maui). It will be in the solution only if you've selected the MAUI as your mobile application option.
#### Project Structure
Entire MAUI application is built on the AppShell pattern of MAUI. You can find the AppShell class in the `Acme.Bookstore.Maui` project. It is the entry point of the application. It is responsible for initializing the application and registering the services. You find all the pages and routing information in the `AppShell.xaml` file.
- **Pages**: Pages are located in the `Pages` folder of the project. Each page has a XAML & C# file. XAML file is responsible for the UI and C# file is responsible for the initialization of the page.
- **ViewModels**: ViewModels are located in the `ViewModels` folder of the project. Each ViewModel has a C# file. ViewModels are responsible for the business logic of the pages.
- **Oidc**: Oidc folder contains the logic for the authentication of the application. It contains the `MauiAuthenticationBrowser` class which manages the authentication process of the application.
- **Localization**: Localization folder contains the localization logic of the application. It contains regular ABP Localization logic and the `LocalizationResourceManager` class which is wrapper for the ABP localization logic on MAUI.
- **Messages**: Messages folder contains the message data for the communication inside application. Messages are used to send data between pages and viewmodels. It's designed on the [MVVM Toolkit Messenger](https://learn.microsoft.com/en-us/dotnet/communitytoolkit/mvvm/messenger) feature.
- **Storage**: Storage folder contains the storage logic of the application. It contains the `IStorage` class which is wrapper for the [SecureStorage](https://learn.microsoft.com/en-us/dotnet/maui/platform-integration/storage/secure-storage) feature. It is used to store the authentication data of the user and preferences of the application.
_Rest of the folders are MAUI default folders. You can check the [.NET MAUI single project documentatipon](https://learn.microsoft.com/en-us/dotnet/maui/fundamentals/single-project?view=net-maui-8.0) for more information._
#### Running the application
Before running the MAUI Application, rest of the applications in the solution must be running. Such as AuthServer, MobileGateway and the microservices.
Make sure that you prepared devices for debugging. You can check the following documentation for each platform.
- [Android](https://learn.microsoft.com/en-us/dotnet/maui/android/emulator/)
- [iOS](https://learn.microsoft.com/en-us/dotnet/maui/ios/pair-to-mac)
- [MacCatalyst](https://learn.microsoft.com/en-us/dotnet/maui/mac-catalyst/cli)
- [Windows](https://learn.microsoft.com/en-us/dotnet/maui/windows/setup)
##### Network
All the platforms including iOS, MacCataylst and Windows, runs the applications in the same network of the host. So, you can use the `localhost` address to connect to the applications.
But in the **Android Emulator**, you need to use the `adb reverse` command to connect to the applications. You can use the following command to connect to the AuthServer application:
```bash
adb reverse tcp:44300 tcp:44300
```
> `44300` is an example port. You need to change it based on the port of the AuthServer & MobileGateway application.
> You need to run the command for a running emulator. If you run the emulator after running the command, you need to run the command again.
##### Target Framework
Since MAUI Applications have multiple target frameworks, you need to select the target framework before running the application. You can select the target framework from the context menu of the Solution Runner.
![ABP Studio MAUI Target Framework](images/solutionrunner-maui-targetframework.png)
##### Running with ABP Studio
You can start the MAUI application with the solution runner. You can click the start button of the MAUI application in the solution runner tree. It will start the application on the selected target framework. Since they're not running on a process and they're running on a device, you can't see them as running state in the solution runner. After the application is deployed, it'll be opened on the device and it'll be shown as stopped in the solution runner.
#### Development on MAUI Application
You can follow [Mobile Application Development Tutorial - MAUI](../../tutorials/mobile/maui/index.md) to learn how to develop on MAUI Application.
### The React Native Application
This is the mobile application that is built based on Facebook's [React Native framework](https://reactnative.dev/) and [Expo](https://expo.dev/). It will be in the solution only if you've selected React Native as your mobile application option.
#### Project Structure
- **Environment.js**: file using for provide application level variables like `apiUrl`, `oAuthConfig` and etc.
- **api**: The `api` folder contains HTTP request files that simplify API management in the React Native starter template
- `API.js:` exports **axiosInstance**. It provides axios instance filled api url
- **components**: In the `components` folder you can reach built in react native components that you can use in your app. These components **facilitates** your list, select and etc. operations
- **contexts**: `contexts` folder contains [react context](https://react.dev/reference/react/createContext). You can expots your contexts in this folder. `Localization context provided in here`
- **navigators**: folder contains [react-native stacks](https://reactnavigation.org/docs/stack-navigator/). After create new *FeatureName*Navigator we need to provide in `DrawerNavigator.js` file as `Drawer.Screen`
- **screens**: is the content of navigated page. We'll pass as component property to [Stack.Screen](https://reactnavigation.org/docs/native-stack-navigator/)
- **store**: folder manages state-management operations. We will define `actions`, `reducers`, `sagas` and `selectors` here.
- **styles**: folder contains app styles. `system-style.js` comes built in template we can also add new styles.
- **utils**: folder contains helper functions that we can use in application
#### Running the Application
React Native applications can't be run with the solution runner. You need to run them with the React Native CLI. You can check the [React Native documentation](https://reactnative.dev/docs/environment-setup) to learn how to setup the environment for React Native development.
Before running the React Native application, rest of the applications in the solution must be running. Such as AuthServer, MobileGateway and the microservices.
Then you can run the React Native application by following this documentation: [Getting Started with the React Native](../../framework/ui/react-native/index.md).

74
docs/en/solution-templates/layered-web-application/multi-tenancy.md

@ -0,0 +1,74 @@
# Layered Solution: Multi-Tenancy
```json
//[doc-nav]
{
"Previous": {
"Name": "Swagger integration",
"Path": "solution-templates/layered-web-application/swagger-integration"
},
"Next": {
"Name": "BLOB storing",
"Path": "solution-templates/layered-web-application/blob-storing"
}
}
```
> Some of the features mentioned in this document may not be available in the free version. We're using the **\*** symbol to indicate that a feature is available in the **[Team](https://abp.io/pricing)** and **[Higher](https://abp.io/pricing)** licenses.
Multi-tenancy is a software architecture where a single instance(codebase) of software runs on a server and serves multiple tenants. Tenants are isolated from each other and can have their own data, configurations, and users. This document explains how the multi-tenancy mechanism works in the layered solution template. You can learn more about multi-tenancy in the [Multi-Tenancy](../../framework/architecture/multi-tenancy/index.md), [Tenant Management](../../modules/tenant-management.md) and [SaaS **\***](../../modules/saas.md) documents.
## Multi-Tenancy in Layered Solutions
The layered solution templates use the *Multi-Tenancy* architecture only if you *Enable Multi-Tenancy **\**** option while creating the solution.
![saas-module-selection](images/saas-module-selection.png)
You can use different databases for each tenant or a shared database for all tenants. In the *SaaS **\*** module, you can specify the database connection strings in the [Connection Strings Management Modal](../../modules/saas.md#connection-string). All cached data is isolated by tenant. Each event, background job, and other data is stored with the tenant id.
You can use the `ICurrentTenant` service to get the current tenant information in your application.
```csharp
public class MyService : ITransientDependency
{
private readonly ICurrentTenant _currentTenant;
public MyService(ICurrentTenant currentTenant)
{
_currentTenant = currentTenant;
}
public void MyMethod()
{
var tenantId = _currentTenant.Id;
var tenantName = _currentTenant.Name;
}
}
```
Additionally, you can use the [DataFilter](../../framework/infrastructure/data-filtering.md#idatafilter-service-enabledisable-data-filters) system to disable the tenant filter and list all data in the same database.
```csharp
public class MyBookService : ITransientDependency
{
private readonly IDataFilter<IMultiTenant> _multiTenantFilter;
private readonly IRepository<Book, Guid> _bookRepository;
public MyBookService(
IDataFilter<IMultiTenant> multiTenantFilter,
IRepository<Book, Guid> bookRepository)
{
_multiTenantFilter = multiTenantFilter;
_bookRepository = bookRepository;
}
public async Task<List<Book>> GetAllBooksIncludingDeletedAsync()
{
//Temporary disable the IMultiTenant filter
using (_multiTenantFilter.Disable())
{
return await _bookRepository.GetListAsync();
}
}
}
```

108
docs/en/solution-templates/layered-web-application/overview.md

@ -0,0 +1,108 @@
# Layered Solution: Overview
````json
//[doc-nav]
{
"Previous": {
"Name": "Index",
"Path": "solution-templates/layered-web-application/index"
},
"Next": {
"Name": "Solution Structure",
"Path": "solution-templates/layered-web-application/solution-structure"
}
}
````
> Some of the features mentioned in this document may not be available in the free version. We're using the **\*** symbol to indicate that a feature is available in the **[Team](https://abp.io/pricing)** and **[Higher](https://abp.io/pricing)** licenses.
In this document, you will learn what the Layered solution template offers to you.
## Pre-Installed Libraries & Services
The following **libraries and services** come **pre-installed** and **configured** for both **development** and **production** environments. After creating your solution, you can **modify** or **remove** most of them as needed.
* **[Autofac](https://autofac.org/)** for [Dependency Injection](../../framework/fundamentals/dependency-injection.md).
* **[Serilog](https://serilog.net/)** with File and Console [logging](../../framework/fundamentals/logging.md) providers.
* **[Redis](https://redis.io/)** for [distributed caching](../../framework/fundamentals/caching.md). Redis is used for distributed caching if you select the *Public Website* **\*** or *Tiered* **\*** option.
* **[Swagger](https://swagger.io/)** for exploring and testing HTTP APIs.
* **[OpenIddict](https://github.com/openiddict/openiddict-core)** as the built-in authentication server.
## Pre-Configured Features
The following features are built and pre-configured for you in the solution.
* **Authentication** is fully configured based on best practices.
* **[Permission](../../framework/fundamentals/authorization.md)** (authorization), **[setting](../../framework/infrastructure/settings.md)**, **[feature](../../framework/infrastructure/features.md)** and the **[localization](../../framework/fundamentals/localization.md)** management systems are pre-configured and ready to use.
* **[Background job system](../../framework/infrastructure/background-jobs/index.md)**.
* **[BLOB storge](../../framework/infrastructure/blob-storing/index.md)** system is installed with the [database provider](../../framework/infrastructure/blob-storing/database.md).
* **On-the-fly database migration** system (services automatically migrated their database schema when you deploy a new version). **\***
* **[Helm](https://helm.sh/)** charts are included to deploy the solution to **[Kubernetes](https://kubernetes.io/)**. **\***
* **[Swagger](https://swagger.io/)** authentication is configured to test the authorized HTTP APIs.
## Fundamental Modules
The following modules are pre-installed and configured for the solution:
* **[Account](../../modules/account.md)** to authenticate users (login, register, two factor auth **\***, etc)
* **[Identity](../../modules/identity.md)** to manage roles and users
* **[OpenIddict](../../modules/openiddict.md)** (the core part) to implement the OAuth authentication flows
In addition these, [Feature Management](../../modules/feature-management.md), [Permission Management](../../modules/permission-management.md) and [Setting Management](../../modules/setting-management.md) modules are pre-installed as they are the fundamental feature modules of the ABP.
## Optional Modules
The following modules are optionally included in the solution, so you can select the ones you need:
* **[Audit Logging](../../modules/audit-logging.md)**
* **[Chat](../../modules/chat.md)** **\***
* **[File Management](../../modules/file-management.md)** **\***
* **[GDPR](../../modules/gdpr.md)** **\***
* **[Language Management](../../modules/language-management.md)** **\***
* **[OpenIddict (Management UI)](../../modules/openiddict.md)** **\***
* **[Tenant Management](../../modules/tenant-management.md) (Multi-Tenancy) or [SaaS](../../modules/saas.md)** **\***
* **[Text Template Management](../../modules/text-template-management.md)** **\***
## UI Theme
The **[LeptonX Lite](../../ui-themes/lepton-x-lite/index.md) or [LeptonX theme](https://leptontheme.com/)** **\*** is pre-configured for the solution. You can select one of the color palettes (System, Light or Dark) as default, while the end-user dynamically change it on the fly.
## Other Options
Layered startup template asks for some preferences while creating your solution.
### Database Providers
There are two database provider options are provided on a new solution creation:
* **[Entity Framework Core](../../framework/data/entity-framework-core/index.md)** with SQL Server, MySQL and PostgreSQL DBMS options. You can [switch to anther DBMS](../../framework/data/entity-framework-core/other-dbms.md) manually after creating your solution.
* **[MongoDB](../../framework/data/mongodb/index.md)**
### UI Frameworks
The solution comes with a main web application with the following UI Framework options:
* **None** (doesn't include a web application to the solution)
* **Angular**
* **MVC / Razor Pages UI**
* **Blazor WebAssembly**
* **Blazor Server**
* **Blazor WebApp**
* **MAUI with Blazor (Hybrid)** **\***
### The Mobile Application
If you prefer, the solution includes a mobile application. The mobile application is fully integrated to the system, implements authentication (login) and other ABP features, and includes a few screens that you can use and take as example. The following options are available:
* **None** (doesn't include a mobile application to the solution)
* **MAUI** **\***
* **React Native** **\***
### Multi-Tenancy & SaaS Module **\***
The **[SaaS module](../../modules/saas.md)** is included as an option. When you select it, the **[multi-tenancy](../../framework/architecture/multi-tenancy/index.md)** system is automatically configured. Otherwise, the system will not include any multi-tenancy overhead.
## See Also
* [Quick Start: Creating a Layered Web Application with ABP Studio](../../get-started/layered-web-application.md)

222
docs/en/solution-templates/layered-web-application/solution-structure.md

@ -0,0 +1,222 @@
# Layered Solution: The Structure
````json
//[doc-nav]
{
"Previous": {
"Name": "Overview",
"Path": "solution-templates/layered-web-application/overview"
},
"Next": {
"Name": "Main Components",
"Path": "solution-templates/layered-web-application/main-components"
}
}
````
> Some of the features mentioned in this document may not be available in the free version. We're using the **\*** symbol to indicate that a feature is available in the **[Team](https://abp.io/pricing)** and **[Higher](https://abp.io/pricing)** licenses.
This document explains the solution and folder structure of ABP Studio's [layered solution template](index.md).
> This document assumes that you've created a new layered solution by following the *[Quick Start: Creating a Layered Web Application with ABP Studio](../../get-started/layered-web-application.md)* guide. (Choose the *Entity Framework Core* as the database provider.)
## Understanding the ABP Solution Structure
When you create a new layered solution, you will see a tree structure similar to the one below in the *Solution Explorer* panel:
![layered-solution-in-explorer](images/layered-solution-in-explorer.png)
`Acme.Bookstore` is the main **ABP Studio module** of the solution. It includes two folders: `src` and `test`, as shown in the image above. The `src` folder contains the source code of the solution, which is structured according to [DDD](../../framework/architecture/domain-driven-design/index.md) principles, while the `test` folder holds the unit and integration tests.
> Refer to the *[Concepts](../../studio/concepts.md)* document for a comprehensive definition of ABP Studio solution, module, and package terms.
## Exploring the Folder Structure
You can right-click the root item in the solution explorer (`Acme.Bookstore` for this example) and select the *Open with* -> *Explorer* command to open the folder containing the solution in your file system:
![open-solution-with-explorer](images/open-solution-with-explorer.png)
The root folder of the solution will be similar to the following:
![solution-folders](images/solution-folders.png)
* `.abpstudio` folder stores your personal preferences for this solution and is excluded from source control (Git ignored). It is created and used by ABP Studio.
* `etc` folder contains additional files for the solution, organized into the following sub-folders:
* `abp-studio` folder holds settings managed by ABP Studio. This folder is included in source control and shared among developers.
* `docker` folder provides docker-compose configurations to easily run infrastructure dependencies (e.g., RabbitMQ, Redis) for the solution on your local machine.
* `helm` folder contains Helm charts and related scripts for deploying the solution to Kubernetes. **\***
* `src` folder contains the solution's source code, structured according to [DDD](../../framework/architecture/domain-driven-design/index.md) principles. It also includes database migrations and, depending on your project creation options, may include mobile and web application projects.
* `test` folder contains unit and integration tests for the solution.
## Understanding the Layered Solution Structure
The diagram below illustrates the application's layers and project dependencies:
![layered-solution-layers](images/layered-project-dependencies.png)
### .Domain.Shared Project
This project contains constants, enums and other objects these are actually a part of the domain layer, but needed to be used by all layers/projects in the solution.
A `BookType` enum and a `BookConsts` class (which may have some constant fields for the `Book` entity, like `MaxNameLength`) are good candidates for this project.
* This project has no dependency on other projects in the solution. All other projects depend on this one directly or indirectly.
### .Domain Project
This is the domain layer of the solution. It mainly contains [entities, aggregate roots](../../framework/architecture/domain-driven-design/entities.md), [domain services](../../framework/architecture/domain-driven-design/domain-services.md), [value objects](../../framework/architecture/domain-driven-design/value-objects.md), [repository interfaces](../../framework/architecture/domain-driven-design/repositories.md) and other domain objects.
A `Book` entity, a `BookManager` domain service and an `IBookRepository` interface are good candidates for this project.
* Depends on the `.Domain.Shared` because it uses constants, enums and other objects defined in that project.
### .Application.Contracts Project
This project mainly contains [application service](../../framework/architecture/domain-driven-design/application-services.md) **interfaces** and [Data Transfer Objects](../../framework/architecture/domain-driven-design/data-transfer-objects.md) (DTO) of the application layer. It exists to separate the interface & implementation of the application layer. In this way, the interface project can be shared to the clients as a contract package.
An `IBookAppService` interface and a `BookCreationDto` class are good candidates for this project.
* Depends on the `.Domain.Shared` because it may use constants, enums and other shared objects of this project in the application service interfaces and DTOs.
### .Application Project
This project contains the [application service](../../framework/architecture/domain-driven-design/application-services.md) **implementations** of the interfaces defined in the `.Application.Contracts` project.
A `BookAppService` class is a good candidate for this project.
* Depends on the `.Application.Contracts` project to be able to implement the interfaces and use the DTOs.
* Depends on the `.Domain` project to be able to use domain objects (entities, repository interfaces... etc.) to perform the application logic.
### .EntityFrameworkCore Project
This is the integration project for the EF Core. It defines the `DbContext` and implements repository interfaces defined in the `.Domain` project.
* Depends on the `.Domain` project to be able to reference to entities and repository interfaces.
> This project is available only if you are using EF Core as the database provider. If you select another database provider, its name will be different.
### .DbMigrator Project
This is a console application that simplifies the execution of database migrations on development and production environments. When you run this application, it:
* Creates the database if necessary.
* Applies the pending database migrations.
* Seeds initial data if needed.
> This project has its own `appsettings.json` file. So, if you want to change the database connection string, remember to change this file too.
Especially, seeding initial data is important at this point. ABP has a modular data seed infrastructure. See [its documentation](../../framework/infrastructure/data-seeding.md) for more about the data seeding.
While creating database & applying migrations seem only necessary for relational databases, this project comes even if you choose a NoSQL database provider (like MongoDB). In that case, it still seeds the initial data which is necessary for the application.
* Depends on the `.EntityFrameworkCore` project (for EF Core) since it needs to access to the migrations.
* Depends on the `.Application.Contracts` project to be able to access permission definitions, because the initial data seeder grants all permissions to the admin role by default.
### .HttpApi Project
This project is used to define your API Controllers.
Most of the time you don't need to manually define API Controllers since ABP's [Auto API Controllers](../../framework/api-development/auto-controllers.md) feature creates them automagically based on your application layer. However, in case of you need to write API controllers, this is the best place to do it.
* Depends on the `.Application.Contracts` project to be able to inject the application service interfaces.
### .HttpApi.Client Project
This is a project that defines C# client proxies to use the HTTP APIs of the solution. You can share this library to 3rd-party clients, so they can easily consume your HTTP APIs in their Dotnet applications (For other types of applications, they can still use your APIs, either manually or using a tool in their own platform)
Most of the time you don't need to manually create C# client proxies, thanks to ABP's [Dynamic C# API Clients](../../framework/api-development/dynamic-csharp-clients.md) feature.
`.HttpApi.Client.ConsoleTestApp` project is a console application created to demonstrate the usage of the client proxies.
* Depends on the `.Application.Contracts` project to be able to share the same application service interfaces and DTOs with the remote service.
> You can delete this project & dependencies if you don't need to create C# client proxies for your APIs.
### .Web Project
This project contains the User Interface (UI) of the application if you are using ASP.NET Core MVC UI. It contains Razor pages, JavaScript files, CSS files, images and so on...
This project contains the main `appsettings.json` file that contains the connection string and other configurations of the application.
* Depends on the `.HttpApi` project since the UI layer needs to use APIs and the application service interfaces of the solution.
> If you check the source code of the `.Web.csproj` file, you will see the references to the `.Application` and the `.EntityFrameworkCore` projects.
>
> These references are actually not needed while coding your UI layer, because the UI layer normally doesn't depend on the EF Core or the Application layer's implementation. These startup templates are ready for tiered deployment, where the API layer is hosted on a separate server than the UI layer.
>
> However, if you don't choose the `--tiered` option, these references will be in the .Web project to be able to host the Web, API and application layers in a single application endpoint.
>
> This gives you the ability to use domain entities & repositories in your presentation layer. However, this is considered as a bad practice according to DDD.
### Test Projects
The solution has multiple test projects, one for each layer:
* `.Domain.Tests` is used to test the domain layer.
* `.Application.Tests` is used to test the application layer.
* `.EntityFrameworkCore.Tests` is used to test EF Core configuration and custom repositories.
* `.Web.Tests` is used to test the UI (if you are using ASP.NET Core MVC UI).
* `.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 .NET application.
Test projects are prepared for integration testing;
* It is fully integrated into the ABP and all services in your application.
* It uses SQLite in-memory database for EF Core. For MongoDB, it uses the [EphemeralMongo](https://github.com/asimmon/ephemeral-mongo) library.
* Authorization is disabled, so any application service can be easily used in tests.
You can still create unit tests for your classes which will be harder to write (because you will need to prepare mock/fake objects), but faster to run (because it only tests a single class and skips all the initialization processes).
### How to Run?
You can open the [Solution Runner](../../studio/running-applications.md) panel and start the all applications. The default username is `admin` and the password is `1q2w3E*`.
![run-solution](images/run-solution.png)
See [Getting Started With the ASP.NET Core MVC Template](../../get-started/layered-web-application.md) for more information.
## Tiered Structure **\***
If you have selected the ASP.NET Core UI and specified the `--tiered` option, the solution created will be a tiered solution. The purpose of the tiered structure is to be able to **deploy Web applications and HTTP API to different servers**:
![tiered-solution](images/tiered-solution-servers.png)
* Browser runs your UI by executing HTML, CSS & JavaScript.
* Web servers host static UI files (CSS, JavaScript, image... etc.) & dynamic components (e.g. Razor pages). It performs HTTP requests to the API server to execute the business logic of the application.
* The API Server hosts the HTTP APIs which then use the application & domain layers of the application to perform the business logic.
* Finally, database server hosts your database.
> Unless you actually need such a 4-tiered deployment, it's suggested to go with the default structure which is simpler to develop, deploy and maintain.
The solution structure is shown below:
![bookstore-solution-tiered](images/bookstore-solution-tiered.png)
As different from the default structure, two new projects come into play: `.AuthServer` & `.HttpApi.Host`.
### .AuthServer Project
This project is used as an authentication server for other projects. `.Web` 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 HTTP API server. HTTP API server uses bearer token authentication to obtain claims from the access token to authorize the current user.
![tiered-solution-applications](images/tiered-solution-applications-authserver.png)
ABP uses the [OpenIddict Module](../../modules/openiddict.md) that uses the open-source [OpenIddict-core](https://github.com/openiddict/openiddict-core) library for the authentication between applications. See [OpenIddict documentation](https://documentation.openiddict.com/) for details about the OpenIddict and OpenID Connect protocol.
It has its own `appsettings.json` that contains database connection and other configurations.
### .HttpApi.Host Project
This project is an application that hosts the API of the solution. It has its own `appsettings.json` that contains database connection and other configurations.
### .Web Project
Just like the default structure, this project contains the User Interface (UI) of the application. It contains razor pages, JavaScript files, style files, images and so on...
This project contains an `appsettings.json` file, but this time it does not have a connection string because it never connects to the database. Instead, it mainly contains the endpoint of the remote API server and the authentication server.
### How to Run?
You can open the [Solution Runner](../../studio/running-applications.md) panel and start the all applications. The default username is `admin` and the password is `1q2w3E*`.
![run-solution-tiered](images/run-solution-tiered.png)

19
docs/en/solution-templates/layered-web-application/swagger-integration.md

@ -0,0 +1,19 @@
# Layered Solution: Swagger Integration
```json
//[doc-nav]
{
"Previous": {
"Name": "Logging (with Serilog)",
"Path": "solution-templates/layered-web-application/logging"
},
"Next": {
"Name": "Multi-Tenancy",
"Path": "solution-templates/layered-web-application/multi-tenancy"
}
}
```
[Swagger](https://swagger.io/) is a tool that helps to create, document, and consume RESTful web services. It provides a user interface to interact with the APIs and also a way to generate client SDKs for the APIs.
In the [Swagger Integration](../../framework/api-development/swagger.md) document, you can find general information about Swagger integration with ABP Framework.

178
docs/en/solution-templates/layered-web-application/web-applications.md

@ -0,0 +1,178 @@
# Layered Solution: Web Applications
````json
//[doc-nav]
{
"Previous": {
"Name": "Main Components",
"Path": "solution-templates/layered-web-application/main-components"
},
"Next": {
"Name": "Db Migrator",
"Path": "solution-templates/layered-web-application/db-migrator"
}
}
````
> Some of the features mentioned in this document may not be available in the free version. We're using the **\*** symbol to indicate that a feature is available in the **[Team](https://abp.io/pricing)** and **[Higher](https://abp.io/pricing)** licenses.
The web applications are the main user interfaces of the solution. They are the entry points for users to interact with the system. The Layered Solution Template supports the following web applications:
- **MVC / Razor Pages**: This is an ASP.NET Core MVC application. It is a traditional web application that serves HTML pages to users and is suitable for building web applications with server-side rendering.
- **Angular**: This is an Angular application, a single-page application (SPA) that runs on the client side. It communicates with the server using HTTP requests and is ideal for building modern web applications with rich user interfaces.
- **Blazor UI**: A flexible framework for building web applications with .NET. It supports various hosting models:
- **Blazor WebAssembly**: This is a client-side SPA that runs entirely in the user's browser. It communicates with the server using HTTP requests and is suitable for modern web applications with rich interactivity and offline capabilities.
- **Blazor Server**: This is a server-side SPA that runs on the server and communicates with the client in real time using SignalR. It is ideal for applications requiring constant connectivity and rapid server updates.
- **Blazor WebApp**: This is a combination of Blazor technologies optimized for building hybrid web applications that can leverage both client-side and server-side capabilities.
- **Maui Blazor (Hybrid)** **\***: This enables building cross-platform applications that combine Blazor for the UI with .NET MAUI for native device integration. It is suitable for building apps that work across desktop and mobile platforms.
- **No UI**: This option creates a backend-only solution without a web interface, suitable for scenarios like API-only applications or headless services.
You can select the web application type that fits your requirements during the solution creation process in the *UI Framework* step. The Layered Solution Template generates the selected web applications with the necessary configurations and integrations.
![Web Applications](images/web-applications.png)
## MVC / Razor Pages
MVC (Model-View-Controller) is a design pattern commonly used for building web applications. Razor Pages, on the other hand, is a page-based programming model designed to make building web applications simpler and more productive.
When you select the MVC / Razor Pages option in the Layered Solution Template, it generates an ASP.NET Core MVC application named something like `Acme.BookStore.Web`. This application serves as the web interface for your solution, using server-side rendering to deliver dynamic HTML pages to users.
## Angular
Angular is a popular front-end framework for building single-page applications (SPAs). It offers a rich set of features for creating modern web applications with dynamic and interactive user interfaces.
When you select the Angular option in the Layered Solution Template, it generates:
- An Angular application located under the solution's root folder, typically named `angular`.
- An ASP.NET Core application, usually named something like `Acme.Bookstore.HttpApi.Host`.
The Angular application runs as a client-side SPA in the user's browser and communicates with the server by sending HTTP requests to the `*.HttpApi.Host` application.
![angular-folder-structure](images/angular-folder-structure.png)
Each of ABP modules is an NPM package. Some ABP modules are added as a dependency in `package.json`. These modules install with their dependencies. To see all ABP packages, you can run the following command in the `angular` folder:
```bash
yarn list --pattern abp
```
Angular application module structure:
![Angular template structure diagram](images/angular-template-structure-diagram.png)
### AppModule
`AppModule` is the root module of the application. Some of the ABP modules and some essential modules are imported to `AppModule`.
ABP Config modules have also been imported to `AppModule` for initial requirements of the lazy-loadable ABP modules.
### AppRoutingModule
There are lazy-loadable ABP modules in the `AppRoutingModule` as routes.
> Paths of ABP Modules should not be changed.
You should add `routes` property in the `data` object to add a link on the menu to redirect to your custom pages.
```js
{
path: 'dashboard',
loadChildren: () => import('./dashboard/dashboard.module').then(m => m.DashboardModule),
canActivate: [authGuard, permissionGuard],
data: {
routes: {
name: 'ProjectName::Menu:Dashboard',
order: 2,
iconClass: 'fa fa-dashboard',
requiredPolicy: 'ProjectName.Dashboard.Host'
} as ABP.Route
}
}
```
In the above example;
* If the user is not logged in, authGuard blocks access and redirects to the login page.
* permissionGuard checks the user's permission with the `requiredPolicy` property of the `routes` object. If the user is not authorized to access the page, the 403 page appears.
* The `name` property of `routes` is the menu link label. A localization key can be defined.
* The `iconClass` property of the `routes` object is the menu link icon class.
* The `requiredPolicy` property of the `routes` object is the required policy key to access the page.
After the above `routes` definition, if the user is authorized, the dashboard link will appear on the menu.
### Shared Module
The modules that may be required for all modules have been imported to the `SharedModule`. You should import `SharedModule` to all modules.
See the [Sharing Modules](https://angular.io/guide/sharing-ngmodules) document.
### Environments
The files under the `src/environments` folder have the essential configuration of the application.
### Home Module
Home module is an example lazy-loadable module that loads on the root address of the application.
### Styles
The required style files are added to the `styles` array in `angular.json`. `AppComponent` loads some style files lazily via `LazyLoadService` after the main bundle is loaded to shorten the first rendering time.
### Testing
You should create your tests in the same folder as the file you want to test.
See the [testing document](https://angular.io/guide/testing).
### Depended Packages
* [NG Bootstrap](https://ng-bootstrap.github.io/) is used as UI component library.
* [NGXS](https://www.ngxs.io/) is used as state management library.
* [angular-oauth2-oidc](https://github.com/manfredsteyer/angular-oauth2-oidc) is used to support for OAuth 2 and OpenId Connect (OIDC).
* [Chart.js](https://www.chartjs.org/) is used to create widgets.
* [ngx-validate](https://github.com/ng-turkey/ngx-validate) is used for dynamic validation of reactive forms.
## Blazor UI
Blazor is a flexible framework for building web applications with .NET. It supports various hosting models, including Blazor WebAssembly, Blazor Server, Blazor WebApp, and Maui Blazor (Hybrid).
### Blazor WebAssembly
Blazor WebAssembly is a client-side SPA that runs entirely in the user's browser. It communicates with the server using HTTP requests and is suitable for modern web applications with rich interactivity and offline capabilities.
When you select the Blazor WebAssembly option in the Layered Solution Template, it generates:
- A Blazor application located under the solution's root folder, typically named `*.Blazor`, which serves as the main Blazor host project.
- A Blazor client application, named `*.Blazor.Client`, where you can write the client-side (UI logic) code.
- An ASP.NET Core application, named `*.HttpApi.Host`, where the server-side (business logic) code runs.
The Blazor client application communicates with the server by sending HTTP requests to the `*.HttpApi.Host` application.
### Blazor Server
Blazor Server is a server-side SPA that runs on the server and communicates with the client in real time using SignalR. It is ideal for applications requiring constant connectivity and rapid server updates.
When you select the Blazor Server option in the Layered Solution Template, it generates:
- A Blazor application located under the solution's root folder, typically named `*.Blazor`, which serves as the main Blazor host project.
### Blazor WebApp
Blazor WebApp is a combination of Blazor technologies optimized for building hybrid web applications that can leverage both client-side and server-side capabilities.
When you select the Blazor WebApp option in the Layered Solution Template, it generates:
- A Blazor application located under the solution's root folder, typically named `*.Blazor`, which serves as the main Blazor host project.
- A Blazor client application, named `*.Blazor.Client`, where you can write the client-side (UI logic) code.
The Blazor client application communicates with the server by sending HTTP requests to the `*.Blazor` application.
### Maui Blazor (Hybrid) **\***
Maui Blazor (Hybrid) enables building cross-platform applications that combine Blazor for the UI with .NET MAUI for native device integration. It is suitable for building apps that work across desktop and mobile platforms.
When you select the Maui Blazor (Hybrid) option in the Layered Solution Template, it generates:
- A Maui Blazor (Hybrid) application located under the solution's root folder, typically named `*.MauiBlazor`, which serves as the main UI host project.
- An ASP.NET Core application, named `*.HttpApi.Host`, where the server-side (business logic) code runs.
The Maui Blazor (Hybrid) application communicates with the server by sending HTTP requests to the `*.HttpApi.Host` application.
## No UI
This option creates a backend-only solution without a web interface, suitable for scenarios like API-only applications or headless services.
When you select the No UI option in the Layered Solution Template, it generates an ASP.NET Core application named `*.HttpApi.Host` that serves as the backend API for your solution.

4
docs/en/solution-templates/microservice/microservices.md

@ -12,7 +12,7 @@
> You must have an ABP Business or a higher license to be able to create a microservice solution.
The ABP Studio Microservice solution consists of a few microservices at the beginning. It is expected that you [add more microservices](guides/add-new-microservice.md) as your solution grows. This document briefly explains the structure of pre-built microservices in the solution.
The ABP Studio Microservice solution consists of a few microservices at the beginning. It is expected that you [add more microservices](adding-new-microservices.md) as your solution grows. This document briefly explains the structure of pre-built microservices in the solution.
The microservice count varies based on the options you've selected during the solution creation. However, the following microservices are always included:
@ -41,7 +41,7 @@ Let's explain the projects:
* `Acme.CloudCrm.AdministrationService.Contracts` contains service interfaces and data transfer objects of your service. It is useful to separate contracts. In this way, you can share the *Contracts* package with the clients, so they can easily consume your services. See the [communication](communication.md) document to learn how to do it.
* `Acme.CloudCrm.AdministrationService.Tests` contains the unit and integration tests for that microservice. While it is highly suggested to build tests for your services, you can delete that project if you don't want to write tests.
> We haven't applied **layering** for the pre-built microservices, because they don't include much code and no need for such complexity. Microservices should be small (micro!) services, so you typically can manage your codebase in a single project/layer. However, if you want to implement layering for your microservices, you can create a layered microservice by following the *[Adding New Microservice](guides/add-new-microservice.md)* guide.
> We haven't applied **layering** for the pre-built microservices, because they don't include much code and no need for such complexity. Microservices should be small (micro!) services, so you typically can manage your codebase in a single project/layer. However, if you want to implement layering for your microservices, you can create a layered microservice by following the *[Adding New Microservice](adding-new-microservices.md)* guide.
Next sections introduces and explains the pre-build services of the solution.

BIN
docs/en/studio/images/solution-runner/cli-application-context-menu.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 13 KiB

BIN
docs/en/studio/images/solution-runner/csharp-application-context-menu-build.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 37 KiB

After

Width:  |  Height:  |  Size: 27 KiB

BIN
docs/en/studio/images/solution-runner/csharp-application-context-menu-monitor.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 KiB

After

Width:  |  Height:  |  Size: 20 KiB

BIN
docs/en/studio/images/solution-runner/csharp-application-context-menu.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 47 KiB

After

Width:  |  Height:  |  Size: 22 KiB

BIN
docs/en/studio/images/solution-runner/folder-context-menu-add.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 14 KiB

BIN
docs/en/studio/images/solution-runner/folder-context-menu-build.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 14 KiB

BIN
docs/en/studio/images/solution-runner/folder-context-menu.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 14 KiB

BIN
docs/en/studio/images/solution-runner/manage-start-actions.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

BIN
docs/en/studio/images/solution-runner/profile-root-context-menu-add.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.1 KiB

After

Width:  |  Height:  |  Size: 10 KiB

BIN
docs/en/studio/images/solution-runner/profile-root-context-menu-build.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.7 KiB

After

Width:  |  Height:  |  Size: 6.5 KiB

BIN
docs/en/studio/images/solution-runner/profile-root-context-menu.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

BIN
docs/en/studio/images/solution-runner/solutioın-runner-properties.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 16 KiB

10
docs/en/studio/release-notes.md

@ -2,6 +2,16 @@
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.9.16 (2024-12-11)
> This version does not work for macOS, we are currently working on that manner.
* Added a new command for refreshing the previously runned C#/Js Proxies.
* Added kubernetes configurations to Blazor WebApp for Microservice Template.
* Handled multiple dbcontexts for ef core migration operations.
* Made enhancements for dynamic localization feature in Microservice Template.
* Upgraded LeptonX Theme package versions to `4.0.2`.
## 0.9.15 (2024-12-05)
* Upgraded templates to version `9.0.1`.

67
docs/en/studio/running-applications.md

@ -41,27 +41,22 @@ When you click *Add New Profile*, it opens the *Create New Profile* window. You
## Using the Profile
After selecting the current profile, which is the *Default* profile that comes pre-configured, we can utilize the tree items. This allows us to execute collective commands and create various tree structures based on our specific needs. You can navigate through the root of the tree and right-click to view the context menu, which includes 3 options: `Run`, `Build` and `Add`.
After selecting the current profile, which is the *Default* profile that comes pre-configured, we can utilize the tree items. This allows us to execute collective commands and create various tree structures based on our specific needs. You can navigate through the root of the tree and right-click to view the context menu, which includes the following options: `Start All`, `Stop All`, `Build`, `Add`, and `Manage Start Actions`.
![profile-root-context-menu](images/solution-runner/profile-root-context-menu.png)
### Run
### Start/Stop All
We can start/stop the applications with this option. Go to root of the tree and right-click to view the context menu, in this example *Acme.Bookstore(Default)* -> *Run*.
![profile-root-context-menu-run](images/solution-runner/profile-root-context-menu-run.png)
We can start/stop the applications with these options. Go to the root of the tree and right-click to view the context menu:
- `Start All`: Start all(CLI, C#) applications.
- `Stop All`: Stop all(CLI, C#) applications.
- `Build & Start All`: Builds each C# application in the [Background Tasks](./overview#background-tasks) and starts all (CLI, C#) applications after the build tasks are completed.
> `Start All` doesn't build the C# applications before running. If you're running it for the first time or if you've made changes, you should build the applications. You can simply use the `Build & Start All`.
> You can change the current profile while applications are running in the previous profile. The applications continue to run under the previous profile. For example if we start the `Acme.BookStore.AdministrationService`, `Acme.BookStore.IdentityService` applications when current profile is *team-1* and after change the current profile to *team-2* the applications continue to run under *team-1*.
> You can change the current profile while applications are running in the previous profile. The applications continue to run under the previous profile. For example, if we start the `Acme.BookStore.AdministrationService`, `Acme.BookStore.IdentityService` applications when the current profile is *team-1* and after changing the current profile to *team-2* the applications continue to run under *team-1*.
### Build
We can use common [dotnet](https://learn.microsoft.com/en-us/dotnet/core/tools) commands in this option. Go to root of the tree and right-click to view the context menu, in this example *Acme.Bookstore(Default)* -> *Build*, there are 4 options available:
We can use common [dotnet](https://learn.microsoft.com/en-us/dotnet/core/tools) commands in this option. Go to the root of the tree and right-click to view the context menu, in this example *Acme.Bookstore(Default)* -> *Build*, there are 4 options available:
![profile-root-context-menu-build](images/solution-runner/profile-root-context-menu-build.png)
@ -80,7 +75,7 @@ We can add 3 different item type to *Profile* for defining the tree structure. T
#### C# Application
When we go to root of the tree and right-click, in this example *Acme.BookStore(Default)* -> *Add* -> *C# Application* it opens the *Add Application* window. There are two methods to add applications: *This solution* and *External*. To add via the *This solution* tab, follow these steps:
When we go to the root of the tree and right-click, in this example *Acme.BookStore(Default)* -> *Add* -> *C# Application* it opens the *Add Application* window. There are two methods to add applications: *This solution* and *External*. To add via the *This solution* tab, follow these steps:
![profile-root-add-csharp-application](images/solution-runner/profile-root-add-csharp-application.png)
@ -98,7 +93,7 @@ The C# project doesn't have to be within the current [Solution Explorer](./solut
- `Path`: Provide the path to the .csproj file you wish to add. The path will be [normalized](https://learn.microsoft.com/en-us/dotnet/standard/io/file-path-formats#path-normalization), allowing the project location to be flexible, as long as it's accessible from the current [ABP Solution](./concepts.md#solution).
- `Name`: Give an arbitrary name to see in solution runner. This name should be unique for each profile.
- `Launch url`: Is the url when we want to browse. But if added project doesn't have launch url we can leave it empty.
- `Launch url`: This is the url when we want to browse. But if the added project doesn't have launch url we can leave it empty.
- `Kubernetes service`: If you're not using the *Kubernetes* panel leave it empty. But if there is a helm chart for added application we should give the correct regex pattern. It's necessary for browse, when we connect the kubernetes cluster we should browse the services instead *Launch url*. Give the matching regex pattern for your helm chart kubernetes service name.
You can click the `OK` button to add the C# application to the profile.
@ -137,17 +132,27 @@ You can click the `OK` button to add the folder to the profile.
- To remove a folder from the tree, open the context menu by right-clicking the folder and selecting *Delete*.
- When starting applications, they continue to restart until the application starts gracefully. To stop the restarting process when attempting to restart the application, click the icon on the left. Additionally, you can review the *Logs* to understand why the application isn't starting gracefully.
### Manage Start Actions
This command will open a dialog where you can set start actions and start orders of sub-applications and sub-folders.
![manage-start-actions](images/solution-runner/manage-start-actions.png)
You can order the applications by dragging the icon in the first column. In the screenshot above, applications & folders are ordered like this: *Applications under infrastructure* > *Applications under services* > *Applications under gateways* > *AuthServer* > *Angular*. You can also set starting order and other actions for each folder by performing `right click > Manage Start Actions` on them.
- **Action**: There are two options: `Start` and `Don't start`. This is usefull if you want to exclude applications from batch start.
- **Build**: This option allows to disable/enable build before starting the application. If you are working on a single application, you can exclude the other applications from build to save time. This option can also be set by performing `right click > properties` on applications.
- **Watch**: When enabled, changes in your code are watched and dotnet hot-reloads the application or restarts it if needed. This option also can be set by performing `right click > properties` on applications.
## Folder
We already now why we need folder in the [previous](./running-applications.md#folder) section, we can use collective commands within this folder items. To do that go to folder and open the context menu by right-clicking, which includes 5 options `Start`, `Build`, `Add`, `Rename` and `Delete`.
We already now why we need folder in the [previous](./running-applications.md#folder) section, we can use collective commands within this folder items. To do that go to folder and open the context menu by right-clicking, which includes 5 options `Start`, `Stop`, `Build`, `Add`, `Manage Start Actions`, `Rename` and `Delete`.
![folder-context-menu](images/solution-runner/folder-context-menu.png)
### Start
You can see the context menu by right-clicking *Folder* -> *Start*, it's [similar](#run) like *Acme.BookStore(Default)* -> *Run* options, there are 3 options available. The only difference with root of the tree and folder is gonna be execute in selected folder.
### Start/Stop
![folder-context-menu-start](images/solution-runner/folder-context-menu-start.png)
You can see the context menu by right-clicking *Folder*. It will start/stop all the applications under the folder.
### Build
@ -157,7 +162,7 @@ You can see the context menu by right-clicking *Folder* -> *Start*, it's [simila
### Add
*Folder* -> *Add* context menu, it's the [same](#add) options like *Acme.BookStore(Default)* -> *Add* there are 3 options avaiable. The only difference, it's gonna add item to selected folder.
*Folder* -> *Add* context menu, it's the [same](#add) options like *Acme.BookStore(Default)* -> *Add* there are 3 options avaiable. The only difference, it's gonna add item to the selected folder.
![folder-context-menu-add](images/solution-runner/folder-context-menu-add.png)
@ -168,29 +173,16 @@ You can see the context menu by right-clicking *Folder* -> *Start*, it's [simila
## C# Application
The .NET icon indicates that the application is a C# project. After we [add](#c-application) the C# applications to root of the tree or folder, we can go to any C# application and right-click to view the context menu; `Run`, `Build`, `Browse`, `Requests`, `Exceptions`, `Logs`, `Copy URL`, `Properties`, `Remove`.
The .NET icon indicates that the application is a C# project. After we [add](#c-application) the C# applications to the root of the tree or folder, we can go to any C# application and right-click to view the context menu; `Start`, `Build`, `Browse`, `Requests`, `Exceptions`, `Logs`, `Copy URL`, `Properties`, `Remove`.
![csharp-application-context-menu](images/solution-runner/csharp-application-context-menu.png)
### Run
We have several options in C# applications. Those options are `Start`(If the application started this option shown as `Stop`), `Build & Start`(If the application started this option shown as `Build & Restart`), `Enable Watch`(If the watch is enabled this option shown as `Disable Watch`), `Restart`(It's only shown when the application started)
![csharp-application-context-menu-run](images/solution-runner/csharp-application-context-menu-run.png)
### Start
- `Start`: Starts the selected application. This option doesn't build before run. If you're running it for the first time or if you've made changes, you should build the application. If the application is started this option changed as `Stop`.
- `Build & Start`: We can simply use if we wanna build first and start. If the application is started this option changes to `Build & Restart`.
- `Enable Watch`: When this option is enabled, there's no need to perform `Build & Start` after any change. ABP Studio watches for changes, re-builds, and re-runs your application automatically upon saving. If this option is enabled it changes to `Disable Watch`.
- `Restart`: Restarts the application. This option visible only if the application started.
Starts the selected application. Once it is started, *Stop* and *Restart* options will be available.
> When you start the C# application, you should see a *chain* icon next to the application name, that means the started application connected to ABP Studio. C# applications can connect to ABP Studio even when running from outside the ABP Studio environment, for example debugging with Visual Studio. If the application is run from outside the ABP Studio environment, it will display *(external)* information next to the chain icon.
> When *Watch* is enable you should see an *eye* icon next to the application name.
> Hint: Performing CTRL+Click on the start icon left to a stopped C# application equals to `Build & Start` command. Same applies for folders.
![csharp-application-context-menu-run-connection](images/solution-runner/csharp-application-context-menu-run-connection.png)
### Build
It's the [similar](#build) options like root of the tree options. The only difference between them it's gonna be execute the selected application.
@ -214,7 +206,10 @@ We can open the *Application Properties* window to change *Launch url*, *Kuberne
![solutioın-runner-properties](images/solution-runner/solutioın-runner-properties.png)
You can click the `OK` button to save the changes.
- **Skip build before starting**: When enabled, application is started without build and it makes starting faster. This is useful when you are working on a single application out of multiple, so you don't need to build others everytime they start.
- **Watch changes while running**: When enabled, you should see an *eye* icon next to the application name.
![csharp-application-context-menu-run-connection](images/solution-runner/csharp-application-context-menu-run-connection.png)
### Miscellaneous
@ -228,7 +223,7 @@ CLI applications uses the [powershell](https://learn.microsoft.com/en-us/powersh
![cli-application-context-menu](images/solution-runner/cli-application-context-menu.png)
- `Run`: This option includes 3 actions: *Start*, *Stop*, and *Restart* for the CLI application.
- `Start`: Starts the application. Once it is started, *Start* and *Restart* options will be available.
- `Browse`: This option is available when a *Launch URL* is specified upon adding the CLI application. It opens the *Browse* tab, can be clicked while the application is running.
- `Logs`: It opens the *Logs* tab, we can see the logs for *Start* and *Stop* commands.
- `Copy URL`: This option copies the *Launch URL* of the selected application. It is visible if there is a specified *Launch URL*

2
docs/en/studio/version-mapping.md

@ -4,7 +4,7 @@ This document provides a general overview of the relationship between various ve
| **ABP Studio Version** | **ABP Version of Startup Template** |
|------------------------|---------------------------|
| 0.9.15 | 9.0.1 |
| 0.9.15 - 0.9.16 | 9.0.1 |
| 0.9.9 to 0.9.14 | 9.0.0 |
| 0.9.8 | 8.3.4 |
| 0.9.5 to 0.9.7 | 8.3.3 |

18
docs/en/suite/how-to-start.md

@ -26,4 +26,20 @@ abp suite
If you run the ABP Suite with ABP CLI, then it will open in your default browser. Do not close the command line window until you finish your work, otherwise the Suite will not function. When you finish your work, you can return to the command line and press `CTRL+C` to close the Suite.
Remember that, first access to the Suite requires to have an active internet connection, so make sure you are connected to the internet.
Remember that, first access to the Suite requires to have an active internet connection, so make sure you are connected to the internet.
## Starting ABP Suite in Different Port
ABP Suite runs at port 3000 by default. If you want to run the ABP Suite in a different port, you can choose one of the following options:
1. You can pass the `--AbpSuite:ApplicationUrl` commandline parameter to run in a different port:
```bash
abp-suite --AbpSuite:ApplicationUrl="http://localhost:4000"
```
2. Update the `ApplicationUrl` in the _appsettings.json_ file of the dotnet tools directory (_%USERPROFILE%\.dotnet\tools\.store\volo.abp.suite\9.0.0\volo.abp.suite\9.0.0\tools\net9.0\any\appsettings.json_):
![suite-registry](../images/suite-registry.png)
> **Note:** Also, you can use this file to configure ABP Suite options.

7
docs/en/tutorials/book-store-with-abp-suite/part-01.md

@ -10,6 +10,10 @@
````json
//[doc-nav]
{
"Previous": {
"Name": "Overview",
"Path": "tutorials/book-store-with-abp-suite/index"
},
"Next": {
"Name": "Creating the Books",
"Path": "tutorials/book-store-with-abp-suite/part-02"
@ -21,11 +25,14 @@ Before starting the development, create a new solution named `Acme.BookStore` an
You can use the following configurations:
* **Solution Template:** Application (Layered)
* **Solution Name:** `Acme.BookStore`
* **UI Framework:** {{if UI=="MVC"}} ASP.NET Core MVC / Razor Pages {{end}}
* **UI Theme:** LeptonX
* **Mobile Framework:** None
* **Database Provider:** {{if DB=="EF"}} Entity Framework Core {{end}}
* **Public Website:** No
* **Tiered:** No
You can select the other options based on your preference.

62
docs/en/tutorials/book-store-with-abp-suite/part-02.md

@ -36,7 +36,28 @@ After clicking the related command, pre-integrated browser of ABP Studio should
## Creating the Book Entity
Let's create a `Book` entity with some properties. First, type `Book` for the *Name* field and leave the other options as is. ABP Suite automatically calculates proper values for the rest of the inputs for you:
Before creating the `Book` entity, first we can create a `BookType` enum in the `Acme.BookStore.Domain.Shared` project under the **Books** folder as follows:
```csharp
namespace Acme.BookStore.Books;
public enum BookType
{
Undefined,
Adventure,
Biography,
Dystopia,
Fantastic,
Horror,
Science,
ScienceFiction,
Poetry
}
```
After creating an _enum_ file in your project, you can define it as a property while creating the entity. ABP Suite asks for an enum path to read the enum file, and set the namespace, and enum name in the generated code accordingly. Then, you can create the `Book` entity with some properties.
Type `Book` for the *Name* field and leave the other options as is. ABP Suite automatically calculates proper values for the rest of the inputs for you:
![](./images/suite-book-entity-1.png)
@ -55,10 +76,16 @@ After, specifying the entity metadata, open the *Properties* tab and create the
![](./images/suite-book-entity-3.png)
Here the details:
While defining the properties, you define a *Type* property with the type of *enum*. ABP Suite asks for an enum path and fill the all other inputs by reading the specified enum file. Therefore, you can specify the enum path for the `Type` property like in the following figure:
![](./images/suite-book-entity-4.png)
> After you select the enum file, ABP Suite automatically sets the namespace and enum name, and lists your enum values in the next section. You can change these values, but for now, you can leave as is.
Here is the all details for the `Book` entity:
* `Name` is **required**, it's a **string** property and maximum length is **128**.
* `Type` is an **enum** and the enum file path is *\Acme.BookStore.Domain.Shared\Books\BookType.cs* (we will create the file, in the next section).
* `Type` is an **enum** and the enum file path is *\Acme.BookStore.Domain.Shared\Books\BookType.cs*.
* `PublishDate` is a **DateTime** property and **not nullable**.
* `Price` is a **float** property and **required**.
@ -66,33 +93,6 @@ You can leave the other configurations as default.
> ABP Suite allows you to define properties with a great range of options, for example, you can specify the property type as *string*, *int*, *float*, *Guid*, *DateTime*, and even *File* (for file upload) and also you can set any options while defining your properties, such as specifying it as *required*, or *nullable*, setting *max-min length*, *default value* and more...
While defining the properties, you defined a *Type* property with the type of *enum*. ABP Suite asks for an enum path to read the enum file, and set the namespace, and enum name in the generated code.
For that purpose, you should create a `BookType` enum in the `Acme.BookStore.Domain.Shared` project under the **Books** folder as follows:
```csharp
namespace Acme.BookStore.Books;
public enum BookType
{
Undefined,
Adventure,
Biography,
Dystopia,
Fantastic,
Horror,
Science,
ScienceFiction,
Poetry
}
```
Then, you can specify the enum path for the `Type` property in ABP Suite like in the following figure:
![](./images/suite-book-entity-4.png)
> After you select the enum file, ABP Suite automatically sets the namespace and enum name, and lists your enum values in the next section. You can change these values, but for now, you can leave as is.
After that, you can click the **Save and Generate** button to start the code generation process:
![](./images/suite-book-entity-5.png)
@ -106,7 +106,7 @@ ABP Suite will generate the necessary code for you. It generates:
* **Unit & integration tests**,
* A new **migration** (and also applies to the database),
* All related **permission**, **object mapping** and **navigation menu item** configurations,
* and all required **UI components and pages**.
* and all required **UI components and pages**...
It will take some time to complete the process. After the process is completed, you will see a success message, you can click the *Ok* button, and build & start the application by clicking the *Run -> Build & Start* button in the *Solution Runner* panel:

4
docs/en/tutorials/book-store-with-abp-suite/part-03.md

@ -50,9 +50,9 @@ After, specifying the entity metadata, open the *Properties* tab and create the
Here the details:
* `Name` is **required**, it's a **string** property, and it's a **textarea**. Minimum length is **2** and maximum length is **128**.
* `Name` is **required**, it's a **string** property. Minimum length is **2** and maximum length is **128**.
* `BirthDate` is a **DateTime** property and **not nullable**.
* `ShortBio` is a **string** property, it's **required**, maximum length is **256**.
* `ShortBio` is **required**, it's a **string** property, it's a **textarea**, maximum length is **256**.
You can leave the other configurations as default.

2
docs/en/tutorials/book-store-with-abp-suite/part-04.md

@ -49,6 +49,8 @@ Here is the details:
* Selected the display property as *Name*, this will be used in the dropdown component to set an author with a book & also it will be shown in the datatable of the *Books* page.
* Also, made the relation **required** and set it **filterable** so books can be filterable by authors.
> **Note**: You should delete all existing books in the database (if any), before the code generation. Because, a new foreign-key will be added to the _books_ table and if there is any record in the table, then a new migration can't apply to the database and you may need to update the database manually.
After, specifying the metadata, you can click the *Ok* button to close the modal. Then, click the **Save and generate** button to start code generation process. ABP Suite will establish one-to-many relationship between the entities, and will generate all necessary code automatically:
![](./images/suite-end-of-generation-modal.png)

12
docs/en/tutorials/book-store/part-02.md

@ -577,8 +577,6 @@ Open the `Books.razor` and replace the content as the following:
@using Volo.Abp.Application.Dtos
@using Acme.BookStore.Books
@using Acme.BookStore.Localization
@using Microsoft.Extensions.Localization
@inject IStringLocalizer<BookStoreResource> L
@inherits AbpCrudPageBase<IBookAppService, BookDto, Guid, PagedAndSortedResultRequestDto, CreateUpdateBookDto>
<Card>
@ -625,13 +623,21 @@ Open the `Books.razor` and replace the content as the following:
</DataGrid>
</CardBody>
</Card>
@code
{
public Books() // Constructor
{
LocalizationResource = typeof(BookStoreResource);
}
}
````
> If you see some syntax errors, you can ignore them if your application is properly built and running. Visual Studio still has some bugs with Blazor.
* Inherited from `AbpCrudPageBase<IBookAppService, BookDto, Guid, PagedAndSortedResultRequestDto, CreateUpdateBookDto>` which implements all the CRUD details for us.
* `Entities`, `TotalCount`, `PageSize`, `OnDataGridReadAsync` are defined in the base class.
* Injected `IStringLocalizer<BookStoreResource>` (as `L` object) and used for localization.
* `LocalizationResource` is set to the `BookStoreResource` to localize the texts.
While the code above is pretty easy to understand, you can check the Blazorise [Card](https://blazorise.com/docs/components/card/) and [DataGrid](https://blazorise.com/docs/extensions/datagrid/) documents to understand them better.

11
docs/en/tutorials/book-store/part-03.md

@ -1351,7 +1351,6 @@ Here's the complete code to create the book management CRUD page, that has been
@using Acme.BookStore.Localization
@using Microsoft.Extensions.Localization
@using Volo.Abp.AspNetCore.Components.Web
@inject IStringLocalizer<BookStoreResource> L
@inject AbpBlazorMessageLocalizerHelper<BookStoreResource> LH
@inherits AbpCrudPageBase<IBookAppService, BookDto, Guid, PagedAndSortedResultRequestDto, CreateUpdateBookDto>
@ -1396,7 +1395,7 @@ Here's the complete code to create the book management CRUD page, that has been
Field="@nameof(BookDto.Type)"
Caption="@L["Type"]">
<DisplayTemplate>
@L[$"Enum:BookType.{context.Type}"]
@L[$"Enum:BookType.{context.Type:D}"]
</DisplayTemplate>
</DataGridColumn>
<DataGridColumn TItem="BookDto"
@ -1527,6 +1526,14 @@ Here's the complete code to create the book management CRUD page, that has been
</Form>
</ModalContent>
</Modal>
@code
{
public Books() // Constructor
{
LocalizationResource = typeof(BookStoreResource);
}
}
````
{{end}}

28
docs/en/tutorials/book-store/part-05.md

@ -420,6 +420,8 @@ Add the following code block to the end of the `Books.razor` file:
{
public Books() // Constructor
{
LocalizationResource = typeof(BookStoreResource);
CreatePolicyName = BookStorePermissions.Books.Create;
UpdatePolicyName = BookStorePermissions.Books.Edit;
DeletePolicyName = BookStorePermissions.Books.Delete;
@ -509,14 +511,11 @@ var bookStoreMenu = new ApplicationMenuItem(
context.Menu.AddItem(bookStoreMenu);
//CHECK the PERMISSION
if (await context.IsGrantedAsync(BookStorePermissions.Books.Default))
{
bookStoreMenu.AddItem(new ApplicationMenuItem(
"BooksStore.Books",
l["Menu:Books"],
url: "/books"
));
}
bookStoreMenu.AddItem(new ApplicationMenuItem(
"BooksStore.Books",
l["Menu:Books"],
url: "/books"
).RequirePermissions(BookStorePermissions.Books.Default));
````
You also need to add `async` keyword to the `ConfigureMenuAsync` method and re-arrange the return value. The final `ConfigureMainMenuAsync` method should be the following:
@ -545,14 +544,11 @@ private async Task ConfigureMainMenuAsync(MenuConfigurationContext context)
context.Menu.AddItem(bookStoreMenu);
//CHECK the PERMISSION
if (await context.IsGrantedAsync(BookStorePermissions.Books.Default))
{
bookStoreMenu.AddItem(new ApplicationMenuItem(
"BooksStore.Books",
l["Menu:Books"],
url: "/books"
));
}
bookStoreMenu.AddItem(new ApplicationMenuItem(
"BooksStore.Books",
l["Menu:Books"],
url: "/books"
).RequirePermissions(BookStorePermissions.Books.Default));
}
````

2
docs/en/tutorials/book-store/part-06.md

@ -41,7 +41,6 @@ Create an `Authors` folder (namespace) in the `Acme.BookStore.Domain` project an
````csharp
using System;
using JetBrains.Annotations;
using Volo.Abp;
using Volo.Abp.Domain.Entities.Auditing;
@ -115,7 +114,6 @@ Created this class inside the `Acme.BookStore.Domain.Shared` project since we wi
````csharp
using System;
using System.Threading.Tasks;
using JetBrains.Annotations;
using Volo.Abp;
using Volo.Abp.Domain.Services;

7
docs/en/tutorials/book-store/part-09.md

@ -1214,14 +1214,11 @@ You will need to declare a `using Acme.BookStore.Authors;` statement to the begi
Open the `BookStoreMenuContributor.cs` in the {{ if UI == "BlazorServer" }}`Acme.BookStore.Blazor`{{ else }}`Acme.BookStore.Blazor.Client`{{ end }} project and add the following code to the end of the `ConfigureMainMenuAsync` method:
````csharp
if (await context.IsGrantedAsync(BookStorePermissions.Authors.Default))
{
context.Menu.AddItem(new ApplicationMenuItem(
context.Menu.AddItem(new ApplicationMenuItem(
"BooksStore.Authors",
l["Menu:Authors"],
url: "/authors"
));
}
).RequirePermissions(BookStorePermissions.Books.Default));
````
### Localizations

2
docs/en/tutorials/book-store/part-10.md

@ -1132,6 +1132,8 @@ The final `@code` block should be the following:
public Books() // Constructor
{
LocalizationResource = typeof(BookStoreResource);
CreatePolicyName = BookStorePermissions.Books.Create;
UpdatePolicyName = BookStorePermissions.Books.Edit;
DeletePolicyName = BookStorePermissions.Books.Delete;

2
docs/en/tutorials/microservice/part-03.md

@ -117,6 +117,8 @@ After the application is started, you can right-click and [Browse](../../studio/
> If you can't see the *Products* menu item, you need to grant the `CatalogService` *Product* permission to the *admin* role. You can do this by navigating to *Identity Management* -> *Roles* and editing the *admin* role. Alternatively, you can restart the *CloudCrm.AdministrationService* application to automatically seed all permissions for the *admin* role.
> When we create `Catalog` microservice, the `CatalogService` API scope is also created automatically if the "Enable integration" option is selected. You can verify the new scope in the `CloudCrm.IdentityService` module (.NET solution), in the `CloudCrm.IdentityService` project within the `OpenIddictDataSeeder` class's `CreateApiScopesAsync` method. If you are already logged in to the application, you may need to log out and log back in to reauthorize with the newly created API scope.
You can open the Sql Server Management Studio to see the created tables and data:
![sql-server-management-studio-products](images/sql-server-management-studio-products.png)

4
docs/en/tutorials/microservice/part-05.md

@ -118,7 +118,7 @@ In this code snippet, we configure the `Order` entity to use the `Orders` table
Now, we can add a new database migration. You can use Entity Framework Core's `Add-Migration` (or `dotnet ef migrations add`) terminal command, but in this tutorial, we will use ABP Studio's shortcut UI.
Ensure that the solution has built. You can right-click the `CloudCrm.OrderingService` (under the `services` folder) on ABP Studio *Solution Explorer* and select the *Dotnet CLI* -> *Graph Build* command.
Please stop the applications if they are running and ensure that the solution has built. You can right-click the `CloudCrm.OrderingService` (under the `services` folder) on ABP Studio *Solution Explorer* and select the *Dotnet CLI* -> *Graph Build* command.
Right-click the `CloudCrm.OrderingService` package and select the *EF Core CLI* -> *Add Migration* command:
@ -217,7 +217,7 @@ namespace CloudCrm.OrderingService.Services;
public class OrderAppService : ApplicationService, IOrderAppService
{
private readonly IRepository<Order> _orderRepository;
private readonly IRepository<Order, Guid> _orderRepository;
public OrderAppService(IRepository<Order, Guid> orderRepository)
{

33
docs/en/tutorials/microservice/part-06.md

@ -103,24 +103,6 @@ public class ProductIntegrationService : ApplicationService, IProductIntegration
> Here, we directly used `List<T>` classes, but instead, you could wrap inputs and outputs into [DTOs](../../framework/architecture/domain-driven-design/data-transfer-objects.md). In that way, it can be possible to add new properties to these DTOs without changing the signature of your integration service method (and without introducing breaking changes for your client applications).
### Exposing the Integration Service as an API
Integration services are not exposed as HTTP APIs by default. However, you can expose them as HTTP APIs if you need to. To do this, you should configure the `AbpAspNetCoreMvcOptions` in the `ConfigureServices` method of the `CloudCrmCatalogServiceModule`. Open the `CloudCrm.CatalogService` project and locate the `CloudCrmCatalogServiceModule` class. Add the following code to the `ConfigureServices` method:
```csharp
public override void ConfigureServices(ServiceConfigurationContext context)
{
// Other configurations...
Configure<AbpAspNetCoreMvcOptions>(options =>
{
options.ExposeIntegrationServices = true;
});
}
```
This code configures the `AbpAspNetCoreMvcOptions` to expose integration services as HTTP APIs. This is useful when you need to call the integration service from a different service using HTTP. You can learn more about this in the [Integration Services](../../framework/api-development/integration-services.md#exposing-integration-services) document.
## Consuming the Products Integration Service
Now that we have created the `IProductIntegrationService` interface and the `ProductIntegrationService` class, we can consume this service from the Ordering service.
@ -161,7 +143,7 @@ namespace CloudCrm.OrderingService.Services;
public class OrderAppService : ApplicationService, IOrderAppService
{
private readonly IRepository<Order> _orderRepository;
private readonly IRepository<Order, Guid> _orderRepository;
private readonly IProductIntegrationService _productIntegrationService;
public OrderAppService(
@ -274,6 +256,19 @@ We have generated the proxy classes for the `IProductIntegrationService` interfa
> **BaseUrl** refers to the base URL of the Catalog service. You can use the *Copy Url* option from the Catalog service's context menu in the ABP Studio **Solution Runner** to paste it here.
Lastly, open the `CloudCrmOrderingServiceModule` class (the `CloudCrmOrderingServiceModule.cs` file under the `CloudCrm.OrderingService` project of the `CloudCrm.OrderingService` .NET solution) and add the following code to the `ConfigureServices` method:
```csharp
public override void ConfigureServices(ServiceConfigurationContext context)
{
// Other configurations...
context.Services.AddStaticHttpClientProxies(
typeof(CloudCrmCatalogServiceContractsModule).Assembly,
"CatalogService");
}
```
### Updating the UI to Display the Product Name
Open the `Index.cshtml` file (the `Index.cshtml` file under the `Pages/Orders` folder of the `CloudCrm.Web` project of the `CloudCrm.Web` .NET solution) and update the table content to display the product name instead of the product ID:

8
docs/en/tutorials/microservice/part-07.md

@ -16,7 +16,7 @@ ABP provides two types of event buses for loosely coupled communication:
* [Local Event Bus](../../framework/infrastructure/event-bus/local/index.md) is suitable for in-process messaging. However, it’s not suitable for microservices as it cannot communicate across different processes. For distributed systems, consider using a distributed event bus.
* **[Distributed Event Bus](../../framework/infrastructure/event-bus/distributed/index.md)** is normal for inter-process messaging, like microservices, for publishing and subscribing to distributed events. However, ABP's distributed event bus works as local (in-process) by default (actually, it uses the Local Event Bus under the hood by default) unless you configure an external message broker.
* [Distributed Event Bus](../../framework/infrastructure/event-bus/distributed/index.md) is normal for inter-process messaging, like microservices, for publishing and subscribing to distributed events. However, ABP's distributed event bus works as local (in-process) by default (actually, it uses the Local Event Bus under the hood by default) unless you configure an external message broker.
In this tutorial, we will use the distributed event bus to communicate between the `Order` and `Catalog` microservices.
@ -64,7 +64,7 @@ namespace CloudCrm.OrderingService.Services;
public class OrderAppService : ApplicationService, IOrderAppService
{
private readonly IRepository<Order> _orderRepository;
private readonly IRepository<Order, Guid> _orderRepository;
private readonly IProductIntegrationService _productIntegrationService;
private readonly IDistributedEventBus _distributedEventBus;
@ -170,9 +170,9 @@ public class OrderEventHandler :
IDistributedEventHandler<OrderPlacedEto>,
ITransientDependency
{
private readonly IRepository<Product, Guid> _productRepository;
private readonly IProductRepository _productRepository;
public OrderEventHandler(IRepository<Product, Guid> productRepository)
public OrderEventHandler(IProductRepository productRepository)
{
_productRepository = productRepository;
}

2
docs/en/tutorials/modular-crm/part-05.md

@ -320,7 +320,7 @@ namespace ModularCrm.Ordering.Services;
public class OrderAppService : OrderingAppService, IOrderAppService
{
private readonly IRepository<Order> _orderRepository;
private readonly IRepository<Order, Guid> _orderRepository;
public OrderAppService(IRepository<Order, Guid> orderRepository)
{

2
docs/en/tutorials/modular-crm/part-06.md

@ -162,7 +162,7 @@ namespace ModularCrm.Ordering.Services;
public class OrderAppService : ApplicationService, IOrderAppService
{
private readonly IRepository<Order> _orderRepository;
private readonly IRepository<Order, Guid> _orderRepository;
private readonly IProductIntegrationService _productIntegrationService;
public OrderAppService(

6
docs/en/tutorials/modular-crm/part-07.md

@ -74,7 +74,7 @@ namespace ModularCrm.Ordering.Services;
public class OrderAppService : OrderingAppService, IOrderAppService
{
private readonly IRepository<Order> _orderRepository;
private readonly IRepository<Order, Guid> _orderRepository;
private readonly IProductIntegrationService _productIntegrationService;
private readonly IDistributedEventBus _distributedEventBus;
@ -184,9 +184,9 @@ namespace ModularCrm.Products.Orders
IDistributedEventHandler<OrderPlacedEto>,
ITransientDependency
{
private readonly IRepository<Product, Guid> _productRepository;
private readonly IProductRepository _productRepository;
public OrderEventHandler(IRepository<Product, Guid> productRepository)
public OrderEventHandler(IProductRepository productRepository)
{
_productRepository = productRepository;
}

1
docs/en/ui-themes/basic-theme/index.md

@ -0,0 +1 @@
Read this document [here](../../framework/ui/mvc-razor-pages/basic-theme.md).

14
framework/Volo.Abp.sln

@ -473,6 +473,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.BlobStoring.Google
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
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.Sms.TencentCloud", "src\Volo.Abp.Sms.TencentCloud\Volo.Abp.Sms.TencentCloud.csproj", "{BE7109C5-7368-4688-8557-4A15D3F4776A}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.Sms.TencentCloud.Tests", "test\Volo.Abp.Sms.TencenCloud.Tests\Volo.Abp.Sms.TencentCloud.Tests.csproj", "{C753DDD6-5699-45F8-8669-08CE0BB816DE}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -1411,6 +1415,14 @@ Global
{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
{BE7109C5-7368-4688-8557-4A15D3F4776A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{BE7109C5-7368-4688-8557-4A15D3F4776A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BE7109C5-7368-4688-8557-4A15D3F4776A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{BE7109C5-7368-4688-8557-4A15D3F4776A}.Release|Any CPU.Build.0 = Release|Any CPU
{C753DDD6-5699-45F8-8669-08CE0BB816DE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C753DDD6-5699-45F8-8669-08CE0BB816DE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C753DDD6-5699-45F8-8669-08CE0BB816DE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C753DDD6-5699-45F8-8669-08CE0BB816DE}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -1649,6 +1661,8 @@ Global
{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}
{BE7109C5-7368-4688-8557-4A15D3F4776A} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}
{C753DDD6-5699-45F8-8669-08CE0BB816DE} = {447C8A77-E5F0-4538-8687-7383196D04EA}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {BB97ECF4-9A84-433F-A80B-2A3285BDD1D5}

4
framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/Builder/AbpApplicationBuilderExtensions.cs

@ -177,14 +177,14 @@ public static class AbpApplicationBuilderExtensions
throw new AbpException("The app(IApplicationBuilder) is not an IEndpointRouteBuilder.");
}
app.UseVirtualStaticFiles();
var options = app.ApplicationServices.GetRequiredService<IOptions<AbpAspNetCoreContentOptions>>().Value;
foreach (var folder in options.AllowedExtraWebContentFolders)
{
app.UseVirtualStaticFiles(folder);
}
app.UseVirtualStaticFiles();
return endpoints.MapStaticAssets(staticAssetsManifestPath);
}

10
framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Auditing/AbpAspNetCoreAuditingUrlOptions.cs

@ -0,0 +1,10 @@
namespace Volo.Abp.AspNetCore.Auditing;
public class AbpAspNetCoreAuditingUrlOptions
{
public bool IncludeSchema { get; set; }
public bool IncludeHost { get; set; }
public bool IncludeQuery { get; set; }
}

35
framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Auditing/AspNetCoreAuditLogContributor.cs

@ -1,9 +1,11 @@
using System;
using System.Linq;
using System.Text;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.Extensions.Options;
using Volo.Abp.AspNetCore.ExceptionHandling;
using Volo.Abp.AspNetCore.WebClientInfo;
using Volo.Abp.Auditing;
@ -40,7 +42,7 @@ public class AspNetCoreAuditLogContributor : AuditLogContributor, ITransientDepe
if (context.AuditInfo.Url == null)
{
context.AuditInfo.Url = BuildUrl(httpContext);
context.AuditInfo.Url = GetUrl(context, httpContext);
}
var clientInfoProvider = context.ServiceProvider.GetRequiredService<IWebClientInfoProvider>();
@ -88,18 +90,29 @@ public class AspNetCoreAuditLogContributor : AuditLogContributor, ITransientDepe
context.AuditInfo.HttpStatusCode = httpContext.Response.StatusCode;
}
protected virtual string BuildUrl(HttpContext httpContext)
protected virtual string GetUrl(AuditLogContributionContext context, HttpContext httpContext)
{
//TODO: Add options to include/exclude query, schema and host
var options = context.ServiceProvider.GetRequiredService<IOptions<AbpAspNetCoreAuditingUrlOptions>>();
var stringBuilder = new StringBuilder();
var uriBuilder = new UriBuilder
if (options.Value.IncludeSchema)
{
Scheme = httpContext.Request.Scheme,
Host = httpContext.Request.Host.Host,
Path = httpContext.Request.Path.ToString(),
Query = httpContext.Request.QueryString.ToString()
};
return uriBuilder.Uri.AbsolutePath;
stringBuilder.Append(httpContext.Request.Scheme);
stringBuilder.Append("://");
}
if (options.Value.IncludeHost)
{
stringBuilder.Append(httpContext.Request.Host.Host);
}
stringBuilder.Append(httpContext.Request.Path.ToString());
if (options.Value.IncludeQuery)
{
stringBuilder.Append(httpContext.Request.QueryString.ToString());
}
return stringBuilder.ToString();
}
}

7
framework/src/Volo.Abp.BackgroundJobs/Volo/Abp/BackgroundJobs/AbpBackgroundJobWorkerOptions.cs

@ -33,6 +33,12 @@ public class AbpBackgroundJobWorkerOptions
/// </summary>
public double DefaultWaitFactor { get; set; }
/// <summary>
/// Distributed lock name for the worker.
/// Default value: "AbpBackgroundJobWorker".
/// </summary>
public string DistributedLockName { get; set; }
public AbpBackgroundJobWorkerOptions()
{
MaxJobFetchCount = 1000;
@ -40,5 +46,6 @@ public class AbpBackgroundJobWorkerOptions
DefaultFirstWaitDuration = 60;
DefaultTimeout = 172800;
DefaultWaitFactor = 2.0;
DistributedLockName = "AbpBackgroundJobWorker";
}
}

4
framework/src/Volo.Abp.BackgroundJobs/Volo/Abp/BackgroundJobs/BackgroundJobWorker.cs

@ -13,8 +13,6 @@ namespace Volo.Abp.BackgroundJobs;
public class BackgroundJobWorker : AsyncPeriodicBackgroundWorkerBase, IBackgroundJobWorker
{
protected const string DistributedLockName = "AbpBackgroundJobWorker";
protected AbpBackgroundJobOptions JobOptions { get; }
protected AbpBackgroundJobWorkerOptions WorkerOptions { get; }
@ -39,7 +37,7 @@ public class BackgroundJobWorker : AsyncPeriodicBackgroundWorkerBase, IBackgroun
protected override async Task DoWorkAsync(PeriodicBackgroundWorkerContext workerContext)
{
await using (var handler = await DistributedLock.TryAcquireAsync(DistributedLockName, cancellationToken: StoppingToken))
await using (var handler = await DistributedLock.TryAcquireAsync(WorkerOptions.DistributedLockName, cancellationToken: StoppingToken))
{
if (handler != null)
{

4
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/LIbs/InstallLibsService.cs

@ -72,7 +72,7 @@ public class InstallLibsService : IInstallLibsService, ITransientDependency
}
else
{
NpmHelper.RunNpmInstall(projectDirectory);
NpmHelper.RunNpmInstall(projectDirectory, "--legacy-peer-deps");
}
}
@ -92,7 +92,7 @@ public class InstallLibsService : IInstallLibsService, ITransientDependency
}
else
{
NpmHelper.RunNpmInstall(projectDirectory);
NpmHelper.RunNpmInstall(projectDirectory, "--no-audit");
}
await CleanAndCopyResources(projectDirectory);

5
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Utils/NpmHelper.cs

@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
@ -48,10 +49,10 @@ public class NpmHelper : ITransientDependency
return version > SemanticVersion.Parse("1.20.0");
}
public void RunNpmInstall(string directory)
public void RunNpmInstall(string directory, params string[] args)
{
Logger.LogInformation($"Running npm install on {directory}");
CmdHelper.RunCmd($"npm install", directory);
CmdHelper.RunCmd($"npm install {args.JoinAsString(" ")}", directory);
}
public void RunYarn(string directory)

2
framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/Migrations/EfCoreRuntimeDatabaseMigratorBase.cs

@ -135,7 +135,7 @@ public abstract class EfCoreRuntimeDatabaseMigratorBase<TDbContext> : ITransient
throw;
}
Logger.LogWarning($"{ex.GetType().Name} has been thrown. The operation will be tried {maxTryCount} times more. Exception:\n{ex.Message}. Stack Trace:\n{ex.StackTrace}");
Logger.LogWarning(ex, $"{ex.GetType().Name} has been thrown. The operation will be tried {maxTryCount} times more.");
await Task.Delay(RandomHelper.GetRandom(MinValueToWaitOnFailure, MaxValueToWaitOnFailure));

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

Loading…
Cancel
Save