Browse Source

Merge branch 'dev' into dev-issue-6369

pull/6659/head
Jack Gao 6 years ago
committed by GitHub
parent
commit
3ec2d2366f
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      .github/workflows/build-and-test.yml
  2. 5
      .gitignore
  3. 29
      Directory.Build.props
  4. 7
      NuGet.Config
  5. 99
      README.md
  6. 14
      abp_io/AbpIoLocalization/AbpIoLocalization/Account/Localization/Resources/de-DE.json
  7. 14
      abp_io/AbpIoLocalization/AbpIoLocalization/Account/Localization/Resources/es.json
  8. 3
      abp_io/AbpIoLocalization/AbpIoLocalization/Account/Localization/Resources/zh-Hans.json
  9. 199
      abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/de-DE.json
  10. 199
      abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/es.json
  11. 116
      abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/zh-Hans.json
  12. 33
      abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/de-DE.json
  13. 5
      abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/en.json
  14. 33
      abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/es.json
  15. 4
      abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/zh-Hans.json
  16. 35
      abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/de-DE.json
  17. 4
      abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json
  18. 35
      abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/es.json
  19. 7
      abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/zh-Hans.json
  20. 90
      abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/de-DE.json
  21. 18
      abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/en.json
  22. 90
      abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/es.json
  23. 149
      abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/zh-Hans.json
  24. 189
      abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/de-DE.json
  25. 40
      abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/en.json
  26. 189
      abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/es.json
  27. 43
      abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/zh-Hans.json
  28. 6
      build/common.ps1
  29. 11
      common.DotSettings
  30. 6
      common.props
  31. 35
      docs/en/API/Auto-API-Controllers.md
  32. 53
      docs/en/API/Dynamic-CSharp-API-Clients.md
  33. 68
      docs/en/Application-Services.md
  34. 2
      docs/en/AspNet-Boilerplate-Migration-Guide.md
  35. 31
      docs/en/Authentication/Social-External-Logins.md
  36. 6
      docs/en/Authorization.md
  37. 132
      docs/en/Background-Jobs-RabbitMq.md
  38. 47
      docs/en/Background-Jobs.md
  39. 2
      docs/en/Background-Workers-Quartz.md
  40. 2
      docs/en/Background-Workers.md
  41. 5
      docs/en/Best-Practices/Application-Services.md
  42. 2
      docs/en/Blob-Storing.md
  43. 8
      docs/en/Blog-Posts/2020-05-08 v2_7_Release/Post.md
  44. 271
      docs/en/Blog-Posts/2020-10-15 v3_3_Preview/POST.md
  45. BIN
      docs/en/Blog-Posts/2020-10-15 v3_3_Preview/abp-blazor-ui.png
  46. BIN
      docs/en/Blog-Posts/2020-10-15 v3_3_Preview/abp-commercial-blazor-ui.png
  47. BIN
      docs/en/Blog-Posts/2020-10-15 v3_3_Preview/abp-commercial-linked-users.png
  48. BIN
      docs/en/Blog-Posts/2020-10-15 v3_3_Preview/abp-commercial-setting-account-external-logins.png
  49. 47
      docs/en/Blog-Posts/2020-10-27 v3_3_Release_Stable/POST.md
  50. 143
      docs/en/Blog-Posts/2020-11-12 v4_0_Preview/POST.md
  51. BIN
      docs/en/Blog-Posts/2020-11-12 v4_0_Preview/abp-suite-auto-complete-dropdown.png
  52. 87
      docs/en/Blog-Posts/2020-12-04 v4_0_Release_Stable/POST.md
  53. BIN
      docs/en/Blog-Posts/2020-12-04 v4_0_Release_Stable/abp-contribution-graph-4-years.png
  54. BIN
      docs/en/Blog-Posts/2020-12-04 v4_0_Release_Stable/ddd-implementation-guide-sample.png
  55. 39
      docs/en/CLI.md
  56. 147
      docs/en/CSRF-Anti-Forgery.md
  57. 8
      docs/en/Community-Articles/2020-04-19-Customize-the-SignIn-Manager/POST.md
  58. 14
      docs/en/Community-Articles/2020-08-07-Passwordless-Authentication/POST.md
  59. 2
      docs/en/Community-Articles/2020-08-31-Adding-User-Navigation-In-Suite/POST.md
  60. 477
      docs/en/Community-Articles/2020-09-09-Replacing-Email-Template-and-Sending-Emails/POST.md
  61. BIN
      docs/en/Community-Articles/2020-09-09-Replacing-Email-Template-and-Sending-Emails/bee.gif
  62. BIN
      docs/en/Community-Articles/2020-09-09-Replacing-Email-Template-and-Sending-Emails/db-migrator-1.jpg
  63. BIN
      docs/en/Community-Articles/2020-09-09-Replacing-Email-Template-and-Sending-Emails/db-migrator-2.jpg
  64. BIN
      docs/en/Community-Articles/2020-09-09-Replacing-Email-Template-and-Sending-Emails/db-migrator-3.jpg
  65. BIN
      docs/en/Community-Articles/2020-09-09-Replacing-Email-Template-and-Sending-Emails/email-last.jpg
  66. BIN
      docs/en/Community-Articles/2020-09-09-Replacing-Email-Template-and-Sending-Emails/embedded-resource-2.jpg
  67. BIN
      docs/en/Community-Articles/2020-09-09-Replacing-Email-Template-and-Sending-Emails/embedded-resource.jpg
  68. BIN
      docs/en/Community-Articles/2020-09-09-Replacing-Email-Template-and-Sending-Emails/inline-content.png
  69. BIN
      docs/en/Community-Articles/2020-09-09-Replacing-Email-Template-and-Sending-Emails/message.jpg
  70. BIN
      docs/en/Community-Articles/2020-09-09-Replacing-Email-Template-and-Sending-Emails/settings.jpg
  71. BIN
      docs/en/Community-Articles/2020-09-09-Replacing-Email-Template-and-Sending-Emails/template-definitions.png
  72. 160
      docs/en/Community-Articles/2020-10-08-How-To-Add-Custom-Property-To-The-User-Entity/How-To-Add-Custom-Property-To-The-User-Entity.md
  73. BIN
      docs/en/Community-Articles/2020-10-08-How-To-Add-Custom-Property-To-The-User-Entity/added-new-migration.png
  74. BIN
      docs/en/Community-Articles/2020-10-08-How-To-Add-Custom-Property-To-The-User-Entity/custom-identity-user-list.png
  75. BIN
      docs/en/Community-Articles/2020-10-08-How-To-Add-Custom-Property-To-The-User-Entity/initial-project.png
  76. BIN
      docs/en/Community-Articles/2020-10-08-How-To-Add-Custom-Property-To-The-User-Entity/new-user.png
  77. BIN
      docs/en/Community-Articles/2020-10-08-How-To-Add-Custom-Property-To-The-User-Entity/nuget-package-manager.png
  78. BIN
      docs/en/Community-Articles/2020-10-08-How-To-Add-Custom-Property-To-The-User-Entity/user-table.png
  79. 46
      docs/en/Community-Articles/2020-11-02-How-To-Add-New-Language/POST.md
  80. BIN
      docs/en/Community-Articles/2020-11-02-How-To-Add-New-Language/add-to-languages.png
  81. BIN
      docs/en/Community-Articles/2020-11-02-How-To-Add-New-Language/database-table.png
  82. BIN
      docs/en/Community-Articles/2020-11-02-How-To-Add-New-Language/language-target.png
  83. BIN
      docs/en/Community-Articles/2020-11-02-How-To-Add-New-Language/website-new-language.png
  84. 936
      docs/en/Community-Articles/2020-12-04-Event-Organizer/Post.md
  85. BIN
      docs/en/Community-Articles/2020-12-04-Event-Organizer/images/event-create-ui.png
  86. BIN
      docs/en/Community-Articles/2020-12-04-Event-Organizer/images/event-detail-ui.png
  87. BIN
      docs/en/Community-Articles/2020-12-04-Event-Organizer/images/event-list-ui.png
  88. BIN
      docs/en/Community-Articles/2020-12-04-Event-Organizer/images/index-title.png
  89. BIN
      docs/en/Community-Articles/2020-12-04-Event-Organizer/images/swagger-event-all.png
  90. BIN
      docs/en/Community-Articles/2020-12-04-Event-Organizer/images/swagger-event-create.png
  91. BIN
      docs/en/Community-Articles/2020-12-04-Event-Organizer/images/swagger-event-upcoming.png
  92. 27
      docs/en/Contribution/Index.md
  93. 85
      docs/en/Customizing-Application-Modules-Overriding-Services.md
  94. 10
      docs/en/Data-Access.md
  95. 2
      docs/en/Data-Filtering.md
  96. 32
      docs/en/Data-Seeding.md
  97. 65
      docs/en/Distributed-Event-Bus-Rebus-Integration.md
  98. 7
      docs/en/Distributed-Event-Bus.md
  99. 1978
      docs/en/Domain-Driven-Design-Implementation-Guide.md
  100. 16
      docs/en/Domain-Driven-Design.md

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

@ -17,7 +17,7 @@ jobs:
- uses: actions/checkout@v2
- uses: actions/setup-dotnet@master
with:
dotnet-version: 3.1.102
dotnet-version: 5.0.100
- name: Build All
run: .\build-all.ps1

5
.gitignore

@ -6,6 +6,7 @@
*.user
*.userosscache
*.sln.docstates
*.editorconfig
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
@ -304,3 +305,7 @@ modules/virtual-file-explorer/app/Volo.Abp.VirtualFileExplorer.DemoApp/Logs/
/templates/app/angular/package-lock.json
/modules/client-simulation/demo/Volo.ClientSimulation.Demo/package-lock.json
abp-build-config.json
/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor/Pages/Test/
# Identity Server temp signature file
tempkey.jwk

29
Directory.Build.props

@ -0,0 +1,29 @@
<Project>
<PropertyGroup>
<!-- All Microsoft packages -->
<MicrosoftPackageVersion>5.0.0</MicrosoftPackageVersion>
<!-- Microsoft.NET.Test.Sdk https://www.nuget.org/packages/Microsoft.NET.Test.Sdk -->
<MicrosoftNETTestSdkPackageVersion>16.6.1</MicrosoftNETTestSdkPackageVersion>
<!-- NSubstitute https://www.nuget.org/packages/NSubstitute -->
<NSubstitutePackageVersion>4.2.2</NSubstitutePackageVersion>
<!-- Shouldly https://www.nuget.org/packages/Shouldly -->
<ShouldlyPackageVersion>3.0.2</ShouldlyPackageVersion>
<!-- xunit https://www.nuget.org/packages/xUnit -->
<xUnitPackageVersion>2.4.1</xUnitPackageVersion>
<!-- xunit.extensibility.execution https://www.nuget.org/packages/xunit.extensibility.execution -->
<xUnitExtensibilityExecutionPackageVersion>2.4.1</xUnitExtensibilityExecutionPackageVersion>
<!-- xunit.runner.visualstudio https://www.nuget.org/packages/xunit.runner.visualstudio -->
<xUnitRunnerVisualstudioPackageVersion>2.4.2</xUnitRunnerVisualstudioPackageVersion>
<!-- Mongo2Go https://www.nuget.org/packages/Mongo2Go -->
<Mongo2GoPackageVersion>2.2.14</Mongo2GoPackageVersion>
</PropertyGroup>
</Project>

7
NuGet.Config

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
<add key="BlazoriseMyGet" value="https://www.myget.org/F/blazorise/api/v3/index.json" />
</packageSources>
</configuration>

99
README.md

@ -5,19 +5,102 @@
[![MyGet (with prereleases)](https://img.shields.io/myget/abp-nightly/vpre/Volo.Abp.svg?style=flat-square)](https://docs.abp.io/en/abp/latest/Nightly-Builds)
[![NuGet Download](https://img.shields.io/nuget/dt/Volo.Abp.Core.svg?style=flat-square)](https://www.nuget.org/packages/Volo.Abp.Core)
ABP is an **open source application framework** focused on ASP.NET Core based web application development, but also supports developing other type of applications.
ABP Framework is a complete **infrastructure** based on the **ASP.NET Core** to create **modern web applications** and **APIs** by following the software development **best practices** and the **latest technologies**.
## Links
## Getting Started
* <a href="https://abp.io/" target="_blank">Official Web Site</a>
- [Getting Started Guide](https://docs.abp.io/en/abp/latest/Getting-Started) is the easiest way to start a new web application with the ABP Framework.
- [Web Application Development Tutorial](https://docs.abp.io/en/abp/latest/Tutorials/Part-1) is a complete tutorial to develop a full stack web application.
### Quick Start
Install the ABP CLI:
````bash
> dotnet tool install -g Volo.Abp.Cli
````
Create a new solution:
````bash
> abp new BookStore -u mvc -d ef
````
> See the [CLI documentation](https://docs.abp.io/en/abp/latest/CLI) for all available options.
### UI Framework Options
<img width="500" src="docs/en/images/ui-options.png">
### Database Provider Options
<img width="500" src="docs/en/images/db-options.png">
## What ABP Provides?
ABP provides a **full stack developer experience**.
### Architecture
<img src="docs/en/images/ddd-microservice-simple.png">
ABP offers a complete, **modular** and **layered** software architecture based on **[Domain Driven Design](https://docs.abp.io/en/abp/latest/Domain-Driven-Design)** principles and patterns. It also provides the necessary infrastructure and guiding to [implement this architecture](https://docs.abp.io/en/abp/latest/Domain-Driven-Design-Implementation-Guide).
ABP Framework is suitable for **[microservice solutions](https://docs.abp.io/en/abp/latest/Microservice-Architecture)** as well as monolithic applications.
### Infrastructure
There are a lot of features provided by the ABP Framework to achieve real world scenarios easier, like [Event Bus](https://docs.abp.io/en/abp/latest/Event-Bus), [Background Job System](https://docs.abp.io/en/abp/latest/Background-Jobs), [Audit Logging](https://docs.abp.io/en/abp/latest/Audit-Logging), [BLOB Storing](https://docs.abp.io/en/abp/latest/Blob-Storing), [Data Seeding](https://docs.abp.io/en/abp/latest/Data-Seeding), [Data Filtering](https://docs.abp.io/en/abp/latest/Data-Filtering), etc.
### Cross Cutting Concerns
ABP also simplifies (and even automates wherever possible) cross cutting concerns and common non-functional requirements like [Exception Handling](https://docs.abp.io/en/abp/latest/Exception-Handling), [Validation](https://docs.abp.io/en/abp/latest/Validation), [Authorization](https://docs.abp.io/en/abp/latest/Authorization), [Localization](https://docs.abp.io/en/abp/latest/Localization), [Caching](https://docs.abp.io/en/abp/latest/Caching), [Dependency Injection](https://docs.abp.io/en/abp/latest/Dependency-Injection), [Setting Management](https://docs.abp.io/en/abp/latest/Settings), etc.
### Application Modules
ABP is a modular framework and the Application Modules provide **pre-built application functionalities**;
- [**Account**](https://docs.abp.io/en/abp/latest/Modules/Account): Provides UI for the account management and allows user to login/register to the application.
- **[Identity](https://docs.abp.io/en/abp/latest/Modules/Identity)**: Manages organization units, roles, users and their permissions, based on the Microsoft Identity library.
- [**IdentityServer**](https://docs.abp.io/en/abp/latest/Modules/IdentityServer): Integrates to IdentityServer4.
- [**Tenant Management**](https://docs.abp.io/en/abp/latest/Modules/Tenant-Management): Manages tenants for a [multi-tenant](https://docs.abp.io/en/abp/latest/Multi-Tenancy) (SaaS) application.
See the [Application Modules](https://docs.abp.io/en/abp/latest/Modules/Index) document for all pre-built modules.
### Startup Templates
The [Startup templates](https://docs.abp.io/en/abp/latest/Startup-Templates/Index) are pre-built Visual Studio solution templates. You can create your own solution based on these templates to **immediately start your development**.
## ABP Community
### ABP Community Web Site
The [ABP Community](https://community.abp.io/) is a website to publish **articles** and share **knowledge** about the ABP Framework. You can also create content for the community!
### Blog
Follow the [ABP Blog](https://blog.abp.io/) to learn the latest happenings in the ABP Framework.
### Samples
See the [sample projects](https://docs.abp.io/en/abp/latest/Samples/Index) built with the ABP Framework.
### Want to Contribute?
ABP is a community-driven open source project. See [the contribution guide](https://docs.abp.io/en/abp/latest/Contribution/Index) if you want to be a part of this project.
## Official Links
* <a href="https://abp.io/" target="_blank">Main Web Site</a>
* <a href="https://abp.io/get-started" target="_blank">Get Started</a>
* <a href="https://abp.io/features" target="_blank">Features</a>
* <a href="https://docs.abp.io/" target="_blank">Documentation</a>
* <a href="https://docs.abp.io/en/abp/latest/Samples/Index" target="_blank">Samples</a>
* <a href="https://blog.abp.io/" target="_blank">Blog</a>
* <a href="https://docs.abp.io/" target="_blank">Documentation</a>
* <a href="https://docs.abp.io/en/abp/latest/Samples/Index" target="_blank">Samples</a>
* <a href="https://blog.abp.io/" target="_blank">Blog</a>
* <a href="https://community.abp.io/" target="_blank">Community</a>
* <a href="https://stackoverflow.com/questions/tagged/abp" target="_blank">Stack overflow</a>
* <a href="https://twitter.com/abpframework" target="_blank">Twitter</a>
## Contribution
## Support the ABP Framework
ABP is an open source platform. Check [the contribution guide](docs/en/Contribution/Index.md) if you want to contribute to the project.
Love ABP Framework? **Please give a star** to this repository :star:

14
abp_io/AbpIoLocalization/AbpIoLocalization/Account/Localization/Resources/de-DE.json

@ -0,0 +1,14 @@
{
"culture": "de-DE",
"texts": {
"Account": "ABP Benutzerkonto - Anmeldung & Registrierung | ABP.IO",
"Welcome": "Willkommen",
"UseOneOfTheFollowingLinksToContinue": "Nutzen Sie einen der nachfolgenden Links um fortzusetzen",
"FrameworkHomePage": "Framework Website",
"FrameworkDocumentation": "Framework Dokumentation",
"OfficialBlog": "Offizieller Blog",
"CommercialHomePage": "Commercial Website",
"CommercialSupportWebSite": "Commercial Support-Website",
"CommunityWebSite": "ABP Community-Website"
}
}

14
abp_io/AbpIoLocalization/AbpIoLocalization/Account/Localization/Resources/es.json

@ -0,0 +1,14 @@
{
"culture": "es",
"texts": {
"Account": "Cuenta de ABP - Iniciar sesión y registrarse | ABP.IO",
"Welcome": "Bienvenido",
"UseOneOfTheFollowingLinksToContinue": "Usa uno de los siguientes links para continuar",
"FrameworkHomePage": "Página de inicio del framework",
"FrameworkDocumentation": "Documentación del framework",
"OfficialBlog": "Blog Oficial",
"CommercialHomePage": "Página de inicio comercial",
"CommercialSupportWebSite": "Sitio web de soporte comercial",
"CommunityWebSite": "Sitio web comunidad ABP"
}
}

3
abp_io/AbpIoLocalization/AbpIoLocalization/Account/Localization/Resources/zh-Hans.json

@ -8,6 +8,7 @@
"FrameworkDocumentation": "框架文档",
"OfficialBlog": "官方博客",
"CommercialHomePage": "商业版首页",
"CommercialSupportWebSite": "商业版支持网站"
"CommercialSupportWebSite": "商业版支持网站",
"CommunityWebSite": "ABP社区网站"
}
}

199
abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/de-DE.json

@ -0,0 +1,199 @@
{
"culture": "de-DE",
"texts": {
"Permission:Organizations": "Organisationen",
"Permission:Manage": "Organisationen verwalten",
"Permission:DiscountRequests": "Rabattanfragen",
"Permission:DiscountManage": "Rabattanfragen verwalten",
"Permission:Disable": "Deaktivieren",
"Permission:Enable": "Aktivieren",
"Permission:EnableSendEmail": "E-Mail-Senden aktivieren",
"Permission:SendEmail": "E-Mail senden",
"Permission:NpmPackages": "NPM-Pakete",
"Permission:NugetPackages": "Nuget-Pakete",
"Permission:Maintenance": "Wartung",
"Permission:Maintain": "Warten",
"Permission:ClearCaches": "Caches leeren",
"Permission:Modules": "Module",
"Permission:Packages": "Pakete",
"Permission:Edit": "Bearbeiten",
"Permission:Delete": "Löschen",
"Permission:Create": "Erstellen",
"Permission:Accounting": "Abrechnung",
"Permission:Accounting:Quotation": "Angebot",
"Permission:Accounting:Invoice": "Rechnung",
"Menu:Organizations": "Organisationen",
"Menu:Accounting": "Abrechnung",
"Menu:Packages": "Pakete",
"Menu:DiscountRequests": "Rabattanfragen",
"NpmPackageDeletionWarningMessage": "Dieses NPM-Paket wird entfernt. Bestätigen Sie das?",
"NugetPackageDeletionWarningMessage": "Dieses Nuget-Paket wird entfernt. Bestägiten Sie das?",
"ModuleDeletionWarningMessage": "Dieses Modul wird entfernt. Bestätigen Sie das?",
"Name": "Name",
"DisplayName": "Anzeigename",
"ShortDescription": "Kurzbeschreibung",
"NameFilter": "Name",
"CreationTime": "Erstellungszeitpunkt",
"IsPro": "Ist pro",
"ShowOnModuleList": "In Modulliste anzeigen",
"EfCoreConfigureMethodName": "Methodenname konfigurieren",
"IsProFilter": "Ist pro",
"ApplicationType": "Anwendungstyp",
"Target": "Ziel",
"TargetFilter": "Ziel",
"ModuleClass": "Modulklasse",
"NugetPackageTarget.DomainShared": "Gemeinsame Domain",
"NugetPackageTarget.Domain": "Domain",
"NugetPackageTarget.Application": "Anwendung",
"NugetPackageTarget.ApplicationContracts": "Anwedungsverträge",
"NugetPackageTarget.HttpApi": "HTTP-API",
"NugetPackageTarget.HttpApiClient": "HTTP-API-Client",
"NugetPackageTarget.Web": "Web",
"NugetPackageTarget.EntityFrameworkCore": "DeleteAllEntityFramework Core",
"NugetPackageTarget.MongoDB": "MongoDB",
"Edit": "Bearbeiten",
"Delete": "Löschen",
"Refresh": "Aktualisieren",
"NpmPackages": "NPM-Pakete",
"NugetPackages": "Nuget-Pakete",
"NpmPackageCount": "NPM-Paketanzahl",
"NugetPackageCount": "Nuget-Paketanzahl",
"Module": "Module",
"ModuleInfo": "Modulinfo",
"CreateANpmPackage": "Erstellen Sie ein NPM Paket",
"CreateAModule": "Erstellen Sie in Modul",
"CreateANugetPackage": "Erstellen Sei ein Nuget-Paket",
"AddNew": "Neu hinzufügen",
"PackageAlreadyExist{0}": "\"{0}\" Paket ist bereits hinzugefügt.",
"ModuleAlreadyExist{0}": "\"{0}\" Modul ist bereits hinzugefügt.",
"ClearCache": "Cache leeren",
"SuccessfullyCleared": "Erfolgreich geleert",
"Menu:NpmPackages": "NPM-Pakete",
"Menu:Modules": "Module",
"Menu:Maintenance": "Wartung",
"Menu:NugetPackages": "Nuget-Pakete",
"CreateAnOrganization": "Erstellen Sie eine Organisation",
"Organizations": "Organisationen",
"LongName": "Lange Name",
"LicenseType": "Lizenztyp",
"MissingLicenseTypeField": "Das Feld Lizenztyp ist erforderlich!",
"LicenseStartTime": "Startzeit der Lizenz",
"LicenseEndTime": "Endzeit der Lizenz",
"AllowedDeveloperCount": "Zulässige Entwickleranzahl",
"UserNameOrEmailAddress": "Benutzername oder E-Mail-Adresse",
"AddOwner": "Besitzer hinzufügen",
"UserName": "Benutzername",
"Email": "E-Mail",
"Developers": "Entwickler",
"AddDeveloper": "Entwickler hinzufügen",
"Create": "Erstellen",
"UserNotFound": "Benutzer nicht gefunden",
"{0}WillBeRemovedFromDevelopers": "{0} wird von den Entwicklern entfernt. Bestätigen Sie das?",
"{0}WillBeRemovedFromOwners": "{0} wird von den Besitzern entfernt. Bestätigen Sie das?",
"Computers": "Computer",
"UniqueComputerId": "Eindeutig Computer-ID",
"LastSeenDate": "Zuletzt gesehenes Datum",
"{0}Computer{1}WillBeRemovedFromRecords": "Computer von {0} ({1}) wird aus den Datensätzen entfernt",
"OrganizationDeletionWarningMessage": "Organisation wird gelöscht",
"DeletingLastOwnerWarningMessage": "Eine Organisation muss zumindest einen Besitzer aufweisen! Daher können Sie diesen Besitzer nicht entfernen",
"This{0}AlreadyExistInThisOrganization": "Dies {0} existiert bereits in dieser Organisation",
"AreYouSureYouWantToDeleteAllComputers": "Sind Sie sicher, dass Sie alle Computer löschen möchten?",
"DeleteAll": "Alles Löschen",
"DoYouWantToCreateNewUser": "Möchten Sie einen neuen Benutzer erstellen?",
"MasterModules": "Master-Module",
"OrganizationName": "Organisationsname",
"CreationDate": "Erstellungsdatum",
"LicenseStartDate": "Startdatum der Lizenz",
"LicenseEndDate": "Enddatum der Lizenz",
"OrganizationNamePlaceholder": "Organisationsname...",
"TotalQuestionCountPlaceholder": "Gesamtzahl der Fragen...",
"RemainingQuestionCountPlaceholder": "Anzahl verbleibender Fragen...",
"LicenseTypePlaceholder": "Lizenztyp...",
"CreationDatePlaceholder": "Erstellungsdatum...",
"LicenseStartDatePlaceholder": "Startdatum der Lizenz...",
"LicenseEndDatePlaceholder": "Enddatum der Lizenz...",
"UsernameOrEmail": "Benutzername oder E-Mail-Adresse",
"UsernameOrEmailPlaceholder": "Benutzername oder E-Mail-Adresse...",
"Member": "Mitglied",
"PurchaseOrderNo": "Bestellnummer",
"QuotationDate": "Angebotsdatum",
"CompanyName": "Firmenname",
"CompanyAddress": "Firmenanschrift",
"Price": "Preis",
"DiscountText": "Rabatttext",
"DiscountQuantity": "Rabattmenge",
"DiscountPrice": "Rabattpreis",
"Quotation": "Angebot",
"ExtraText": "Zusätzlicher Text",
"ExtraAmount": "Zusätzliche Menge",
"DownloadQuotation": "Angebot herunterladen",
"Invoice": "Rechnung",
"TaxNumber": "Steuernummer",
"InvoiceNumber": "Rechnungsnummer",
"InvoiceDate": "Rechnungsdatum",
"InvoiceNote": "Rechnungsnotiz",
"Quantity": "Menge",
"AddProduct": "Produkt hinzufügen",
"AddProductWarning": "Sie müssen ein Produkt hinzufügen!",
"TotalPrice": "Gesamtpreis",
"Generate": "Generieren",
"MissingQuantityField": "Das Feld Menge ist erforderlich!",
"MissingPriceField": "Das Feld Preis ist erforderlich!",
"CodeUsageStatus": "Status",
"Country": "Land",
"DeveloperCount": "Entwickleranzahl",
"RequestCode": "Anfrage-Code",
"WebSite": "Webseite",
"GithubUsername": "Github Benutzername",
"PhoneNumber": "Telefonnummer",
"ProjectDescription": "Projektbeschreibung",
"Referrer": "Referrer",
"DiscountRequests": "Rabattanfrage",
"Copylink": "Link kopieren",
"Disable": "Deaktivieren",
"Enable": "Aktivieren",
"EnableSendEmail": "E-Mail-Senden aktivieren",
"SendEmail": "E-Mail senden",
"SuccessfullyDisabled": "Erfolgreich deaktiviert",
"SuccessfullyEnabled": "Erfolgreich aktiviert",
"EmailSent": "E-Mail gesendet",
"SuccessfullySent": "Erfolgreich gesendet",
"SuccessfullyDeleted": "Erfolgreich gelöscht",
"DiscountRequestDeletionWarningMessage": "Rabattanfrage wird gelöscht",
"BusinessType": "Unternehmensart",
"TotalQuestionCount": "Gesamtzahl der Fragen",
"RemainingQuestionCount": "Anzahl verbleibender Fragen",
"TotalQuestionMustBeGreaterWarningMessage": "TotalQuestionCount muss größer sein als RemainingQuestionCount !",
"QuestionCountsMustBeGreaterThanZero": "TotalQuestionCount und RemainingQuestionCount müssen Null oder größer als Null sein !",
"UnlimitedQuestionCount": "Unbegrenzte Anzahl von Fragen",
"Notes": "Anmerkungen",
"Menu:Community": "Community",
"Menu:Articles": "Beiträge",
"Wait": "Warten",
"Approve": "Genehmigen",
"Reject": "Ablehnen",
"Details": "Details",
"Url": "URL",
"Title": "Titel",
"ContentSource": "Inhaltsquelle",
"Status": "Status",
"ReadArticle": "Beitrag lesen",
"ArticleHasBeenWaiting": "Beitrag hat gewartet",
"ArticleHasBeenApproved": "Beitrag wurde genehmigt",
"ArticleHasBeenRejected": "Beitrag wurde abgelehnt",
"Permission:Community": "Community",
"Permission:CommunityArticle": "Beitrag",
"Link": "Link",
"Enum:ContentSource:0": "Github",
"Enum:ContentSource:1": "Extern",
"Enum:Status:0": "Wartend",
"Enum:Status:1": "Abgelehnt",
"Enum:Status:2": "Genehmigt",
"Summary": "Zusammenfassung",
"AuthorName": "Autorenname",
"CoverImage": "Titelbild",
"RemoveCacheConfirmationMessage": "Sind Sie sicher, dass Sie den Cache für den Artikel \"{0}\" entfernen wollen?",
"SuccessfullyRemoved": "Erfolgreich geleert",
"RemoveCache": "Cache entfernen"
}
}

199
abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/es.json

@ -0,0 +1,199 @@
{
"culture": "es",
"texts": {
"Permission:Organizations": "Organizaciones",
"Permission:Manage": "Gestionar organizaciones",
"Permission:DiscountRequests": "Solicitudes de descuento",
"Permission:DiscountManage": "Gestionar solicitudes de descuento",
"Permission:Disable": "Desactivar",
"Permission:Enable": "Activar",
"Permission:EnableSendEmail": "Activar enviar email",
"Permission:SendEmail": "Enviar email",
"Permission:NpmPackages": "Paquetes NPM",
"Permission:NugetPackages": "Paquetes Nuget",
"Permission:Maintenance": "Mantenimiento",
"Permission:Maintain": "Mantener",
"Permission:ClearCaches": "Borrar cachés",
"Permission:Modules": "Módulos",
"Permission:Packages": "Paquetes",
"Permission:Edit": "Editar",
"Permission:Delete": "Borrar",
"Permission:Create": "Crear",
"Permission:Accounting": "Contabilidad",
"Permission:Accounting:Quotation": "Cotización",
"Permission:Accounting:Invoice": "Factura",
"Menu:Organizations": "Organizaciones",
"Menu:Accounting": "Contabilidad",
"Menu:Packages": "Paquetes",
"Menu:DiscountRequests": "Solicitudes de descuento",
"NpmPackageDeletionWarningMessage": "Este NPM paquete será borrado. ¿Quieres confirmar?",
"NugetPackageDeletionWarningMessage": "Este NPM paquete será borrado. ¿Quieres confirmar?",
"ModuleDeletionWarningMessage": "Este NPM paquete será borrado. ¿Quieres confirmar?",
"Name": "Nombre",
"DisplayName": "Nombre para mostrar",
"ShortDescription": "Descripción corta",
"NameFilter": "Nombre",
"CreationTime": "Fecha de creación",
"IsPro": "Es pro",
"ShowOnModuleList": "Mostrar en la lista de módulos",
"EfCoreConfigureMethodName": "configurar nombre de método",
"IsProFilter": "Es pro",
"ApplicationType": "tipo de aplicación",
"Target": "Destino",
"TargetFilter": "Destino",
"ModuleClass": "Módulo de clase",
"NugetPackageTarget.DomainShared": "Dominio compartido",
"NugetPackageTarget.Domain": "Dominio",
"NugetPackageTarget.Application": "Aplicación",
"NugetPackageTarget.ApplicationContracts": "Contratos de aplicación",
"NugetPackageTarget.HttpApi": "Http Api",
"NugetPackageTarget.HttpApiClient": "Cliente Http Api",
"NugetPackageTarget.Web": "Web",
"NugetPackageTarget.EntityFrameworkCore": "Delete todo EntityFramework Core",
"NugetPackageTarget.MongoDB": "MongoDB",
"Edit": "Editar",
"Delete": "Borrar",
"Refresh": "Refrescar",
"NpmPackages": "Paquetes NPM",
"NugetPackages": "Paquetes Nuget",
"NpmPackageCount": "Número de paquetes NPM",
"NugetPackageCount": "Número de paquetes Nuget",
"Module": "Módulos",
"ModuleInfo": "Info de módulo",
"CreateANpmPackage": "Crear un paquete NPM",
"CreateAModule": "Crear un módulo",
"CreateANugetPackage": "Crear un paquete de Nuget",
"AddNew": "Añadir nuevo",
"PackageAlreadyExist{0}": "\"{0}\" paquete ya se encuentra añadido",
"ModuleAlreadyExist{0}": "\"{0}\" módulo ya se encuentra añadido.",
"ClearCache": "Borrar caché",
"SuccessfullyCleared": "Borrado satisfactoriamente",
"Menu:NpmPackages": "Paquetes de NPM",
"Menu:Modules": "Módulos",
"Menu:Maintenance": "Mantenimiento",
"Menu:NugetPackages": "Paquetes Nuget",
"CreateAnOrganization": "Crear una organización",
"Organizations": "Organizaciones",
"LongName": "Nombre largo",
"LicenseType": "Tipo de licencia",
"MissingLicenseTypeField": "El campo tipo de licencia es requerido!",
"LicenseStartTime": "Fecha de inicio de licencia",
"LicenseEndTime": "Fecha de caducidad de licencia",
"AllowedDeveloperCount": "Número de desarrolladores permitidos",
"UserNameOrEmailAddress": "Nombre de usuario o",
"AddOwner": "Añadir propietario",
"UserName": "Nombre de usuario",
"Email": "Email",
"Developers": "Desarrolladores",
"AddDeveloper": "Añadir desarrollador",
"Create": "Crear",
"UserNotFound": "Usuario no encontrado",
"{0}WillBeRemovedFromDevelopers": "{0} será eliminado de desarrolladores, ¿deseas continuar?",
"{0}WillBeRemovedFromOwners": "{0} será eliminado de propietarios, ¿deseas continuar?",
"Computers": "Ordenadores",
"UniqueComputerId": "Id única de ordenador",
"LastSeenDate": "Fecha de visto por última vez",
"{0}Computer{1}WillBeRemovedFromRecords": "El ordenador {0} ({1}) será eliminado de los registros",
"OrganizationDeletionWarningMessage": "La organización será eliminada",
"DeletingLastOwnerWarningMessage": "Una organización debe tener al menos un propietario!. Por lo tanto, tu no puedes eliminar este propietario",
"This{0}AlreadyExistInThisOrganization": "Este/a {0} ya existe en esta organización",
"AreYouSureYouWantToDeleteAllComputers": "Estás seguro tu quieres eliminar todos los ordenadores",
"DeleteAll": "Eliminar todo",
"DoYouWantToCreateNewUser": "¿Quieres crear un nuevo usuario?",
"MasterModules": "Módulos maestros",
"OrganizationName": "Nombre de organización",
"CreationDate": "Fecha de creación",
"LicenseStartDate": "Fecha de inicio de licencia",
"LicenseEndDate": "Fecha de caducidad de licencia",
"OrganizationNamePlaceholder": "Nombre de organización...",
"TotalQuestionCountPlaceholder": "Número total de preguntas...",
"RemainingQuestionCountPlaceholder": "Número de preguntas pendientes",
"LicenseTypePlaceholder": "Tipo de licencia...",
"CreationDatePlaceholder": "Fecha de creación...",
"LicenseStartDatePlaceholder": "Fecha de inicio de licencia...",
"LicenseEndDatePlaceholder": "Fecha de caducidad de licencia...",
"UsernameOrEmail": "Usuario o email",
"UsernameOrEmailPlaceholder": "Usuario o email...",
"Member": "Miembro",
"PurchaseOrderNo": "Número de orden de compra",
"QuotationDate": "Fecha de presupuesto",
"CompanyName": "Nombre de empresa",
"CompanyAddress": "Dirección de empresa",
"Price": "Precio",
"DiscountText": "Texto de descuento",
"DiscountQuantity": "Cantidad de descuento",
"DiscountPrice": "Precio de descuento",
"Quotation": "Presupuesto",
"ExtraText": "Texto extra",
"ExtraAmount": "Cantidad extra",
"DownloadQuotation": "Descarga el presupuesto",
"Invoice": "Factura",
"TaxNumber": "Identificación fiscal",
"InvoiceNumber": "Número de factura",
"InvoiceDate": "Fecha de factura",
"InvoiceNote": "Nota de factura",
"Quantity": "Cantidad",
"AddProduct": "Añadir producto",
"AddProductWarning": "Tu necesitas añadir un producto!",
"TotalPrice": "Precio total",
"Generate": "Generar",
"MissingQuantityField": "El campo cantidad es requerido!",
"MissingPriceField": "El campo precio es requerido!",
"CodeUsageStatus": "Estado",
"Country": "País",
"DeveloperCount": "Cuentas de desarrollo",
"RequestCode": "Solicitud de código",
"WebSite": "Sitio web",
"GithubUsername": "Nombre de usuario Github",
"PhoneNumber": "Número de teléfono",
"ProjectDescription": "Descripción del proyecto",
"Referrer": "Referente",
"DiscountRequests": "Solicitud de descuento",
"Copylink": "Copiar Link",
"Disable": "Deshabilitar",
"Enable": "Habilitar",
"EnableSendEmail": "Habilitar el envío de Email",
"SendEmail": "Enviar Email",
"SuccessfullyDisabled": "Deshabilitado correctamente",
"SuccessfullyEnabled": "Habilitado correctamente",
"EmailSent": "Email enviado",
"SuccessfullySent": "Enviado correctamente",
"SuccessfullyDeleted": "Borrado correctamente",
"DiscountRequestDeletionWarningMessage": "La solicitud de descuento será borrada",
"BusinessType": "Tipo de negocio",
"TotalQuestionCount": "Número total de preguntas",
"RemainingQuestionCount": "Número de preguntas restantes",
"TotalQuestionMustBeGreaterWarningMessage": "TotalQuestionCount debe ser mayor que RemainingQuestionCount !",
"QuestionCountsMustBeGreaterThanZero": "TotalQuestionCount y RemainingQuestionCount debe ser cero o más grande que cero !",
"UnlimitedQuestionCount": "Número de preguntas ilimitadas",
"Notes": "Notas",
"Menu:Community": "Comunidad",
"Menu:Articles": "Artículos",
"Wait": "Esperar",
"Approve": "Aprobar",
"Reject": "Rechazar",
"Details": "Detalles",
"Url": "Url",
"Title": "Título",
"ContentSource": "Fuente de contenido",
"Status": "Estado",
"ReadArticle": "Leer artículo",
"ArticleHasBeenWaiting": "El artículo ha sido puesto en espera",
"ArticleHasBeenApproved": "El artículo ha sido aprobado",
"ArticleHasBeenRejected": "El artículo ha sido rechazado",
"Permission:Community": "Comunidad",
"Permission:CommunityArticle": "Artículo",
"Link": "Link",
"Enum:ContentSource:0": "Github",
"Enum:ContentSource:1": "Externo",
"Enum:Status:0": "En espera",
"Enum:Status:1": "Rechazado",
"Enum:Status:2": "Aprobado",
"Summary": "Resumen",
"AuthorName": "Nombre del autor",
"CoverImage": "Imagen de portada",
"RemoveCacheConfirmationMessage": "¿Estás seguro que quieres borrar la caché para \"{0}\" artículo?",
"SuccessfullyRemoved": "Borrada correctamente",
"RemoveCache": ""
}
}

116
abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/zh-Hans.json

@ -3,6 +3,12 @@
"texts": {
"Permission:Organizations": "组织",
"Permission:Manage": "管理组织",
"Permission:DiscountRequests": "折扣请求",
"Permission:DiscountManage": "管理折扣请求",
"Permission:Disable": "禁用",
"Permission:Enable": "启动",
"Permission:EnableSendEmail": "启用发送邮件",
"Permission:SendEmail": "发送邮件",
"Permission:NpmPackages": "NPM包",
"Permission:NugetPackages": "Nuget包",
"Permission:Maintenance": "维护",
@ -13,8 +19,13 @@
"Permission:Edit": "编辑",
"Permission:Delete": "删除",
"Permission:Create": "创建",
"Permission:Accounting": "账单",
"Permission:Accounting:Quotation": "报价",
"Permission:Accounting:Invoice": "发票",
"Menu:Organizations": "组织",
"Menu:Accounting": "账单",
"Menu:Packages": "包",
"Menu:DiscountRequests": "折扣请求",
"NpmPackageDeletionWarningMessage": "该NPM包将会被删除. 你确定吗?",
"NugetPackageDeletionWarningMessage": "该Nuget包将会被删除. 你确定吗?",
"ModuleDeletionWarningMessage": "该模块将会被删除. 你确定吗?",
@ -24,6 +35,7 @@
"NameFilter": "名称",
"CreationTime": "创建时间",
"IsPro": "是否为专业版",
"ShowOnModuleList": "展示模块列表",
"EfCoreConfigureMethodName": "配置方法法",
"IsProFilter": "是否为专业版",
"ApplicationType": "应用程序类型",
@ -53,6 +65,7 @@
"CreateANugetPackage": "创建Nuget包",
"AddNew": "新建",
"PackageAlreadyExist{0}": "\"{0}\"已经被添加.",
"ModuleAlreadyExist{0}": "\"{0}\" 模块已经添加.",
"ClearCache": "清除缓存",
"SuccessfullyCleared": "清除成功",
"Menu:NpmPackages": "NPM包",
@ -63,6 +76,7 @@
"Organizations": "组织",
"LongName": "完整名称",
"LicenseType": "授权类型",
"MissingLicenseTypeField": "许可证类型字段是必需的!",
"LicenseStartTime": "授权开始时间",
"LicenseEndTime": "授权结束时间",
"AllowedDeveloperCount": "允许的开发人员数量",
@ -74,14 +88,112 @@
"AddDeveloper": "添加开发者",
"Create": "创建",
"UserNotFound": "用户不存在",
"{0}WillBeRemovedFromMembers": "{0} 将从成员中删除",
"{0}WillBeRemovedFromDevelopers": "{0} 将从开发者中移除, 你确定吗?",
"{0}WillBeRemovedFromOwners": "{0} 将从所有者中移除, 你确定吗?",
"Computers": "计算机",
"UniqueComputerId": "计算机唯一ID",
"LastSeenDate": "上次查看日期",
"{0}Computer{1}WillBeRemovedFromRecords": "计算机 {0} ({1}) 将从记录中删除",
"OrganizationDeletionWarningMessage": "组织将被删除",
"DeletingLastOwnerWarningMessage": "一个组织必须至少有一个所有者!因此你不能删除此所有者",
"This{0}AlreadyExistInThisOrganization": "该组织中已经存在此 {0}",
"AreYouSureYouWantToDeleteAllComputers": "您确定要删除所有计算机吗?",
"DeleteAll": "删除所有"
"DeleteAll": "删除所有",
"DoYouWantToCreateNewUser": "你想要创建一个新用户吗",
"MasterModules": "主模块",
"OrganizationName": "组织名称",
"CreationDate": "创建时间",
"LicenseStartDate": "许可开始时间",
"LicenseEndDate": "许可结束时间",
"OrganizationNamePlaceholder": "组织名称...",
"TotalQuestionCountPlaceholder": "问题总数...",
"RemainingQuestionCountPlaceholder": "剩下的问题数...",
"LicenseTypePlaceholder": "许可类型...",
"CreationDatePlaceholder": "创建时间...",
"LicenseStartDatePlaceholder": "许可开始时间...",
"LicenseEndDatePlaceholder": "许可结束时间...",
"UsernameOrEmail": "用户名或邮箱",
"UsernameOrEmailPlaceholder": "用户名或邮箱...",
"Member": "成员",
"PurchaseOrderNo": "订单编号",
"QuotationDate": "报价日期",
"CompanyName": "公司名称",
"CompanyAddress": "公司地址",
"Price": "价格",
"DiscountText": "折扣文字",
"DiscountQuantity": "折扣数量",
"DiscountPrice": "折扣价格",
"Quotation": "报价单",
"ExtraText": "额外文字",
"ExtraAmount": "额外金额",
"DownloadQuotation": "下载报价单",
"Invoice": "发票",
"TaxNumber": "税号",
"InvoiceNumber": "发票数字",
"InvoiceDate": "发票日期",
"InvoiceNote": "发票说明",
"Quantity": "数量",
"AddProduct": "添加产品",
"AddProductWarning": "你需要添加产品",
"TotalPrice": "总价",
"Generate": "生成",
"MissingQuantityField": "数量字段为必填项!",
"MissingPriceField": "价格字段为必填项!",
"CodeUsageStatus": "状态",
"Country": "国家",
"DeveloperCount": "开发者数量",
"RequestCode": "请求码",
"WebSite": "网站",
"GithubUsername": "Github用户名",
"PhoneNumber": "手机号",
"ProjectDescription": "产品描述",
"Referrer": "推荐人",
"DiscountRequests": "折扣请求",
"Copylink": "拷贝链接",
"Disable": "禁用",
"Enable": "启用",
"EnableSendEmail": "启用发送邮件",
"SendEmail": "发送邮件",
"SuccessfullyDisabled": "禁用成功",
"SuccessfullyEnabled": "启用成功",
"EmailSent": "邮件发送",
"SuccessfullySent": "发送成功",
"SuccessfullyDeleted": "删除成功",
"DiscountRequestDeletionWarningMessage": "折扣成功将被删除",
"BusinessType": "商业类型",
"TotalQuestionCount": "问题总数",
"RemainingQuestionCount": "剩余问题数",
"TotalQuestionMustBeGreaterWarningMessage": "TotalQuestionCount必须大于RemainingQuestionCount!",
"QuestionCountsMustBeGreaterThanZero": "TotalQuestionCount和RemainingQuestionCount必须为0或大于0",
"UnlimitedQuestionCount": "无限的问题计数",
"Notes": "笔记",
"Menu:Community": "社区",
"Menu:Articles": "文章",
"Wait": "等待",
"Approve": "批准",
"Reject": "拒绝",
"Details": "详情",
"Url": "Url",
"Title": "标题",
"ContentSource": "内容源",
"Status": "状态",
"ReadArticle": "阅读文章",
"ArticleHasBeenWaiting": "文章还在等待",
"ArticleHasBeenApproved": "文章已被批准",
"ArticleHasBeenRejected": "文章已被拒绝",
"Permission:Community": "社区",
"Permission:CommunityArticle": "文字",
"Link": "链接",
"Enum:ContentSource:0": "Github",
"Enum:ContentSource:1": "外部",
"Enum:Status:0": "等待中",
"Enum:Status:1": "已拒绝",
"Enum:Status:2": "已批准",
"Summary": "概要",
"AuthorName": "作者名称",
"CoverImage": "封面图片",
"RemoveCacheConfirmationMessage": "你确定要删除\"{0}\" 文章缓存?",
"SuccessfullyRemoved": "清除成功",
"RemoveCache": "删除缓存"
}
}

33
abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/de-DE.json

@ -0,0 +1,33 @@
{
"culture": "de-DE",
"texts": {
"Volo.AbpIo.Domain:010004": "Maximale Mitgliederanzahl erreicht!",
"Volo.AbpIo.Domain:010005": "Miximale Besizeranzahl erreicht!",
"Volo.AbpIo.Domain:010006": "Dieser Benutzer ist bereits ein Besitzer in dieser Organisation!",
"Volo.AbpIo.Domain:010007": "Dieser Benutzer ist bereits ein Entwickler in dieser Organisation!",
"Volo.AbpIo.Domain:010008": "Die zulässige Entwickleranzahl darf nicht geringer sein als die aktuelle Entwickleranzahl!",
"Volo.AbpIo.Domain:010009": "Die zulässige Entwickleranzahl darf nicht kleiner als 0 sein!",
"Volo.AbpIo.Domain:010010": "Die maximale Anzahl der Mac-Adressen ist überschritten!",
"Volo.AbpIo.Domain:010011": "Die persönliche Lizenz kann nicht mehr als 1 Entwickler haben!",
"Volo.AbpIo.Domain:010012": "Die Lizenz kann nicht einen Monat nach Ablauf der Lizenz verlängert werden!",
"Volo.AbpIo.Domain:020001": "Dieses NPM-Paket konnte nicht gelöscht werden, da \"{NugetPackages}\" Nuget-Pakete von diesem Paket abhängig sind.",
"Volo.AbpIo.Domain:020002": "Dieses NPM-Paket konnte nicht gelöscht werden, da \"{Module}\" Module dieses Paket verwenden.",
"Volo.AbpIo.Domain:020003": "Dieses NPM-Paket konnte nicht gelöscht werden, da \"{Module}\" Module dieses Paket verwenden und \"{NugetPackages}\" Nuget-Pakete von diesem Paket abhängig sind.",
"Volo.AbpIo.Domain:020004": "Dieses Nuget-Paket konnte nicht gelöscht werden, da \"{Module}\" Module dieses Paket verwenden.",
"WantToLearn?": "Wollen Sie sich einlernen?",
"ReadyToGetStarted?": "Bereit anzufangen?",
"JoinOurCommunity": "Tritt unserer Community bei",
"GetStartedUpper": "LOSLEGEN",
"ForkMeOnGitHub": "Fork me on GitHub",
"Features": "Features",
"GetStarted": "Loslegen",
"Documents": "Unterlagen",
"Community": "Community",
"ContributionGuide": "Leitfaden für Mitwirkende",
"Blog": "Blog",
"Commercial": "Commercial",
"MyAccount": "Mein Benutzerkonto",
"SeeDocuments": "Siehe Unterlagen",
"Samples": "Beispiele"
}
}

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

@ -27,6 +27,9 @@
"Blog": "Blog",
"Commercial": "Commercial",
"MyAccount": "My account",
"SeeDocuments": "See Documents"
"Permission:License": "License",
"Permission:UserInfo": "Usere info",
"SeeDocuments": "See Documents",
"Samples": "Samples"
}
}

33
abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/es.json

@ -0,0 +1,33 @@
{
"culture": "es",
"texts": {
"Volo.AbpIo.Domain:010004": "Número máximo de miembros alcanzado!",
"Volo.AbpIo.Domain:010005": "Número máximo de propietarios alcanzado!",
"Volo.AbpIo.Domain:010006": "Este usuario ya es un propietario de esta organización!",
"Volo.AbpIo.Domain:010007": "Este usuario ya es un desarrollador en este organización!",
"Volo.AbpIo.Domain:010008": "Número de desarrolladores permitido no puede ser menor que el número actual de desarrolladores!",
"Volo.AbpIo.Domain:010009": "El número de desarrolladores no puede ser menor que cero!",
"Volo.AbpIo.Domain:010010": "Número máximo de dirección mac excedido!",
"Volo.AbpIo.Domain:010011": "Una licencia personal no puede tener más de un desarrollador!",
"Volo.AbpIo.Domain:010012": "La licencia no puede ser extendida un mes despues de que expire!",
"Volo.AbpIo.Domain:020001": "Este paquete NPM no pudo ser borrado porque \"{NugetPackages}\" paquetes Nuget son dependientes de este paquete.",
"Volo.AbpIo.Domain:020002": "Este paquete NPM no pudo ser borrado porque \"{Modules}\" modulos están usando este paquete.",
"Volo.AbpIo.Domain:020003": "Este paquete NPM no pudo ser borrado porque \"{Modules}\" modulos están usando este paquete.y \"{NugetPackages}\" paquetes Nuget son dependientes de este paquete.",
"Volo.AbpIo.Domain:020004": "Este paquete Nuget no pudo ser borrado porque \"{Modules}\" modulos están usando este paquete.",
"WantToLearn?": "¿Quieres aprender?",
"ReadyToGetStarted?": "¿Preparado para comenzar?",
"JoinOurCommunity": "Unete a nuestra comunidad",
"GetStartedUpper": "COMENZAR",
"ForkMeOnGitHub": "Fork en GitHub",
"Features": "Características",
"GetStarted": "Comenzar",
"Documents": "Documentos",
"Community": "Comunidad",
"ContributionGuide": "Guia de contribución",
"Blog": "Blog",
"Commercial": "Comercial",
"MyAccount": "Mi cuenta",
"SeeDocuments": "Ver documentos",
"Samples": "Ejemplos"
}
}

4
abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/zh-Hans.json

@ -26,6 +26,8 @@
"ContributionGuide": "贡献指南",
"Blog": "博客",
"Commercial": "商业版",
"SeeDocuments": "查看文档"
"MyAccount": "我的账户",
"SeeDocuments": "查看文档",
"Samples": "示例"
}
}

35
abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/de-DE.json

@ -0,0 +1,35 @@
{
"culture": "de-DE",
"texts": {
"OrganizationManagement": "Organisationsverwaltung",
"OrganizationList": "Organisationsauflistung",
"Volo.AbpIo.Commercial:010003": "Sie sind der Besitzer dieser Organisation!",
"OrganizationNotFoundMessage": "Keine Organisation gefunden!",
"DeveloperCount": "Zugeordnete / Gesamte Entwickler",
"QuestionCount": "Verbleibende / Gesamte Fragen",
"Unlimited": "Unbegrenzt",
"Owners": "Besitzer",
"AddMember": "Mitglied hinzufügen",
"AddOwner": "Besizer hinzufügen",
"AddDeveloper": "Entwickler hinzufügen",
"UserName": "Benutzername",
"Name": "Name",
"EmailAddress": "E-Mail-Adress",
"Developers": "Entwickler",
"LicenseType": "Lizenztyp",
"Manage": "Verwalten",
"StartDate": "Startdatum",
"EndDate": "Enddatum",
"Modules": "Module",
"LicenseExtendMessage": "Ihr Lizenzenddatum wird auf {0} verlängert",
"LicenseUpgradeMessage": "Ihre Lizenz wird auf {0} aktualisiert",
"LicenseAddDeveloperMessage": "{0} Entwickler zu Ihrer Lizenz hinzugefügt",
"Volo.AbpIo.Commercial:010004": "Kann den angegebenen Benutzer nicht finden! Der Benutzer muss sich bereits registriert haben.",
"MyOrganizations": "Meine Organisationen",
"ApiKey": "API-Schlüssel",
"UserNameNotFound": "Es gibt keinen Benutzer mit dem Benutzernamen {0}",
"SuccessfullyAddedToNewsletter": "Vielen Dank, dass Sie unseren Newsletter abonniert haben!",
"MyProfile": "Mein Profil",
"EmailNotValid": "Bitte geben Sie eine gültige E-Mail-Adresse ein."
}
}

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

@ -30,6 +30,8 @@
"UserNameNotFound": "There is no user with username {0}",
"SuccessfullyAddedToNewsletter": "Thanks you for subscribing to our newsletter!",
"MyProfile": "My profile",
"EmailNotValid": "Please enter a valid email address."
"EmailNotValid": "Please enter a valid email address.",
"JoinOurMarketingNewsletter": "Join our marketing newsletter",
"WouldLikeToReceiveMarketingMaterials": "I would like to receive marketing materials like product deals & special offers."
}
}

35
abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/es.json

@ -0,0 +1,35 @@
{
"culture": "es",
"texts": {
"OrganizationManagement": "Gestión de la organización",
"OrganizationList": "Lista organización",
"Volo.AbpIo.Commercial:010003": "Tu no eres el propietario de esta organización!",
"OrganizationNotFoundMessage": "Organización no encontrada!",
"DeveloperCount": "Total desarrolladores asignados",
"QuestionCount": "Total de preguntas restantes",
"Unlimited": "Ilimitado",
"Owners": "Propietarios",
"AddMember": "Añadir miembro",
"AddOwner": "Añadir propietario",
"AddDeveloper": "Añadir desarrollador",
"UserName": "Nombre de usuario",
"Name": "Nombre",
"EmailAddress": "Dirección de Email",
"Developers": "Desarrolladores",
"LicenseType": "Tipo de licencia",
"Manage": "Gestionar",
"StartDate": "Fecha de inicio",
"EndDate": "Fecha de fin",
"Modules": "Módulos",
"LicenseExtendMessage": "Tu fecha de finalización de tu licencia ha sido extendido a {0}",
"LicenseUpgradeMessage": "Tu licencia esta actualizada a {0}",
"LicenseAddDeveloperMessage": "{0} desarrolladores añadidos a tu licencia",
"Volo.AbpIo.Commercial:010004": "No se pudo encontrar el usuario especificado. El usuario debe estar ya registrado.",
"MyOrganizations": "Mis organizaciones",
"ApiKey": "API Key",
"UserNameNotFound": "No hay un usuario con el nombre de usuario {0}",
"SuccessfullyAddedToNewsletter": "Gracias por suscribirte a nuestro boletín de noticias!",
"MyProfile": "Mi perfil",
"EmailNotValid": "Por favor, introduce una dirección de email válida."
}
}

7
abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/zh-Hans.json

@ -6,6 +6,8 @@
"Volo.AbpIo.Commercial:010003": "你不是该组织的所有者!",
"OrganizationNotFoundMessage": "找不到任何组织!",
"DeveloperCount": "开发者数量",
"QuestionCount": "剩余 / 问题总数",
"Unlimited": "无限制",
"Owners": "所有者",
"AddMember": "添加成员",
"AddOwner": "添加所有者",
@ -25,6 +27,9 @@
"Volo.AbpIo.Commercial:010004": "不能找到指定的用户! 用户必须已经注册.",
"MyOrganizations": "我的组织",
"ApiKey": "API key",
"UserNameNotFound": "没有用户名为{0}的用户"
"UserNameNotFound": "没有用户名为{0}的用户",
"SuccessfullyAddedToNewsletter": "感谢你订阅我们的新闻通讯!",
"MyProfile": "我的资料",
"EmailNotValid": "请输入有效的电子邮件地址"
}
}

90
abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/de-DE.json

@ -0,0 +1,90 @@
{
"culture": "de-DE",
"texts": {
"Permission:CommunityArticle": "Community-Beitrag",
"Permission:Edit": "Bearbeiten",
"Waiting": "Wartend",
"Approved": "Genehmigt",
"Rejected": "Abgelehnt",
"Wait": "Warten",
"Approve": "Genehmigen",
"Reject": "Ablehnen",
"ReadArticle": "Beitrag lesen",
"Status": "Status",
"ContentSource": "Inhaltsquelle",
"Details": "Details",
"Url": "URL",
"Title": "Titel",
"CreationTime": "Erstellungszeitpunkt",
"Save": "Speichern",
"SameUrlAlreadyExist": "Dieselbe URL existiert bereits, wenn Sie diesen Beitrag hinzufügen möchten, sollten Sie die URL ändern!",
"UrlIsNotValid": "Der URL ist nicht korrekt.",
"UrlNotFound": "URL nicht gefunden.",
"UrlContentNotFound": "URL-Inhalt nicht gefunden",
"Summary": "Zusammenfassung",
"MostRead": "Meist gelesen",
"Latest": "Neueste",
"ContributeAbpCommunity": "Tragen Sie zur ABP Community bei",
"SubmitYourArticle": "Reichen Sie Ihren Beitrag ein",
"ContributionGuide": "Leitfaden für Mitwirkende",
"BugReport": "Fehler melden",
"SeeAllArticles": "Alle Beiträge anzeigen",
"WelcomeToABPCommunity!": "Willkommen in der ABP Community!",
"MyProfile": "Mein Profil",
"MyOrganizations": "Meine Organisationen",
"EmailNotValid": "Bitte geben Sie eine gültige E-Mail-Adresse ein.",
"FeatureRequest": "Featureanfrage",
"CreateArticleTitleInfo": "Titel des Beitrags, der in der Beitragsliste angezeigt werden soll.",
"CreateArticleUrlInfo": "Original GitHub-/externe URL des Beitrags.",
"CreateArticleSummaryInfo": "Eine kurze Zusammenfassung des Beitrags, der in der Beitragsliste angezeigt werden soll.",
"CreateArticleCoverInfo": "Fügen Sie zum Erstellen eines effektiven Beitrags ein Titelbild hinzu. Laden Sie Bilder mit einem Seitenverhältnis von 16: 9 hoch, um die beste Ansicht zu erhalten.",
"ThisExtensionIsNotAllowed": "Diese Erweiterung ist nicht zulässig.",
"TheFileIsTooLarge": "Die Datei ist zu groß.",
"GoToTheArticle": "Gehe zum Beitrag",
"Contribute": "Beitragen",
"OverallProgress": "Gesamtfortschritt",
"Done": "Fertig",
"Open": "Offen",
"Closed": "Geschlossen",
"LatestQuestionOnThe": "Letzte Frage zum",
"Stackoverflow": "Stackoverflow",
"Votes": "Stimmen",
"Answer": "Antwort",
"Views": "Ansichten",
"Answered": "Beantwortet",
"WaitingForYourAnswer": "Warten auf Ihre Antwort",
"Asked": "gefragt",
"AllQuestions": "Alle Fragen",
"NextVersion": "Nächste Version",
"MilestoneErrorMessage": "Die aktuellen Meilensteindetails konnten von Github nicht abgerufen werden.",
"QuestionItemErrorMessage": "Die neuesten Fragendetails konnten von Stackoverflow nicht abgerufen werden.",
"Oops": "Hoppla!",
"CreateArticleSuccessMessage": "Der Beitrag wurde erfolgreich eingereicht. Er wird nach einer Überprüfung durch den Site-Administrator veröffentlicht.",
"ChooseCoverImage": "Ein Titelbild auswählen...",
"CoverImage": "Titelbild",
"ShareYourExperiencesWithTheABPFramework": "Ihre Erfahrungen mit dem ABP Framework teilen!",
"Optional": "Optional",
"UpdateUserWebSiteInfo": "Beispiel: https://johndoe.com",
"UpdateUserTwitterInfo": "Beispiel: johndoe",
"UpdateUserGithubInfo": "Beispiel: johndoe",
"UpdateUserLinkedinInfo": "Beispiel: https://www.linkedin.com/...",
"UpdateUserCompanyInfo": "Beispiel: Volosoft",
"UpdateUserJobTitleInfo": "Beispiel: Software Developer",
"UserName": "Benutzername",
"Company": "Firma",
"PersonalWebsite": "Persönliche Website",
"RegistrationDate": "Registrierungsdatum",
"Social": "Social",
"Biography": "Biographie",
"HasNoPublishedArticlesYet": "hat noch keine Beiträge veröffentlicht",
"Author": "Autor",
"LatestGithubAnnouncements": "Neueste Github-Ankündigungen",
"SeeAllAnnouncements": "Alle Ankündigungen anzeigen",
"LatestBlogPost": "Letzter Blog-Beitrag",
"Edit": "Bearbeiten",
"ProfileImageChange": "Ändern Sie das Profilbild",
"BlogItemErrorMessage": "Die neuesten Blogpost-Details konnten nicht abgerufen werden.",
"PlannedReleaseDate": "Geplantes Erscheinungsdatum",
"CommunityArticleRequestErrorMessage": "Die Anfrage nach den neuesten Beiträgen von Github konnte nicht abgerufen werden."
}
}

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

@ -83,6 +83,22 @@
"LatestBlogPost": "Latest Blog Post",
"Edit": "Edit",
"ProfileImageChange": "Change the profile image",
"BlogItemErrorMessage": "Could not get the latest blog post details from ABP."
"BlogItemErrorMessage": "Could not get the latest blog post details from ABP.",
"PlannedReleaseDate": "Planned release date",
"CommunityArticleRequestErrorMessage": "Could not get the latest article request from Github.",
"ArticleRequestFromGithubIssue": "There are not any article requests now.",
"LatestArticles": "Latest Articles",
"ArticleRequests": "Article Requests",
"AllArticleRequests": "See All Article Requests",
"SubscribeToTheNewsletter": "Subscribe to the Newsletter",
"NewsletterEmailDefinition": "Get information about happenings in ABP like new releases, free sources, articles, and more.",
"NoThanks": "No, thanks",
"MaybeLater": "Maybe later",
"JoinOurArticleNewsletter": "Join our article newsletter",
"Community": "Community",
"Marketing": "Marketing",
"CommunityPrivacyPolicyConfirmation": "I agree to the Terms & Conditions and <a href=\"https://commercial.abp.io/Privacy\">Privacy Policy</a>.",
"ArticleRequestMessageTitle": "<a href=\"https://github.com/abpframework/abp/issues/new\">Open an issue</a> on the GitHub to request an article/tutorial you want to see on this web site.",
"ArticleRequestMessageBody": "Here, the list of the requested articles by the community. Do you want to write a requested article? Please click to the request and join to the discussion."
}
}

90
abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/es.json

@ -0,0 +1,90 @@
{
"culture": "es",
"texts": {
"Permission:CommunityArticle": "Artículo de comunidad",
"Permission:Edit": "Editar",
"Waiting": "Esperando",
"Approved": "Aprobado",
"Rejected": "Rechazado",
"Wait": "Esperar",
"Approve": "Aprobar",
"Reject": "Rechazar",
"ReadArticle": "Leer artículo",
"Status": "Estado",
"ContentSource": "Fuente de contenido",
"Details": "Detalles",
"Url": "Url",
"Title": "Título",
"CreationTime": "Fecha de creación",
"Save": "Guardar",
"SameUrlAlreadyExist": "La url ya existe si tu quieres añadir este artículo, tu debes cambiar la url!",
"UrlIsNotValid": "Url no es valida",
"UrlNotFound": "Url no encontrada",
"UrlContentNotFound": "Contenido de la Url no encontrado",
"Summary": "Resumen",
"MostRead": "Más leído",
"Latest": "Últimos",
"ContributeAbpCommunity": "Contribuye a la comunidad ABP",
"SubmitYourArticle": "Envía tu artículo",
"ContributionGuide": "Guía de contribución",
"BugReport": "Informe de errores",
"SeeAllArticles": "Ver todos los artículos",
"WelcomeToABPCommunity!": "Bienvenido a la comunidad ABP",
"MyProfile": "Mi perfil",
"MyOrganizations": "Mis organizaciones",
"EmailNotValid": "Por favor entra una dirección de email válida.",
"FeatureRequest": "Solucitud de característica",
"CreateArticleTitleInfo": "Título del artículo para ser mostrado en la lista de artículos.",
"CreateArticleUrlInfo": "Url original del artículo GitHub/ Externo",
"CreateArticleSummaryInfo": "Un pequeño resumen del artículo para ser mostrado en la lista de artículos.",
"CreateArticleCoverInfo": "Para crear un artículo eficaz, agregue una foto de portada. Cargue imágenes con una relación de aspecto de 16: 9 para obtener la mejor vista.",
"ThisExtensionIsNotAllowed": "Esta extensión no está permitida.",
"TheFileIsTooLarge": "El fichero es demasiado grande.",
"GoToTheArticle": "Ir a el artículo",
"Contribute": "Contribuir",
"OverallProgress": "Progreso general",
"Done": "Hecho",
"Open": "Abrir",
"Closed": "Cerrado",
"LatestQuestionOnThe": "Última pregunta en la",
"Stackoverflow": "Stackoverflow",
"Votes": "Votos",
"Answer": "Respuesta",
"Views": "Vistas",
"Answered": "Respondido",
"WaitingForYourAnswer": "Esperando tu respuesta",
"Asked": "Preguntado",
"AllQuestions": "Todas las preguntas",
"NextVersion": "Siguiente versión",
"MilestoneErrorMessage": "No se pudieron obtener los detalles del hito actual en Github.",
"QuestionItemErrorMessage": "no se pudieron obtener los detalles de pregunta actual en Stackoverflow.",
"Oops": "Oops!",
"CreateArticleSuccessMessage": "El artículo se ha enviado correctamente. Se publicará después de una revisión del administrador del sitio.",
"ChooseCoverImage": "Elige una imagen de portada...",
"CoverImage": "Imagen de portada",
"ShareYourExperiencesWithTheABPFramework": "Comparte tus experiencias con el ABP Framework!",
"Optional": "Opcional",
"UpdateUserWebSiteInfo": "Ejemplo: https://johndoe.com",
"UpdateUserTwitterInfo": "Ejemplo: johndoe",
"UpdateUserGithubInfo": "Ejemplo: johndoe",
"UpdateUserLinkedinInfo": "Ejemplo: https://www.linkedin.com/...",
"UpdateUserCompanyInfo": "Ejemplo: Volosoft",
"UpdateUserJobTitleInfo": "Ejemplo: desarrollador de software",
"UserName": "Nombre de usuario",
"Company": "Empresa",
"PersonalWebsite": "Sitio web personal",
"RegistrationDate": "Fecha de registro",
"Social": "Social",
"Biography": "Biografía",
"HasNoPublishedArticlesYet": "No has publicado articules todavía",
"Author": "Autor",
"LatestGithubAnnouncements": "Últimas notificaciones de Github",
"SeeAllAnnouncements": "Ver todos las notificaciones",
"LatestBlogPost": "",
"Edit": "Editar",
"ProfileImageChange": "Cambiar la imagen de perfil",
"BlogItemErrorMessage": "No se pudo obtener los detalles del último blog desde ABP.",
"PlannedReleaseDate": "Fecha de entrega planificada",
"CommunityArticleRequestErrorMessage": "No se pudo obtener la última petición de artículo desde Github"
}
}

149
abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/zh-Hans.json

@ -1,64 +1,89 @@
{
"culture": "zh-Hans",
"texts": {
"Permission:CommunityArticle": "社区文章",
"Permission:Edit": "修改",
"Waiting": "等待中",
"Approved": "已批准",
"Rejected": "已拒绝",
"Wait": "等待",
"Approve": "批准",
"Reject": "拒绝",
"ReadArticle": "阅读文章",
"Status": "状态",
"ContentSource": "内容来源",
"Details": "详情",
"Url": "url",
"Title": "标题",
"CreationTime": "创建时间",
"Save": "保存",
"SameUrlAlreadyExist": "url已存在,如果你想要添加这篇文章,你需要更改url!",
"UrlIsNotValid": "Url无效.",
"UrlNotFound" : "Url未找到.",
"UrlContentNotFound": "Url内容未找到.",
"Summary": "摘要",
"MostRead": "阅读最多",
"Latest": "最新",
"ContributeAbpCommunity": "为ABP社区做贡献",
"SubmitYourArticle": "提交你的文章",
"ContributionGuide": "贡献指南",
"BugReport": "Bug报告",
"SeeAllArticles": "查看所有的文章",
"WelcomeToABPCommunity!": "欢迎来到ABP社区!",
"MyProfile": "我的资料",
"MyOrganizations": "我的组织",
"EmailNotValid": "请输入有效的电子邮箱地址.",
"FeatureRequest": "功能请求",
"CreateArticleTitleInfo": "文章标题显示在文章列表中.",
"CreateArticleUrlInfo": "文章的原始GitHub/外部URL.",
"CreateArticleSummaryInfo": "文章的简短摘要将显示在文章列表中.",
"CreateArticleCoverInfo": "为了创建有效的文章,请添加封面图. 仅支持16:9的图片!",
"ThisExtensionIsNotAllowed": "不允许此扩展名.",
"TheFileIsTooLarge": "文件过大.",
"GoToTheArticle": "转到文章",
"Contribute": "贡献",
"OverallProgress": "总体流程",
"Done": "完成",
"Open": "打开",
"Closed": "关闭",
"LatestQuestionOnThe": "有关的最新问题",
"Stackoverflow": "Stackoverflow",
"Votes": "票数",
"Answer": "回答",
"Views": "观看次数",
"Answered": "已回答",
"WaitingForYourAnswer": "等待你的回答",
"Asked": "提问",
"AllQuestions": "所有的问题",
"NextVersion": "下一个版本",
"MilestoneErrorMessage": "无法从Github获取当前的里程碑详细信息.",
"QuestionItemErrorMessage": "无法从Stackoverflow获取最新的问题详细信息.",
"Oops": "哎呀!"
}
"culture": "zh-Hans",
"texts": {
"Permission:CommunityArticle": "社区文章",
"Permission:Edit": "修改",
"Waiting": "等待中",
"Approved": "已批准",
"Rejected": "已拒绝",
"Wait": "等待",
"Approve": "批准",
"Reject": "拒绝",
"ReadArticle": "阅读文章",
"Status": "状态",
"ContentSource": "内容来源",
"Details": "详情",
"Url": "url",
"Title": "标题",
"CreationTime": "创建时间",
"Save": "保存",
"SameUrlAlreadyExist": "url已存在,如果你想要添加这篇文章,你需要更改url!",
"UrlIsNotValid": "Url无效.",
"UrlNotFound": "Url未找到.",
"UrlContentNotFound": "Url内容未找到.",
"Summary": "摘要",
"MostRead": "阅读最多",
"Latest": "最新",
"ContributeAbpCommunity": "为ABP社区做贡献",
"SubmitYourArticle": "提交你的文章",
"ContributionGuide": "贡献指南",
"BugReport": "Bug报告",
"SeeAllArticles": "查看所有的文章",
"WelcomeToABPCommunity!": "欢迎来到ABP社区!",
"MyProfile": "我的资料",
"MyOrganizations": "我的组织",
"EmailNotValid": "请输入有效的电子邮箱地址.",
"FeatureRequest": "功能请求",
"CreateArticleTitleInfo": "文章标题显示在文章列表中.",
"CreateArticleUrlInfo": "文章的原始GitHub/外部URL.",
"CreateArticleSummaryInfo": "文章的简短摘要将显示在文章列表中.",
"CreateArticleCoverInfo": "为了创建有效的文章,请添加封面图. 仅支持16:9的图片!",
"ThisExtensionIsNotAllowed": "不允许此扩展名.",
"TheFileIsTooLarge": "文件过大.",
"GoToTheArticle": "转到文章",
"Contribute": "贡献",
"OverallProgress": "总体流程",
"Done": "完成",
"Open": "打开",
"Closed": "关闭",
"LatestQuestionOnThe": "有关的最新问题",
"Stackoverflow": "Stackoverflow",
"Votes": "票数",
"Answer": "回答",
"Views": "观看次数",
"Answered": "已回答",
"WaitingForYourAnswer": "等待你的回答",
"Asked": "提问",
"AllQuestions": "所有的问题",
"NextVersion": "下一个版本",
"MilestoneErrorMessage": "无法从Github获取当前的里程碑详细信息.",
"QuestionItemErrorMessage": "无法从Stackoverflow获取最新的问题详细信息.",
"Oops": "哎呀!",
"CreateArticleSuccessMessage": "文章提交成功. 网站管理员审核通过后将被发布.",
"ChooseCoverImage": "选项一张封面图片",
"CoverImage": "封面图片",
"ShareYourExperiencesWithTheABPFramework": "分享你的ABP Framework经验!",
"Optional": "可选的",
"UpdateUserWebSiteInfo": "示例: https://johndoe.com",
"UpdateUserTwitterInfo": "示例: johndoe",
"UpdateUserGithubInfo": "示例: johndoe",
"UpdateUserLinkedinInfo": "示例: https://www.linkedin.com/...",
"UpdateUserCompanyInfo": "示例v: Volosoft",
"UpdateUserJobTitleInfo": "示例: Software Developer",
"UserName": "用户名",
"Company": "公司",
"PersonalWebsite": "个人网站",
"RegistrationDate": "注册时间",
"Social": "社交",
"Biography": "传记",
"HasNoPublishedArticlesYet": "尚未发表文章",
"Author": "作者",
"LatestGithubAnnouncements": "最新的Github公告",
"SeeAllAnnouncements": "查看所有公告",
"LatestBlogPost": "最新博客文章",
"Edit": "修改",
"ProfileImageChange": "更改资料图片",
"BlogItemErrorMessage": "无法从ABP获取最新的博客文章详细信息.",
"PlannedReleaseDate": "计划发布日期"
}
}

189
abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/de-DE.json

@ -0,0 +1,189 @@
{
"culture": "de-DE",
"texts": {
"GetStarted": "Erste Schritte - Startvorlagen",
"Create": "Erstellen",
"NewProject": "Neues Projekt",
"DirectDownload": "Direkter Download",
"ProjectName": "Proejktname",
"ProjectType": "Projekttyp",
"DatabaseProvider": "Datenbankanbieter",
"NTier": "N-Tier",
"IncludeUserInterface": "Benutzeroberfläche einschließen",
"CreateNow": "Jetzt erstellen",
"TheStartupProject": "Das Startprojekt",
"Tutorial": "Lernprogramm",
"UsingCLI": "mit CLI",
"SeeDetails": "Details ansehen",
"AbpShortDescription": "ABP Framework ist eine vollständige Infrastruktur zum Erstellen moderner Webanwendungen unter Befolgung von Best Practices und Konventionen für Softwareentwicklung.",
"SourceCodeUpper": "QUELLCODE",
"LatestReleaseLogs": "Akteulle Release",
"Infrastructure": "Infrastrutkur",
"Architecture": "Architektur",
"Modular": "Modular",
"DontRepeatYourself": "Don't Repeat Yourself",
"DeveloperFocused": "Entwickler-Zentriert",
"FullStackApplicationInfrastructure": "Full-Stack-Anwendungsinfrastruktur.",
"DomainDrivenDesign": "Domain Driven Design",
"DomainDrivenDesignExplanation": "Entworfen und entwickelt basierend auf DDD-Mustern und -Prinzipien. Bietet ein Schichtenmodell für Ihre Anwendung.",
"Authorization": "Authorization",
"AuthorizationExplanation": "Erweiterte Autorisierung mit Benutzer-, Rollen- und fein abgestimmtem Berechtigungssystem. Aufbauend auf der Microsoft Identity-Bibliothek.",
"MultiTenancy": "Multi-Tenancy",
"MultiTenancyExplanationShort": "SaaS-Anwendungen leicht gemacht! Integrierte Mandantenfähigkeit von der Datenbank bis zur Benutzeroberfläche.",
"CrossCuttingConcerns": "Cross Cutting Concerns",
"CrossCuttingConcernsExplanationShort": "Komplette Infrastruktur für Autorisierung, Validierung, Ausnahmebehandlung, Caching, Überwachungsprotokollierung, Transaktionsverwaltung und mehr.",
"BuiltInBundlingMinification": "Built-In Bundling & Minification",
"BuiltInBundlingMinificationExplanation": "Für die Bundling und Minification müssen keine externen Tools verwendet werden. ABP bietet eine einfachere, dynamische, leistungsstarke, modulare und integrierte Methode!",
"VirtualFileSystem": "Virtual File System",
"VirtualFileSystemExplanation": "Betten Sie Ansichten, Skripte, Stile, Bilder ... in Pakete/Bibliotheken ein und verwenden Sie sie in verschiedenen Anwendungen wieder.",
"Theming": "Theming",
"ThemingExplanationShort": "Verwenden und passen Sie das Bootstrap-basierte Standard-UI-Design an oder erstellen Sie Ihr eigenes.",
"BootstrapTagHelpersDynamicForms": "Bootstrap Tag Helpers & Dynamic Forms",
"BootstrapTagHelpersDynamicFormsExplanation": "Anstatt die sich wiederholenden Details von Bootstrap-Komponenten manuell zu schreiben, verwenden Sie die Tag-Helper von ABP, um diese zu vereinfachen und dabei die Vorteile von Intellisense zu nutzen. Erstellen Sie mit dem dynamischen Formular-Tag-Helfer schnell UI-Formulare basierend auf einem C#-Modell.",
"HTTPAPIsDynamicProxies": "HTTP APIs & Dynamic Proxies",
"HTTPAPIsDynamicProxiesExplanation": "Stellen Sie Anwendungsdienste automatisch als HTTP-APIs im REST-Stil bereit und verwenden Sie diese mit dynamischen JavaScript- und C#-Proxys.",
"CompleteArchitectureInfo": "Moderne Architektur zur Erstellung wartbarer Softwarelösungen.",
"DomainDrivenDesignBasedLayeringModelExplanation": "Hilft Ihnen bei der Implementierung einer DDD-basierten Schichtarchitektur und beim Aufbau einer wartbaren Codebasis.",
"DomainDrivenDesignBasedLayeringModelExplanationCont": "Bietet Startvorlagen, Abstraktionen, Basisklassen, Dienste, Dokumentation und Anleitungen, mit denen Sie Ihre Anwendung basierend auf DDD-Mustern und -Prinzipien entwickeln können.",
"MicroserviceCompatibleModelExplanation": "Das Kernframework und die vorgefertigten Module sind unter Berücksichtigung der Microservice-Architektur konzipiert.",
"MicroserviceCompatibleModelExplanationCont": "Bietet Infrastruktur, Integrationen, Beispiele und Dokumentation zur einfacheren Implementierung von Microservice-Lösungen, ohne zusätzliche Komplexität zu verursachen, wenn Sie eine monolithische Anwendung wünschen.",
"ModularInfo": "ABP bietet ein Modulsystem, mit dem Sie wiederverwendbare Anwendungsmodule entwickeln, Ereignisse im Anwendungslebenszyklus verknüpfen und Abhängigkeiten zwischen Kernteilen Ihres Systems ausdrücken können.",
"PreBuiltModulesThemes": "Vorgefertigte Module & Themes",
"PreBuiltModulesThemesExplanation": "Open Source- und kommerzielle Module und Themes stehen bereit, um in Ihrer Geschäftsanwendung verwendet zu werden.",
"NuGetNPMPackages": "NuGet- & NPM-Pakete",
"NuGetNPMPackagesExplanation": "Bereitgestellt als NuGet- & NPM-Pakete. Einfach zu installieren und zu aktualisieren.",
"ExtensibleReplaceable": "Erweiterbar/Austauschbar",
"ExtensibleReplaceableExplanation": "Alle Dienste und Module sind auf Erweiterbarkeit ausgelegt. Sie können Dienste, Seiten, Stile und Komponenten ersetzen.",
"CrossCuttingConcernsExplanation2": "Halten Sie Ihre Codebasis kleiner, damit Sie sich auf ihre geschäftsspezifischen Code konzentrieren können.",
"CrossCuttingConcernsExplanation3": "Verbringen Sie keine Zeit damit, grundlegende Anwendungsanforderungen für jedes neue Projekte zu implementieren.",
"AuthenticationAuthorization": "Authentifizierung & Autorisierung",
"ExceptionHandling": "Fehlerbehandlung",
"Validation": "Validierung",
"DatabaseConnection": "Datenbankverbindung",
"TransactionManagement": "Transaktionsmanagement",
"AuditLogging": "Audit Logging",
"Caching": "Caching",
"Multitenancy": "Multimandantenfähigkeit",
"DataFiltering": "Datenfilterung",
"ConventionOverConfiguration": "Convention Over Configuration",
"ConventionOverConfigurationExplanation": "ABP implementiert standardmäßig allgemeine Anwendungskonventionen mit einer minimalen oder Null-Konfiguration.",
"ConventionOverConfigurationExplanationList1": "Automatische Registrierung bekannter Services für Dependency Injection.",
"ConventionOverConfigurationExplanationList2": "Stellt Anwendungsdienste mittels Namenskonventionen als HTTP-APIs bereit.",
"ConventionOverConfigurationExplanationList3": "Erstellt dynamische HTTP-Client-Proxys für C# und JavaScript.",
"ConventionOverConfigurationExplanationList4": "Bietet Standard-Repositorys für Ihre Entities.",
"ConventionOverConfigurationExplanationList5": "Verwaltet die Unit-of-Work gemäß Webanforderung oder Anwendungsdienstmethode.",
"ConventionOverConfigurationExplanationList6": "Triggert Erstellungs-, Aktualisierungs- und Lösch-Events für Ihre Entities.",
"BaseClasses": "Basisklassen",
"BaseClassesExplanation": "Vorgefertigte Basisklassen für gängige Anwendungsmuster.",
"DeveloperFocusedExplanation": "ABP ist für Entwickler",
"DeveloperFocusedExplanationCont": "Es zielt darauf ab, Ihre tägliche Softwareentwicklung zu vereinfachen, ohne Sie daran zu hindern, Low-Level-Code zu schreiben.",
"SeeAllFeatures": "Alle Features anzeigen",
"CLI_CommandLineInterface": "CLI (Command Line Interface)",
"CLI_CommandLineInterfaceExplanation": "Enthält eine CLI, mit der Sie die Erstellung neuer Projekte und das Hinzufügen neuer Module automatisieren können.",
"StartupTemplates": "Startvorlagen",
"StartupTemplatesExplanation": "Verschiedene Startvorlagen bieten eine vollständig konfigurierte Lösung, um Ihre Entwicklung zu beschleunigen.",
"BasedOnFamiliarTools": "Basierend auf vertrauten Tools",
"BasedOnFamiliarToolsExplanation": "Aufbauend auf und integriert mit beliebten Tools, die Sie bereits kennen. Geringe Lernkurve, einfache Anpassung, komfortable Entwicklung.",
"ORMIndependent": "ORM-unabhängig",
"ORMIndependentExplanation": "Das Kernframework ist ORM-/datenbankunabhängig und kann mit jeder Datenquelle arbeiten. Entity Framework Core- und MongoDB-Anbieter sind bereits verfügbar.",
"Features": "Entdecken Sie die ABP Framework-Features",
"ABPCLI": "ABP CLI",
"Modularity": "Modularität",
"BootstrapTagHelpers": "Bootstrap Tag Helpers",
"DynamicForms": "Dynamische Formulare",
"BundlingMinification": "Bundling & Minification",
"BackgroundJobs": "Background Jobs",
"BackgroundJobsExplanation": "Definieren Sie einfache Klassen, um Jobs im Hintergrund in der Warteschlange auszuführen. Verwenden Sie den integrierten Jobmanager oder integrieren Sie Ihren eigenen. <a href=\"{0}\"> Hangfire </a> & <a href=\"{1}\"> RabbitMQ </a> -Integrationen sind bereits verfügbar.",
"DDDInfrastructure": "DDD-Infrastruktur",
"DomainDrivenDesignInfrastructure": "Domain Driven Design-Infrastruktur",
"AutoRESTAPIs": "Auto REST APIs",
"DynamicClientProxies": "Dynamische Client-Proxies",
"DistributedEventBus": "Distributed Event Bus",
"DistributedEventBusWithRabbitMQIntegration": "Distributed Event Bus mit RabbitMQ-Integration",
"TestInfrastructure": "Test-Infrastruktur",
"AuditLoggingEntityHistories": "Audit Logging & Entity Histories",
"ObjectToObjectMapping": "Object to Object Mapping",
"ObjectToObjectMappingExplanation": "<a href=\"{0}\"> Object to Object Mapping </a> Abstraktion mit AutoMapper-Integration.",
"EmailSMSAbstractions": "E-Mail & SMS Abstraktionen",
"EmailSMSAbstractionsWithTemplatingSupport": "E-Mail- und SMS-Abstraktionen mit Vorlagenunterstützung",
"Localization": "Lokalisierung",
"SettingManagement": "Einstellungsverwaltung",
"ExtensionMethods": "Erweiterungsmethoden",
"ExtensionMethodsHelpers": "Erweiterungsmethoden & Helfer",
"AspectOrientedProgramming": "Aspektorientierte Programmierung",
"DependencyInjection": "Dependency Injection",
"DependencyInjectionByConventions": "Dependency Injection durch Konventionen",
"ABPCLIExplanation": "ABP CLI (Command Line Interface) ist ein Befehlszeilenprogramm zum Ausführen einiger gängiger Vorgänge für ABP-basierte Lösungen.",
"ModularityExplanation": "ABP bietet eine vollständige Infrastruktur zum Erstellen eigener Anwendungsmodule, die Entities, Services, Datenbankintegration, APIs, UI-Komponenten usw. enthalten können.",
"MultiTenancyExplanation": "Das ABP-Framework unterstützt nicht nur die Entwicklung von Multi-Mandantenanwendungen, sondern macht Ihren Code von der Mandantenfähigkeit auch weitgehend unabhängig.",
"MultiTenancyExplanation2": "Kann den aktuellen Mandanten automatisch ermitteln und Daten verschiedener Mandanten voneinander isolieren.",
"MultiTenancyExplanation3": "Unterstützt einzelne Datenbank-, Datenbank-pro-Mandanten- und Hybrid-Ansätze.",
"MultiTenancyExplanation4": "Sie konzentrieren sich auf Ihren geschäftsspezifischen Code und lassen das Framework die Mandantenfähigkeit für Sie übernehmen.",
"BootstrapTagHelpersExplanation": "Anstatt die sich wiederholenden Details von Bootstrap-Komponenten manuell zu schreiben, verwenden Sie die Tag-Helper von ABP, um diese zu vereinfachen und dabei die Vorteile von Intellisense zu nutzen. Sie können Bootstrap weitherhin verwenden, wann immer Sie es benötigen.",
"DynamicFormsExplanation": "Helfer für dynamische Formular- und Input-Tags können das vollständige Formular anhand einer C#-Klasse als Model erstellen.",
"AuthenticationAuthorizationExplanation": "Umfangreiche Authentifizierungs- und Autorisierungsoptionen, die in ASP.NET Core Identity & IdentityServer4 integriert sind. Bietet ein erweiterbares und detailliertes Berechtigungssystem.",
"CrossCuttingConcernsExplanation": "Wiederholen Sie sich nicht, um all diese allgemeinen Dinge immer wieder zu implementieren. Konzentrieren Sie sich auf Ihren geschäftsspezifischen Code und lassen Sie ihn von ABP durch Konventionen automatisieren.",
"DatabaseConnectionTransactionManagement": "Datenbankverbindungs- und Transaktionsmanagement",
"CorrelationIdTracking": "Correlation-ID-Verfolgung",
"BundlingMinificationExplanation": "ABP bietet ein einfaches, dynamisches, leistungsstarkes, modulares und integriertes Bundling- und Minification-System.",
"VirtualFileSystemnExplanation": "Das virtuelle Dateisystem ermöglicht die Verwaltung von Dateien, die physisch nicht auf dem Dateisystem (Datenträger) vorhanden sind. Es wird hauptsächlich verwendet, um Dateien (js, css, image, cshtml ...) in Assemblys einzubetten und sie zur Laufzeit wie physische Dateien zu verwenden.",
"ThemingExplanation": "Mit dem Theming-System können Sie Ihre Anwendung & Module Theme-unabhängig entwickeln, indem Sie eine Reihe gemeinsamer Basisbibliotheken und Layouts definieren, die auf dem neuesten Bootstrap-Framework basieren.",
"DomainDrivenDesignInfrastructureExplanation": "Eine vollständige Infrastruktur zum Erstellen von mehrschichtigen Anwendungen basierend auf den Domain Driven Design Entwurfsmustern und -prinzipien;",
"Specification": "Specification",
"Repository": "Repository",
"DomainService": "Domain Service",
"ValueObject": "Value Object",
"ApplicationService": "Application Service",
"DataTransferObject": "Data Transfer Object",
"AggregateRootEntity": "Aggregate Root, Entity",
"AutoRESTAPIsExplanation": "ABP kann Ihre Anwendungsservices gemäß Konvention automatisch als API-Controller konfigurieren.",
"DynamicClientProxiesExplanation": "Verwenden Sie Ihre APIs ganz einfach in JavaScript- und C#-Clients.",
"DistributedEventBusWithRabbitMQIntegrationExplanation": "Veröffentlichen und konsumieren Sie Distributed Events einfach mithilfe des integrierten Distributed Event Bus mit verfügbarer RabbitMQ-Integration.",
"TestInfrastructureExplanation": "Das Framework wurde unter Berücksichtigung von Unit- und Integrationstests entwickelt. Bietet Ihnen Basisklassen, um es einfacher zu machen. Startvorlagen werden mit vorkonfiguriert Tests geliefert.",
"AuditLoggingEntityHistoriesExplanation": "Integriertes Audit Logging für geschäftskritische Anwendungen. Audit Logging auf Request-, Service-, und Methodenebene sowie Entity-Historien mit Details auf Property-Ebene.",
"EmailSMSAbstractionsWithTemplatingSupportExplanation": "IEmailSender- und ISmsSender-Abstraktionen entkoppeln Ihre Anwendungslogik von der Infrastruktur. Das erweiterte E-Mail-Vorlagensystem ermöglicht das Erstellen und Lokalisieren von E-Mail-Vorlagen und deren einfache Verwendung bei Bedarf.",
"LocalizationExplanation": "Das Lokalisierungssystem ermöglicht das Erstellen von Ressourcen in einfachen JSON-Dateien und die Lokalisierung Ihrer Benutzeroberfläche. Es unterstützt erweiterte Szenarien wie Vererbung, Erweiterungen und JavaScript-Integration und ist vollständig mit dem Lokalisierungssystem von AspNet Core kompatibel.",
"SettingManagementExplanation": "Definieren Sie Einstellungen für Ihre Anwendung und erhalten Sie zur Laufzeit Werte basierend auf der aktuellen Konfiguration, dem Mandanten und dem Benutzer.",
"ExtensionMethodsHelpersExplanation": "Wiederholen Sie sich nicht einmal für triviale Codeteile. Erweiterungen und Helfer für Standardtypen machen Ihren Code viel sauberer und einfacher zu schreiben.",
"AspectOrientedProgrammingExplanation": "Bietet eine komfortable Infrastruktur zum Erstellen dynamischer Proxys und zum Implementieren der aspektorientierten Programmierung. Fangen Sie eine Klasse ab und führen Sie Ihren Code vor und nach jeder Methodenausführung aus.",
"DependencyInjectionByConventionsExplanation": "Sie müssen Ihre Klassen nicht manuell für die Dependency Injection registrieren. Registriert gängige Servicetypen automatisch gemäß Konvention. Für andere Arten von Services können Sie Schnittstellen und Attribute verwenden, um dies einfacher gestalten und an Ort und Stelle zu ermöglichen.",
"DataFilteringExplanation": "Definieren und verwenden Sie Datenfilter, die automatisch angewendet werden, wenn Sie Entities aus der Datenbank abfragen. Soft Delete- und Multimandanten-Filter sind sofort verfügbar, wenn Sie einfache Schnittstellen implementieren.",
"PublishEvents": "Events veröffentlichen",
"HandleEvents": "Auf Events reagieren",
"AndMore": "und mehr...",
"Code": "Code",
"Result": "Resultat",
"SeeTheDocumentForMoreInformation": "Weitere Informationen finden Sie in der <a href=\"{1}\"> {0} -Dokumentation </a>",
"IndexPageHeroSection": "<span class=\"first-line shine\"><strong>Open Source</strong></span><span class=\"second-line text-uppercase\">Webanwendung<br />Framework </span><span class=\"third-line shine2\"><strong>für ASP.Net Core</strong></span>",
"UiFramework": "UI-Framework",
"EmailAddress": "E-Mail-Adresse",
"Mobile": "Mobile",
"ReactNative": "React Native",
"Strong": "Stark",
"Complete": "Vollständig",
"BasedLayeringModel": "Based Layering Model",
"Microservice": "Microservice",
"Compatible": "Kompatibel",
"MeeTTheABPCommunityInfo": "Unsere Mission ist es, eine Umgebung zu schaffen, in der Entwickler sich gegenseitig mit Beiträgen, Tutorials, Fallstudien usw. helfen und Gleichgesinnte treffen können.",
"JoinTheABPCommunityInfo": "Beteiligen Sie sich an einer lebendigen Community und tragen Sie zum ABP Framework bei!",
"AllArticles": "Alle Beiträge",
"SubmitYourArticle": "Reichen Sie Ihren Beitrag ein",
"DynamicClientProxyDocument": "In der Dokumentation zu den Dynamischen Client-Proxies finden Sie Informationen zu <a href=\"{0}\">JavaScript</a> & <a href=\"{1}\">C#</a>.",
"EmailSMSAbstractionsDocument": "Weitere Informationen finden Sie in den Unterlagen <a href=\"{0}\">E-Mail-Senden</a> and <a href=\"{1}\">SMS-Senden</a>.",
"CreateProjectWizard": "Dieser Assistent erstellt ein neues Projekt aus der Startvorlage, die ordnungsgemäß konfiguriert ist, um Ihr Projekt zu starten.",
"TieredOption": "Erstellt eine Tiered Lösung, bei der Web- und HTTP-API-Ebenen physisch getrennt sind. Wenn diese Option nicht aktiviert ist, wird eine mehrschichtige Lösung erstellt, die weniger komplex und für die meisten Szenarien geeignet ist.",
"SeparateIdentityServerOption": "Trennt die Serverseite in zwei Anwendungen: Die erste ist für den Identitätsserver und die zweite für die serverseitige HTTP-API.",
"UseslatestPreVersion": "Verwendet die neueste Vorabversion",
"ReadTheDocumentation": "<span class=\"text-primary\">Lesen Sie</span><span class=\"text-success\">Die Dokumentation</span>",
"Documentation": "Dokumentation",
"GettingStartedTutorial": "Erste Schritte Tutorial",
"ApplicationDevelopmentTutorial": "Tutorial zur Anwendungsentwicklung",
"TheStartupTemplate": "Die Startvorlage",
"InstallABPCLIInfo": "ABP CLI ist der schnellste Weg, um eine neue Lösung mit dem ABP-Framework zu starten. Installieren Sie die ABP-CLI über die Eingabeaufforderung:",
"DifferentLevelOfNamespaces": "Sie können verschiedene Ebenen von Namespaces verwenden; z.B. BookStore, Acme.BookStore or Acme.Retail.BookStore.",
"ABPCLIExamplesInfo": "Der Befehl <strong>new</strong> erstellt eine <strong>mehrschichtige MVC-Anwendung</strong> mit <strong>Entity Framework Core</strong> als Datenbankanbieter. Es gibt jedoch zusätzliche Optionen. Beispiele:",
"SeeCliDocumentForMoreInformation": "Weitere Optionen finden Sie im <a href=\"{0}\">ABP CLI-Dokument</a> oder wählen Sie oben die Registerkarte \"Direkter Download\".",
"Optional": "Optional",
"LocalFrameworkRef": "Behalten Sie die lokale Projektreferenz für die Framework-Pakete bei."
}
}

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

@ -45,7 +45,7 @@
"CompleteArchitectureInfo": "Modern architecture to create maintainable software solutions.",
"DomainDrivenDesignBasedLayeringModelExplanation": "Helps you to implement a DDD based layered architecture and build a maintainable code base.",
"DomainDrivenDesignBasedLayeringModelExplanationCont": "Provides startup templates, abstractions, base classes, services, documentation and guides to help you to develop your application based on DDD patterns & principles.",
"MicroserviceCompatibleModelExplanation": "The core framework & pre-build modules are designed the microservice architecture in mind.",
"MicroserviceCompatibleModelExplanation": "The core framework & pre-build modules are designed with microservice architecture in mind.",
"MicroserviceCompatibleModelExplanationCont": "Provides infrastructure, integrations, samples and documentation to implement microservice solutions easier, while it doesn\u2019t bring additional complexity if you want a monolithic application.",
"ModularInfo": "ABP provides a module system that allows you to develop reusable application modules, tie into application lifecycle events, and express dependencies between core parts of your system.",
"PreBuiltModulesThemes": "Pre-Built Modules & Themes",
@ -93,6 +93,7 @@
"DynamicForms": "Dynamic Forms",
"BundlingMinification": "Bundling & Minification",
"BackgroundJobs": "Background Jobs",
"BackgroundJobsExplanation": "Define simple classes to execute jobs in background as queued. Use built-in job manager or integrate your own. <a href=\"{0}\">Hangfire</a> & <a href=\"{1}\">RabbitMQ</a> integrations are already available.",
"DDDInfrastructure": "DDD Infrastructure",
"DomainDrivenDesignInfrastructure": "Domain Driven Design Infrastructure",
"AutoRESTAPIs": "Auto REST APIs",
@ -102,6 +103,7 @@
"TestInfrastructure": "Test Infrastructure",
"AuditLoggingEntityHistories": "Audit Logging & Entity Histories",
"ObjectToObjectMapping": "Object to Object Mapping",
"ObjectToObjectMappingExplanation": "<a href=\"{0}\">Object to object mapping</a> abstraction with AutoMapper integration.",
"EmailSMSAbstractions": "Email & SMS Abstractions",
"EmailSMSAbstractionsWithTemplatingSupport": "Email & SMS Abstractions with Templating Support",
"Localization": "Localization",
@ -156,6 +158,40 @@
"UiFramework": "UI Framework",
"EmailAddress": "Email address",
"Mobile": "Mobile",
"ReactNative": "React Native"
"ReactNative": "React Native",
"Strong": "Strong",
"Complete": "Complete",
"BasedLayeringModel": "Based Layering Model",
"Microservice": "Microservice",
"Compatible": "Compatible",
"MeeTTheABPCommunityInfo": "Our mission is to create an environment where developers can help each other with articles, tutorials, case studies, etc. and meet like-minded people.",
"JoinTheABPCommunityInfo": "Get involved with a vibrant community and become a contributor to the ABP Framework!",
"AllArticles": "All Articles",
"SubmitYourArticle": "Submit Your Article",
"DynamicClientProxyDocument": "See the dynamic client proxy documentations for <a href=\"{0}\">JavaScript</a> & <a href=\"{1}\">C#</a>.",
"EmailSMSAbstractionsDocument": "See the <a href=\"{0}\">emailing</a> and <a href=\"{1}\">SMS sending</a> documents for more information.",
"CreateProjectWizard": "This wizard creates a new project from the startup template which is properly configured to jump start to your project.",
"TieredOption": "Creates a tiered solution where Web and Http API layers are physically separated. If not checked, creates a layered solution which is less complex and suitable for most scenarios.",
"SeparateIdentityServerOption": "Separates server side into two applications: First one is for the identity server and the second one is for your server side HTTP API.",
"UseslatestPreVersion": "Uses latest pre-release version",
"ReadTheDocumentation": "<span class=\"text-primary\">Read</span><span class=\"text-success\">The Documentation</span>",
"Documentation": "Documentation",
"GettingStartedTutorial": "Getting Started Tutorial",
"ApplicationDevelopmentTutorial": "Application Development Tutorial",
"TheStartupTemplate": "The Startup Template",
"InstallABPCLIInfo": "ABP CLI is the fastest way to start a new solution with the ABP framework. Install the ABP CLI using a command line window:",
"DifferentLevelOfNamespaces": "You can use different level of namespaces; e.g. BookStore, Acme.BookStore or Acme.Retail.BookStore.",
"ABPCLIExamplesInfo": "<strong>new</strong> command creates a <strong>layered MVC application</strong> with <strong>Entity Framework Core</strong> as the database provider. However, it has additional options. Examples:",
"SeeCliDocumentForMoreInformation": "See the <a href=\"{0}\">ABP CLI document</a> for more options or select the \"Direct Download\" tab above.",
"Optional": "Optional",
"LocalFrameworkRef": "Keep local project reference for the framework packages.",
"BlobStoring": "BLOB Storing",
"BlobStoringExplanation": "BLOB Storing system provides an abstraction to work with BLOBs. ABP provides some pre-built storage provider integrations (Azure, AWS, File System, Database, etc.) that you can easily use in your applications.",
"TextTemplating": "Text Templating",
"TextTemplatingExplanation": "Text templating is used to dynamically render contents based on a template and a model (a data object). For example, you can use it to create dynamic email contents with a pre-built template.",
"MultipleUIOptions": "Multiple UI Options",
"MultipleDBOptions": "Multiple Database Providers",
"MultipleUIOptionsExplanation": "The core framework is designed as UI independent and can work with any type of UI system, while there are multiple pre-built and integrated options are provided out of the box.",
"MultipleDBOptionsExplanation": "The framework can work with any data source, while the following providers are officially developed and supported;"
}
}

189
abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/es.json

@ -0,0 +1,189 @@
{
"culture": "es",
"texts": {
"GetStarted": "Comencemos - Plantillas de inicio",
"Create": "Crear",
"NewProject": "Nuevo proyecto",
"DirectDownload": "Descarga directa",
"ProjectName": "Nombre de proyecto",
"ProjectType": "Tipo de proyecto",
"DatabaseProvider": "Proveedor de base de datos",
"NTier": "N-Capas",
"IncludeUserInterface": "Incluir interface de usuario",
"CreateNow": "Crear ahora",
"TheStartupProject": "El proyecto de inicio",
"Tutorial": "Tutorial",
"UsingCLI": "Usando CLI",
"SeeDetails": "Ver detalles",
"AbpShortDescription": "ABP Framework es una completa infraestructure para crear modernas aplicaciones web que sigue las mejores prácticas y convenciones de desarrollo de software.",
"SourceCodeUpper": "CÓDIGO FUENTE",
"LatestReleaseLogs": "Últimos registros de lanzamiento",
"Infrastructure": "infraestructura",
"Architecture": "Arquitectura",
"Modular": "Modular",
"DontRepeatYourself": "No te repitas tu mismo",
"DeveloperFocused": "Pensado para el desarrollador",
"FullStackApplicationInfrastructure": "infraestructura de aplicación Full stack",
"DomainDrivenDesign": "",
"DomainDrivenDesignExplanation": "Diseñado y desarrollado basandose en los patrones y principios de DDD. Promorciona una capa de modelo para tus aplicaciones.",
"Authorization": "Autorización",
"AuthorizationExplanation": "Sistema de autorización avanzado con usuarios, roles y permisos de granularidad-fina. Construido sobre la librería Microsoft Identity.",
"MultiTenancy": "Multi-inquilino",
"MultiTenancyExplanationShort": "Aplicaciones SaaS sencillas!, integradas con multi-inquilino desde la base de datos hasta la UI.",
"CrossCuttingConcerns": "Requerimientos comunes",
"CrossCuttingConcernsExplanationShort": "Completa infraestructura de autorización, validación, manejo de excepciones, caching, auditoría, gestión de transacciones y más.",
"BuiltInBundlingMinification": "Empaquetado y minificado integrado",
"BuiltInBundlingMinificationExplanation": "No se necesitan usar herramientas externas para el empaquetado y minificado. ABP ofrece un camino simple, dinámico, potente, modular e integrado.",
"VirtualFileSystem": "Sistema de ficheros virtual",
"VirtualFileSystemExplanation": "Incrusta vistas, scripts, estilos, imágenes en paquetes/ librerias y reusalos en diferentes aplicaciones.",
"Theming": "Temas",
"ThemingExplanationShort": "Usa y personaliza la UI estandar basada en bootstrap o crea tu propio tema.",
"BootstrapTagHelpersDynamicForms": "Boostrap Tag Helpers y formularios dinámicos",
"BootstrapTagHelpersDynamicFormsExplanation": "",
"HTTPAPIsDynamicProxies": "HTTP APIs y proxies dinámicos",
"HTTPAPIsDynamicProxiesExplanation": "Expon servicios de aplicación como REST HTPP APIs y consumelos dinámicamente desde proxies JavaScript y C#.",
"CompleteArchitectureInfo": "Arquitectura moderna para crear soluciones software sostenibles.",
"DomainDrivenDesignBasedLayeringModelExplanation": "Ayuda a implementar ",
"DomainDrivenDesignBasedLayeringModelExplanationCont": "Promorciona plantillas de inicio, clases base, servicios, documentación y guías de ayuda para desarrollar tu aplicación basada en patrones y principios DDD.",
"MicroserviceCompatibleModelExplanation": "El núcleo del framework y los modules pre-construidos están diseñados con una arquitectura microservicios en mente.",
"MicroserviceCompatibleModelExplanationCont": "Proporciona la infraestructura, integraciones, ejemplos y documentación para implementar soluciones microservicios más facilmente, mientras no trae complejidad adicional si quieres una aplicación monolítica.",
"ModularInfo": "ABP proporciona un sistema de modulos que te permite desarrollar modulos de aplicacion resusables. Conectado en el ciclo de eventos de aplicación y mínimas dependencias entre las partes principales de tu sistema.",
"PreBuiltModulesThemes": "Modulos y temas integrados",
"PreBuiltModulesThemesExplanation": "Módulos y temas de código abierto y comerciales preparados para usar en tu aplicación de negocio.",
"NuGetNPMPackages": "Paquetes Nuget y NPM",
"NuGetNPMPackagesExplanation": "Paquetes distribuidos a través de Nuget y NPM para instalar y actualizar.",
"ExtensibleReplaceable": "Extensible/ Reemplazable",
"ExtensibleReplaceableExplanation": "Todos los serivios y módulos están diseñados para ser extensibles. Tu puedes reemplazar servicios, páginas, estilos y componentes.",
"CrossCuttingConcernsExplanation2": "Mantiene tu código base más pequeño y te permite enforcate en el código que es especifico en tu negocio.",
"CrossCuttingConcernsExplanation3": "No pierdas tiempo implementando requerimientos comunes de aplicación en múltiples proyectos.",
"AuthenticationAuthorization": "Autenticación y autorización",
"ExceptionHandling": "Manejo de excepciones.",
"Validation": "Validación",
"DatabaseConnection": "Conexión a la base de datos",
"TransactionManagement": "Gestión de transacciones",
"AuditLogging": "Registro de auditoría",
"Caching": "Caché",
"Multitenancy": "Multi-inquilino",
"DataFiltering": "Filtrado de datos",
"ConventionOverConfiguration": "Convención sobre la configuración",
"ConventionOverConfigurationExplanation": "ABP implementa comunes convenciones de aplicación por defecto con una mínima o nula configuración.",
"ConventionOverConfigurationExplanationList1": "Los registradores conocen los servicios para la inyección de dependencias.",
"ConventionOverConfigurationExplanationList2": "Expone servicios de aplicación como APIs HTTP mediante convenciones de nomenclatura.",
"ConventionOverConfigurationExplanationList3": "Crea clientes proxies HTTP dinámicos para C# y JavaScript.",
"ConventionOverConfigurationExplanationList4": "Proporciona repositorios por defecto para tus entidades.",
"ConventionOverConfigurationExplanationList5": "Maneja Unit of Work por cada petición web o metodo de servicio de aplicación.",
"ConventionOverConfigurationExplanationList6": "Publica, crea, actualiza y borra eventos para tus entidades.",
"BaseClasses": "Clase base",
"BaseClassesExplanation": "Clases base integradas para patrones comunes de aplicación.",
"DeveloperFocusedExplanation": "ABP es para desarrolladores.",
"DeveloperFocusedExplanationCont": "Su objetivo es simplificar su desarrollo diario de software sin restringirle la escritura de código de bajo nivel.",
"SeeAllFeatures": "Ver todas las características",
"CLI_CommandLineInterface": "CLI (Command Line Interface)",
"CLI_CommandLineInterfaceExplanation": "Incluye un CLI que te ayuda a automatizar la creación de nuevos proyectos y añadir nuevos módulos.",
"StartupTemplates": "Plantillas de inicio",
"StartupTemplatesExplanation": "Varias plantillas de inicio proporcionan una solución completamente configurada lista para comenzar el desarrollo.",
"BasedOnFamiliarTools": "Basado en herramientas familiares",
"BasedOnFamiliarToolsExplanation": "Construido y diseñado con herramientas populares que tu ya conoces. Baja curva de aprendizaje, facil adaptación y desarrollo confortable.",
"ORMIndependent": "Independiente del ORM",
"ORMIndependentExplanation": "El núcleo del core es independiente del ORM/ base de datos y puedes trabajar con cualquier fuente de datos. Entity Framework Core y MongoDB están actualmente disponibles.",
"Features": "Explora las características de ABP Framework",
"ABPCLI": "ABP CLI",
"Modularity": "Modularidad",
"BootstrapTagHelpers": "Bootstrap Tag Helpers",
"DynamicForms": "Formularios dinámicos",
"BundlingMinification": "Empaquetado y Minimificación",
"BackgroundJobs": "",
"BackgroundJobsExplanation": "Defina clases simples para ejecutar trabajos en segundo plano como en cola. Utilice el administrador de trabajos integrado o integre el suyo propio. <a href=\"{0}\">Hangfire</a> & <a href=\"{1}\">RabbitMQ</a> integraciones están actualmente disponibles.",
"DDDInfrastructure": "infraestructura DSS",
"DomainDrivenDesignInfrastructure": "infraestructura Domain Driven Design",
"AutoRESTAPIs": "Auto REST APIs",
"DynamicClientProxies": "Clientes proxies dinámicos",
"DistributedEventBus": "Bus de eventos distribuido",
"DistributedEventBusWithRabbitMQIntegration": "Bus de eventos distribuido con la integración RabbitMQ ",
"TestInfrastructure": "infraestructura de Test",
"AuditLoggingEntityHistories": "Registro de auditoría y historial de entidades",
"ObjectToObjectMapping": "Mapeado objeto a objeto",
"ObjectToObjectMappingExplanation": "<a href=\"{0}\">Mapeado objeto a objeto</a> abstracción integrada con AutoMapper.",
"EmailSMSAbstractions": "Abstracciones para Email y SMS",
"EmailSMSAbstractionsWithTemplatingSupport": "Abstracciones para Email y SMS con soporte para plantillas",
"Localization": "Localización",
"SettingManagement": "Gestión de la configuración",
"ExtensionMethods": "Extension Methods",
"ExtensionMethodsHelpers": "Extension Methods & Helpers",
"AspectOrientedProgramming": "Programación orientada a aspectos",
"DependencyInjection": "Inyección de dependencias",
"DependencyInjectionByConventions": "Inyección de dependencias por convenciones",
"ABPCLIExplanation": "ABP CLI (Command Line Interface) es una herramienta en línea de comandos que proporciona ciertas tareas comunes para soluciones basadas en ABP.",
"ModularityExplanation": "ABP proporciona una infraestructura completa para construir tu propios módulos de aplicación que pueden contener entidades, servicios, base de datos integradas, APIs, componentes de UI y otros...",
"MultiTenancyExplanation": "ABP framework no sólo soporta el desarrollo de aplicaciones multi-inquilino, si no también hace que tu código no tenga que preocuparse de multi-inquilino.",
"MultiTenancyExplanation2": "Puedes determinar automaticamente el inquilino actual, y aislar los datos de diferentes inquilinos entre sí. ",
"MultiTenancyExplanation3": "Soporta base de datos única, base de datos por inquilino y enfoques híbridos.",
"MultiTenancyExplanation4": "Enfocate en tu código y deja al framework que maneje multi-inquilino en tu nombre.",
"BootstrapTagHelpersExplanation": "En vez de escribir repetidamente los detalle de componentes bootstrap, usa ABP's tag helpers para simplificarlo y obtener ventaja de intellisence. Tu puedes definitivamente usar Bootstrp cuando tu lo necesites.",
"DynamicFormsExplanation": "Los formularios dinámicos y tag helpers de entrada pueden crear el formulario completo a partir de una clase de C# como modelo. ",
"AuthenticationAuthorizationExplanation": "Autenticación enriquecidad y opciones de autorización integradas con ASP.NET Core Identity & IdentityServer4. Proporciona un extensible y detallado sistema de permisos.",
"CrossCuttingConcernsExplanation": "No te repitas tu mismo al implementar todas esas cosas comunes una y otra vez. Enfocate en tu negocio y permite a ABP automatizarlos por convención.",
"DatabaseConnectionTransactionManagement": "Conexión de base de datos y gestión de transacciones",
"CorrelationIdTracking": "Correlation-Id de seguimiento",
"BundlingMinificationExplanation": "ABP ofrece un sistema simple, dinámico, potente, modular y empaquetado & minificación ",
"VirtualFileSystemnExplanation": "El sistema de archivos virtuales permite administrar archivos que no existen físicamente en el sistema de archivos (disco). Se utiliza principalmente para incrustar (js, css, image, cshtml...) en ensamblados y utilizarlos como archivos físicos en tiempo de ejecución.",
"ThemingExplanation": "El sistema de temas permite desarrollar el tema de su aplicación y módulos independiente mediante la definición de un conjunto de bibliotecas y diseños base comunes, basado en el último marco de Trabajo bootstrap.",
"DomainDrivenDesignInfrastructureExplanation": "Una infraestructura completa para crear aplicaciones en capas basadas en los patrones y principios DDD",
"Specification": "Especificación",
"Repository": "Repositorios",
"DomainService": "Servicio de dominio",
"ValueObject": "Objetos de valor",
"ApplicationService": "Servicio de aplicación",
"DataTransferObject": "Objetos de transferencia de datos",
"AggregateRootEntity": "Agregado ráiz, Entidad",
"AutoRESTAPIsExplanation": "ABP puede configurar automáticamente los servicios de aplicación como controladores de API por convención.",
"DynamicClientProxiesExplanation": "Consuma fácilmente sus API de clientes de JavaScript y C#",
"DistributedEventBusWithRabbitMQIntegrationExplanation": "Publique y consuma eventos distribuidos fácilmente mediante el bus de eventos distribuido integrado con la integración RabbitMQ disponible.",
"TestInfrastructureExplanation": "El framework se ha desarrollado unitariamente y pruebas de integración. Proporciona clases base para que sea más fácil. Las plantillas de inicio vienen preconfiguradas para las pruebas.",
"AuditLoggingEntityHistoriesExplanation": "Registro de auditoría integrado para aplicaciones críticas para el negocio. Registro de auditorías de solicitud, servicio, nivel de método e historiales de entidades con detalles de nivel de propiedad.",
"EmailSMSAbstractionsWithTemplatingSupportExplanation": "Las abstracciones IEmailSender e ISmsSender desacoplan la lógica de la aplicación de la infraestructura. El sistema avanzado de plantillas de correo electrónico permite crear y localizar plantillas de correo electrónico y utilizarlas fácilmente cuando sea necesario.",
"LocalizationExplanation": "El sistema de localización permite crear recursos en archivos JSON sin formato y utilizarlos para localizar la interfaz de usuario. Admite escenarios avanzados como herencia, extensiones e integración de JavaScript, mientras que es totalmente compatible con el sistema de localización de AspNet Core.",
"SettingManagementExplanation": "Defina la configuración de la aplicación y obtenga valores en tiempo de ejecución en función de la configuración actual, el inquilino y el usuario.",
"ExtensionMethodsHelpersExplanation": "No te repitas ni siquiera para partes de código triviales. Extensiones y ayudantes para tipos estándar hace que su código sea mucho más limpio y fácil de escribir.",
"AspectOrientedProgrammingExplanation": "Proporciona una infraestructura cómoda para crear servidores proxy dinámicos e implementar la programación orientada a aspectos. Interceptar cualquier clase y ejecutar el código antes y después de cada ejecución del método.",
"DependencyInjectionByConventionsExplanation": "No es necesario registrar las clases en la inserción de dependencias manualmente. Registra automáticamente los tipos de servicio comunes por convención. Para otro tipo de servicios, puede utilizar interfaces y atributos para que sea más fácil y in situ.",
"DataFilteringExplanation": "Definir y usar filtros de datos que se aplican automáticamente al consultar entidades desde la base de datos. Los filtros Soft Delete & MultiTenant se proporcionan de fábrica cuando se implementan interfaces sencillas.",
"PublishEvents": "Publicar eventos",
"HandleEvents": "Manejar eventos",
"AndMore": "y más...",
"Code": "Código",
"Result": "Resultado",
"SeeTheDocumentForMoreInformation": "Ver el <a href=\"{1}\">{0} documento</a> para más información.",
"IndexPageHeroSection": "<span class=\"first-line shine\"><strong>Código fuente abierto</strong></span><span class=\"second-line text-uppercase\">Web Application<br />Framework </span><span class=\"third-line shine2\"><strong>para asp.net core</strong></span>",
"UiFramework": "UI Framework",
"EmailAddress": "Dirección de correo",
"Mobile": "Móvil",
"ReactNative": "React Nativo",
"Strong": "Fuerte",
"Complete": "Completar",
"BasedLayeringModel": "Módelo basado en capas",
"Microservice": "Microservicio",
"Compatible": "Compatible",
"MeeTTheABPCommunityInfo": "Nuestra misión es crear un entorno en el que los desarrolladores puedan ayudarse entre sí con artículos, tutoriales, estudios de casos, etc. y conocer personas de ideas afines.",
"JoinTheABPCommunityInfo": "¡Participe en una comunidad vibrante y conviértase en colaborador del Marco ABP!",
"AllArticles": "Todos los artículos",
"SubmitYourArticle": "Envía tu artículo",
"DynamicClientProxyDocument": "Ver la documentación del cliente proxy dinámico para <a href=\"{0}\">JavaScript</a> & <a href=\"{1}\">C#</a>.",
"EmailSMSAbstractionsDocument": "Ver los documentos de <a href=\"{0}\">emailing</a> y <a href=\"{1}\">envío SMS </a> para más información.",
"CreateProjectWizard": "Este asistente crea un nuevo proyecto a partir de la plantilla de inicio que está correctamente configurado para comenzar con su proyecto.",
"TieredOption": "Crea una solución por niveles en la que las capas de API Web y HTTP están separadas físicamente. Si no se marca, crea una solución en capas que es menos compleja y adecuada para la mayoría de los escenarios.",
"SeparateIdentityServerOption": "Separa el lado del servidor en dos aplicaciones: la primera es para el servidor de identidad y la segunda es para la API HTTP del lado del servidor.",
"UseslatestPreVersion": "Usar la última versión pre-release",
"ReadTheDocumentation": "<span class=\"text-primary\">Leer</span><span class=\"text-success\">La Documentación</span>",
"Documentation": "Documentación",
"GettingStartedTutorial": "Tutorial para iniciarse",
"ApplicationDevelopmentTutorial": "Tutorial de desarrollo de aplicación",
"TheStartupTemplate": "La Plantilla de Inicio",
"InstallABPCLIInfo": "ABP CLI es la forma más rápida de iniciar una nueva solución con el marco ABP. Instale la CLI de ABP mediante una ventana de línea de comandos:",
"DifferentLevelOfNamespaces": "Tu puedes usar diferentes niveles de espacio de nombres; ej. BookStore, Acme.BookStore or Acme.Retail.BookStore.",
"ABPCLIExamplesInfo": "<strong>nuevo</strong> comando crea una <strong>aplicación MVC por capas</strong> con <strong>Entity Framework Core</strong> como proveedor de base de datos. Sin embargo, tiene distintas opciones. Ejemplos:",
"SeeCliDocumentForMoreInformation": "Ver el <a href=\"{0}\">documento ABP CLI </a> para más opciones o selecciona la \"Direct Download\" pestaña de arriba.",
"Optional": "Opcional",
"LocalFrameworkRef": "Mantén la referencia al proyecto local para los paquetes del framework."
}
}

43
abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/zh-Hans.json

@ -89,10 +89,11 @@
"Features": "功能",
"ABPCLI": "ABP CLI",
"Modularity": "模块化",
"BootstrapTagHelpers": "Bootstrap Tag Helpers",
"BootstrapTagHelpers": "Bootstrap 标签助手",
"DynamicForms": "动态表单",
"BundlingMinification": "Bundling & Minification",
"BackgroundJobs": "后台作业",
"BackgroundJobsExplanation": "定义简单的类以在队列中在后台执行作业. 使用内置的作业管理器或集成你自己的作业管理器. <a href=\"{0}\">Hangfire</a> & <a href=\"{1}\">RabbitMQ</a>集成已经可用.",
"DDDInfrastructure": "DDD基础设施",
"DomainDrivenDesignInfrastructure": "Domain Driven Design基础设施",
"AutoRESTAPIs": "自动REST APIs",
@ -102,6 +103,7 @@
"TestInfrastructure": "测试基础设施",
"AuditLoggingEntityHistories": "审计日志和实体历史",
"ObjectToObjectMapping": "对象映射",
"ObjectToObjectMappingExplanation": "<a href=\"{0}\">对象到对象映射</a> 抽象AutoMapper集成.",
"EmailSMSAbstractions": "电子邮件和短信抽象",
"EmailSMSAbstractionsWithTemplatingSupport": "具有模板支持的电子邮件和短信抽象",
"Localization": "本土化",
@ -112,7 +114,7 @@
"DependencyInjection": "依赖注入",
"DependencyInjectionByConventions": "依据约定的依赖注入",
"ABPCLIExplanation": "ABP CLI(命令行界面)是用于对ABP解决方案执行常见操作的命令行工具.",
"ModularityExplanation": "ABP提供了一个完整的基础设施来构建你自己的应用程序模块,这些模块可能具有实体,服务,数据库集成,API,UI组件等.", //TODO: strong "your own application modules",-
"ModularityExplanation": "ABP提供了一个完整的基础设施来构建你自己的应用程序模块,这些模块可能具有实体,服务,数据库集成,API,UI组件等.",
"MultiTenancyExplanation": "ABP框架不仅支持开发多租户应用程序,而且使你的代码几乎无需知道多租户.",
"MultiTenancyExplanation2": "可以自动确定当前租户,将不同租户的数据相互隔离.",
"MultiTenancyExplanation3": "支持单一数据库,或每个租户单独数据库或者混合方式.",
@ -154,6 +156,41 @@
"SeeTheDocumentForMoreInformation": "查看<a href=\"{1}\">{0} 文档</a>获得更多信息",
"IndexPageHeroSection": "<span class=\"third-line shine2\"><strong>asp.net core的</strong></span><span class=\"first-line shine\"><strong>开源</strong></span><span class=\"second-line text-uppercase\">Web应用程序<br />框架 </span>",
"UiFramework": "UI框架",
"EmailAddress": "电子邮件地址"
"EmailAddress": "电子邮件地址",
"Mobile": "移动",
"ReactNative": "React Native",
"Strong": "强大的",
"Complete": "完整的",
"BasedLayeringModel": "基于分层模型",
"Microservice": "微服务",
"Compatible": "兼容",
"MeeTTheABPCommunityInfo": "我们的使命是创建一个环境使开发人员可以在文章,教程,案例研究等方面互相帮助并结识志趣相投的人.",
"JoinTheABPCommunityInfo": "参与充满活力的社区并成为ABP框架的贡献者",
"AllArticles": "所有的文章",
"SubmitYourArticle": "提交你的文章",
"DynamicClientProxyDocument": "参阅<a href=\"{0}\">JavaScript</a> & <a href=\"{1}\">C#</a>的动态客户端代理文档.",
"EmailSMSAbstractionsDocument": "参阅<a href=\"{0}\">emailing</a> 和 <a href=\"{1}\">SMS sending</a> 文档获得更多信息.",
"CreateProjectWizard": "此向导让你从启动模板创建一个新项目,该启动模板已正确配置为可以快速启动你的项目.",
"TieredOption": "创建一个分层解决方案,其中Web和Http API层在物理上是分离的. 如果没有选中则创建一个不那么复杂且适合大多数场景的分层解决方案.",
"SeparateIdentityServerOption": "将服务器端分离为两个应用程序:第一个应用程序用于身份服务器,第二个应用程序用于服务器端HTTP API.",
"UseslatestPreVersion": "使用最新的预发布版本",
"ReadTheDocumentation": "<span class=\"text-primary\">阅读</span><span class=\"text-success\">文档</span>",
"Documentation": "文档",
"GettingStartedTutorial": "入门教程",
"ApplicationDevelopmentTutorial": "应用程序开发教程",
"TheStartupTemplate": "启动模板",
"InstallABPCLIInfo": "ABP CLI是使用ABP框架启动新解决方案的最快方式. 使用命令行窗口安装ABP CLI:",
"DifferentLevelOfNamespaces": "你可以使用不同级别的名称空间. 例如 BookStore, Acme.BookStore 或 Acme.Retail.BookStore",
"ABPCLIExamplesInfo": "<strong>new</strong>命令创建一个 <strong>分层的MVC应用程序</strong> 使用 <strong>Entity Framework Core</strong> 做为数据库提供程序. 它还有其他选项. 示例:",
"SeeCliDocumentForMoreInformation": "参阅 <a href=\"{0}\">ABP CLI 文档</a> 获得更多选项或选择上方的 \"直接下载\" 标签.",
"Optional": "可选的",
"LocalFrameworkRef": "保留框架包的本地项目引用.",
"BlobStoring": "BLOB存储",
"BlobStoringExplanation": "BLOB存储系统提供了BLOB的抽象. ABP提供了一些预构建的存储提供程序集成(Azure,AWS,文件系统,数据库等),你可以轻松的在你的应用程序中使用它们.",
"TextTemplating": "文本模板",
"TextTemplatingExplanation": "文本模板是基于模板和模型(数据对象)使用动态渲染内容. 例如你可以使用预构建的模板来创建动态的电子邮件内容.",
"MultipleUIOptions": "多个UI选项",
"MultipleDBOptions": "多个数据库提供程序",
"MultipleUIOptionsExplanation": "核心框架设计为独立与UI,可以和任何类型的UI系统一起使用. 同时提供了多个开箱即用的预构建集成选项."
}
}

6
build/common.ps1

@ -16,7 +16,9 @@ $solutionPaths = @(
"../modules/tenant-management",
"../modules/audit-logging",
"../modules/background-jobs",
"../modules/account"
"../modules/account",
"../modules/cms-kit",
"../modules/blob-storing-database"
)
if ($full -eq "-f")
@ -29,6 +31,8 @@ if ($full -eq "-f")
"../modules/blogging",
"../templates/module/aspnet-core",
"../templates/app/aspnet-core",
"../templates/console",
"../templates/wpf",
"../abp_io/AbpIoLocalization"
)
}else{

11
common.DotSettings

@ -20,6 +20,17 @@
<s:String x:Key="/Default/CodeStyle/Generate/=Overrides/Options/=Async/@EntryIndexedValue">False</s:String>
<s:String x:Key="/Default/CodeStyle/Generate/=Overrides/Options/=Mutable/@EntryIndexedValue">False</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=SQL/@EntryIndexedValue">SQL</s:String>
<s:Boolean x:Key="/Default/Environment/InlayHints/CppTypeNameHintsOptions/HideTypeNameHintsWhenTypeNameIsEvidentFromVariableName/@EntryValue">False</s:Boolean>
<s:String x:Key="/Default/Environment/InlayHints/CppTypeNameHintsOptions/ShowMethodReturnTypeNameHints/@EntryValue">Never</s:String>
<s:String x:Key="/Default/Environment/InlayHints/CppTypeNameHintsOptions/ShowTypeNameHintsForImplicitlyTypedVariables/@EntryValue">Never</s:String>
<s:Boolean x:Key="/Default/Environment/InlayHints/CSharpTypeNameHintsOptions/HideTypeNameHintsWhenTypeNameIsEvidentFromVariableName/@EntryValue">False</s:Boolean>
<s:String x:Key="/Default/Environment/InlayHints/CSharpTypeNameHintsOptions/ShowMethodReturnTypeNameHints/@EntryValue">Never</s:String>
<s:String x:Key="/Default/Environment/InlayHints/CSharpTypeNameHintsOptions/ShowTypeNameHintsForImplicitlyTypedVariables/@EntryValue">Never</s:String>
<s:String x:Key="/Default/Environment/InlayHints/CSharpTypeNameHintsOptions/ShowTypeNameHintsForLambdaExpressionParameters/@EntryValue">Never</s:String>
<s:String x:Key="/Default/Environment/InlayHints/CSharpTypeNameHintsOptions/ShowTypeNameHintsForLinqQueryRangeVariables/@EntryValue">Never</s:String>
<s:String x:Key="/Default/Environment/InlayHints/CSharpTypeNameHintsOptions/ShowTypeNameHintsForPatternMatchingExpressions/@EntryValue">Never</s:String>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EFeature_002EServices_002ECpp_002EDaemon_002ETypeNameHints_002ECppTypeNameHintsOptionsMigration/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EFeature_002EServices_002ECSharp_002ETypeNameHints_002ECSharpTypeNameHintsOptionsMigration/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/TypeNameHintsOptions/HideTypeNameHintsWhenTypeNameIsEvidentFromVariableName/@EntryValue">False</s:Boolean>
<s:Boolean x:Key="/Default/Environment/TypeNameHintsOptions/ShowMethodReturnTypeNameHints/@EntryValue">False</s:Boolean>
<s:Boolean x:Key="/Default/Environment/TypeNameHintsOptions/ShowTypeNameHintsForImplicitlyTypedVariables/@EntryValue">False</s:Boolean>

6
common.props

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

35
docs/en/API/Auto-API-Controllers.md

@ -75,17 +75,48 @@ Configure<AbpAspNetCoreMvcOptions>(options =>
Then the route for getting a book will be '**/api/volosoft/book-store/book/{id}**'. This sample uses two-level root path, but you generally use a single level depth.
* Continues with the **normalized controller/service name**. Normalization removes 'AppService', 'ApplicationService' and 'Service' postfixes and converts it to **camelCase**. If your application service class name is 'BookAppService' then it becomes only '/book'.
* Continues with the **normalized controller/service name**. Normalization removes 'AppService', 'ApplicationService' and 'Service' postfixes and converts it to **kebab-case**. If your application service class name is 'ReadingBookAppService' then it becomes only '/reading-book'.
* If you want to customize naming, then set the `UrlControllerNameNormalizer` option. It's a func delegate which allows you to determine the name per controller/service.
* If the method has an '**id**' parameter then it adds '**/{id}**' ro the route.
* Then it adds the action name if necessary. Action name is obtained from the method name on the service and normalized by;
* Removing '**Async**' postfix. If the method name is 'GetPhonesAsync' then it becomes 'GetPhones'.
* Removing **HTTP method prefix**. 'GetList', 'GetAll', 'Get', 'Put', 'Update', 'Delete', 'Remove', 'Create', 'Add', 'Insert', 'Post' and 'Patch' prefixes are removed based on the selected HTTP method. So, 'GetPhones' becomes 'Phones' since 'Get' prefix is a duplicate for a GET request.
* Converting the result to **camelCase**.
* Converting the result to **kebab-case**.
* If the resulting action name is **empty** then it's not added to the route. If it's not empty, it's added to the route (like '/phones'). For 'GetAllAsync' method name it will be empty, for 'GetPhonesAsync' method name it will be 'phones'.
* Normalization can be customized by setting the `UrlActionNameNormalizer` option. It's an action delegate that is called for every method.
* If there is another parameter with 'Id' postfix, then it's also added to the route as the final route segment (like '/phoneId').
#### Customizing the Route Calculation
`IConventionalRouteBuilder` is used to build the route. It is implemented by the `ConventionalRouteBuilder` by default and works as explained above. You can replace/override this service to customize the route calculation strategy.
#### Version 3.x Style Route Calculation
The route calculation was different before the version 4.0. It was using camelCase conventions, while the ABP Framework version 4.0+ uses kebab-case. If you use the old route calculation strategy, follow one of the approaches;
* Set `UseV3UrlStyle` to `true` in the options of the `options.ConventionalControllers.Create(...)` method. Example:
````csharp
options.ConventionalControllers
.Create(typeof(BookStoreApplicationModule).Assembly, opts =>
{
opts.UseV3UrlStyle = true;
});
````
This approach effects only the controllers for the `BookStoreApplicationModule`.
* Set `UseV3UrlStyle` to `true` for the `AbpConventionalControllerOptions` to set it globally. Example:
```csharp
Configure<AbpConventionalControllerOptions>(options =>
{
options.UseV3UrlStyle = true;
});
```
Setting it globally effects all the modules in a modular application.
## Service Selection
Creating conventional HTTP API controllers are not unique to application services actually.

53
docs/en/API/Dynamic-CSharp-API-Clients.md

@ -1,10 +1,23 @@
# Dynamic C# API Clients
# Dynamic C# API Client Proxies
ABP can dynamically create C# API client proxies to call remote HTTP services (REST APIs). In this way, you don't need to deal with `HttpClient` and other low level HTTP features to call remote services and get results.
ABP can dynamically create C# API client proxies to call your remote HTTP services (REST APIs). In this way, you don't need to deal with `HttpClient` and other low level details to call remote services and get results.
Dynamic C# proxies automatically handles the following stuff for you;
* Maps C# **method calls** to remote server **HTTP calls** by considering the HTTP method, route, query string parameters, request payload and other details.
* **Authenticates** the HTTP Client by adding access token to the HTTP header.
* **Serializes** to and deserialize from JSON.
* Handles HTTP API **versioning**.
* Add **correlation id**, current **tenant** id and the current **culture** to the request.
* Properly **handles the error messages** sent by the server and throws proper exceptions.
This system can be used by any type of .NET client to consume your HTTP APIs.
## Service Interface
Your service/controller should implement an interface that is shared between the server and the client. So, first define a service interface in a shared library project. Example:
Your service/controller should implement an interface that is shared between the server and the client. So, first define a service interface in a shared library project, typically in the `Application.Contracts` project if you've created your solution using the startup templates.
Example:
````csharp
public interface IBookAppService : IApplicationService
@ -13,7 +26,7 @@ public interface IBookAppService : IApplicationService
}
````
Your interface should implement the `IRemoteService` interface to be automatically discovered. Since the `IApplicationService` inherits the `IRemoteService` interface, the `IBookAppService` above satisfies this condition.
> Your interface should implement the `IRemoteService` interface to be automatically discovered. Since the `IApplicationService` inherits the `IRemoteService` interface, the `IBookAppService` above satisfies this condition.
Implement this class in your service application. You can use [auto API controller system](Auto-API-Controllers.md) to expose the service as a REST API endpoint.
@ -55,6 +68,8 @@ public class MyClientAppModule : AbpModule
`AddHttpClientProxies` method gets an assembly, finds all service interfaces in the given assembly, creates and registers proxy classes.
> The startup templates already comes pre-configured for the client proxy generation, in the `HttpApi.Client` project.
### Endpoint Configuration
`RemoteServices` section in the `appsettings.json` file is used to get remote service address by default. Simplest configuration is shown below:
@ -106,7 +121,7 @@ While you can inject `IBookAppService` like above to use the client proxy, you c
### AbpRemoteServiceOptions
`AbpRemoteServiceOptions` is automatically set from the `appsettings.json` by default. Alternatively, you can use `Configure` method to set or override it. Example:
`AbpRemoteServiceOptions` is automatically set from the `appsettings.json` by default. Alternatively, you can configure it in the `ConfigureServices` method of your [module](../Module-Development-Basics.md) to set or override it. Example:
````csharp
public override void ConfigureServices(ServiceConfigurationContext context)
@ -162,4 +177,30 @@ context.Services.AddHttpClientProxies(
Using `asDefaultServices: false` may only be needed if your application has already an implementation of the service and you do not want to override/replace the other implementation by your client proxy.
> If you disable `asDefaultServices`, you can only use `IHttpClientProxy<T>` interface to use the client proxies. See the *IHttpClientProxy Interface* section above.
> If you disable `asDefaultServices`, you can only use `IHttpClientProxy<T>` interface to use the client proxies. See the *IHttpClientProxy Interface* section above.
### Retry/Failure Logic & Polly Integration
If you want to add retry logic for the failing remote HTTP calls for the client proxies, you can configure the `AbpHttpClientBuilderOptions` in the `PreConfigureServices` method of your module class.
**Example: Use the [Polly](https://github.com/App-vNext/Polly) library to re-try 3 times on a failure**
````csharp
public override void PreConfigureServices(ServiceConfigurationContext context)
{
PreConfigure<AbpHttpClientBuilderOptions>(options =>
{
options.ProxyClientBuildActions.Add((remoteServiceName, clientBuilder) =>
{
clientBuilder.AddTransientHttpErrorPolicy(policyBuilder =>
policyBuilder.WaitAndRetryAsync(
3,
i => TimeSpan.FromSeconds(Math.Pow(2, i))
)
);
});
});
}
````
This example uses the [Microsoft.Extensions.Http.Polly](https://www.nuget.org/packages/Microsoft.Extensions.Http.Polly) package. You also need to import the `Polly` namespace (`using Polly;`) to be able to use the `WaitAndRetryAsync` method.

68
docs/en/Application-Services.md

@ -342,12 +342,12 @@ public class DistrictAppService
{
}
protected override async Task DeleteByIdAsync(DistrictKey id)
protected async override Task DeleteByIdAsync(DistrictKey id)
{
await Repository.DeleteAsync(d => d.CityId == id.CityId && d.Name == id.Name);
}
protected override async Task<District> GetEntityByIdAsync(DistrictKey id)
protected async override Task<District> GetEntityByIdAsync(DistrictKey id)
{
return await AsyncQueryableExecuter.FirstOrDefaultAsync(
Repository.Where(d => d.CityId == id.CityId && d.Name == id.Name)
@ -400,7 +400,7 @@ public class MyPeopleAppService : CrudAppService<Person, PersonDto, Guid>
{
}
protected override async Task CheckDeletePolicyAsync()
protected async override Task CheckDeletePolicyAsync()
{
await AuthorizationService.CheckAsync("...");
}
@ -445,6 +445,68 @@ These methods are used to convert Entities to DTOs and vice verse. They uses the
* `MapToEntityAsync(TCreateInput)` is used to create an entity from `TCreateInput`.
* `MapToEntityAsync(TUpdateInput, TEntity)` is used to update an existing entity from `TUpdateInput`.
## Miscellaneous
### Working with Streams
`Stream` object itself is not serializable. So, you may have problems if you directly use `Stream` as the parameter or the return value for your application service. ABP Framework provides a special type, `IRemoteStreamContent` to be used to get or return streams in the application services.
**Example: Application Service Interface that can be used to get and return streams**
````csharp
using System;
using System.Threading.Tasks;
using Volo.Abp.Application.Services;
using Volo.Abp.Content;
namespace MyProject.Test
{
public interface ITestAppService : IApplicationService
{
Task Upload(Guid id, IRemoteStreamContent streamContent);
Task<IRemoteStreamContent> Download(Guid id);
}
}
````
**Example: Application Service Implementation that can be used to get and return streams**
````csharp
using System;
using System.IO;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.Application.Services;
using Volo.Abp.Content;
namespace MyProject.Test
{
public class TestAppService : ApplicationService, ITestAppService
{
public Task<IRemoteStreamContent> Download(Guid id)
{
var fs = new FileStream("C:\\Temp\\" + id + ".blob", FileMode.OpenOrCreate);
return Task.FromResult(
(IRemoteStreamContent) new RemoteStreamContent(fs) {
ContentType = "application/octet-stream"
}
);
}
public async Task Upload(Guid id, IRemoteStreamContent streamContent)
{
using (var fs = new FileStream("C:\\Temp\\" + id + ".blob", FileMode.Create))
{
await streamContent.GetStream().CopyToAsync(fs);
await fs.FlushAsync();
}
}
}
}
````
`IRemoteStreamContent` is compatible with the [Auto API Controller](API/Auto-API-Controllers.md) and [Dynamic C# HTTP Proxy](API/Dynamic-CSharp-API-Clients.md) systems.
## Lifetime
Lifetime of application services are [transient](Dependency-Injection.md) and they are automatically registered to the dependency injection system.

2
docs/en/AspNet-Boilerplate-Migration-Guide.md

@ -438,7 +438,7 @@ ABP Framework uses and extends ASP.NET Core's [distributed caching abstraction](
### Logging
ASP.NET Boilerplate uses Castle Windsor's [logging facility](http://docs.castleproject.org/Windsor.Logging-Facility.ashx) as an abstraction and supports multiple logging providers including Log4Net (the default one comes with the startup projects) and Serilog. You typically property-inject the logger:
ASP.NET Boilerplate uses Castle Windsor's [logging facility](https://github.com/castleproject/Windsor/blob/master/docs/logging-facility.md) as an abstraction and supports multiple logging providers including Log4Net (the default one comes with the startup projects) and Serilog. You typically property-inject the logger:
````csharp
using Castle.Core.Logging; //1: Import Logging namespace

31
docs/en/Authentication/Social-External-Logins.md

@ -1,32 +1,3 @@
# Social/External Logins
The [Account Module](../Modules/Account.md) has already configured to handle social or external logins out of the box. You can follow the ASP.NET Core documentation to add a social/external login provider to your application.
## Example: Facebook Authentication
Follow the [ASP.NET Core Facebook integration document](https://docs.microsoft.com/en-us/aspnet/core/security/authentication/social/facebook-logins) to support the Facebook login for your application.
#### Add the NuGet Package
Add the [Microsoft.AspNetCore.Authentication.Facebook](https://www.nuget.org/packages/Microsoft.AspNetCore.Authentication.Facebook) package to your project. Based on your architecture, this can be `.Web`, `.IdentityServer` (for tiered setup) or `.Host` project.
#### Configure the Provider
Use the `.AddFacebook(...)` extension method in the `ConfigureServices` method of your [module](../Module-Development-Basics.md), to configure the client:
````csharp
context.Services.AddAuthentication()
.AddFacebook(facebook =>
{
facebook.AppId = "...";
facebook.AppSecret = "...";
facebook.Scope.Add("email");
facebook.Scope.Add("public_profile");
});
````
> It would be a better practice to use the `appsettings.json` or the ASP.NET Core User Secrets system to store your credentials, instead of a hard-coded value like that. Follow the [Microsoft's document](https://docs.microsoft.com/en-us/aspnet/core/security/authentication/social/facebook-logins) to learn the user secrets usage.
## Angular UI
Beginning from the v3.1, the Angular UI uses authorization code flow (as a best practice) to authenticate the user by redirecting to the MVC UI login page. So, even if you are using the Angular UI, social/external login integration is same as explained above and it will work out of the box.
> This document has been moved. See the [Account Module](../Modules/Account.md) documentation.

6
docs/en/Authorization.md

@ -234,7 +234,7 @@ context
When you write this code inside your permission definition provider, it finds the "role deletion" permission of the [Identity Module](Modules/Identity.md) and disabled the permission, so no one can delete a role on the application.
> Tip: It is better to check the value returned by the `GetPermissionOrNull` method since it may return null if the given permission was not defined.
> Tip: It is better to check the value returned by the `GetPermissionOrNull` method since it may return null if the given permission was not defined.
## IAuthorizationService
@ -354,7 +354,7 @@ public class SystemAdminPermissionValueProvider : PermissionValueProvider
public override string Name => "SystemAdmin";
public override async Task<PermissionGrantResult>
public async override Task<PermissionGrantResult>
CheckAsync(PermissionValueCheckContext context)
{
if (context.Principal?.FindFirst("User_Type")?.Value == "SystemAdmin")
@ -406,5 +406,5 @@ This is already done for the startup template integration tests.
## See Also
* [Permission Management Module](Modules/Permission-Management.md)
* [ASP.NET Core MVC / Razor Pages JavaScript Auth API](API/JavaScript-API/Auth.md)
* [ASP.NET Core MVC / Razor Pages JavaScript Auth API](UI/AspNetCore/JavaScript-API/Auth.md)
* [Permission Management in Angular UI](UI/Angular/Permission-Management.md)

132
docs/en/Background-Jobs-RabbitMq.md

@ -1,3 +1,133 @@
# RabbitMQ Background Job Manager
TODO
RabbitMQ is an industry standard message broker. While it is typically used for inter-process communication (messaging / distributed events), it is pretty useful to store and execute background jobs in FIFO (First In First Out) order.
ABP Framework provides the [Volo.Abp.BackgroundJobs.RabbitMQ](https://www.nuget.org/packages/Volo.Abp.BackgroundJobs.RabbitMQ) NuGet package to use the RabbitMQ for background job execution.
> See the [background jobs document](Background-Jobs.md) to learn how to use the background job system. This document only shows how to install and configure the RabbitMQ integration.
## Installation
Use the ABP CLI to add [Volo.Abp.BackgroundJobs.RabbitMQ](https://www.nuget.org/packages/Volo.Abp.BackgroundJobs.RabbitMQ) NuGet package to your project:
* Install the [ABP CLI](https://docs.abp.io/en/abp/latest/CLI) if you haven't installed before.
* Open a command line (terminal) in the directory of the `.csproj` file you want to add the `Volo.Abp.BackgroundJobs.RabbitMQ` package.
* Run `abp add-package Volo.Abp.BackgroundJobs.RabbitMQ` command.
If you want to do it manually, install the [Volo.Abp.BackgroundJobs.RabbitMQ](https://www.nuget.org/packages/Volo.Abp.BackgroundJobs.RabbitMQ) NuGet package to your project and add `[DependsOn(typeof(AbpBackgroundJobsRabbitMqModule))]` to the [ABP module](Module-Development-Basics.md) class inside your project.
## Configuration
### Default Configuration
The default configuration automatically connects to the local RabbitMQ server (localhost) with the standard port. **In this case, no configuration needed.**
### RabbitMQ Connection(s)
You can configure the RabbitMQ connections using the standard [configuration system](Configuration.md), like using the `appsettings.json` file, or using the [options](Options.md) classes.
#### `appsettings.json` file configuration
This is the simplest way to configure the RabbitMQ connections. It is also very strong since you can use any other configuration source (like environment variables) that is [supported by the AspNet Core](https://docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration/).
**Example: Configuring the Default RabbitMQ Connection**
````json
{
"RabbitMQ": {
"Connections": {
"Default": {
"HostName": "123.123.123.123",
"Port": "5672"
}
}
}
}
````
You can use any of the [ConnectionFactry](http://rabbitmq.github.io/rabbitmq-dotnet-client/api/RabbitMQ.Client.ConnectionFactory.html#properties) properties as the connection properties. See [the RabbitMQ document](https://www.rabbitmq.com/dotnet-api-guide.html#exchanges-and-queues) to understand these options better.
Defining multiple connections is allowed. In this case, you can use different connections for different background job types (see the `AbpRabbitMqBackgroundJobOptions` section below).
**Example: Declare two connections**
````json
{
"RabbitMQ": {
"Connections": {
"Default": {
"HostName": "123.123.123.123"
},
"SecondConnection": {
"HostName": "321.321.321.321"
}
}
}
}
````
#### AbpRabbitMqOptions
`AbpRabbitMqOptions` class can be used to configure the connection strings for the RabbitMQ. You can configure this options inside the `ConfigureServices` of your [module](Module-Development-Basics.md).
**Example: Configure the connection**
````csharp
Configure<AbpRabbitMqOptions>(options =>
{
options.Connections.Default.UserName = "user";
options.Connections.Default.Password = "pass";
options.Connections.Default.HostName = "123.123.123.123";
options.Connections.Default.Port = 5672;
});
````
Using these options classes can be combined with the `appsettings.json` way. Configuring an option property in the code overrides the value in the configuration file.
### AbpRabbitMqBackgroundJobOptions
#### Job Queue Names
By default, each job type uses a separate queue. Queue names are calculated by combining a standard prefix and the job name. Default prefix is `AbpBackgroundJobs.` So, if the job name is `EmailSending` then the queue name in the RabbitMQ becomes `AbpBackgroundJobs.EmailSending`
> Use `BackgroundJobName` attribute on the background **job argument** class to specify the job name. Otherwise, the job name will be the full name (with namespace) of the job class.
#### Job Connections
By default, all the job types use the `Default` RabbitMQ connection.
#### Customization
`AbpRabbitMqBackgroundJobOptions` can be used to customize the queue names and the connections used by the jobs.
**Example:**
````csharp
Configure<AbpRabbitMqBackgroundJobOptions>(options =>
{
options.DefaultQueueNamePrefix = "my_app_jobs.";
options.JobQueues[typeof(EmailSendingArgs)] =
new JobQueueConfiguration(
typeof(EmailSendingArgs),
queueName: "my_app_jobs.emails",
connectionName: "SecondConnection"
);
});
````
* This example sets the default queue name prefix to `my_app_jobs.`. If different applications use the same RabbitMQ server, it would be important to use different prefixes for each application to not consume jobs of each other.
* Also specifies a different connection string for the `EmailSendingArgs`.
`JobQueueConfiguration` class has some additional options in its constructor;
* `queueName`: The queue name that is used for this job. The prefix is not added, so you need to specify the full name of the queue.
* `connectionName`: The RabbitMQ connection name (see the connection configuration above). This is optional and the default value is `Default`.
* `durable` (optional, default: `true`).
* `exclusive` (optional, default: `false`).
* `autoDelete` (optional, default: `false`)
See the RabbitMQ documentation if you want to understand the `durable`, `exclusive` and `autoDelete` options better, while most of the times the default configuration is what you want.
## See Also
* [Background Jobs](Background-Jobs.md)

47
docs/en/Background-Jobs.md

@ -13,7 +13,7 @@ Background jobs are **persistent** that means they will be **re-tried** and **ex
ABP provides an **abstraction** module and **several implementations** for background jobs. It has a built-in/default implementation as well as Hangfire, RabbitMQ and Quartz integrations.
`Volo.Abp.BackgroundJobs.Abstractions` nuget package provides needed services to create background jobs and queue background job items. If your module only depend on this package, it can be independent from the actual implementation/integration.
`Volo.Abp.BackgroundJobs.Abstractions` NuGet package provides needed services to create background jobs and queue background job items. If your module only depend on this package, it can be independent from the actual implementation/integration.
> `Volo.Abp.BackgroundJobs.Abstractions` package is installed to the startup templates by default.
@ -24,23 +24,29 @@ A background job is a class that implements the `IBackgroundJob<TArgs>` interfac
This example is used to send emails in background. First, define a class to store arguments of the background job:
````csharp
public class EmailSendingArgs
namespace MyProject
{
public string EmailAddress { get; set; }
public string Subject { get; set; }
public string Body { get; set; }
public class EmailSendingArgs
{
public string EmailAddress { get; set; }
public string Subject { get; set; }
public string Body { get; set; }
}
}
````
Then create a background job class that uses an `EmailSendingArgs` object to send an email:
````csharp
using System.Threading.Tasks;
using Volo.Abp.BackgroundJobs;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Emailing;
namespace MyProject
{
public class EmailSendingJob : BackgroundJob<EmailSendingArgs>, ITransientDependency
public class EmailSendingJob
: AsyncBackgroundJob<EmailSendingArgs>, ITransientDependency
{
private readonly IEmailSender _emailSender;
@ -49,9 +55,9 @@ namespace MyProject
_emailSender = emailSender;
}
public override void Execute(EmailSendingArgs args)
public override async Task ExecuteAsync(EmailSendingArgs args)
{
_emailSender.Send(
await _emailSender.SendAsync(
args.EmailAddress,
args.Subject,
args.Body
@ -63,10 +69,35 @@ namespace MyProject
This job simply uses `IEmailSender` to send emails (see [email sending document](Emailing.md)).
> `AsyncBackgroundJob` is used to create a job needs to perform async calls. You can inherit from `BackgroundJob<TJob>` and override the `Execute` method if the method doesn't need to perform any async call.
#### Exception Handling
A background job should not hide exceptions. If it throws an exception, the background job is automatically re-tried after a calculated waiting time. Hide exceptions only if you don't want to re-run the background job for the current argument.
#### Job Name
Each background job has a name. Job names are used in several places. For example, RabbitMQ provider uses job names to determine the RabbitMQ Queue names.
Job name is determined by the **job argument type**. For the `EmailSendingArgs` example above, the job name is `MyProject.EmailSendingArgs` (full name, including the namespace). You can use the `BackgroundJobName` attribute to set a different job name.
**Example**
```csharp
using Volo.Abp.BackgroundJobs;
namespace MyProject
{
[BackgroundJobName("emails")]
public class EmailSendingArgs
{
public string EmailAddress { get; set; }
public string Subject { get; set; }
public string Body { get; set; }
}
}
```
### Queue a Job Item
Now, you can queue an email sending job using the `IBackgroundJobManager` service:

2
docs/en/Background-Workers-Quartz.md

@ -37,7 +37,7 @@ public class YourModule : AbpModule
````
> Quartz background worker integration provided `QuartzPeriodicBackgroundWorkerAdapter` to adapt `PeriodicBackgroundWorkerBase` and `AsyncPeriodicBackgroundWorkerBase` derived class. So, you can still fllow the [background workers document](Background-Workers.md) to define the background worker.
> `BackgroundJobWorker` checks todo jobs every 5 seconds, but quartz will not block when long time jobs are executing. So,after Added Quartz background worker integration, you also need to add [Quartz Background Jobs](Background-Jobs-Quartz.md) or [Hangfire Background Jobs](Background-Jobs-Hangfire.md) to avoid duplicate execution jobs.
> `BackgroundJobWorker` checks jobs every 5 seconds, but quartz will not block when long time jobs are executing. So,after Added Quartz background worker integration, you also need to add [Quartz Background Jobs](Background-Jobs-Quartz.md) or [Hangfire Background Jobs](Background-Jobs-Hangfire.md) to avoid duplicate execution jobs.
## Configuration

2
docs/en/Background-Workers.md

@ -54,7 +54,7 @@ public class PassiveUserCheckerWorker : AsyncPeriodicBackgroundWorkerBase
Timer.Period = 600000; //10 minutes
}
protected override async Task DoWorkAsync(
protected async override Task DoWorkAsync(
PeriodicBackgroundWorkerContext workerContext)
{
Logger.LogInformation("Starting: Setting status of inactive users...");

5
docs/en/Best-Practices/Application-Services.md

@ -213,6 +213,11 @@ This method votes a question and returns the current score of the question.
* **Do** always get all the related entities from repositories to perform the operations on them.
* **Do** call repository's Update/UpdateAsync method after updating an entity. Because, not all database APIs support change tracking & auto update.
#### Handle files
* **Do not** use any web components like `IFormFile` or `Stream` in the application services. If you want to serve a file you can use `byte[]`.
* **Do** use a `Controller` to handle file uploading then pass the `byte[]` of the file to the application service method.
#### Using Other Application Services
* **Do not** use other application services of the same module/application. Instead;

2
docs/en/Blob-Storing.md

@ -21,7 +21,7 @@ The ABP Framework has already the following storage provider implementations;
* [Azure](Blob-Storing-Azure.md): Stores BLOBs on the [Azure BLOB storage](https://azure.microsoft.com/en-us/services/storage/blobs/).
* [Aliyun](Blob-Storing-Aliyun.md): Stores BLOBs on the [Aliyun Storage Service](https://help.aliyun.com/product/31815.html).
* [Minio](Blob-Storing-Minio.md): Stores BLOBs on the [MinIO Object storage](https://min.io/).
* [Aws](Blob-Storing-Aws.md): Stores BLOBs on the[Amazon Simple Storage Service](https://min.io/).
* [Aws](Blob-Storing-Aws.md): Stores BLOBs on the[Amazon Simple Storage Service](https://aws.amazon.com/s3/).
More providers will be implemented by the time. You can [request](https://github.com/abpframework/abp/issues/new) it for your favorite provider or [create it yourself](Blob-Storing-Custom-Provider.md) and [contribute](Contribution/Index.md) to the ABP Framework.

8
docs/en/Blog-Posts/2020-05-08 v2_7_Release/Post.md

@ -16,7 +16,7 @@ ABP.IO Platform is rapidly growing and we are getting more and more contribution
### Object Extending System
In the last few releases, we've mostly focused on providing ways to extend existing modules when you use them as NuGet/NPM Packages.
In the last few releases, we've mostly focused on providing ways to extend existing modules when you use them as NuGet/NPM Packages.
The Object Extending System allows module developers to create extensible modules and allows application developers to customize and extend a module easily.
@ -43,7 +43,7 @@ ObjectExtensionManager.Instance
options.Attributes.Add(new RequiredAttribute());
options.Attributes.Add(
new StringLengthAttribute(32) {
MinimumLength = 6
MinimumLength = 6
}
);
});
@ -121,7 +121,7 @@ Just create a class derived from the `ExceptionSubscriber` class in your applica
````csharp
public class MyExceptionSubscriber : ExceptionSubscriber
{
public override async Task HandleAsync(ExceptionNotificationContext context)
public async override Task HandleAsync(ExceptionNotificationContext context)
{
//TODO...
}
@ -244,4 +244,4 @@ We ([Volosoft](https://volosoft.com/) - the core team behind the ABP.IO platform
[ABP Framework](https://abp.io/) provides all the infrastructure and application independent framework features to make you more productive, focus on your own business code and implement software development best practices. It provides you a well defined and comfortable development experience without repeating yourself.
[ABP Commercial](https://commercial.abp.io/) provides pre-built functionalities, themes and tooling to save your time if your requirements involve these functionalities in addition to the premium support for the framework and the pre-built modules.
[ABP Commercial](https://commercial.abp.io/) provides pre-built functionalities, themes and tooling to save your time if your requirements involve these functionalities in addition to the premium support for the framework and the pre-built modules.

271
docs/en/Blog-Posts/2020-10-15 v3_3_Preview/POST.md

@ -0,0 +1,271 @@
# ABP Framework 3.3 RC Has Been Published
We have released the [ABP Framework](https://abp.io/) (and the [ABP Commercial](https://commercial.abp.io/)) `3.3.0-rc.1` today. This blog post introduces the new features and important changes in the new version.
## Get Started with the 3.3 RC.1
If you want to try the version `3.3.0-rc.1` today, follow the steps below;
1) **Upgrade** the ABP CLI to the version `3.3.0-rc.1` using a command line terminal:
````bash
dotnet tool update Volo.Abp.Cli -g --version 3.3.0-rc.1
````
**or install** if you haven't installed before:
````bash
dotnet tool install Volo.Abp.Cli -g --version 3.3.0-rc.1
````
2) Create a **new application** with the `--preview` option:
````bash
abp new BookStore --preview
````
See the [ABP CLI documentation](https://docs.abp.io/en/abp/3.3/CLI) for all the available options.
> You can also use the *Direct Download* tab on the [Get Started](https://abp.io/get-started) page by selecting the Preview checkbox.
## What's new with the ABP Framework 3.3
### The Blazor UI
We had released an experimental early preview version of the Blazor UI with the [previous version](https://blog.abp.io/abp/ABP-Framework-ABP-Commercial-3.2-RC-With-The-New-Blazor-UI). In this version, we've completed most of the fundamental infrastructure features and the application modules (like identity and tenant management).
It currently has almost the same functionalities as the other UI types (Angular & MVC / Razor Pages).
**Example screenshot**: User management page of the Blazor UI
![abp-blazor-ui](abp-blazor-ui.png)
> We've adapted the [Lepton Theme](https://commercial.abp.io/themes) for the ABP Commercial, see the related section below.
We are still working on the fundamentals. So, the next version may introduce breaking changes of the Blazor UI. We will work hard to keep them with the minimal effect on your application code.
#### Breaking Changes on the Blazor UI
There are some breaking changes with the Blazor UI. If you've built an application and upgrade it, your application might not properly work. See [the migration guide](https://docs.abp.io/en/abp/3.3/Migration-Guides/BlazorUI-3_3) for the changes you need to do after upgrading your application.
### Automatic Validation for AntiForgery Token for HTTP APIs
Starting with the version 3.3, all your HTTP API endpoints are **automatically protected** against CSRF attacks, unless you disable it for your application. So, no configuration needed, just upgrade the ABP Framework.
[See the documentation](https://docs.abp.io/en/abp/3.3/CSRF-Anti-Forgery) to if you want to understand why you need it and how ABP Framework solves the problem.
### Rebus Integration Package for the Distributed Event Bus
[Rebus](https://github.com/rebus-org/Rebus) describes itself as "Simple and lean service bus implementation for .NET". There are a lot of integration packages like RabbitMQ and Azure Service Bus for the Rebus. The new [Volo.Abp.EventBus.Rebus](https://www.nuget.org/packages/Volo.Abp.EventBus.Rebus) package allows you to use the Rebus as the [distributed event bus](https://docs.abp.io/en/abp/latest/Distributed-Event-Bus) for the ABP Framework.
See [the documentation](https://docs.abp.io/en/abp/3.3/Distributed-Event-Bus-Rebus-Integration) to learn how to use Rebus with the ABP Framework.
### Async Repository LINQ Extension Methods
You have a problem when you want to use **Async LINQ Extension Methods** (e.g. `FirstOrDefaultAsync(...)`) in your **domain** and **application** layers. These async methods are **not included in the standard LINQ extension methods**. Those are defined by the [Microsoft.EntityFrameworkCore](https://www.nuget.org/packages/Microsoft.EntityFrameworkCore) NuGet package (see [the code](https://github.com/dotnet/efcore/blob/main/src/EFCore/Extensions/EntityFrameworkQueryableExtensions.cs)). To be able to use these `async` methods, you need to reference to the `Microsoft.EntityFrameworkCore` package.
If you don't want to depend on the EF Core in your business layer, then ABP Framework provides the `IAsyncQueryableExecuter` service to execute your queries asynchronously without depending on the EF Core package. You can see [the documentation](https://docs.abp.io/en/abp/latest/Repositories#option-3-iasyncqueryableexecuter) to get more information about this service.
ABP Framework version 3.3 takes this one step further and allows you to directly execute the async LINQ extension methods on the `IRepository` interface.
**Example: Use `CountAsync` and `FirstOrDefaultAsync` methods on the repositories**
````csharp
using System;
using System.Threading.Tasks;
using Volo.Abp.Application.Services;
using Volo.Abp.Domain.Repositories;
namespace MyCompanyName.MyProjectName
{
public class BookAppService : ApplicationService, IBookAppService
{
private readonly IRepository<Book, Guid> _bookRepository;
public BookAppService(IRepository<Book, Guid> bookRepository)
{
_bookRepository = bookRepository;
}
public async Task DemoAsync()
{
var countAll = await _bookRepository
.CountAsync();
var count = await _bookRepository
.CountAsync(x => x.Name.Contains("A"));
var book1984 = await _bookRepository
.FirstOrDefaultAsync(x => x.Name == "1984");
}
}
}
````
All the standard LINQ methods are supported: *AllAsync, AnyAsync, AverageAsync, ContainsAsync, CountAsync, FirstAsync, FirstOrDefaultAsync, LastAsync, LastOrDefaultAsync, LongCountAsync, MaxAsync, MinAsync, SingleAsync, SingleOrDefaultAsync, SumAsync, ToArrayAsync, ToListAsync*.
This approach still has a limitation. You need to execute the extension method directly on the repository object. For example, the below usage is **not supported**:
````csharp
var count = await _bookRepository.Where(x => x.Name.Contains("A")).CountAsync();
````
This is because the object returned from the `Where` method is not a repository object, it is a standard `IQueryable`. In such cases, you can still use the `IAsyncQueryableExecuter`:
````csharp
var count = await AsyncExecuter.CountAsync(
_bookRepository.Where(x => x.Name.Contains("A"))
);
````
`AsyncExecuter` has all the standard extension methods, so you don't have any restriction here. See [the repository documentation](https://docs.abp.io/en/abp/latest/Repositories#iqueryable-async-operations) for all the options you have.
> ABP Framework does its best to not depend on the EF Core and still be able to use the async LINQ extension methods. However, there is no problem to depend on the EF Core for your application, you can add the `Microsoft.EntityFrameworkCore` NuGet package and use the native methods.
### Stream Support for the Application Service Methods
[Application services](https://docs.abp.io/en/abp/latest/Application-Services) are consumed by clients and the parameters and return values (typically [Data Transfer Objects](https://docs.abp.io/en/abp/latest/Data-Transfer-Objects)). In case of the client is a remote application, then these objects should be serialized & deserialized.
Until the version 3.3, we hadn't suggest to use the `Stream` in the application service contracts, since it is not serializable/deserializable. However, with the version 3.3, ABP Framework properly supports this scenario by introducing the new `IRemoteStreamContent` interface.
Example: An application service that can get or return streams
````csharp
using System;
using System.Threading.Tasks;
using Volo.Abp.Application.Services;
using Volo.Abp.Content;
namespace MyProject.Test
{
public interface ITestAppService : IApplicationService
{
Task Upload(Guid id, IRemoteStreamContent streamContent);
Task<IRemoteStreamContent> Download(Guid id);
}
}
````
The implementation can be as shown below:
````csharp
using System;
using System.IO;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.Application.Services;
using Volo.Abp.Content;
namespace MyProject.Test
{
public class TestAppService : ApplicationService, ITestAppService
{
public Task<IRemoteStreamContent> Download(Guid id)
{
var fs = new FileStream("C:\\Temp\\" + id + ".blob", FileMode.OpenOrCreate);
return Task.FromResult(
(IRemoteStreamContent) new RemoteStreamContent(fs) {
ContentType = "application/octet-stream"
}
);
}
public async Task Upload(Guid id, IRemoteStreamContent streamContent)
{
using (var fs = new FileStream("C:\\Temp\\" + id + ".blob", FileMode.Create))
{
await streamContent.GetStream().CopyToAsync(fs);
await fs.FlushAsync();
}
}
}
}
````
> This is just a demo code. Do it better in your production code :)
Thanks to [@alexandru-bagu](https://github.com/alexandru-bagu) for the great contribution!
### Other Changes
* Upgraded all the .NET Core / ASP.NET Core related packages to the version 3.1.8. If you have additional dependencies to the .NET Core / ASP.NET Core related packages, we suggest you to updates your packages to the version 3.1.8 to have the latest bug and security fixes published by Microsoft.
* The blogging module now uses the [BLOB Storing](https://docs.abp.io/en/abp/latest/Blob-Storing) system to store images & files of the blog posts. If you are using this module, then you need to manually migrate the local files to the BLOB Storing system after the upgrade.
* The Angular UI is now redirecting to the profile management page of the MVC UI instead of using its own UI, if you've configured the authorization code flow (which is default since the version 3.2.0).
## What's new with the ABP Commercial 3.3
### The Blazor UI
We have good news for the ABP Commercial Blazor UI too. We have implemented the [Lepton Theme](https://commercial.abp.io/themes) integration, so it is now available with the Blazor UI. Also, implemented most of the fundamental [modules](https://commercial.abp.io/modules).
**A screenshot from the ABP Commercial startup template with the Blazor UI**
![abp-commercial-blazor-ui](abp-commercial-blazor-ui.png)
There are still missing features and modules. However, we are working on it to have a more complete version in the next release.
#### Breaking Changes on the Blazor UI
There are some breaking changes with the Blazor UI. If you've built an application and upgrade it, your application might not properly work. See the [ABP Commercial Blazor UI v 3.3 Migration Guide](https://docs.abp.io/en/commercial/3.3/migration-guides/blazor-ui-3_3) for the changes you need to do after upgrading your application.
#### Known Issues
When you create a new project, profile management doesn't work, you get an exception because it can't find the `/libs/cropperjs/css/cropper.min.css` file. To fix the issue;
* Add `"@volo/account": "^3.3.0-rc.1"` to the `package.json` in the `.Host` project.
* Run `yarn` (or `npm install`), then `gulp` on a command line terminal in the root folder of the `.Host` project.
### Multi-Tenant Social Logins
[Account module](https://commercial.abp.io/modules/Volo.Account.Pro) now supports to manage the social/external logins in the UI. You can **enable/disable** and **set options** in the settings page. It also supports to use **different credentials for the tenants** and it is also **configured on the runtime**.
![abp-commercial-setting-account-external-logins](abp-commercial-setting-account-external-logins.png)
### Linked Accounts
Linked user system allows you to link other accounts (including account in a different tenant) with your account, so you can switch between different accounts with a single-click. It is practical since you no longer need to logout and login again with entering the credentials of the target account.
To manage the linked accounts, go to the profile management page from the user menu;
![abp-commercial-linked-users](abp-commercial-linked-users.png)
### Paypal & Stripe Integrations
The [Payment Module](https://commercial.abp.io/modules/Volo.Payment) was supporting PayU and 2Checkout providers until the version 3.3. It's now integrated to PayPal and Stripe. See the [technical documentation](https://docs.abp.io/en/commercial/latest/modules/payment) to learn how to use it.
### ABP Suite Improvements
We've done a lot of small improvements for the [ABP Suite](https://commercial.abp.io/tools/suite). Some of the enhancements are;
* Show the previously installed modules as *installed* on the module list.
* Switch between the latest stable, the latest [preview](https://docs.abp.io/en/abp/latest/Previews) and the latest [nightly build](https://docs.abp.io/en/abp/latest/Nightly-Builds) versions of the ABP related packages.
* Moved the file that stores the *previously created entities* into the solution folder to allow you to store it in your source control system.
### Others
* Added an option to the Account Module to show reCAPTCHA on the login & the registration forms.
Besides the new features introduced in this post, we've done a lot of small other enhancements and bug fixes to provide a better development experience and increase the developer productivity.
## New Articles
The core ABP Framework team & the community continue to publish new articles on the [ABP Community](https://community.abp.io/) web site. The recently published articles are;
* [Replacing Email Templates and Sending Emails](https://community.abp.io/articles/replacing-email-templates-and-sending-emails-jkeb8zzh) (by [@EngincanV](https://community.abp.io/members/EngincanV))
* [How to Add Custom Properties to the User Entity](https://community.abp.io/articles/how-to-add-custom-property-to-the-user-entity-6ggxiddr) (by [@berkansasmaz](https://community.abp.io/members/berkansasmaz))
* [Using the AdminLTE Theme with the ABP Framework MVC / Razor Pages UI](https://community.abp.io/articles/using-the-adminlte-theme-with-the-abp-framework-mvc-razor-pages-ui-gssbhb7m) (by [@mucahiddanis](https://community.abp.io/members/mucahiddanis))
* [Using DevExtreme Angular Components With the ABP Framework](https://community.abp.io/articles/using-devextreme-angular-components-with-the-abp-framework-x5nyvj3i) (by [@bunyamin](https://community.abp.io/members/bunyamin))
It is appreciated if you want to [submit an article](https://community.abp.io/articles/submit) related to the ABP Framework.
## About the Next Release
The next version will be `4.0.0`. We are releasing a major version, since we will move the ABP Framework to .NET 5.0. We see that for most of the applications this will not be a breaking change and we hope you easily upgrade to it.
The planned 4.0.0-rc.1 (Release Candidate) version date is **November 11**, just after the Microsoft releases the .NET 5.0 final. The planned 4.0.0 final release date is **November 26**.
Follow the [GitHub milestones](https://github.com/abpframework/abp/milestones) for all the planned ABP Framework version release dates.
## Feedback
Please check out the ABP Framework 3.3.0 RC and [provide feedback](https://github.com/abpframework/abp/issues/new) to help us to release a more stable version. The planned release date for the [3.3.0 final](https://github.com/abpframework/abp/milestone/44) version is October 27th.

BIN
docs/en/Blog-Posts/2020-10-15 v3_3_Preview/abp-blazor-ui.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

BIN
docs/en/Blog-Posts/2020-10-15 v3_3_Preview/abp-commercial-blazor-ui.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 181 KiB

BIN
docs/en/Blog-Posts/2020-10-15 v3_3_Preview/abp-commercial-linked-users.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

BIN
docs/en/Blog-Posts/2020-10-15 v3_3_Preview/abp-commercial-setting-account-external-logins.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 199 KiB

47
docs/en/Blog-Posts/2020-10-27 v3_3_Release_Stable/POST.md

@ -0,0 +1,47 @@
# ABP Framework & ABP Commercial 3.3 Final Have Been Released
ABP Framework & ABP Commercial 3.3.0 have been released today.
Since all the new features are already explained in details with the [3.3 RC Announcement Post](https://blog.abp.io/abp/ABP-Framework-ABP-Commercial-v3.3-RC-Have-Been-Released), I will not repeat all the details again. Please read [the RC post](https://blog.abp.io/abp/ABP-Framework-ABP-Commercial-v3.3-RC-Have-Been-Released) for **new feature and changes** you may need to do for your solution while upgrading to the version 3.3.
## Creating New Solutions
You can create a new solution with the ABP Framework version 3.3 by either using the `abp new` command or using the **direct download** tab on the [get started page](https://abp.io/get-started).
> See the [getting started document](https://docs.abp.io/en/abp/latest/Getting-Started) for details.
## How to Upgrade an Existing Solution
### Install/Update the ABP CLI
First of all, install the ABP CLI or upgrade to the latest version.
If you haven't installed yet:
````bash
dotnet tool install -g Volo.Abp.Cli
````
To update an existing installation:
```bash
dotnet tool update -g Volo.Abp.Cli
```
### ABP UPDATE Command
[ABP CLI](https://docs.abp.io/en/abp/latest/CLI) provides a handy command to update all the ABP related NuGet and NPM packages in your solution with a single command:
````bash
abp update
````
Run this command in the root folder of your solution. After the update command, check [the RC blog post](https://blog.abp.io/abp/ABP-Framework-ABP-Commercial-v3.3-RC-Have-Been-Released) to learn if you need to make any changes in your solution.
> You may want to see the new [upgrading document](https://docs.abp.io/en/abp/latest/Upgrading).
## About the Next Version: 4.0
The next version will be 4.0 and it will be mostly related to completing the Blazor UI features and upgrading the ABP Framework & ecosystem to the .NET 5.0.
The goal is to complete the version 4.0 with a stable Blazor UI with the fundamental features implemented and publish it just after the Microsoft lunches .NET 5 in this November. The planned 4.0 preview release date is November 11th.

143
docs/en/Blog-Posts/2020-11-12 v4_0_Preview/POST.md

@ -0,0 +1,143 @@
# ABP Framework 4.0 RC Has Been Published based on .NET 5.0!
Today, we have released the [ABP Framework](https://abp.io/) (and the [ABP Commercial](https://commercial.abp.io/)) 4.0.0 RC that is based on the **.NET 5.0**. This blog post introduces the new features and important changes in the new version.
> **The planned release date for the [4.0.0 final](https://github.com/abpframework/abp/milestone/45) version is November 26, 2020**.
## Get Started with the 4.0 RC
If you want to try the version `4.0.0` today, follow the steps below;
1) **Upgrade** the ABP CLI to the version `4.0.0-rc.3` using a command line terminal:
````bash
dotnet tool update Volo.Abp.Cli -g --version 4.0.0-rc.3
````
**or install** if you haven't installed before:
````bash
dotnet tool install Volo.Abp.Cli -g --version 4.0.0-rc.3
````
2) Create a **new application** with the `--preview` option:
````bash
abp new BookStore --preview
````
See the [ABP CLI documentation](https://docs.abp.io/en/abp/3.3/CLI) for all the available options.
> You can also use the *Direct Download* tab on the [Get Started](https://abp.io/get-started) page by selecting the **Preview checkbox**.
## Migrating From 3.x to 4.0
The version 4.0 comes with some major changes including the **migration from .NET Core 3.1 to .NET 5.0**.
We've prepared a **detailed [migration document](https://docs.abp.io/en/abp/4.0/Migration-Guides/Abp-4_0)** to explain all the changes and the actions you need to take while upgrading your existing solutions.
## What's new with the ABP Framework 4.0
### The Blazor UI
The Blazor UI is now stable and officially supported. The [web application development tutorial](https://docs.abp.io/en/abp/4.0/Tutorials/Part-1?UI=Blazor) has been updated based on the version 4.0.
#### abp bundle command
Introducing the `abp bundle` CLI command to manage static JavaScript & CSS file dependencies of a Blazor application. This command is currently used to add the dependencies to the `index.html` file in the dependency order by respecting to modularity. In the next version it will automatically unify & minify the files. The documentation is being prepared.
#### Removed the JQuery & Bootstrap JavaScript
Removed JQuery & Bootstrap JavaScript dependencies for the Blazor UI.
>There are some other changes in the startup template and some public APIs. Follow the [Migration Guide](https://docs.abp.io/en/abp/4.0/Migration-Guides/Abp-4_0) to apply changes for existing solutions that you're upgrading from the version 3.3. While we will continue to make improvements add new features, we no longer make breaking changes on the existing APIs until the version 5.0.
#### Others
A lot of minor and major improvements have been done for the Blazor UI. Some of them are listed below:
* Implemented `IComponentActivator` to resolve the component from the `IServiceProvider`. So, you can now inject dependencies into the constructor of your razor component.
* Introduced the `AbpComponentBase` base class that you derive your components from. It has useful base properties that you can use in your pages/components.
* Introduced `IUiNotificationService` service to show toast notifications on the UI.
* Improved the `IUiMessageService` to show message & confirmation dialogs.
### System.Text.Json
ABP Framework 4.0 uses the System.Text.Json by default as the JSON serialization library. It, actually, using a hybrid approach: Continues to use the Newtonsoft.Json when it needs to use the features not supported by the System.Text.Json.
Follow the [Migration Guide](https://docs.abp.io/en/abp/4.0/Migration-Guides/Abp-4_0) to learn how to configure to use the Newtonsoft.Json for some specific types or switch back to the Newtonsoft.Json as the default JSON serializer.
### Identity Server 4 Upgrade
ABP Framework upgrades the [IdentityServer4](https://www.nuget.org/packages/IdentityServer4) library from 3.x to 4.1.1 with the ABP Framework version 4.0. IdentityServer 4.x has a lot of changes. Some of them are **breaking changes in the data structure**.
Follow the [Migration Guide](https://docs.abp.io/en/abp/4.0/Migration-Guides/Abp-4_0) to upgrade existing solutions.
### Creating a New Module Inside the Application
ABP CLI has now a command to create a new module and add it to an existing solution. In this way, you can create modular applications easier than before.
Example: Create a *ProductManagement* module into your solution.
````bash
abp add-module ProductManagement --new --add-to-solution-file
````
Execute this command in a terminal in the root folder of your solution. If you don't specify the `--add-to-solution-file` option, then the module projects will not be added to the main solution, but the project references still be added. In this case, you need to open the module's solution to develop the module.
See the [CLI document](https://docs.abp.io/en/abp/4.0/CLI) for other options.
### WPF Startup Template
Introducing the WPF startup template for the ABP Framework. Use the ABP CLI new command to create a new WPF application:
````bash
abp new MyWpfApp -t wpf
````
This is a minimalist, empty project template that is integrated to the ABP Framework.
### New Languages
**Thanks to the contributors** from the ABP Community, the framework modules and the startup template have been localized to **German** language by [Alexander Pilhar](https://github.com/alexanderpilhar) & [Nico Lachmuth](https://github.com/tntwist).
### Other Notes
* Upgraded to Angular 11.
* Since [Mongo2Go](https://github.com/Mongo2Go/Mongo2Go) library not supports transactions, you can use transactions in unit tests for MongoDB.
## What's new with the ABP Commercial 4.0
### The Blazor UI
The Blazor UI for the ABP Commercial is also becomes stable and feature rich with the version 4.0;
* [ABP Suite](https://commercial.abp.io/tools/suite) now supports to generate CRUD pages for the Blazor UI.
* Completed the [Lepton Theme](https://commercial.abp.io/themes) for the Blazor UI.
* Implemented the [File Management](https://commercial.abp.io/modules/Volo.FileManagement) module for the Blazor UI.
### The ABP Suite
While creating create/edit modals with a navigation property, we had two options: A dropdown to select the target entity and a modal to select the entity by searching with a data table.
Dropdown option now supports **lazy load, search and auto-complete**. In this way, selecting a navigation property becomes much easier and supports large data sets on the dropdown.
**Example: Select an author while creating a new book**
![abp-suite-auto-complete-dropdown](abp-suite-auto-complete-dropdown.png)
With the new version, you can **disable backend code generation** on CRUD page generation. This is especially useful if you want to regenerate the page with a different UI framework, but don't want to regenerate the server side code.
### Identity Server Management UI Revised
Completely revised the Identity Server Management UI based on the IDS 4.x changes.
## About the Next Release
The next feature version, `4.1.0`, will mostly focus on completing the missing documents, fixing bugs, performance optimizations and improving the Blazor UI features. The planned preview release date for the version `4.1.0` is December 10 and the final (stable) version release date is December 24.
Follow the [GitHub milestones](https://github.com/abpframework/abp/milestones) for all the planned ABP Framework version release dates.
## Feedback
Please check out the ABP Framework 4.0.0 RC and [provide feedback](https://github.com/abpframework/abp/issues/new) to help us to release a more stable version. **The planned release date for the [4.0.0 final](https://github.com/abpframework/abp/milestone/45) version is November 26**.

BIN
docs/en/Blog-Posts/2020-11-12 v4_0_Preview/abp-suite-auto-complete-dropdown.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

87
docs/en/Blog-Posts/2020-12-04 v4_0_Release_Stable/POST.md

@ -0,0 +1,87 @@
# ABP.IO Platform 4.0 with .NET 5.0 in the 4th Year!
Today, we are extremely happy to release ABP Framework 4.0 with **.NET 5.0 support**!
## 4 Years of Work
As a nice coincidence, today is the **4th year** since the first commit made in the [abp repository](https://github.com/abpframework/abp)! So, we can say "*Happy Birthday ABP Framework!*".
![abp-contribution-graph-4-years](abp-contribution-graph-4-years.png)
### Some Statistics
ABP.IO Platform and the ABP Community is growing. Here, a summary of these 4 years.
From GitHub, only from the main [abp repository](https://github.com/abpframework/abp);
* **15,297 commits** done.
* **3,764 issues** are closed.
* **2,133 pull requests** are merged.
* **158 contributors**.
* **88 releases** published.
* **5.2K stars** on GitHub.
From NuGet & NPM;
* **220 NuGet** packages & **52 NPM** packages.
* **1,000,000 downloads** only for the core NuGet package.
From Website;
* **200,000 visitors**.
* **1,000,000+ sessions**.
## What's New With 4.0?
Since all the new features are already explained in details with the [4.0 RC Announcement Post](https://blog.abp.io/abp/ABP.IO-Platform-v4.0-RC-Has-Been-Released-based-on-.NET-5.0), I will not repeat all the details again. Please read [the RC post](https://blog.abp.io/abp/ABP.IO-Platform-v4.0-RC-Has-Been-Released-based-on-.NET-5.0) for **new feature and changes** you may need to do for your solution while upgrading to the version 4.0.
Here, a brief list of major features and changes;
* Migrated to **.NET 5.0**.
* Stable **Blazor** UI.
* Moved to **System.Text.Json**.
* Upgraded to **IdentityServer** version 4.0.
* **WPF** startup template.
## Creating New Solutions
You can create a new solution with the ABP Framework version 4.0 by either using the `abp new` command or using the **direct download** tab on the [get started page](https://abp.io/get-started).
> See the [getting started document](https://docs.abp.io/en/abp/latest/Getting-Started) for details.
## How to Upgrade an Existing Solution
This is a **major version** and requires some **manual work**, especially related to **.NET 5.0** and **IdentityServer** 4.0 upgrades.
* See the [MIGRATION GUIDE](https://docs.abp.io/en/abp/latest/Migration-Guides/Abp-4_0) that covers all the details about the upgrade progress.
* You can also see the [upgrading document](https://docs.abp.io/en/abp/latest/Upgrading).
## New Guides / Documents
We are constantly improving the documentation. Our purpose is not only document the ABP Framework, but also write architectural and practical guides for developers.
### Implementing Domain Driven Design
[Implementing Domain Driven Design](https://docs.abp.io/en/abp/latest/Domain-Driven-Design-Implementation-Guide) is a practical guide for they want to implement the DDD principles in their solutions. While the implementation details rely on the ABP Framework infrastructure, core concepts, principles and patterns are applicable in any kind of solution, even if it is not a .NET solution.
![ddd-implementation-guide-sample](ddd-implementation-guide-sample.png)
### Testing
The new [Testing document](https://docs.abp.io/en/abp/latest/Testing) discusses different kind of automated tests and explains how you can write tests for your ABP based solutions.
### UI Documents
We've created a lot of documents for the [MVC](https://docs.abp.io/en/abp/latest/UI/AspNetCore/Overall), [Blazor](https://docs.abp.io/en/abp/latest/UI/Blazor/Overall) and the [Angular](https://docs.abp.io/en/abp/latest/UI/Angular/Quick-Start) UI.
## About the Next Version
The next versions 4.1 will mostly focus on;
* Improving current features.
* Complete module features for the Blazor UI.
* Improve developer experience and productivity.
* More documentation and examples.
Planned preview date for the version **4.1 is December 17, 2020**. See the [Road Map](https://docs.abp.io/en/abp/latest/Road-Map) document and [GitHub Milestones](https://github.com/abpframework/abp/milestones) to learn what's planned for the next versions. We are trying to be clear about the coming features and the next release dates.

BIN
docs/en/Blog-Posts/2020-12-04 v4_0_Release_Stable/abp-contribution-graph-4-years.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

BIN
docs/en/Blog-Posts/2020-12-04 v4_0_Release_Stable/ddd-implementation-guide-sample.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 149 KiB

39
docs/en/CLI.md

@ -41,6 +41,7 @@ Here, the list of all available commands before explaining their details:
* **`login`**: Authenticates on your computer with your [abp.io](https://abp.io/) username and password.
* **`logout`**: Logouts from your computer if you've authenticated before.
* **`build`**: Builds a GIT repository and depending repositories or a single .NET solution.
* **`bundle`**: Generates script and style references for an ABP Blazor project.
### help
@ -106,6 +107,7 @@ abp new Acme.BookStore
* `--create-solution-folder` or `-csf`: Specifies if the project will be in a new folder in the output folder or directly the output folder.
* `--connection-string` or `-cs`: Overwrites the default connection strings in all `appsettings.json` files. The default connection string is `Server=localhost;Database=MyProjectName;Trusted_Connection=True;MultipleActiveResultSets=true` for EF Core and it is configured to use the SQL Server. If you want to use the EF Core, but need to change the DBMS, you can change it as [described here](Entity-Framework-Core-Other-DBMS.md) (after creating the solution).
* `--local-framework-ref --abp-path`: Uses local projects references to the ABP framework instead of using the NuGet packages. This can be useful if you download the ABP Framework source code and have a local reference to the framework from your application.
* `--no-random-port`: Uses template's default ports.
### update
@ -159,6 +161,8 @@ abp add-package Volo.Abp.MongoDB
Adds a [multi-package application module](Modules/Index) to a solution by finding all packages of the module, finding related projects in the solution and adding each package to the corresponding project in the solution.
It can also create a new module for your solution and add it to your solution. See `--new-template` option.
> A business module generally consists of several packages (because of layering, different database provider options or other reasons). Using `add-module` command dramatically simplifies adding a module to a solution. However, each module may require some additional configurations which is generally indicated in the documentation of the related module.
Usage
@ -167,21 +171,29 @@ Usage
abp add-module <module-name> [options]
````
Example:
Examples:
```bash
abp add-module Volo.Blogging
```
* This example add the Volo.Blogging module to the solution.
* This example adds the `Volo.Blogging` module to the solution.
```bash
abp add-module ProductManagement --new --add-to-solution-file
```
* This command creates a fresh new module customized for your solution (named `ProductManagement`) and adds it to your solution.
#### Options
* `--solution` or `-s`: Specifies the solution (.sln) file path. If not specified, CLI tries to find a .sln file in the current directory.
* `--skip-db-migrations`: For EF Core database provider, it automatically adds a new code first migration (`Add-Migration`) and updates the database (`Update-Database`) if necessary. Specify this option to skip this operation.
* `-sp` or `--startup-project`: Relative path to the project folder of the startup project. Default value is the current folder.
* `--with-source-code`: Downloads the source code of the module to your solution folder and uses local project references instead of NuGet/NPM packages.
* `--add-to-solution-file`: Adds the downloaded module to your solution file, so you will also see the projects of the module when you open the solution on a IDE. (only available when `--with-source-code` is used.)
* `--new`: Creates a fresh new module (customized for your solution) and adds it to your solution.
* `--with-source-code`: Downloads the source code of the module to your solution folder and uses local project references instead of NuGet/NPM packages. This options is always `True` if `--new` is used.
* `--add-to-solution-file`: Adds the downloaded/created module to your solution file, so you will also see the projects of the module when you open the solution on a IDE. (only available when `--with-source-code` is `True`.)
### get-source
@ -383,10 +395,27 @@ abp build --build-name "prod" --dotnet-build-arguments "\"--no-dependencies\""
#### Options
* ```--working-directory``` or ```-w```: Specifies the working directory. This option is useful when the command is executed outside of a GIT repository or when executing directory doesn't contain a .NET solution file.
* ```--working-directory``` or ```-wd```: Specifies the working directory. This option is useful when the command is executed outside of a GIT repository or when executing directory doesn't contain a .NET solution file.
* ```--build-name``` or ```-n```: Specifies a name for the build. This option is useful when same repository is used for more than one different builds.
* ```--dotnet-build-arguments``` or ```-a```: Arguments to pass ```dotnet build``` when building project files. This parameter must be passed like ```"\"{params}\""``` .
* ```--force``` or ```-f```: Forces to build projects even they are not changed from the last successful build.
For more details, see [build command documentation](CLI-BuildCommand.md).
#### bundle
This command generates script and style references for an ABP Blazor project and updates the **index.html** file. It helps developers to manage dependencies required by ABP modules easily. In order ```bundle``` command to work, its **executing directory** or passed ```--working-directory``` parameter's directory must contain a Blazor project file(*.csproj).
Usage:
````bash
abp bundle [options]
````
#### Options
* ```--working-directory``` or ```-wd```: Specifies the working directory. This option is useful when executing directory doesn't contain a Blazor project file.
* ```--force``` or ```-f```: Forces to build project before generating references.
For more details about managing style and script references in Blazor apps, see [Managing Global Scripts & Styles](UI/Blazor/Global-Scripts-Styles.md)

147
docs/en/CSRF-Anti-Forgery.md

@ -0,0 +1,147 @@
# CSRF/XSRF & Anti Forgery System
"*Cross-Site Request Forgery (CSRF) is a type of attack that occurs when a malicious web site, email, blog, instant message, or program causes a user’s web browser to perform an unwanted action on a trusted site for which the user is currently authenticated*" ([OWASP](https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)_Prevention_Cheat_Sheet)).
**ABP Framework completely automates CSRF preventing** and works out of the box without any configuration. Read this documentation only if you want to understand it better or need to customize.
## The Problem
ASP.NET Core [provides infrastructure](https://docs.microsoft.com/en-us/aspnet/core/security/anti-request-forgery) to prevent CSRF attacks by providing a system to **generate** and **validate antiforgery tokens**. However, the standard implementation has a few drawbacks;
Antiforgery token validation is only **enabled for razor pages by default** and not enabled for **HTTP APIs**. You need to enable it yourself for the Controllers. You can use the `[ValidateAntiForgeryToken]` attribute for a specific API Controller/Action or the `[AutoValidateAntiforgeryToken]` attribute to prevent attacks globally.
Once you enable it;
* You need to manually add an HTTP header, named `RequestVerificationToken` to every **AJAX request** made in your application. You should care about obtaining the token, saving in the client side and adding to the HTTP header on every HTTP request.
* All your clients, including **non-browser clients**, should care about obtaining and sending the antiforgery token in every request. In fact, non-browser clients has no CSRF risk and should not care about this.
Especially, the second point is a pain for your clients and unnecessarily consumes your server resources.
> You can read more about the ASP.NET Core antiforgery system in its own [documentation](https://docs.microsoft.com/en-us/aspnet/core/security/anti-request-forgery).
## The Solution
ABP Framework provides `[AbpValidateAntiForgeryToken]` and `[AbpAutoValidateAntiforgeryToken]` attributes, just like the attributes explained above. `[AbpAutoValidateAntiforgeryToken]` is already added to the global filters, so you should do nothing to enable it for your application.
ABP Framework also automates the following infrastructure;
* Server side sets a **special cookie**, named `XSRF-TOKEN` by default, that is used make the antiforgery token value available to the browser. This is **done automatically** (by the [application configuration](API/Application-Configuration.md) endpoint). Nothing to do in the client side.
* In the client side, it reads the token from the cookie and sends it in the **HTTP header** (named `RequestVerificationToken` by default). This is implemented for all the supported UI types.
* Server side validates the antiforgery token **only for same and cross site requests** made by the browser. It bypasses the validation for non-browser clients.
That's all. The systems works smoothly.
## Configuration / Customization
### AbpAntiForgeryOptions
`AbpAntiForgeryOptions` is the main [options class](Options.md) to configure the ABP Antiforgery system. It has the following properties;
* `TokenCookie`: Can be used to configure the cookie details. This cookie is used to store the antiforgery token value in the client side, so clients can read it and sends the value as the HTTP header. Default cookie name is `XSRF-TOKEN`, expiration time is 10 years (yes, ten years! It should be a value longer than the authentication cookie max life time, for the security).
* `AuthCookieSchemaName`: The name of the authentication cookie used by your application. Default value is `Identity.Application` (which becomes `AspNetCore.Identity.Application` on runtime). The default value properly works with the ABP startup templates. **If you change the authentication cookie name, you also must change this.**
* `AutoValidate`: The single point to enable/disable the ABP automatic antiforgery validation system. Default value is `true`.
* `AutoValidateFilter`: A predicate that gets a type and returns a boolean. ABP uses this predicate to check a controller type. If it returns false for a controller type, the controller is excluded from the automatic antiforgery token validation.
* `AutoValidateIgnoredHttpMethods`: A list of HTTP Methods to ignore on automatic antiforgery validation. Default value: "GET", "HEAD", "TRACE", "OPTIONS". These HTTP Methods are safe to skip antiforgery validation since they don't change the application state.
If you need to change these options, do it in the `ConfigureServices` method of your [module](Module-Development-Basics.md).
**Example: Configuring the AbpAntiForgeryOptions**
```csharp
Configure<AbpAntiForgeryOptions>(options =>
{
options.TokenCookie.Expiration = TimeSpan.FromDays(365);
options.AutoValidateIgnoredHttpMethods.Remove("GET");
options.AutoValidateFilter =
type => !type.Namespace.StartsWith("MyProject.MyIgnoredNamespace");
});
```
This configuration;
* Sets the antiforgery token expiration time to ~1 year.
* Enables antiforgery token validation for GET requests too.
* Ignores the controller types in the specified namespace.
### AntiforgeryOptions
`AntiforgeryOptions` is the standard [options class](Options.md) of the ASP.NET Core. **You can find all the information about this class in its [own documentation](https://docs.microsoft.com/en-us/aspnet/core/security/anti-request-forgery)**.
`HeaderName` option is especially important for the ABP Framework point of view. Default value of this value is `RequestVerificationToken` and the clients uses this name while sending the token value in the header. So, if you change this option, you should also arrange your clients to align the change. If you don't have a good reason, leave it as default.
### AbpValidateAntiForgeryToken Attribute
If you disable the automatic validation or want to perform the validation for an endpoint that is not validated by default (for example, an endpoint with HTTP GET Method), you can use the `[AbpValidateAntiForgeryToken]` attribute for a **controller type or method** (action).
**Example: Add `[AbpValidateAntiForgeryToken]` to a HTTP GET method**
```csharp
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Volo.Abp.AspNetCore.Mvc;
using Volo.Abp.AspNetCore.Mvc.AntiForgery;
namespace MyCompanyName.MyProjectName.Controllers
{
[Route("api/products")]
public class ProductController : AbpController
{
[HttpGet]
[AbpValidateAntiForgeryToken]
public async Task GetAsync()
{
//TODO: ...
}
}
}
```
### Angular UI
Angular supports CSRF Token out of box, but the token header name is `X-XSRF-TOKEN`. Since ABP Framework follows the ASP.NET Core conventions, it changes this value to `RequestVerificationToken` in the core package.
You don't need to make anything unless you need to change the `AntiforgeryOptions.HeaderName` as explained before. If you change it, remember to change the header name for the Angular application too. To do that, add an import declaration for the `HttpClientXsrfModule` into your root module.
**Example: Change the header name to *MyCustomHeaderName***
```typescript
@NgModule({
// ...
imports: [
//...
HttpClientXsrfModule.withOptions({
cookieName: 'XSRF-TOKEN',
headerName: 'MyCustomHeaderName'
})
],
})
export class AppModule {}
```
**Note:** XSRF-TOKEN is only valid if both frontend application and APIs run on the same domain. Therefore, when you make a request, you should use a relative path.
For example, let's say your APIs is hosted at `https://testdomain.com/ws`
and your angular application is hosted at `https://testdomain.com/admin`
So if your API request should look like this `https://testdomain.com/ws/api/identity/users`
your `environment.prod.ts` has to be as follows:
```typescript
export const environment = {
production: true,
// ....
apis: {
default: {
url: '/ws', // <- just use the context root here
// ...
},
},
} as Config.Environment;
```
Let's talk about why.
First, take a look at [Angular's code](https://github.com/angular/angular/blob/master/packages/common/http/src/xsrf.ts#L81)
It does not intercept any request that starts with `http://` or `https://`. There is a good reason for that. Any cross-site request does not need this token for security. This verification is only valid if the request is made to the same domain from which the web page is served. So, simply put, if you serve everything from a single domain, you just use a relative path.

8
docs/en/Community-Articles/2020-04-19-Customize-the-SignIn-Manager/POST.md

@ -1,6 +1,6 @@
# How to Customize the SignIn Manager for ABP Applications
After creating a new application using the [application startup template](https://docs.abp.io/en/abp/latest/Startup-Templates/Application), you may want extend or change the default behavior of the SignIn Manager for your authentication and registration flow needs. ABP [Account Module](https://docs.abp.io/en/abp/latest/Modules/Account) uses the [Identity Management Module](https://docs.abp.io/en/abp/latest/Modules/Identity) for SignIn Manager and the [Identity Management Module](https://docs.abp.io/en/abp/latest/Modules/Identity) uses default [Microsoft Identity SignIn Manager](https://github.com/dotnet/aspnetcore/blob/master/src/Identity/Core/src/SignInManager.cs) ([see here](https://github.com/abpframework/abp/blob/be32a55449e270d2d456df3dabdc91f3ffdd4fa9/modules/identity/src/Volo.Abp.Identity.AspNetCore/Volo/Abp/Identity/AspNetCore/AbpIdentityAspNetCoreModule.cs#L17)).
After creating a new application using the [application startup template](https://docs.abp.io/en/abp/latest/Startup-Templates/Application), you may want extend or change the default behavior of the SignIn Manager for your authentication and registration flow needs. ABP [Account Module](https://docs.abp.io/en/abp/latest/Modules/Account) uses the [Identity Management Module](https://docs.abp.io/en/abp/latest/Modules/Identity) for SignIn Manager and the [Identity Management Module](https://docs.abp.io/en/abp/latest/Modules/Identity) uses default [Microsoft Identity SignIn Manager](https://github.com/dotnet/aspnetcore/blob/master/src/Identity/Core/src/SignInManager.cs) ([see here](https://github.com/abpframework/abp/blob/be32a55449e270d2d456df3dabdc91f3ffdd4fa9/modules/identity/src/Volo.Abp.Identity.AspNetCore/Volo/Abp/Identity/AspNetCore/AbpIdentityAspNetCoreModule.cs#L17)).
To write your Custom SignIn Manager, you need to extend [Microsoft Identity SignIn Manager](https://github.com/dotnet/aspnetcore/blob/master/src/Identity/Core/src/SignInManager.cs) class and register it to the DI container.
@ -27,7 +27,7 @@ public class CustomSignInManager : Microsoft.AspNetCore.Identity.SignInManager<V
}
````
> It is important to use **Volo.Abp.Identity.IdentityUser** type for SignInManager to inherit, not the AppUser of your application.
> It is important to use **Volo.Abp.Identity.IdentityUser** type for SignInManager to inherit, not the AppUser of your application.
Afterwards you can override any of the SignIn Manager methods you need and add new methods and properties needed for your authentication or registration flow.
@ -38,7 +38,7 @@ In this case we'll be overriding the `GetExternalLoginInfoAsync` method which is
A good way to override a method is copying its [source code](https://github.com/dotnet/aspnetcore/blob/c56aa320c32ee5429d60647782c91d53ac765865/src/Identity/Core/src/SignInManager.cs#L638-L674). In this case, we will be using a minorly modified version of the source code which explicitly shows the namespaces of the methods and properties to help better understanding of the concept.
````csharp
public override async Task<Microsoft.AspNetCore.Identity.ExternalLoginInfo> GetExternalLoginInfoAsync(string expectedXsrf = null)
public async override Task<Microsoft.AspNetCore.Identity.ExternalLoginInfo> GetExternalLoginInfoAsync(string expectedXsrf = null)
{
var auth = await Context.AuthenticateAsync(Microsoft.AspNetCore.Identity.IdentityConstants.ExternalScheme);
var items = auth?.Properties?.Items;
@ -93,4 +93,4 @@ PreConfigure<IdentityBuilder>(identityBuilder =>
## The Source Code
You can find the source code of the completed example [here](https://github.com/abpframework/abp-samples/tree/master/Authentication-Customization).
You can find the source code of the completed example [here](https://github.com/abpframework/abp-samples/tree/master/Authentication-Customization).

14
docs/en/Community-Articles/2020-08-07-Passwordless-Authentication/POST.md

@ -33,7 +33,7 @@ namespace PasswordlessAuthentication.Web
}
//We need to override this method as well.
public override async Task<string> GetUserModifierAsync(string purpose, UserManager<TUser> manager, TUser user)
public async override Task<string> GetUserModifierAsync(string purpose, UserManager<TUser> manager, TUser user)
{
var userId = await manager.GetUserIdAsync(user);
@ -105,7 +105,7 @@ namespace PasswordlessAuthentication.Web.Pages
UserManager = userManager;
_userRepository = userRepository;
}
public ActionResult OnGet()
{
if (!CurrentUser.IsAuthenticated)
@ -115,15 +115,15 @@ namespace PasswordlessAuthentication.Web.Pages
return Page();
}
//added for passwordless authentication
public async Task<IActionResult> OnPostGeneratePasswordlessTokenAsync()
{
var adminUser = await _userRepository.FindByNormalizedUserNameAsync("admin");
var token = await UserManager.GenerateUserTokenAsync(adminUser, "PasswordlessLoginProvider",
"passwordless-auth");
PasswordlessLoginUrl = Url.Action("Login", "Passwordless",
new {token = token, userId = adminUser.Id.ToString()}, Request.Scheme);
@ -238,7 +238,7 @@ namespace PasswordlessAuthentication.Web.Controllers
return Redirect("/");
}
private static IEnumerable<Claim> CreateClaims(IUser user, IEnumerable<string> roles)
{
var claims = new List<Claim>
@ -272,4 +272,4 @@ That's all! We created a passwordless login with 7 steps.
## Source Code
The completed sample is available on [GitHub repository](https://github.com/abpframework/abp-samples/tree/master/PasswordlessAuthentication).
The completed sample is available on [GitHub repository](https://github.com/abpframework/abp-samples/tree/master/PasswordlessAuthentication).

2
docs/en/Community-Articles/2020-08-31-Adding-User-Navigation-In-Suite/POST.md

@ -22,6 +22,8 @@ Then add a string property called `Title`, as an example property.
### Create AppUserDto
_Note that, creating `AppUserDto` is not necessary after ABP v4.X_
ABP Suite needs a DTO for the target entity (user, in this case) in order to define a navigation property.
To do this, create a new folder called "Users" in `*.Application.Contracts` then add a new class called `AppUserDto` inherited from `IdentityUserDto`.

477
docs/en/Community-Articles/2020-09-09-Replacing-Email-Template-and-Sending-Emails/POST.md

@ -0,0 +1,477 @@
# Replacing Email Templates and Sending Emails
## Introduction
Hi, in this step by step article, we will send an email by using standard email template and then we will replace the standard email template with our new created template, thanks to [Text Templating System](https://docs.abp.io/en/abp/latest/Text-Templating#replacing-the-existing-templates) and [Virtual File System](https://docs.abp.io/en/abp/latest/Virtual-File-System). Let's start by explaining what these systems do.
* ABP framework provides a strong and flexible [Text Templating System](https://docs.abp.io/en/abp/latest/Text-Templating). So, we can use the text templating system to create dynamic email contents on a template and a model.
* In this article, we will use `StandardEmailTemplates.Message` as standard email template. Then we will create a new template and replace the standard email template with our new template by using [Virtual File System](https://docs.abp.io/en/abp/latest/Virtual-File-System).
* The `Virtual File System` makes it possible to manage files that do not physically exist on the file system. That means we can override `StandardEmailTemplates.Message` template by changing it's path with our new template's path.
## Creating the Solution
> ABP Framework offers startup templates to get into the business faster.
In this article, I will create a new startup template and perform the operations on this template. But if you already have a project you don't need to create a new startup template, you can implement the following steps to your existing project. (These steps can be applied to any project. (MVC, Angular etc.))
> If you have already a project you can skip this section.
Before starting to development, we will create a solution named `TemplateReplace` (or whatever you want). We can create a new startup template by using [ABP CLI](https://docs.abp.io/en/abp/latest/CLI) :
````bash
abp new TemplateReplace
````
Our project boilerplate will be ready after the download is finished. Then, open the solution in the Visual Studio (or your favorite IDE).
Run the `TemplateReplace.DbMigrator` application as below to create the database and seed initial data (which creates the admin user, admin role, permissions etc.).
![db-migrator-1](db-migrator-1.jpg)
* Right click to `TemplateReplace.DbMigrator` and choose the `Debug`.
![db-migrator-2](db-migrator-2.jpg)
* After that, click the `Start new instance` option to start the database migrations.
![db-migrator-3](db-migrator-3.jpg)
Then we can run the `TemplateReplace.Web` project to see our application working.
> _Default login credentials for admin: username is **admin** and password is **1q2w3E\***_
## Starting the Development
First thing we need to do is, creating a email service to sending emails. ABP Framework provides `IEmailSender` service that is used to send emails.
### Step - 1
Create an `Emailing` folder in the `TemplateReplace.Domain` project and add a class named `EmailService` inside of it.
```csharp
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Emailing;
using Volo.Abp.Emailing.Templates;
using Volo.Abp.TextTemplating;
namespace TemplateReplace.Emailing
{
public class EmailService : ITransientDependency
{
private readonly IEmailSender _emailSender;
private readonly ITemplateRenderer _templateRenderer;
public EmailService(IEmailSender emailSender, ITemplateRenderer templateRenderer)
{
_emailSender = emailSender;
_templateRenderer = templateRenderer;
}
public async Task SendAsync(string targetEmail)
{
var emailBody = await _templateRenderer.RenderAsync(
StandardEmailTemplates.Message,
new
{
message = "ABP Framework provides IEmailSender service that is used to send emails."
}
);
await _emailSender.SendAsync(
targetEmail,
"Subject",
emailBody
);
}
}
}
```
* To create an email content, we need to inject `ITemplateRenderer` and use the `RenderAsync` method to render a template.
* We've used `StandardEmailTemplates.Message` as standart email template. This provides us a standard and simple message template to send mails.
* The resulting email body should be like shown below:
```html
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
</head>
<body>
ABP Framework provides IEmailSender service that is used to send emails.
</body>
</html>
```
### Step - 2 (Configuring Email Settings)
* Now, we need to configure some email settings by following [settings documentation](https://docs.abp.io/en/abp/latest/Settings#setting-values-in-the-application-configuration). For achieve this, open the `appsettings.json` file under `TemplateReplace.Web` and configure your email settings in **settings** section like below.
![appsettings.json](settings.jpg)
* Here, I used Google's SMTP settings to send emails via Gmail. You can change these setting values by your need.
> **Note:** If you want to use Google's SMTP server settings and send emails via Gmail, you should confirm [this](https://myaccount.google.com/u/0/lesssecureapps).
### Step - 3
* After that we need to open `TemplateReplaceDomainModule.cs` file and change its contents as below to sending real-time emails.
```csharp
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using TemplateReplace.MultiTenancy;
using Volo.Abp.AuditLogging;
using Volo.Abp.BackgroundJobs;
using Volo.Abp.Emailing;
using Volo.Abp.FeatureManagement;
using Volo.Abp.Identity;
using Volo.Abp.IdentityServer;
using Volo.Abp.Modularity;
using Volo.Abp.MultiTenancy;
using Volo.Abp.PermissionManagement.Identity;
using Volo.Abp.PermissionManagement.IdentityServer;
using Volo.Abp.SettingManagement;
using Volo.Abp.TenantManagement;
namespace TemplateReplace
{
[DependsOn(
typeof(TemplateReplaceDomainSharedModule),
typeof(AbpAuditLoggingDomainModule),
typeof(AbpBackgroundJobsDomainModule),
typeof(AbpFeatureManagementDomainModule),
typeof(AbpIdentityDomainModule),
typeof(AbpPermissionManagementDomainIdentityModule),
typeof(AbpIdentityServerDomainModule),
typeof(AbpPermissionManagementDomainIdentityServerModule),
typeof(AbpSettingManagementDomainModule),
typeof(AbpTenantManagementDomainModule),
typeof(AbpEmailingModule)
)]
public class TemplateReplaceDomainModule : AbpModule
{
public override void OnApplicationInitialization(ApplicationInitializationContext context)
{
var settingManager = context.ServiceProvider.GetService<SettingManager>();
//encrypts the password on set and decrypts on get
settingManager.SetGlobalAsync(EmailSettingNames.Smtp.Password, "your_password");
}
public override void ConfigureServices(ServiceConfigurationContext context)
{
Configure<AbpMultiTenancyOptions>(options =>
{
options.IsEnabled = MultiTenancyConsts.IsEnabled;
});
// #if DEBUG
// context.Services.Replace(ServiceDescriptor.Singleton<IEmailSender, NullEmailSender>());
// #endif
}
}
}
```
* `NullEmailSender` is a built-in class that implements the `IEmailSender`, but writes email contents to the standard log system, rather than actually sending the emails. This class can be useful especially in development time where you generally don't want to send real emails. Therefore ABP framework defined this by default. But in our case we want to send real emails, so we must remove these lines or we must take it to the comment line.
* `Abp.Mailing.Smtp.Password` must be an encrypted value. Therefore we used `SettingManager` in here to set the password. It internally **encrypts** the values on set and **decrypts** on get.
* After all these steps, whenever we want to send an email, we can do it by using our `EmailService` class. We can inject this class and invoke the `SendAsync` method to sending email where its needed.
After sending the email we should see the template like below.
![email-message](message.jpg)
### Step - 4 (Defining New Template)
* So far we've sent mail by using standard email template of ABP. But we may want to replace the email template with the new one. We can achieve this by following the `Text Templating` [documentation](https://docs.abp.io/en/abp/latest/Text-Templating#replacing-the-existing-templates).
* In this article, I will create a email template by using free template generator named **Bee**. You can reach the free templates from [here](https://beefree.io/templates/free/).
* When we find a template for our purpose, we can hover the link and click the **get started** button to edit the template. (I chose a template named "gdpr".)
* Here, you can edit your template as below. (You can delete or add sections, edit texts, and so on.)
![bee](bee.gif)
> **Note:** After editing our template, we need to export it to reach our created template's content. You can see the **export** button top-right of the template editing page.
* After choosing and editing our free template, we can create a new **email template** in our project. For this, create a folder named `Templates` under `Emailing` folder in `TemplateReplace.Domain` and add `EmailTemplate.tpl` file inside of it. And copy-paste the below content or your template's content.
```tpl
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional //EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:v="urn:schemas-microsoft-com:vml">
<head>
<meta content="text/html; charset=utf-8" http-equiv="Content-Type"/>
<meta content="width=device-width" name="viewport"/>
<meta content="IE=edge" http-equiv="X-UA-Compatible"/>
<style type="text/css">
body {
margin: 0;
padding: 0;
}
table,
td,
tr {
vertical-align: top;
border-collapse: collapse;
}
* {
line-height: inherit;
}
a[x-apple-data-detectors=true] {
color: inherit !important;
text-decoration: none !important;
}
</style>
<style id="media-query" type="text/css">
@media (max-width: 670px) {
.block-grid,
.col {
min-width: 320px !important;
max-width: 100% !important;
display: block !important;
}
.block-grid {
width: 100% !important;
}
.col {
width: 100% !important;
}
.col>div {
margin: 0 auto;
}
img.fullwidth,
img.fullwidthOnMobile {
max-width: 100% !important;
}
.no-stack .col {
min-width: 0 !important;
display: table-cell !important;
}
.no-stack.two-up .col {
width: 50% !important;
}
.no-stack .col.num2 {
width: 16.6% !important;
}
.no-stack .col.num3 {
width: 25% !important;
}
.no-stack .col.num4 {
width: 33% !important;
}
.no-stack .col.num5 {
width: 41.6% !important;
}
.no-stack .col.num6 {
width: 50% !important;
}
.no-stack .col.num7 {
width: 58.3% !important;
}
.no-stack .col.num8 {
width: 66.6% !important;
}
.no-stack .col.num9 {
width: 75% !important;
}
.no-stack .col.num10 {
width: 83.3% !important;
}
.video-block {
max-width: none !important;
}
.mobile_hide {
min-height: 0px;
max-height: 0px;
max-width: 0px;
display: none;
overflow: hidden;
font-size: 0px;
}
.desktop_hide {
display: block !important;
max-height: none !important;
}
}
</style>
</head>
<body class="clean-body" style="margin: 0; padding: 0; -webkit-text-size-adjust: 100%; background-color: #3d1554;">
<table bgcolor="#3d1554" cellpadding="0" cellspacing="0" class="nl-container" role="presentation" style="table-layout: fixed; vertical-align: top; min-width: 320px; border-spacing: 0; border-collapse: collapse; mso-table-lspace: 0pt; mso-table-rspace: 0pt; background-color: #3d1554; width: 100%;" valign="top" width="100%">
<tbody>
<tr style="vertical-align: top;" valign="top">
<td style="word-break: break-word; vertical-align: top;" valign="top">
<div style="background-color:transparent;overflow:hidden">
<div class="block-grid" style="min-width: 320px; max-width: 650px; overflow-wrap: break-word; word-wrap: break-word; word-break: break-word; Margin: 0 auto; width: 100%; background-color: transparent;">
<div style="border-collapse: collapse;display: table;width: 100%;background-color:transparent;">
<div class="col num12" style="min-width: 320px; max-width: 650px; display: table-cell; vertical-align: top; width: 650px;">
<div style="width:100% !important;">
<div style="border-top:0px solid transparent; border-left:0px solid transparent; border-bottom:0px solid transparent; border-right:0px solid transparent; padding-top:35px; padding-bottom:0px; padding-right: 0px; padding-left: 0px;">
<div align="center" class="img-container center autowidth" style="padding-right: 0px;padding-left: 0px;"></div>
</div>
</div>
</div>
</div>
</div>
</div>
<div style="background-color:transparent;overflow:hidden">
<div class="block-grid" style="min-width: 320px; max-width: 650px; overflow-wrap: break-word; word-wrap: break-word; word-break: break-word; Margin: 0 auto; width: 100%; background-color: transparent;">
<div style="border-collapse: collapse;display: table;width: 100%;background-color:transparent;">
<div class="col num12" style="min-width: 320px; max-width: 650px; display: table-cell; vertical-align: top; width: 642px;">
<div style="width:100% !important;">
<div style="border-top:0px solid transparent; border-left:4px solid #57366E; border-bottom:0px solid transparent; border-right:4px solid #57366E; padding-top:55px; padding-bottom:60px; padding-right: 0px; padding-left: 0px;">
<div style="color:#fbd711;font-family:Poppins, Arial, Helvetica, sans-serif;line-height:1.2;padding-top:10px;padding-right:10px;padding-bottom:10px;padding-left:10px;">
<div style="line-height: 1.2; font-size: 12px; color: #fbd711; font-family: Poppins, Arial, Helvetica, sans-serif; mso-line-height-alt: 14px;">
<p style="font-size: 14px; line-height: 1.2; word-break: break-word; text-align: center; mso-line-height-alt: 17px; margin: 0;"><strong><span style="font-size: 30px;">ABP Community </span></strong></p>
</div>
</div>
<div style="color:#ffffff;font-family:Poppins, Arial, Helvetica, sans-serif;line-height:1.8;padding-top:10px;padding-right:50px;padding-bottom:10px;padding-left:50px;">
<div style="line-height: 1.8; font-size: 12px; color: #ffffff; font-family: Poppins, Arial, Helvetica, sans-serif; mso-line-height-alt: 22px;">
<p style="line-height: 1.8; word-break: break-word; font-size: 14px; mso-line-height-alt: 25px; margin: 0;"><span style="font-size: 14px;">Share your experiences with the ABP Framework!</span><br/><span style="font-size: 14px;">ABP is an open source and community driven project. This guide is aims to help anyone wants to contribute to the project.</span></p>
<p style="line-height: 1.8; word-break: break-word; font-size: 14px; mso-line-height-alt: 25px; margin: 0;"><span style="font-size: 14px;">If you want to write articles or "how to" guides related to the ABP Framework and ASP.NET Core, please submit your article to the community.abp.io web site.</span></p>
</div>
</div>
<div align="center" class="button-container" style="padding-top:12px;padding-right:10px;padding-bottom:12px;padding-left:10px;">
<a href="http://www.example.com/" style="-webkit-text-size-adjust: none; text-decoration: none; display: inline-block; color: #000000; background-color: #fbd711; border-radius: 30px; -webkit-border-radius: 30px; -moz-border-radius: 30px; width: auto; width: auto; border-top: 1px solid #fbd711; border-right: 1px solid #fbd711; border-bottom: 1px solid #fbd711; border-left: 1px solid #fbd711; padding-top: 10px; padding-bottom: 10px; font-family: Poppins, Arial, Helvetica, sans-serif; text-align: center; mso-border-alt: none; word-break: keep-all;" target="_blank"><span style="padding-left:45px;padding-right:45px;font-size:18px;display:inline-block;"><span style="font-size: 16px; line-height: 2; word-break: break-word; mso-line-height-alt: 32px;"><span data-mce-style="font-size: 18px; line-height: 36px;" style="font-size: 18px; line-height: 36px;"><strong>Contribute</strong></span></span></span></a>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</td>
</tr>
</tbody>
</table>
</body>
</html>
```
* Then we need to make the template file as "Embedded Resource". We can do this as below.
* First right click to **EmailTemplate.tpl** and choose `Properties`.
![embedded-resource](embedded-resource.jpg)
* Then be sure about build action is **Embedded resource**.
![embedded-resource-2](embedded-resource-2.jpg)
### Step - 4 (Replacing the Email Template)
* To replace the current email template with our new email template, we need to override it. To achieve this, create a class named `EmailTemplateDefinitionProvider` under `Emailing` folder in `TemplateReplace.Domain` and fill it with the below content.
```csharp
using Volo.Abp.DependencyInjection;
using Volo.Abp.Emailing.Templates;
using Volo.Abp.TextTemplating;
namespace TemplateReplace.Emailing
{
public class EmailTemplateDefinitionProvider : TemplateDefinitionProvider, ITransientDependency
{
public override void Define(ITemplateDefinitionContext context)
{
var emailLayoutTemplate = context.GetOrNull(StandardEmailTemplates.Message);
emailLayoutTemplate
.WithVirtualFilePath(
"/Emailing/Templates/EmailTemplate.tpl",
isInlineLocalized: true
);
}
}
}
```
* In here we've created a template definition provider class that gets the email layout template and change the virtual file path for the template.
* This approach allows us to locate templates in any folder instead of the folder defined by the depended module. For more detail, check the [Virtual File System](https://docs.abp.io/en/abp/latest/Virtual-File-System).
### Step - 5
* Lastly, we need to configure the [Virtual File System](https://docs.abp.io/en/abp/latest/Virtual-File-System). To do this open your `TemplateReplaceDomainModule.cs` in `TemplateReplace.Domain` and update the content as below.
```csharp
using TemplateReplace.MultiTenancy;
using Volo.Abp.AuditLogging;
using Volo.Abp.BackgroundJobs;
using Volo.Abp.Emailing;
using Volo.Abp.FeatureManagement;
using Volo.Abp.Identity;
using Volo.Abp.IdentityServer;
using Volo.Abp.Modularity;
using Volo.Abp.MultiTenancy;
using Volo.Abp.PermissionManagement.Identity;
using Volo.Abp.PermissionManagement.IdentityServer;
using Volo.Abp.SettingManagement;
using Volo.Abp.TenantManagement;
using Volo.Abp.VirtualFileSystem;
namespace TemplateReplace
{
[DependsOn(
typeof(TemplateReplaceDomainSharedModule),
typeof(AbpAuditLoggingDomainModule),
typeof(AbpBackgroundJobsDomainModule),
typeof(AbpFeatureManagementDomainModule),
typeof(AbpIdentityDomainModule),
typeof(AbpPermissionManagementDomainIdentityModule),
typeof(AbpIdentityServerDomainModule),
typeof(AbpPermissionManagementDomainIdentityServerModule),
typeof(AbpSettingManagementDomainModule),
typeof(AbpTenantManagementDomainModule),
typeof(AbpEmailingModule)
)]
public class TemplateReplaceDomainModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
Configure<AbpMultiTenancyOptions>(options =>
{
options.IsEnabled = MultiTenancyConsts.IsEnabled;
});
//Add this configuration
Configure<AbpVirtualFileSystemOptions>(options =>
{
options.FileSets.AddEmbedded<TemplateReplaceDomainModule>();
});
}
}
}
```
* And now when we send a new email, we should see our newly defined template as the message like below.
![email-last](email-last.jpg)
## Text Template Management
* Generally, more than one e-mail is required in applications. We create email templates for **"password changes"** or **"welcome"** etc in our applications. In such cases, it is necessary to create different templates for each mail. ABP Commercial allows us to perform these operations on UI in a simple way. Text Template Management provides UI to easily create and manage email templates.
![template-definitions](template-definitions.png)
* ABP Commercial's [Text Template Management](https://commercial.abp.io/modules/Volo.TextTemplateManagement) module is really fascinating. It makes it super easy to stores and edits template contents. We can list all templates on a page, editing them, localizing them, and so on.
![inline-content](inline-content.png)
* ABP Commercial's text template management module, allows us to modify a template through the UI.
* I highly recommend you to [check it out](https://commercial.abp.io/modules/Volo.TextTemplateManagement).
## References
* [Text Templating](https://docs.abp.io/en/abp/latest/Text-Templating)
* [Emailing](https://docs.abp.io/en/abp/latest/Emailing)
* [Virtual File System](https://docs.abp.io/en/abp/latest/Virtual-File-System)

BIN
docs/en/Community-Articles/2020-09-09-Replacing-Email-Template-and-Sending-Emails/bee.gif

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 MiB

BIN
docs/en/Community-Articles/2020-09-09-Replacing-Email-Template-and-Sending-Emails/db-migrator-1.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

BIN
docs/en/Community-Articles/2020-09-09-Replacing-Email-Template-and-Sending-Emails/db-migrator-2.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

BIN
docs/en/Community-Articles/2020-09-09-Replacing-Email-Template-and-Sending-Emails/db-migrator-3.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

BIN
docs/en/Community-Articles/2020-09-09-Replacing-Email-Template-and-Sending-Emails/email-last.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 111 KiB

BIN
docs/en/Community-Articles/2020-09-09-Replacing-Email-Template-and-Sending-Emails/embedded-resource-2.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

BIN
docs/en/Community-Articles/2020-09-09-Replacing-Email-Template-and-Sending-Emails/embedded-resource.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 KiB

BIN
docs/en/Community-Articles/2020-09-09-Replacing-Email-Template-and-Sending-Emails/inline-content.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

BIN
docs/en/Community-Articles/2020-09-09-Replacing-Email-Template-and-Sending-Emails/message.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

BIN
docs/en/Community-Articles/2020-09-09-Replacing-Email-Template-and-Sending-Emails/settings.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

BIN
docs/en/Community-Articles/2020-09-09-Replacing-Email-Template-and-Sending-Emails/template-definitions.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 91 KiB

160
docs/en/Community-Articles/2020-10-08-How-To-Add-Custom-Property-To-The-User-Entity/How-To-Add-Custom-Property-To-The-User-Entity.md

@ -0,0 +1,160 @@
# How to Add Custom Properties to the User Entity
## Introduction
In this step-by-step article, I will explain how you can customize the user entity class, which is available in every web application you create using the ABP framework, according to your needs. When you read this article, you will learn how to override the services of built-in modules, extend the entities, extend data transfer objects and customize the user interface in the applications you develop using the ABP framework.
You can see the screenshots below which we will reach at the end of the article.
![custom-identity-user-list](./custom-identity-user-list.png)
![new-user](./new-user.png)
## Preparing the Project
### Startup template and the initial run
Abp Framework offers startup templates to get into the work faster. We can create a new startup template using Abp CLI:
`abp new CustomizeUserDemo`
> In this article, I will go through the MVC application, but it will work also in the [Angular](https://docs.abp.io/en/abp/latest/Getting-Started?UI=NG&DB=EF&Tiered=No) application.
After the download is finished, we can run **CustomizeUserDemo.DbMigrator** project to create the database migrations and seed the initial data (admin user, role, etc). Then we can run `CustomizeUserDemo.Web` to see that our application is working.
> Default admin username is **admin** and password is **1q2w3E\***
![initial-project](./initial-project.png)
In this article, we will go through a scenario together and find the solutions to our questions through this scenario. However, since the scenario is not a real-life scenario, it may be strange, please don't get too about this issue :)
## Step-1
Add two new properties to the `AppUser` in the Users folder of the **CustomizeUserDemo.Domain** project as follows:
```csharp
public string Title { get; protected set; }
public int Reputation { get; protected set; }
```
## Step-2
Create the Users folder in the **CustomizeUserDemo.Domain.Shared** project, create the class `UserConsts` inside the folder and update the class you created as below:
```csharp
public static class UserConsts
{
public const string TitlePropertyName = "Title";
public const string ReputationPropertyName = "Reputation";
public const int MaxTitleLength = 64;
public const double MaxReputationValue = 1_000;
public const double MinReputationValue = 1;
}
```
## Step-3
Update the `CustomizeUserDemoEfCoreEntityExtensionMappings` class in the **CustomizeUserDemo.EntityFramework** project in the EntityFrameworkCore folder as below:
```csharp
public static class CustomizeUserDemoEfCoreEntityExtensionMappings
{
private static readonly OneTimeRunner OneTimeRunner = new OneTimeRunner();
public static void Configure()
{
CustomizeUserDemoGlobalFeatureConfigurator.Configure();
CustomizeUserDemoModuleExtensionConfigurator.Configure();
OneTimeRunner.Run(() =>
{
ObjectExtensionManager.Instance
.MapEfCoreProperty<IdentityUser, string>(
nameof(AppUser.Title),
(entityBuilder, propertyBuilder) =>
{
propertyBuilder.IsRequired();
propertyBuilder.HasMaxLength(UserConsts.MaxTitleLength);
}
).MapEfCoreProperty<IdentityUser, int>(
nameof(AppUser.Reputation),
(entityBuilder, propertyBuilder) =>
{
propertyBuilder.HasDefaultValue(UserConsts.MinReputationValue);
}
);
});
}
}
```
This class can be used to map these extra properties to table fields in the database. Please read [this](https://docs.abp.io/en/abp/latest/Customizing-Application-Modules-Extending-Entities) article to improve your understanding of what we are doing.
So far, we have added our extra features to the `User` entity and matched these features with the `ef core`.
Now we need to add migration to see what has changed in our database. This for, open the Package Manager Console (PMC) under the menu Tools > NuGet Package Manager.
![nuget-package-manager](./nuget-package-manager.png)
Select the **CustomizeUserDemo.EntityFramework.DbMigrations** as the **default project** and execute the following command:
```bash
Add-Migration "Updated-User-Entity"
```
![added-new-migration](./added-new-migration.png)
This will create a new migration class inside the `Migrations` folder of the **CustomizeUserDemo.EntityFrameworkCore.DbMigrations** project.
> If you are using another IDE than the Visual Studio, you can use `dotnet-ef` tool as [documented here](https://docs.microsoft.com/en-us/ef/core/managing-schemas/migrations/?tabs=dotnet-core-cli#create-a-migration).
Finally, run the **CustomizeUserDemo.DbMigrator** project to update the database.
When we updated the database, you can see that the `Title` and `Reputation` columns are added to the `Users` table.
![user-table](./user-table.png)
## Step-4
Open the `CustomizeUserDemoModuleExtensionConfigurator` in the **CustomizeUserDemo.Domain.Shared** project, and change the contents of the `ConfigureExtraProperties` method as shown below:
```csharp
private static void ConfigureExtraProperties()
{
ObjectExtensionManager.Instance.Modules().ConfigureIdentity(identity =>
{
identity.ConfigureUser(user =>
{
user.AddOrUpdateProperty<string>(
UserConsts.TitlePropertyName,
options =>
{
options.Attributes.Add(new RequiredAttribute());
options.Attributes.Add(
new StringLengthAttribute(UserConsts.MaxTitleLength)
);
}
);
user.AddOrUpdateProperty<int>(
UserConsts.ReputationPropertyName,
options =>
{
options.DefaultValue = UserConsts.MinReputationValue;
options.Attributes.Add(
new RangeAttribute(UserConsts.MinReputationValue, UserConsts.MaxReputationValue)
);
}
);
});
});
}
```
That's it. Now let's run the application and look at the Identity user page. You can also try to edit and recreate a record if you want, it will work even though we haven't done anything extra. Here is the magic code behind ABP framework.
If there is a situation you want to add, you can click the contribute button or make a comment. Also, if you like the article, don't forget to share it :)
Happy coding :)

BIN
docs/en/Community-Articles/2020-10-08-How-To-Add-Custom-Property-To-The-User-Entity/added-new-migration.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

BIN
docs/en/Community-Articles/2020-10-08-How-To-Add-Custom-Property-To-The-User-Entity/custom-identity-user-list.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 119 KiB

BIN
docs/en/Community-Articles/2020-10-08-How-To-Add-Custom-Property-To-The-User-Entity/initial-project.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

BIN
docs/en/Community-Articles/2020-10-08-How-To-Add-Custom-Property-To-The-User-Entity/new-user.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

BIN
docs/en/Community-Articles/2020-10-08-How-To-Add-Custom-Property-To-The-User-Entity/nuget-package-manager.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 94 KiB

BIN
docs/en/Community-Articles/2020-10-08-How-To-Add-Custom-Property-To-The-User-Entity/user-table.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 193 KiB

46
docs/en/Community-Articles/2020-11-02-How-To-Add-New-Language/POST.md

@ -0,0 +1,46 @@
# How to add a new language to your ABP project?
Adding a new language to your ABP project is pretty simple. Let's add the German language to our ABP project:
1. Go to your solution's root folder and write the following CLI command. This command will generate an empty translation file from English.
```bash
abp translate -c de-DE
```
Check out for [the complete supported culture codes](https://docs.microsoft.com/en-us/bingmaps/rest-services/common-parameters-and-types/supported-culture-codes).
(For internal development `D:\Github\abp` and `D:\Github\volo\abp`)
2. Fill the `target` fields in your target language.
![Fill target fields](language-target.png)
3. Copy `abp-translation.json` your solution's root folder (Do not change the filename!)
4. Run the following command. This command will create the necessary `json` files.
```bash
abp translate --apply
```
5. Open your solution and add the new language to the language list. To do this;
* open `MyProjectNameDomainModule.cs` and in `ConfigureServices` you'll find `Configure<AbpLocalizationOptions>`. If you have `HttpApi.Host` project then you need to add this in `MyProjectNameHttpApiHostModule.cs`
```
options.Languages.Add(new LanguageInfo("de-DE", "de-DE", "Deutsch", "de"));
```
![Add to languages](add-to-languages.png)
The last parameter is the flag icon. You can find the list of flag icons on https://flagicons.lipis.dev/
6. The last step is running the DbMigrator project. It will seed the database for the new language.
![The database table](database-table.png)
Close the IIS Express / Kestrel to invalidate the language cache and run the project. You will see the new language on your website.
![See the final result](website-new-language.png)

BIN
docs/en/Community-Articles/2020-11-02-How-To-Add-New-Language/add-to-languages.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

BIN
docs/en/Community-Articles/2020-11-02-How-To-Add-New-Language/database-table.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

BIN
docs/en/Community-Articles/2020-11-02-How-To-Add-New-Language/language-target.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

BIN
docs/en/Community-Articles/2020-11-02-How-To-Add-New-Language/website-new-language.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

936
docs/en/Community-Articles/2020-12-04-Event-Organizer/Post.md

@ -0,0 +1,936 @@
# Creating an Event Organizer Application with the ABP Framework & Blazor UI.
## Introduction
In this article, we will create an example application that is a simple **meeting/event organizer**: People create events and other people registers to the event.
The application has been developed with **Blazor** as the UI framework and **MongoDB** as the database provider.
> This tutorial is based on my notes that I'd created to implement this application in a workshop. It shows the necessary steps to build the application rather than detailed explanations.
### Source Code
Source code of the completed application is [available on GitHub](https://github.com/abpframework/abp-samples/tree/master/EventOrganizer).
### Screenshots
Here, the pages of the final application.
**Home Page - Event List**
![event-list-ui](images/event-list-ui.png)
**Creating a new Event**
![event-create-ui](images/event-create-ui.png)
**Event Detail Page**
![event-detail-ui](images/event-detail-ui.png)
## Requirements
The following tools are needed to be able to run the solution.
* .NET 5.0 SDK
* Visual Studio 2019 16.8.0+ or another compatible IDE
* MongoDB Server (with MongoDB Compass)
## Development
### Creating a new Application
* Use the following ABP CLI command:
````bash
abp new EventOrganizer -u blazor -d mongodb
````
### Open & Run the Application
* Open the solution in Visual Studio (or your favorite IDE).
* Run the `EventOrganizer.DbMigrator` application to seed the initial data.
* Run the `EventOrganizer.HttpApi.Host` application that starts the server side.
* Run the `EventOrganizer.Blazor` application to start the UI.
### Apply the Custom Styles
* Add styles to `wwwroot/main.css`:
````css
body.abp-application-layout {
background-color: #222 !important;
font-size: 18px;
}
nav#main-navbar.bg-dark {
background-color: #222 !important;
box-shadow: none !important;
}
.event-pic {
width: 100%;
border-radius: 12px;
box-shadow: 5px 5px 0px 0px rgba(0,0,0,.5);
margin-bottom: 10px;
}
.event-link:hover, .event-link:hover *{
text-decoration: none;
}
.event-link:hover .event-pic {
box-shadow: 5px 5px 0px 0px #ffd800;
}
.event-form {
background-color: #333 !important;
box-shadow: 5px 5px 0px 0px rgba(0,0,0,.5);
border-radius: 12px;
}
.table {
background: #fff;
border-radius: 12px;
box-shadow: 5px 5px 0px 0px rgba(0,0,0,.5);
}
.table th{
border: 0 !important;
}
.modal {
color: #333;
}
.page-item:first-child .page-link {
margin-left: 0;
border-top-left-radius: 12px;
border-bottom-left-radius: 12px;
}
.page-item:last-child .page-link {
border-top-right-radius: 12px;
border-bottom-right-radius: 12px;
}
.btn {
border-radius: 8px;
}
.att-list {
list-style: none;
padding: 0;
}
.att-list li {
padding: 4px 0 0 0;
}
````
* `wwwroot/index.html`: Remove `bg-light` class from the `body` tag and add `bg-dark text-light`.
### Domain Layer
* Add the following `Event` aggregate (with `EventAttendee`) to the solution:
**Event**
````csharp
using System;
using System.Collections.Generic;
using Volo.Abp.Domain.Entities.Auditing;
namespace EventOrganizer.Events
{
public class Event : FullAuditedAggregateRoot<Guid>
{
public string Title { get; set; }
public string Description { get; set; }
public bool IsFree { get; set; }
public DateTime StartTime { get; set; }
public ICollection<EventAttendee> Attendees { get; set; }
public Event()
{
Attendees = new List<EventAttendee>();
}
}
}
````
**EventAttendee**
```csharp
using System;
using Volo.Abp.Auditing;
namespace EventOrganizer.Events
{
public class EventAttendee : IHasCreationTime
{
public Guid UserId { get; set; }
public DateTime CreationTime { get; set; }
}
}
```
### MongoDB Mapping
* Add the following property to the `EventOrganizerMongoDbContext`:
````csharp
public IMongoCollection<Event> Events => Collection<Event>();
````
### Clean Index.razor & Add the Header & "Create Event" button
* Clean the `Index.razor` file.
* Replace the content with the following code:
````html
@page "/"
@inherits EventOrganizerComponentBase
<Row Class="mb-4">
<Column Class="text-left">
<h1>Upcoming Events</h1>
</Column>
<Column Class="text-right">
@if (CurrentUser.IsAuthenticated)
{
<a class="btn btn-primary" href="/create-event">
<i class="fa fa-plus"></i> @L["CreateEvent"]
</a>
}
</Column>
</Row>
````
* Open `Localization/EventOrganizer/en.json` in the `EventOrganizer.Domain.Shared` project and add the following entry:
````json
"CreateEvent": "Create a new event!"
````
The Result (run the `EventOrganizer.Blazor` application to see):
![index-title](images/index-title.png)
### Event Creation
* Create the Initial `IEventAppService` with the `CreateAsync` method:
````csharp
using System;
using System.Threading.Tasks;
using Volo.Abp.Application.Services;
namespace EventOrganizer.Events
{
public interface IEventAppService : IApplicationService
{
Task<Guid> CreateAsync(EventCreationDto input);
}
}
````
* Add `EventCreationDto` class:
````csharp
using System;
using System.ComponentModel.DataAnnotations;
namespace EventOrganizer.Events
{
public class EventCreationDto
{
[Required]
[StringLength(100)]
public string Title { get; set; }
[Required]
[StringLength(2000)]
public string Description { get; set; }
public bool IsFree { get; set; }
public DateTime StartTime { get; set; }
}
}
````
* Implement the `EventAppService`:
````csharp
using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Volo.Abp.Domain.Repositories;
namespace EventOrganizer.Events
{
public class EventAppService : EventOrganizerAppService, IEventAppService
{
private readonly IRepository<Event, Guid> _eventRepository;
public EventAppService(IRepository<Event, Guid> eventRepository)
{
_eventRepository = eventRepository;
}
[Authorize]
public async Task<Guid> CreateAsync(EventCreationDto input)
{
var eventEntity = ObjectMapper.Map<EventCreationDto, Event>(input);
await _eventRepository.InsertAsync(eventEntity);
return eventEntity.Id;
}
}
}
````
* Add AutoMapper mapping to the `EventOrganizerApplicationAutoMapperProfile` class:
````csharp
using AutoMapper;
using EventOrganizer.Events;
namespace EventOrganizer
{
public class EventOrganizerApplicationAutoMapperProfile : Profile
{
public EventOrganizerApplicationAutoMapperProfile()
{
CreateMap<EventCreationDto, Event>();
}
}
}
````
This will automatically create the HTTP (REST) API for the application service (run the `EventOrganizer.HttpApi.Host` application to see it on the Swagger UI):
![swagger-event-create](images/swagger-event-create.png)
* Create the `CreateEvent.razor` file:
````csharp
@page "/create-event"
@inherits EventOrganizerComponentBase
<Heading Size="HeadingSize.Is3" Margin="Margin.Is5.FromTop.Is4.FromBottom" Class="text-center">Create Event</Heading>
<Row>
<Column ColumnSize="ColumnSize.Is6.Is3.WithOffset">
<div class="p-lg-5 p-md-3 event-form">
<EditForm Model="@Event" OnValidSubmit="Create">
<Field>
<FieldLabel>@L["Title"]</FieldLabel>
<TextEdit @bind-Text="@Event.Title" />
</Field>
<Field>
<FieldLabel>@L["Description"]</FieldLabel>
<MemoEdit @bind-Text="@Event.Description" />
</Field>
<Field>
<Check TValue="bool" @bind-Checked="@Event.IsFree">@L["Free"]</Check>
</Field>
<Field>
<FieldLabel>@L["StartTime"]</FieldLabel>
<DateEdit TValue="DateTime" @bind-Date="@Event.StartTime" />
</Field>
<Button Type="@ButtonType.Submit" Block="true" Color="@Color.Primary" Size="Size.Large">@L["Save"]</Button>
</EditForm>
</div>
</Column>
</Row>
````
* Create a partial `CreateEvent` class in the same folder, with the `CreateEvent.razor.cs` as the file name:
````csharp
using System.Threading.Tasks;
using EventOrganizer.Events;
using Microsoft.AspNetCore.Components;
namespace EventOrganizer.Blazor.Pages
{
public partial class CreateEvent
{
private EventCreationDto Event { get; set; } = new EventCreationDto();
private readonly IEventAppService _eventAppService;
private readonly NavigationManager _navigationManager;
public CreateEvent(
IEventAppService eventAppService,
NavigationManager navigationManager)
{
_eventAppService = eventAppService;
_navigationManager = navigationManager;
}
private async Task Create()
{
var eventId = await _eventAppService.CreateAsync(Event);
_navigationManager.NavigateTo("/events/" + eventId);
}
}
}
````
The final UI is (run the `EventOrganizer.Blazor` application and click to the "Create Event" button):
![event-create-ui](images/event-create-ui.png)
### Upcoming Events (Home Page)
* Open the `IEventAppService` and add a `GetUpcomingAsync` method to get the list of upcoming events:
````csharp
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Volo.Abp.Application.Services;
namespace EventOrganizer.Events
{
public interface IEventAppService : IApplicationService
{
Task<Guid> CreateAsync(EventCreationDto input);
Task<List<EventDto>> GetUpcomingAsync();
}
}
````
* Add a `EventDto` class:
````csharp
using System;
using Volo.Abp.Application.Dtos;
namespace EventOrganizer.Events
{
public class EventDto : EntityDto<Guid>
{
public string Title { get; set; }
public string Description { get; set; }
public bool IsFree { get; set; }
public DateTime StartTime { get; set; }
public int AttendeesCount { get; set; }
}
}
````
* Implement the `GetUpcomingAsync` in the `EventAppService` class:
````csharp
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Volo.Abp.Domain.Repositories;
namespace EventOrganizer.Events
{
public class EventAppService : EventOrganizerAppService, IEventAppService
{
private readonly IRepository<Event, Guid> _eventRepository;
public EventAppService(IRepository<Event, Guid> eventRepository)
{
_eventRepository = eventRepository;
}
[Authorize]
public async Task<Guid> CreateAsync(EventCreationDto input)
{
var eventEntity = ObjectMapper.Map<EventCreationDto, Event>(input);
await _eventRepository.InsertAsync(eventEntity);
return eventEntity.Id;
}
public async Task<List<EventDto>> GetUpcomingAsync()
{
var events = await AsyncExecuter.ToListAsync(
_eventRepository
.Where(x => x.StartTime > Clock.Now)
.OrderBy(x => x.StartTime)
);
return ObjectMapper.Map<List<Event>, List<EventDto>>(events);
}
}
}
````
* Add the following line into the `EventOrganizerApplicationAutoMapperProfile` constructor:
````csharp
CreateMap<Event, EventDto>();
````
Run the `EventOrganizer.HttpApi.Host` application to see the new `upcoming` endpoint on the Swagger UI:
![swagger-event-upcoming](images/swagger-event-upcoming.png)
* Change the `Pages/Index.razor.cs` content in the `EventOrganizer.Blazor` project as shown below:
```csharp
using System.Collections.Generic;
using System.Threading.Tasks;
using EventOrganizer.Events;
namespace EventOrganizer.Blazor.Pages
{
public partial class Index
{
private List<EventDto> UpcomingEvents { get; set; } = new List<EventDto>();
private readonly IEventAppService _eventAppService;
public Index(IEventAppService eventAppService)
{
_eventAppService = eventAppService;
}
protected override async Task OnInitializedAsync()
{
UpcomingEvents = await _eventAppService.GetUpcomingAsync();
}
}
}
```
* Change the `Pages/Index.razor` content in the `EventOrganizer.Blazor` project as shown below:
````html
@page "/"
@inherits EventOrganizerComponentBase
<Row Class="mb-4">
<Column Class="text-left">
<h1>Upcoming Events</h1>
</Column>
<Column Class="text-right">
@if (CurrentUser.IsAuthenticated)
{
<a class="btn btn-primary" href="/create-event">
<i class="fa fa-plus"></i> @L["CreateEvent"]
</a>
}
</Column>
</Row>
<Row>
@foreach (var upcomingEvent in UpcomingEvents)
{
<Column Class="col-12 col-lg-4 col-md-6">
<a class="mb-5 position-relative d-block event-link" href="/events/@upcomingEvent.Id">
<div class="position-absolute text-right w-100 px-3 py-2" style="left: 0; top: 2px;">
@if (upcomingEvent.IsFree)
{
<Badge Color="Color.Success" Class="mr-1">FREE</Badge>
}
<span class="badge badge-warning font-weight-normal">
<i class="fas fa-user-friends"></i>
<span class="font-weight-bold">@upcomingEvent.AttendeesCount</span>
</span>
</div>
<img src="https://picsum.photos/seed/@upcomingEvent.Id/400/300" class="event-pic"/>
<div class="px-3 py-1">
<small class="font-weight-bold text-warning my-2 d-block text-uppercase">@upcomingEvent.StartTime.ToLongDateString()</small>
<p class="h4 text-light d-block mb-2">@upcomingEvent.Title</p>
<p class="text-light" style="opacity: .65;">@upcomingEvent.Description.TruncateWithPostfix(150)</p>
</div>
</a>
</Column>
}
</Row>
````
The new home page is shown below:
![event-list-ui](images/event-list-ui.png)
### Event Detail Page
* Add `GetAsync`, `RegisterAsync`, `UnregisterAsync` and `DeleteAsync` methods to the `IEventAppService`:
````csharp
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Volo.Abp.Application.Services;
namespace EventOrganizer.Events
{
public interface IEventAppService : IApplicationService
{
Task<Guid> CreateAsync(EventCreationDto input);
Task<List<EventDto>> GetUpcomingAsync();
Task<EventDetailDto> GetAsync(Guid id);
Task RegisterAsync(Guid id);
Task UnregisterAsync(Guid id);
Task DeleteAsync(Guid id);
}
}
````
* Add `EventDetailDto` class:
````csharp
using System;
using System.Collections.Generic;
using Volo.Abp.Application.Dtos;
namespace EventOrganizer.Events
{
public class EventDetailDto : CreationAuditedEntityDto<Guid>
{
public string Title { get; set; }
public string Description { get; set; }
public bool IsFree { get; set; }
public DateTime StartTime { get; set; }
public List<EventAttendeeDto> Attendees { get; set; }
}
}
````
* Add `EventAttendeeDto` class:
````csharp
using System;
namespace EventOrganizer.Events
{
public class EventAttendeeDto
{
public Guid UserId { get; set; }
public string UserName { get; set; }
public DateTime CreationTime { get; set; }
}
}
````
* Implement the new methods in the `EventAppService`:
````csharp
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using EventOrganizer.Users;
using Microsoft.AspNetCore.Authorization;
using Volo.Abp;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.Users;
namespace EventOrganizer.Events
{
public class EventAppService : EventOrganizerAppService, IEventAppService
{
private readonly IRepository<Event, Guid> _eventRepository;
private readonly IRepository<AppUser, Guid> _userRepository;
public EventAppService(IRepository<Event, Guid> eventRepository, IRepository<AppUser, Guid> userRepository)
{
_eventRepository = eventRepository;
_userRepository = userRepository;
}
[Authorize]
public async Task<Guid> CreateAsync(EventCreationDto input)
{
var eventEntity = ObjectMapper.Map<EventCreationDto, Event>(input);
await _eventRepository.InsertAsync(eventEntity);
return eventEntity.Id;
}
public async Task<List<EventDto>> GetUpcomingAsync()
{
var events = await AsyncExecuter.ToListAsync(
_eventRepository
.Where(x => x.StartTime > Clock.Now)
.OrderBy(x => x.StartTime)
);
return ObjectMapper.Map<List<Event>, List<EventDto>>(events);
}
public async Task<EventDetailDto> GetAsync(Guid id)
{
var @event = await _eventRepository.GetAsync(id);
var attendeeIds = @event.Attendees.Select(a => a.UserId).ToList();
var attendees = (await AsyncExecuter.ToListAsync(_userRepository.Where(u => attendeeIds.Contains(u.Id))))
.ToDictionary(x => x.Id);
var result = ObjectMapper.Map<Event, EventDetailDto>(@event);
foreach (var attendeeDto in result.Attendees)
{
attendeeDto.UserName = attendees[attendeeDto.UserId].UserName;
}
return result;
}
[Authorize]
public async Task RegisterAsync(Guid id)
{
var @event = await _eventRepository.GetAsync(id);
if (@event.Attendees.Any(a => a.UserId == CurrentUser.Id))
{
return;
}
@event.Attendees.Add(new EventAttendee {UserId = CurrentUser.GetId(), CreationTime = Clock.Now});
await _eventRepository.UpdateAsync(@event);
}
[Authorize]
public async Task UnregisterAsync(Guid id)
{
var @event = await _eventRepository.GetAsync(id);
var removedItems = @event.Attendees.RemoveAll(x => x.UserId == CurrentUser.Id);
if (removedItems.Any())
{
await _eventRepository.UpdateAsync(@event);
}
}
[Authorize]
public async Task DeleteAsync(Guid id)
{
var @event = await _eventRepository.GetAsync(id);
if (CurrentUser.Id != @event.CreatorId)
{
throw new UserFriendlyException("You don't have the necessary permission to delete this event!");
}
await _eventRepository.DeleteAsync(id);
}
}
}
````
* Add the following mappings into the `EventOrganizerApplicationAutoMapperProfile`:
````csharp
CreateMap<Event, EventDetailDto>();
CreateMap<EventAttendee, EventAttendeeDto>();
````
Run the `EventOrganizer.HttpApi.Host` application to see the complete Event HTTP API in the Swagger UI:
![swagger-event-all](images/swagger-event-all.png)
* Create `EventDetail.razor` component with the following content:
````html
@page "/events/{id}"
@inherits EventOrganizerComponentBase
@if (Event != null)
{
<Row Class="mb-4">
<Column Class="text-left">
<h1>@Event.Title</h1>
</Column>
<Column Class="text-right pt-2">
<a href="/" Class="btn btn-dark"><i class="fa fa-arrow-left"></i> Back</a>
@if (CurrentUser.IsAuthenticated && CurrentUser.Id == Event.CreatorId)
{
<Button Color="Color.Danger" Clicked="Delete" Class="ml-1">Delete</Button>
}
</Column>
</Row>
<Row>
<Column Class="col-12 col-md-8">
<div class="position-relative">
<div class="position-absolute text-right w-100 px-3 py-2" style="left: 0; top: 2px;">
@if (Event.IsFree)
{
<Badge Color="Color.Success" Class="mr-1">FREE</Badge>
}
<span class="badge badge-warning font-weight-normal">
<i class="fas fa-user-friends"></i>
<span class="font-weight-bold">@Event.Attendees.Count</span>
</span>
</div>
<img src="https://picsum.photos/seed/@Event.Id/800/600" class="event-pic" />
<small class="font-weight-bold text-warning my-2 d-block text-uppercase">Start time: @Event.StartTime.ToLongDateString()</small>
<p style="opacity: .65;">@Event.Description</p>
</div>
</Column>
<Column Class="col-12 col-md-4">
<div class="p-4 event-form">
@if (CurrentUser.IsAuthenticated)
{
<div>
@if (!IsRegistered)
{
<Button Color="Color.Primary" Clicked="Register" Class="btn-block btn-lg">Register now!</Button>
}
else
{
<p>You are registered in this event</p>
<Button Color="Color.Secondary" Clicked="UnRegister" Class="btn-block">Cancel registration!</Button>
}
</div>
}
else
{
<a class="btn btn-primary" href="/authentication/login">
<i class="fa fa-sign-in-alt"></i> Login to attend!
</a>
}
</div>
<div class="mt-4 event-form p-4">
<span class="font-weight-bold"><i class="fas fa-user-friends"></i> Attendees <span class="float-right font-weight-normal" style="opacity:.65;">(@Event.Attendees.Count)</span></span>
<ul class="mt-1 mb-0 att-list">
@foreach (var attendee in Event.Attendees)
{
<li><i class="fa fa-check"></i> @attendee.UserName</li>
}
</ul>
</div>
</Column>
</Row>
}
````
* Create `EventDetail.razor.cs` file with the following content:
````csharp
using System;
using System.Linq;
using System.Threading.Tasks;
using EventOrganizer.Events;
using Microsoft.AspNetCore.Components;
namespace EventOrganizer.Blazor.Pages
{
public partial class EventDetail
{
[Parameter]
public string Id { get; set; }
private EventDetailDto Event { get; set; }
private bool IsRegistered { get; set; }
private readonly IEventAppService _eventAppService;
private readonly NavigationManager _navigationManager;
public EventDetail(
IEventAppService eventAppService,
NavigationManager navigationManager)
{
_eventAppService = eventAppService;
_navigationManager = navigationManager;
}
protected override async Task OnInitializedAsync()
{
await GetEventAsync();
}
private async Task GetEventAsync()
{
Event = await _eventAppService.GetAsync(Guid.Parse(Id));
if (CurrentUser.IsAuthenticated)
{
IsRegistered = Event.Attendees.Any(a => a.UserId == CurrentUser.Id);
}
}
private async Task Register()
{
await _eventAppService.RegisterAsync(Guid.Parse(Id));
await GetEventAsync();
}
private async Task UnRegister()
{
await _eventAppService.UnregisterAsync(Guid.Parse(Id));
await GetEventAsync();
}
private async Task Delete()
{
if (!await Message.Confirm("This event will be deleted: " + Event.Title))
{
return;
}
await _eventAppService.DeleteAsync(Guid.Parse(Id));
_navigationManager.NavigateTo("/");
}
}
}
````
The resulting page is shown below:
![event-detail-ui](images/event-detail-ui.png)
### Integration Tests
Create an `EventAppService_Tests` class in the `EventOrganizer.Application.Tests` project:
````csharp
using System;
using System.Threading.Tasks;
using Shouldly;
using Xunit;
namespace EventOrganizer.Events
{
[Collection(EventOrganizerTestConsts.CollectionDefinitionName)]
public class EventAppService_Tests : EventOrganizerApplicationTestBase
{
private readonly IEventAppService _eventAppService;
public EventAppService_Tests()
{
_eventAppService = GetRequiredService<IEventAppService>();
}
[Fact]
public async Task Should_Create_A_Valid_Event()
{
// Create an event
var eventId = await _eventAppService.CreateAsync(
new EventCreationDto
{
Title = "My test event 1",
Description = "My test event description 1",
IsFree = true,
StartTime = DateTime.Now.AddDays(2)
}
);
eventId.ShouldNotBe(Guid.Empty);
// Get the event
var @event = await _eventAppService.GetAsync(eventId);
@event.Title.ShouldBe("My test event 1");
// Get upcoming events
var events = await _eventAppService.GetUpcomingAsync();
events.ShouldContain(x => x.Title == "My test event 1");
}
}
}
````
## Source Code
Source code of the completed application is [available on GitHub](https://github.com/abpframework/abp-samples/tree/master/EventOrganizer).

BIN
docs/en/Community-Articles/2020-12-04-Event-Organizer/images/event-create-ui.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

BIN
docs/en/Community-Articles/2020-12-04-Event-Organizer/images/event-detail-ui.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

BIN
docs/en/Community-Articles/2020-12-04-Event-Organizer/images/event-list-ui.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 865 KiB

BIN
docs/en/Community-Articles/2020-12-04-Event-Organizer/images/index-title.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

BIN
docs/en/Community-Articles/2020-12-04-Event-Organizer/images/swagger-event-all.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

BIN
docs/en/Community-Articles/2020-12-04-Event-Organizer/images/swagger-event-create.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

BIN
docs/en/Community-Articles/2020-12-04-Event-Organizer/images/swagger-event-upcoming.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

27
docs/en/Contribution/Index.md

@ -2,31 +2,36 @@
ABP is an [open source](https://github.com/abpframework) and community driven project. This guide is aims to help anyone wants to contribute to the project.
## community.abp.io
## ABP Community Website
If you want to write articles or "how to" guides related to the ABP Framework and ASP.NET Core, please submit your article to the [community.abp.io](https://community.abp.io/) web site.
If you want to write **articles** or **how to guides** related to the ABP Framework and ASP.NET Core, please submit your article to the [community.abp.io](https://community.abp.io/) website.
## Code Contribution
You can always send pull requests to the Github repository.
You can always send pull requests to the GitHub repository.
- Clone the [ABP repository](https://github.com/abpframework/abp/) from Github.
- Make the required changes.
- Clone the [ABP repository](https://github.com/abpframework/abp/) from GitHub.
- Build the repository using the `/build/build-all.ps1 -f` for one time.
- Make the necessary changes, including unit/integration tests.
- Send a pull request.
> When you open a solution in Visual Studio, you may need to execute `dotnet restore` in the root folder of the solution for one time, after it is fully opened in the Visual Studio. This is needed since VS can't properly resolves local references to projects out of the solution.
### GitHub Issues
Before making any change, please discuss it on the [Github issues](https://github.com/abpframework/abp/issues). In this way, no other developer will work on the same issue and your PR will have a better chance to be accepted.
### Bug Fixes & Enhancements
#### Bug Fixes & Enhancements
You may want to fix a known bug or work on a planned enhancement. See [the issue list](https://github.com/abpframework/abp/issues) on Github.
### Feature Requests
#### Feature Requests
If you have a feature idea for the framework or modules, [create an issue](https://github.com/abpframework/abp/issues/new) on Github or attend to an existing discussion. Then you can implement it if it's embraced by the community.
## Document Translation
You may want to translate the complete [documentation](https://abp.io/documents/) (including this one) to your mother language. If so, follow these steps:
You may want to translate the complete [documentation](https://docs.abp.io) (including this one) to your mother language. If so, follow these steps:
* Clone the [ABP repository](https://github.com/abpframework/abp/) from Github.
* To add a new language, create a new folder inside the [docs](https://github.com/abpframework/abp/tree/master/docs) folder. Folder names can be "en", "es", "fr", "tr" and so on based on the language (see [all culture codes](https://msdn.microsoft.com/en-us/library/hh441729.aspx)).
@ -35,9 +40,9 @@ You may want to translate the complete [documentation](https://abp.io/documents/
There are some fundamental documents need to be translated before publishing a language on the [ABP documentation web site](https://docs.abp.io):
* Getting Started documents
* Tutorials
* CLI
* Index (Home)
* Getting Started
* Web Application Development Tutorial
A new language is published after these minimum translations have been completed.

85
docs/en/Customizing-Application-Modules-Overriding-Services.md

@ -29,7 +29,7 @@ public class TestAppService : IIdentityUserAppService, ITransientDependency
}
````
The dependency injection system allows to register multiple services for the same interface. The last registered one is used when the interface is injected. It is a good practice to explicitly replace the service.
The dependency injection system allows to register multiple services for the same interface. The last registered one is used when the interface is injected. It is a good practice to explicitly replace the service.
Example:
@ -59,7 +59,6 @@ In most cases, you will want to change one or a few methods of the current imple
### Example: Overriding an Application Service
````csharp
//[RemoteService(IsEnabled = false)] // If you use dynamic controller feature you can disable remote service. Prevent creating duplicate controller for the application service.
[Dependency(ReplaceServices = true)]
[ExposeServices(typeof(IIdentityUserAppService), typeof(IdentityUserAppService), typeof(MyIdentityUserAppService))]
public class MyIdentityUserAppService : IdentityUserAppService
@ -76,7 +75,7 @@ public class MyIdentityUserAppService : IdentityUserAppService
{
}
public override async Task<IdentityUserDto> CreateAsync(IdentityUserCreateDto input)
public async override Task<IdentityUserDto> CreateAsync(IdentityUserCreateDto input)
{
if (input.PhoneNumber.IsNullOrWhiteSpace())
{
@ -109,33 +108,33 @@ public class MyIdentityUserManager : IdentityUserManager
{
public MyIdentityUserManager(
IdentityUserStore store,
IIdentityRoleRepository roleRepository,
IIdentityRoleRepository roleRepository,
IIdentityUserRepository userRepository,
IOptions<IdentityOptions> optionsAccessor,
IOptions<IdentityOptions> optionsAccessor,
IPasswordHasher<IdentityUser> passwordHasher,
IEnumerable<IUserValidator<IdentityUser>> userValidators,
IEnumerable<IPasswordValidator<IdentityUser>> passwordValidators,
IEnumerable<IUserValidator<IdentityUser>> userValidators,
IEnumerable<IPasswordValidator<IdentityUser>> passwordValidators,
ILookupNormalizer keyNormalizer,
IdentityErrorDescriber errors,
IServiceProvider services,
ILogger<IdentityUserManager> logger,
ICancellationTokenProvider cancellationTokenProvider) :
ILogger<IdentityUserManager> logger,
ICancellationTokenProvider cancellationTokenProvider) :
base(store,
roleRepository,
userRepository,
optionsAccessor,
passwordHasher,
userValidators,
userRepository,
optionsAccessor,
passwordHasher,
userValidators,
passwordValidators,
keyNormalizer,
errors,
services,
logger,
keyNormalizer,
errors,
services,
logger,
cancellationTokenProvider)
{
}
public override async Task<IdentityResult> CreateAsync(IdentityUser user)
public async override Task<IdentityResult> CreateAsync(IdentityUser user)
{
if (user.PhoneNumber.IsNullOrWhiteSpace())
{
@ -162,6 +161,50 @@ This example class inherits from the `IdentityUserManager` [domain service](Doma
Check the [localization system](Localization.md) to learn how to localize the error messages.
### Example: Overriding a Controller
````csharp
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Volo.Abp.Account;
using Volo.Abp.DependencyInjection;
namespace MyProject.Controllers
{
[Dependency(ReplaceServices = true)]
[ExposeServices(typeof(AccountController))]
public class MyAccountController : AccountController
{
public MyAccountController(IAccountAppService accountAppService)
: base(accountAppService)
{
}
public async override Task SendPasswordResetCodeAsync(
SendPasswordResetCodeDto input)
{
Logger.LogInformation("Your custom logic...");
await base.SendPasswordResetCodeAsync(input);
}
}
}
````
This example replaces the `AccountController` (An API Controller defined in the [Account Module](Modules/Account.md)) and overrides the `SendPasswordResetCodeAsync` method.
**`[ExposeServices(typeof(AccountController))]` is essential** here since it registers this controller for the `AccountController` in the dependency injection system. `[Dependency(ReplaceServices = true)]` is also recommended to clear the old registration (even the ASP.NET Core DI system selects the last registered one).
In addition, The `AccountController` will be removed from [`ApplicationModel`](https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.mvc.applicationmodels.applicationmodel.controllers) because it defines `ExposeServicesAttribute`. If you don't want to remove it, you can configure `AbpAspNetCoreMvcOptions`:
```csharp
Configure<AbpAspNetCoreMvcOptions>(options =>
{
options.IgnoredControllersOnModelExclusion.AddIfNotContains(typeof(AccountController));
});
```
### Overriding Other Classes
Overriding controllers, framework services, view component classes and any other type of classes registered to dependency injection can be overridden just like the examples above.
@ -179,7 +222,7 @@ Assuming that you've already added a `SocialSecurityNumber` as described in the
You can use the [object extension system](Object-Extensions.md) to add the property to the `IdentityUserDto`. Write this code inside the `YourProjectNameDtoExtensions` class comes with the application startup template:
````csharp
ObjectExtensionManager.Instance
ObjectExtensionManager.Instance
.AddOrUpdateProperty<IdentityUserDto, string>(
"SocialSecurityNumber"
);
@ -251,8 +294,8 @@ ObjectExtensionManager.Instance
.AddOrUpdateProperty<string>(
new[]
{
typeof(IdentityUserDto),
typeof(IdentityUserCreateDto),
typeof(IdentityUserDto),
typeof(IdentityUserCreateDto),
typeof(IdentityUserUpdateDto)
},
"SocialSecurityNumber"

10
docs/en/Data-Access.md

@ -1,15 +1,13 @@
# Data Access
## Database Providers
ABP framework was designed as database agnostic. It can work any type of data source by the help of the [repository](Repositories.md) and [unit of work](Unit-Of-Work.md) abstractions. However, currently the following providers are implemented:
ABP framework was designed as database agnostic. It can work any type of data source by the help of the [repository](Repositories.md) and [unit of work](Unit-Of-Work.md) abstractions. Currently, the following providers are implemented as official:
* [Entity Framework Core](Entity-Framework-Core.md) (works with [various DBMS and providers](https://docs.microsoft.com/en-us/ef/core/providers/).)
* [MongoDB](MongoDB.md)
* [Dapper](Dapper.md)
More providers will be added in the future.
## See Also
* [Connection Strings](Connection-Strings.md)
* [Connection Strings](Connection-Strings.md)
* [Data Seeding](Data-Seeding.md)
* [Data Filtering](Data-Filtering.md)

2
docs/en/Data-Filtering.md

@ -32,6 +32,8 @@ namespace Acme.BookStore
> `ISoftDelete` filter is enabled by default and you can not get deleted entities from database unless you explicitly disable it. See the `IDataFilter` service below.
> Soft-delete entities can be hard-deleted when you use `HardDeleteAsync` method on the repositories.
### IMultiTenant
[Multi-tenancy](Multi-Tenancy.md) is an efficient way of creating SaaS applications. Once you create a multi-tenant application, you typically want to isolate data between tenants. Implement `IMultiTenant` interface to make your entity "multi-tenant aware".

32
docs/en/Data-Seeding.md

@ -38,31 +38,37 @@ namespace Acme.BookStore
{
private readonly IRepository<Book, Guid> _bookRepository;
private readonly IGuidGenerator _guidGenerator;
private readonly ICurrentTenant _currentTenant;
public BookStoreDataSeedContributor(
IRepository<Book, Guid> bookRepository,
IGuidGenerator guidGenerator)
IGuidGenerator guidGenerator,
ICurrentTenant currentTenant)
{
_bookRepository = bookRepository;
_guidGenerator = guidGenerator;
_currentTenant = currentTenant;
}
public async Task SeedAsync(DataSeedContext context)
{
if (await _bookRepository.GetCountAsync() > 0)
using (_currentTenant.Change(context?.TenantId))
{
return;
if (await _bookRepository.GetCountAsync() > 0)
{
return;
}
var book = new Book(
id: _guidGenerator.Create(),
name: "The Hitchhiker's Guide to the Galaxy",
type: BookType.ScienceFiction,
publishDate: new DateTime(1979, 10, 12),
price: 42
);
await _bookRepository.InsertAsync(book);
}
var book = new Book(
id: _guidGenerator.Create(),
name: "The Hitchhiker's Guide to the Galaxy",
type: BookType.ScienceFiction,
publishDate: new DateTime(1979, 10, 12),
price: 42
);
await _bookRepository.InsertAsync(book);
}
}
}

65
docs/en/Distributed-Event-Bus-Rebus-Integration.md

@ -0,0 +1,65 @@
# Distributed Event Bus Rebus Integration
> This document explains **how to configure the [Rebus](http://mookid.dk/category/rebus/)** as the distributed event bus provider. See the [distributed event bus document](Distributed-Event-Bus.md) to learn how to use the distributed event bus system
## Installation
Use the ABP CLI to add [Volo.Abp.EventBus.Rebus](https://www.nuget.org/packages/Volo.Abp.EventBus.Rebus) NuGet package to your project:
* Install the [ABP CLI](https://docs.abp.io/en/abp/latest/CLI) if you haven't installed before.
* Open a command line (terminal) in the directory of the `.csproj` file you want to add the `Volo.Abp.EventBus.Rebus` package.
* Run `abp add-package Volo.Abp.EventBus.Rebus` command.
If you want to do it manually, install the [Volo.Abp.EventBus.Rebus](https://www.nuget.org/packages/Volo.Abp.EventBus.Rebus) NuGet package to your project and add `[DependsOn(typeof(AbpEventBusRebusModule))]` to the [ABP module](Module-Development-Basics.md) class inside your project.
## Configuration
You can configure using the standard [configuration system](Configuration.md), like using the [options](Options.md) classes.
### The Options Classes
`AbpRebusEventBusOptions` classe can be used to configure the event bus options for the Rebus.
You can configure this options inside the `PreConfigureServices` of your [module](Module-Development-Basics.md).
**Example: Minimize configuration**
```csharp
PreConfigure<AbpRebusEventBusOptions>(options =>
{
options.InputQueueName = "eventbus";
});
```
Rebus has many options, you can use the `Configurer` property of `AbpRebusEventBusOptions` class to configure.
Default events are **stored in memory**. See the [rebus document](https://github.com/rebus-org/Rebus/wiki/Transport) for more details.
**Example: Configure the store**
````csharp
PreConfigure<AbpRebusEventBusOptions>(options =>
{
options.InputQueueName = "eventbus";
options.Configurer = rebusConfigurer =>
{
rebusConfigurer.Transport(t => t.UseMsmq("eventbus"));
rebusConfigurer.Subscriptions(s => s.UseJsonFile(@"subscriptions.json"));
};
});
````
You can use the `Publish` properpty of `AbpRebusEventBusOptions` class to change the publishing method
**Example: Configure the event publishing**
````csharp
PreConfigure<AbpRebusEventBusOptions>(options =>
{
options.InputQueueName = "eventbus";
options.Publish = async (bus, type, data) =>
{
await bus.Publish(data);
};
});
````

7
docs/en/Distributed-Event-Bus.md

@ -8,7 +8,8 @@ Distributed event bus system provides an **abstraction** that can be implemented
* `LocalDistributedEventBus` is the default implementation that implements the distributed event bus to work as in-process. Yes! The **default implementation works just like the [local event bus](Local-Event-Bus.md)**, if you don't configure a real distributed provider.
* `RabbitMqDistributedEventBus` implements the distributed event bus with the [RabbitMQ](https://www.rabbitmq.com/). See the [RabbitMQ integration document](Distributed-Event-Bus-RabbitMQ-Integration.md) to learn how to configure it.
* `KafkaDistributedEventBus` implements the distributed event bus with the [RabbitMQ](https://kafka.apache.org/). See the [Kafka integration document](Distributed-Event-Bus-Kafka-Integration.md) to learn how to configure it.
* `KafkaDistributedEventBus` implements the distributed event bus with the [Kafka](https://kafka.apache.org/). See the [Kafka integration document](Distributed-Event-Bus-Kafka-Integration.md) to learn how to configure it.
* `RebusDistributedEventBus` implements the distributed event bus with the [Rebus](http://mookid.dk/category/rebus/). See the [Rebus integration document](Distributed-Event-Bus-Rebus-Integration.md) to learn how to configure it.
Using a local event bus as default has a few important advantages. The most important one is that: It allows you to write your code compatible to distributed architecture. You can write a monolithic application now that can be split into microservices later. It is a good practice to communicate between bounded contexts (or between application modules) via distributed events instead of local events.
@ -44,7 +45,7 @@ namespace AbpDemo
public virtual async Task ChangeStockCountAsync(Guid productId, int newCount)
{
await _distributedEventBus.PublishAsync(
new StockCountChangedEvent
new StockCountChangedEto
{
ProductId = productId,
NewCount = newCount
@ -300,4 +301,4 @@ namespace AbpDemo
}
````
This example uses the `AutoMap` attribute of the AutoMapper to configure the mapping. You could create a profile class instead. Please refer to the AutoMapper document for more options.
This example uses the `AutoMap` attribute of the AutoMapper to configure the mapping. You could create a profile class instead. Please refer to the AutoMapper document for more options.

1978
docs/en/Domain-Driven-Design-Implementation-Guide.md

File diff suppressed because it is too large

16
docs/en/Domain-Driven-Design.md

@ -10,7 +10,7 @@ ABP framework provides an **infrastructure** to make **Domain Driven Design** ba
> - Basing complex designs on a model of the domain;
> - Initiating a creative collaboration between technical and domain experts to iteratively refine a conceptual model that addresses particular domain problems.
### Layers
## Layers & Building Blocks
ABP follows DDD principles and patterns to achieve a layered application model which consists of four fundamental layers:
@ -19,15 +19,19 @@ ABP follows DDD principles and patterns to achieve a layered application model w
- **Domain Layer**: Includes business objects and the core (domain) business rules. This is the heart of the application.
- **Infrastructure Layer**: Provides generic technical capabilities that support higher layers mostly using 3rd-party libraries.
## Contents
DDD mostly interest in the **Domain** and the **Application** layers, rather than the Infrastructure and the Presentation layers. The following documents explains the **infrastructure** provided by the ABP Framework to implement **Building Blocks** of the DDD:
* **Domain Layer**
* [Entities & Aggregate Roots](Entities.md)
* Value Objects
* [Repositories](Repositories.md)
* Domain Services
* Specifications
* [Domain Services](Domain-Services.md)
* [Value Objects](Value-Objects.md)
* [Specifications](Specifications.md)
* **Application Layer**
* [Application Services](Application-Services.md)
* [Data Transfer Objects (DTOs)](Data-Transfer-Objects.md)
* Unit of Work
* [Unit of Work](Unit-Of-Work.md)
## The Ultimate DDD Implementation Guide
See the [Implementing Domain Driven Design](Domain-Driven-Design-Implementation-Guide.md) guide as a **complete reference**. The Guide explains the Domain Driven Design and introduces explicit **rules and examples** to give a deep understanding of the **implementation details**.

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

Loading…
Cancel
Save