Browse Source

Merge branch 'rel-8.3' into auto-merge/rel-8-2/2974

pull/20728/head
maliming 1 year ago
parent
commit
3cd1cda67b
No known key found for this signature in database GPG Key ID: A646B9CB645ECEA4
  1. 22
      .github/workflows/auto-pr.yml
  2. 7
      Directory.Packages.props
  3. 232
      LICENSE.md
  4. 101
      README.md
  5. 3
      abp_io/AbpIoLocalization/AbpIoLocalization/Account/Localization/Resources/en.json
  6. 3
      abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/ar.json
  7. 3
      abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/cs.json
  8. 3
      abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/de.json
  9. 2
      abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json
  10. 3
      abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/es.json
  11. 3
      abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/fi.json
  12. 3
      abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/fr.json
  13. 3
      abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/hi.json
  14. 4
      abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/hr.json
  15. 3
      abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/hu.json
  16. 3
      abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/is.json
  17. 3
      abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/it.json
  18. 3
      abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/nl.json
  19. 3
      abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/pl-PL.json
  20. 3
      abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/pt-BR.json
  21. 3
      abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/ro-RO.json
  22. 3
      abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/sk.json
  23. 3
      abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/sl.json
  24. 4
      abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/tr.json
  25. 3
      abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/vi.json
  26. 4
      abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/zh-Hans.json
  27. 4
      abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/zh-Hant.json
  28. 5
      abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/ar.json
  29. 4
      abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/cs.json
  30. 4
      abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/de.json
  31. 2
      abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/en-GB.json
  32. 25
      abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/en.json
  33. 4
      abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/es.json
  34. 4
      abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/fi.json
  35. 4
      abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/fr.json
  36. 4
      abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/hi.json
  37. 4
      abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/hr.json
  38. 4
      abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/hu.json
  39. 4
      abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/is.json
  40. 4
      abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/it.json
  41. 4
      abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/nl.json
  42. 4
      abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/pl-PL.json
  43. 4
      abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/pt-BR.json
  44. 4
      abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/ro-RO.json
  45. 4
      abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/sk.json
  46. 4
      abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/sl.json
  47. 5
      abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/tr.json
  48. 4
      abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/vi.json
  49. 4
      abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/zh-Hans.json
  50. 4
      abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/zh-Hant.json
  51. 4
      abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/zh-Hans.json
  52. 4
      common.props
  53. 4
      docs/en/Blog-Posts/2024-05 ABP Unification/post.md
  54. 14
      docs/en/cli/index.md
  55. 96
      docs/en/framework/architecture/multi-tenancy/index.md
  56. 181
      docs/en/framework/ui/angular/localization.md
  57. 4
      docs/en/framework/ui/angular/quick-start.md
  58. 4
      docs/en/get-started/layered-web-application.md
  59. 2
      docs/en/get-started/microservice.md
  60. 4
      docs/en/get-started/single-layer-web-application.md
  61. BIN
      docs/en/images/cmskit-module-markedItems.png
  62. BIN
      docs/en/images/cmskit-module-markedItemsFilter.gif
  63. BIN
      docs/en/images/docs-referencing.png
  64. 4
      docs/en/modules/account/authority-delegation.md
  65. 1
      docs/en/modules/cms-kit/index.md
  66. 123
      docs/en/modules/cms-kit/marked-items.md
  67. 54
      docs/en/modules/docs.md
  68. 11
      docs/en/modules/openiddict-pro.md
  69. 11
      docs/en/modules/openiddict.md
  70. 68
      docs/en/release-info/migration-guides/abp-8-3.md
  71. 1
      docs/en/release-info/migration-guides/index.md
  72. 15
      docs/en/release-info/release-notes.md
  73. 136
      docs/en/release-info/road-map.md
  74. 6
      docs/en/solution-templates/microservice/adding-new-api-gateways.md
  75. 6
      docs/en/solution-templates/microservice/adding-new-applications.md
  76. 372
      docs/en/solution-templates/microservice/adding-new-microservices.md
  77. BIN
      docs/en/solution-templates/microservice/images/folder-structure.png
  78. 2
      docs/en/studio/installation.md
  79. 2
      docs/en/tutorials/todo/layered/index.md
  80. 2
      docs/en/tutorials/todo/single-layer/index.md
  81. 12
      framework/src/Volo.Abp.AspNetCore.Abstractions/Volo/Abp/AspNetCore/Authentication/AbpAspNetCoreTokenUnauthorizedErrorInfo.cs
  82. 28
      framework/src/Volo.Abp.AspNetCore.Authentication.JwtBearer/Microsoft/Extensions/DependencyInjection/AbpJwtBearerExtensions.cs
  83. 1
      framework/src/Volo.Abp.AspNetCore.Authentication.JwtBearer/Volo.Abp.AspNetCore.Authentication.JwtBearer.csproj
  84. 3
      framework/src/Volo.Abp.AspNetCore.Authentication.JwtBearer/Volo/Abp/AspNetCore/Authentication/JwtBearer/AbpAspNetCoreAuthenticationJwtBearerModule.cs
  85. 2
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardBodyTagHelperService.cs
  86. 2
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpSelectTagHelperService.cs
  87. 15
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/Volo/Abp/AspNetCore/Mvc/UI/Bundling/AbpAspNetCoreMvcUiBundlingModule.cs
  88. 10
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Packages/Volo/Abp/AspNetCore/Mvc/UI/Packages/DatatablesNet/DatatablesNetScriptContributor.cs
  89. 19
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/datatables/datatables-extensions.js
  90. 7
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcModule.cs
  91. 16
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ExceptionHandling/AbpExceptionFilter.cs
  92. 15
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ExceptionHandling/AbpExceptionPageFilter.cs
  93. 6
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Libs/AbpMvcLibsOptions.cs
  94. 93
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Libs/AbpMvcLibsService.cs
  95. 6
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Libs/IAbpMvcLibsService.cs
  96. 1
      framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/Builder/AbpApplicationBuilderExtensions.cs
  97. 8
      framework/src/Volo.Abp.AspNetCore/Microsoft/Extensions/DependencyInjection/AbpAspNetCoreServiceCollectionExtensions.cs
  98. 9
      framework/src/Volo.Abp.AspNetCore/Volo/Abp/ApplicationInitializationContextExtensions.cs
  99. 4
      framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Security/Claims/AbpClaimsMapMiddleware.cs
  100. 35
      framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Security/Claims/AbpClaimsTransformation.cs

22
.github/workflows/auto-pr.yml

@ -1,13 +1,13 @@
name: Merge branch rel-8.3 with rel-8.2
name: Merge branch dev with rel-8.3
on:
push:
branches:
- rel-8.2
- rel-8.3
permissions:
contents: read
jobs:
merge-rel-8-3-with-rel-8-2:
merge-dev-with-rel-8-3:
permissions:
contents: write # for peter-evans/create-pull-request to create branch
pull-requests: write # for peter-evans/create-pull-request to create a PR
@ -15,22 +15,22 @@ jobs:
steps:
- uses: actions/checkout@v2
with:
ref: rel-8.3
ref: dev
- name: Reset promotion branch
run: |
git fetch origin rel-8.2:rel-8.2
git reset --hard rel-8.2
git fetch origin rel-8.3:rel-8.3
git reset --hard rel-8.3
- name: Create Pull Request
uses: peter-evans/create-pull-request@v3
with:
branch: auto-merge/rel-8-2/${{github.run_number}}
title: Merge branch rel-8.3 with rel-8.2
body: This PR generated automatically to merge rel-8.3 with rel-8.2. Please review the changed files before merging to prevent any errors that may occur.
branch: auto-merge/rel-8-3/${{github.run_number}}
title: Merge branch dev with rel-8.3
body: This PR generated automatically to merge dev with rel-8.3. Please review the changed files before merging to prevent any errors that may occur.
reviewers: maliming
token: ${{ github.token }}
- name: Merge Pull Request
env:
GH_TOKEN: ${{ secrets.BOT_SECRET }}
run: |
gh pr review auto-merge/rel-8-2/${{github.run_number}} --approve
gh pr merge auto-merge/rel-8-2/${{github.run_number}} --merge --auto --delete-branch
gh pr review auto-merge/rel-8-3/${{github.run_number}} --approve
gh pr merge auto-merge/rel-8-3/${{github.run_number}} --merge --auto --delete-branch

7
Directory.Packages.props

@ -48,8 +48,8 @@
<PackageVersion Include="LdapForNet" Version="2.7.15" />
<PackageVersion Include="LibGit2Sharp" Version="0.28.0" />
<PackageVersion Include="Magick.NET-Q16-AnyCPU" Version="13.4.0" />
<PackageVersion Include="MailKit" Version="4.3.0" />
<PackageVersion Include="Markdig.Signed" Version="0.33.0" />
<PackageVersion Include="MailKit" Version="4.7.1.1" />
<PackageVersion Include="Markdig.Signed" Version="0.37.0" />
<PackageVersion Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.4" />
<PackageVersion Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="8.0.4" />
<PackageVersion Include="Microsoft.AspNetCore.Authorization" Version="8.0.4" />
@ -61,7 +61,6 @@
<PackageVersion Include="Microsoft.AspNetCore.Components.WebAssembly.Authentication" Version="8.0.4" />
<PackageVersion Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="8.0.4" />
<PackageVersion Include="Microsoft.AspNetCore.DataProtection.StackExchangeRedis" Version="8.0.4" />
<PackageVersion Include="Microsoft.AspNetCore.Hosting.Abstractions" Version="2.2.0" />
<PackageVersion Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="8.0.4" />
<PackageVersion Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="8.0.4" />
<PackageVersion Include="Microsoft.AspNetCore.Mvc.Testing" Version="8.0.4" />
@ -164,7 +163,7 @@
<PackageVersion Include="System.Security.Principal.Windows" Version="5.0.0" />
<PackageVersion Include="System.Text.Encoding.CodePages" Version="8.0.0" />
<PackageVersion Include="System.Text.Encodings.Web" Version="8.0.0" />
<PackageVersion Include="System.Text.Json" Version="8.0.0" />
<PackageVersion Include="System.Text.Json" Version="8.0.4" />
<PackageVersion Include="System.IdentityModel.Tokens.Jwt" Version="7.5.1" />
<PackageVersion Include="TimeZoneConverter" Version="6.1.0" />
<PackageVersion Include="Unidecode.NET" Version="2.1.0" />

232
LICENSE.md

@ -1,165 +1,89 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.
This version of the GNU Lesser General Public License incorporates the terms and conditions of version 3 of the GNU General Public.
The license is supplemented by the additional permissions listed below.
This version of the GNU Lesser General Public License incorporates
the terms and conditions of version 3 of the GNU General Public
License, supplemented by the additional permissions listed below.
0. Additional Definitions.
As used herein, "this License" refers to version 3 of the GNU Lesser
General Public License, and the "GNU GPL" refers to version 3 of the GNU
General Public License.
**0. Additional Definitions.**
As used herein, "this License" refers to version 3 of the GNU Lesser General Public License, and the "GNU GPL" refers to version 3 of the GNU General Public License.
"The Library" refers to a covered work governed by this License, other than an Application or a Combined Work as defined below.
An "Application" is any work that makes use of an interface provided by the Library but which is not otherwise based on the Library. Defining a subclass of a class defined by the Library is deemed a mode of using an interface provided by the Library.
A "Combined Work" is a work produced by combining or linking an Application with the Library. The particular version of the Library with which the Combined Work was made is also called the "Linked Version".
The "Minimal Corresponding Source" for a Combined Work means the Corresponding Source for the Combined Work, excluding any source code for portions of the Combined Work that, considered in isolation, are based on the Application and not on the Linked Version.
The "Corresponding Application Code" for a Combined Work means the object code and/or source code for the Application, including any data and utility programs needed for reproducing the Combined Work from the Application, but excluding the System Libraries of the Combined Work.
**1. Exception to Section 3 of the GNU GPL.**
You may convey a covered work under sections 3 and 4 of this License without being bound by section 3 of the GNU GPL.
**2. Conveying Modified Versions.**
If you modify a copy of the Library and, in your modifications, a facility refers to a function or data to be supplied by an Application that uses the facility (other than as an argument passed when the facility is invoked), then you may convey a copy of the modified version:
**a)** under this License, provided that you make a good-faith effort to ensure that, in the event an Application does not supply the
function or data, the facility still operates and performs whatever part of its purpose remains meaningful, or
**b)** under the GNU GPL, with none of the additional permissions of this License is applicable to that copy.
**3. Object Code Incorporating Material from Library Header Files.**
The object code form of an Application may incorporate material from a header file that is part of the Library. You may convey such an object code under terms of your choice, provided that if the incorporated material is not limited to numerical parameters, data structure layouts and accessors, or small macros, inline functions and templates (ten or fewer lines in length), you do both of the following:
**a)** Give prominent notice with each copy of the object code that the Library is used in it, and the Library and its use are covered by this License.
**b)** Accompany the object code with a copy of the GNU GPL and this license document.
**4. Combined Works.**
You may convey a Combined Work under terms of your choice that, taken together, effectively do not restrict modification of the portions of the Library contained in the Combined Work and reverse engineering for debugging such modifications, if you also do each of the following:
**a)** Give prominent notice with each copy of the Combined Work that the Library is used in it and that the Library and its use are covered by this License.
**b)** Accompany the Combined Work with a copy of the GNU GPL and this license document.
**c)** For a Combined Work that displays copyright notices during execution, including the copyright notice for the Library among these notices, as well as a reference directing the user to the copies of the GNU GPL and this license document.
**d)** Do one of the following:
0) Convey the Minimal Corresponding Source under the terms of this License and the Corresponding Application Code in a form suitable for, and under terms that permit, the user to recombine or relink the Application with a modified version of the Linked Version to produce a modified Combined Work in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source.
1) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (a) uses at run time a copy of the Library already present on the user's computer system and (b) will operate properly with a modified version of the Library that is interface-compatible with the Linked Version.
**e)** Provide Installation Information, but only if you would otherwise be required to provide such information under section 6 of the GNU GPL, and only to the extent that such information is necessary to install and execute a modified version of the Combined Work produced by recombining or relinking the Application with a modified version of the Linked Version. (If you use option 4d0, the Installation Information must accompany the Minimal Corresponding Source and Corresponding Application Code. If you use option 4d1, you must provide the Installation Information in the manner specified by section 6 of the GNU GPL for conveying the Corresponding Source.)
"The Library" refers to a covered work governed by this License,
other than an Application or a Combined Work as defined below.
An "Application" is any work that makes use of an interface provided
by the Library, but which is not otherwise based on the Library.
Defining a subclass of a class defined by the Library is deemed a mode
of using an interface provided by the Library.
A "Combined Work" is a work produced by combining or linking an
Application with the Library. The particular version of the Library
with which the Combined Work was made is also called the "Linked
Version".
The "Minimal Corresponding Source" for a Combined Work means the
Corresponding Source for the Combined Work, excluding any source code
for portions of the Combined Work that, considered in isolation, are
based on the Application, and not on the Linked Version.
The "Corresponding Application Code" for a Combined Work means the
object code and/or source code for the Application, including any data
and utility programs needed for reproducing the Combined Work from the
Application, but excluding the System Libraries of the Combined Work.
1. Exception to Section 3 of the GNU GPL.
You may convey a covered work under sections 3 and 4 of this License
without being bound by section 3 of the GNU GPL.
2. Conveying Modified Versions.
If you modify a copy of the Library, and, in your modifications, a
facility refers to a function or data to be supplied by an Application
that uses the facility (other than as an argument passed when the
facility is invoked), then you may convey a copy of the modified
version:
a) under this License, provided that you make a good faith effort to
ensure that, in the event an Application does not supply the
function or data, the facility still operates, and performs
whatever part of its purpose remains meaningful, or
b) under the GNU GPL, with none of the additional permissions of
this License applicable to that copy.
3. Object Code Incorporating Material from Library Header Files.
The object code form of an Application may incorporate material from
a header file that is part of the Library. You may convey such object
code under terms of your choice, provided that, if the incorporated
material is not limited to numerical parameters, data structure
layouts and accessors, or small macros, inline functions and templates
(ten or fewer lines in length), you do both of the following:
a) Give prominent notice with each copy of the object code that the
Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the object code with a copy of the GNU GPL and this license
document.
4. Combined Works.
You may convey a Combined Work under terms of your choice that,
taken together, effectively do not restrict modification of the
portions of the Library contained in the Combined Work and reverse
engineering for debugging such modifications, if you also do each of
the following:
a) Give prominent notice with each copy of the Combined Work that
the Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the Combined Work with a copy of the GNU GPL and this license
document.
c) For a Combined Work that displays copyright notices during
execution, include the copyright notice for the Library among
these notices, as well as a reference directing the user to the
copies of the GNU GPL and this license document.
d) Do one of the following:
0) Convey the Minimal Corresponding Source under the terms of this
License, and the Corresponding Application Code in a form
suitable for, and under terms that permit, the user to
recombine or relink the Application with a modified version of
the Linked Version to produce a modified Combined Work, in the
manner specified by section 6 of the GNU GPL for conveying
Corresponding Source.
1) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (a) uses at run time
a copy of the Library already present on the user's computer
system, and (b) will operate properly with a modified version
of the Library that is interface-compatible with the Linked
Version.
e) Provide Installation Information, but only if you would otherwise
be required to provide such information under section 6 of the
GNU GPL, and only to the extent that such information is
necessary to install and execute a modified version of the
Combined Work produced by recombining or relinking the
Application with a modified version of the Linked Version. (If
you use option 4d0, the Installation Information must accompany
the Minimal Corresponding Source and Corresponding Application
Code. If you use option 4d1, you must provide the Installation
Information in the manner specified by section 6 of the GNU GPL
for conveying Corresponding Source.)
5. Combined Libraries.
You may place library facilities that are a work based on the
Library side by side in a single library together with other library
facilities that are not Applications and are not covered by this
License, and convey such a combined library under terms of your
choice, if you do both of the following:
a) Accompany the combined library with a copy of the same work based
on the Library, uncombined with any other library facilities,
conveyed under the terms of this License.
b) Give prominent notice with the combined library that part of it
is a work based on the Library, and explaining where to find the
accompanying uncombined form of the same work.
6. Revised Versions of the GNU Lesser General Public License.
The Free Software Foundation may publish revised and/or new versions
of the GNU Lesser General Public License from time to time. Such new
versions will be similar in spirit to the present version, but may
differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the
Library as you received it specifies that a certain numbered version
of the GNU Lesser General Public License "or any later version"
applies to it, you have the option of following the terms and
conditions either of that published version or of any later version
published by the Free Software Foundation. If the Library as you
received it does not specify a version number of the GNU Lesser
General Public License, you may choose any version of the GNU Lesser
General Public License ever published by the Free Software Foundation.
If the Library as you received it specifies that a proxy can decide
whether future versions of the GNU Lesser General Public License shall
apply, that proxy's public statement of acceptance of any version is
permanent authorization for you to choose that version for the
Library.
You may place library facilities that are work based on the Library side by side in a single library together with other library facilities that are not Applications and are not covered by this License and convey such a combined library under the terms of your choice if you do both of the following:
**a)** Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities, conveyed under the terms of this License.
**b)** Give prominent notice with the combined library that part of it is a work based on the Library and explains where to find the accompanying uncombined form of the same work.
**6. Revised Versions of the GNU Lesser General Public License.**
The Free Software Foundation may publish revised and/or new versions of the GNU Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Library as you received it specifies that a certain numbered version of the GNU Lesser General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that published version or of any later version published by the Free Software Foundation. If the Library as you received, it does not specify a version number of the GNU Lesser
General Public License, you may choose any version of the GNU Lesser General Public License ever published by the Free Software Foundation. If the Library as you received it specifies that a proxy can decide whether future versions of the GNU Lesser General Public License shall apply, that proxy's public statement of acceptance of any version is permanent authorization for you to choose that version for the Library.

101
README.md

@ -1,22 +1,18 @@
# ABP Framework
![build and test](https://img.shields.io/github/actions/workflow/status/abpframework/abp/build-and-test.yml?branch=dev&style=flat-square)
[![codecov](https://codecov.io/gh/abpframework/abp/branch/dev/graph/badge.svg?token=jUKLCxa6HF)](https://codecov.io/gh/abpframework/abp)
[![NuGet](https://img.shields.io/nuget/v/Volo.Abp.Core.svg?style=flat-square)](https://www.nuget.org/packages/Volo.Abp.Core)
[![NuGet (with prereleases)](https://img.shields.io/nuget/vpre/Volo.Abp.Core.svg?style=flat-square)](https://www.nuget.org/packages/Volo.Abp.Core)
[![MyGet (nightly builds)](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)
[![Code of Conduct](https://img.shields.io/badge/Contributor%20Covenant-v2.0%20adopted-ff69b4.svg)](https://github.com/abpframework/abp/blob/dev/CODE_OF_CONDUCT.md)
[![CLA Signed](https://cla-assistant.io/readme/badge/abpframework/abp)](https://cla-assistant.io/abpframework/abp)
[![ABP Discord server](https://img.shields.io/discord/951497912645476422?label=Discord)](https://discord.gg/abp)
ABP Framework is a complete **infrastructure** based on **ASP.NET Core** to create **modern web applications** and **APIs** by following the software development **best practices** and the **latest technologies**. Check out https://abp.io
![build and test](https://img.shields.io/github/actions/workflow/status/abpframework/abp/build-and-test.yml?branch=dev&style=flat-square) 🔹 [![codecov](https://codecov.io/gh/abpframework/abp/branch/dev/graph/badge.svg?token=jUKLCxa6HF)](https://codecov.io/gh/abpframework/abp) 🔹 [![NuGet](https://img.shields.io/nuget/v/Volo.Abp.Core.svg?style=flat-square)](https://www.nuget.org/packages/Volo.Abp.Core) 🔹 [![NuGet (with prereleases)](https://img.shields.io/nuget/vpre/Volo.Abp.Core.svg?style=flat-square)](https://www.nuget.org/packages/Volo.Abp.Core) 🔹 [![MyGet (nightly builds)](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) 🔹 [![Code of Conduct](https://img.shields.io/badge/Contributor%20Covenant-v2.0%20adopted-ff69b4.svg)](https://github.com/abpframework/abp/blob/dev/CODE_OF_CONDUCT.md) 🔹 [![CLA Signed](https://cla-assistant.io/readme/badge/abpframework/abp)](https://cla-assistant.io/abpframework/abp) 🔹 [![Discord Shield](https://discord.com/api/guilds/951497912645476422/widget.png?style=shield)](https://discord.gg/abp)
ABP Framework is a complete **infrastructure** based on **ASP.NET Core** that creates **modern web applications** and **APIs** by following the software development **best practices** and the **latest technologies**.
[![ABP Platform](https://github.com/abpframework/abp/assets/9526587/47531496-4088-406d-9c69-63cb0ffec2ba)](https://abp.io)
## Getting Started
- [Quick Start](https://docs.abp.io/en/abp/latest/Tutorials/Todo/Index) is a single-part, quick-start tutorial to build a simple application with the ABP Framework. Start with this tutorial if you want to quickly understand how ABP works.
- [Getting Started guide](https://docs.abp.io/en/abp/latest/Getting-Started) can be used to create and run ABP based solutions with different options and details.
- [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 with all aspects of a real-life solution.
- [Quick Start](https://docs.abp.io/en/abp/latest/Tutorials/Todo/Index) is a single-part, quick-start tutorial to build a simple application with the ABP Framework. Start with this tutorial if you want to understand how ABP works quickly.
- [Getting Started guide](https://docs.abp.io/en/abp/latest/Getting-Started) can be used to create and run ABP-based solutions with different options and details.
- [Web Application Development Tutorial](https://docs.abp.io/en/abp/latest/Tutorials/Part-1) is a complete tutorial on developing a full-stack web application with all aspects of a real-life solution.
### Quick Start
@ -34,28 +30,26 @@ Create a new solution:
> 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">
## The Book: Mastering ABP Framework
Written by the creator of ABP Framework, this book will help you to gain a complete understanding of the ABP Framework and modern web application development techniques.
* [Buy on Amazon](https://www.amazon.com/gp/product/B097Z2DM8Q)
* [Buy on Packt Publishing](https://www.packtpub.com/product/mastering-abp-framework/9781801079242)
* [More details about the book](https://abp.io/books/mastering-abp-framework)
![book-mastering-abp-framework](docs/en/images/book-mastering-abp-framework.png)
## What ABP Provides?
ABP provides a **full stack developer experience**.
### Architecture
<img src="docs/en/images/ddd-microservice-simple.png">
@ -64,30 +58,48 @@ ABP offers a complete, **modular** and **layered** software architecture based o
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.
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.
### 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.
- **[Identity](https://docs.abp.io/en/abp/latest/Modules/Identity)**: Manages organization units, roles, users and their permissions based on the Microsoft Identity library.
- [**OpenIddict**](https://docs.abp.io/en/abp/latest/Modules/OpenIddict): Integrates to OpenIddict.
- [**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
## Mastering ABP Framework Book
This book will help you to gain a complete understanding of the ABP Framework and modern web application development techniques. It is written by the creator and team lead of the ABP Framework. You can buy from [Amazon](https://www.amazon.com/gp/product/B097Z2DM8Q) or [Packt Publishing](https://www.packtpub.com/product/mastering-abp-framework/9781801079242). Find further info about the book at [abp.io/books/mastering-abp-framework](https://abp.io/books/mastering-abp-framework).
![book-mastering-abp-framework](docs/en/images/book-mastering-abp-framework.png)
## The Community
### ABP Community Web Site
@ -103,28 +115,31 @@ See the [sample projects](https://docs.abp.io/en/abp/latest/Samples/Index) built
### 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.
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 participate in 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://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>
* [Home Website](https://abp.io)
* [Get Started](https://abp.io/get-started)
* [Features](https://abp.io/features)
* [Documents](https://docs.abp.io/)
* [Samples](https://docs.abp.io/en/abp/latest/Samples/Index)
* [Blog](https://blog.abp.io/)
* [Community](https://community.abp.io/)
* [Stackoverflow](https://stackoverflow.com/questions/tagged/abp)
* [Twitter](https://twitter.com/abpframework)
## Support ABP
## Support the ABP Framework
GitHub repository stars are an important indicator of popularity and the size of the community. If you like ABP Framework, support us by clicking the star :star: on the repository.
Love ABP Framework? **Please give a star** to this repository :star:
## Discord Channel
You can use this link to join the ABP Community Discord Server: https://discord.gg/abp
## Discord Server
## ABP Commercial
We have a Discord server where you can chat with other ABP users. Share your ideas, report technical issues, showcase your creations, share the tips that worked for you and catch up with the latest news and announcements about ABP Framework. Join 👉 https://discord.gg/abp.
See also [ABP Commercial](https://commercial.abp.io/) if you are looking for pre-built application modules, professional themes, code generation tooling and premium support for the ABP Framework.

3
abp_io/AbpIoLocalization/AbpIoLocalization/Account/Localization/Resources/en.json

@ -12,6 +12,7 @@
"CommunityWebSite": "ABP community website",
"ManageAccount": "My Account | ABP.IO",
"ManageYourProfile": "Manage your profile",
"ReturnToApplication": "Return to application"
"ReturnToApplication": "Return to application",
"IdentityUserNotAvailable:Deleted": "This email address is not available. Reason: Already deleted."
}
}

3
abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/ar.json

@ -816,6 +816,7 @@
"ErrorExceptionMessage": "حدث خطأ أثناء معالجة طلبك",
"WatchTakeCodeGeneration": "شاهد فيديو \"استكشاف إمكانات إنشاء الأكواد البرمجية: ABP Suite\"!",
"ExtendNow": "تمديد / تجديد",
"RegisterDemo": "يسجل"
"RegisterDemo": "يسجل",
"AbpStudio_ComingSoon": "إذا كنت ترغب في اختبار ABP Studio قبل أي شخص آخر، يمكنك أن تصبح أحد مختبري النسخة التجريبية"
}
}

3
abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/cs.json

@ -431,6 +431,7 @@
"ErrorExceptionMessage": "Při zpracování vašeho požadavku nastala chyba",
"WatchTakeCodeGeneration": "Podívejte se na video „Prozkoumejte potenciál generování kódu: ABP Suite“!",
"ExtendNow": "Prodloužit / Obnovit",
"RegisterDemo": "Registrovat"
"RegisterDemo": "Registrovat",
"AbpStudio_ComingSoon": "Pokud chcete ABP Studio otestovat dříve než kdokoli jiný, staňte se BETA testerem"
}
}

3
abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/de.json

@ -411,6 +411,7 @@
"SendUsEmail": "Senden Sie uns eine E-Mail",
"ErrorExceptionMessage": "Während Ihrer Anfrage ist ein Fehler aufgetreten",
"WatchTakeCodeGeneration": "Sehen Sie sich das Video „Entdecken Sie das Potenzial der Codegenerierung: ABP Suite“ an!",
"ExtendNow": "Verlängern / Erneuern"
"ExtendNow": "Verlängern / Erneuern",
"AbpStudio_ComingSoon": "Wenn Sie ABP Studio vor allen anderen testen möchten, werden Sie BETA-Tester"
}
}

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

@ -916,7 +916,7 @@
"AbpStudio_Description": "ABP Studio is still under development. You can fill out the form below to be one of the first users.",
"AbpStudio_Description1": "ABP Studio is a <span class=\"text-highlight-white\">cross-platform desktop application</span> for ABP developers.",
"AbpStudio_Description2": "It is <span class=\"text-highlight-white\">well integrated</span> to the ABP Framework and aims to provide a comfortable development environment for you by <span class=\"text-highlight-white\">automating things, providing insights</span> about your solution, making <span class=\"text-highlight-white\">develop, run</span> and <span class=\"text-highlight-white\">deploy</span> your solutions much easier.",
"AbpStudio_ComingSoon": "Coming Soon <span class=\"opacity-50 ms-0 ms-md-3 d-block d-md-inline-block \">Planned beta release date: Q4 of 2023.</span>",
"AbpStudio_ComingSoon": "If you want to test ABP Studio before anyone else, become a BETA tester",
"AbpStudio_PlannedPreviewDate": "Planned preview release date: Q4 of 2023.",
"BetaRequest": "Beta Request",
"CreateNewSolutions": "Create New Solutions",

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

@ -411,6 +411,7 @@
"SendUsEmail": "Envíanos un correo electrónico",
"ErrorExceptionMessage": "Se produjo un error al procesar su solicitud.",
"WatchTakeCodeGeneration": "¡Mire el vídeo \"Explore el potencial de la generación de código: ABP Suite\"!",
"ExtendNow": "Ampliar / Renovar"
"ExtendNow": "Ampliar / Renovar",
"AbpStudio_ComingSoon": "Si quieres probar ABP Studio antes que nadie, conviértete en tester BETA"
}
}

3
abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/fi.json

@ -852,6 +852,7 @@
"ErrorExceptionMessage": "Virhe pyynnön käsittelyn yhteydessä",
"WatchTakeCodeGeneration": "Katso \"Tutki koodin luomisen potentiaalia: ABP Suite\" -video!",
"ExtendNow": "Laajenna / Uusi",
"RegisterDemo": "Rekisteröidy"
"RegisterDemo": "Rekisteröidy",
"AbpStudio_ComingSoon": "Jos haluat testata ABP Studiota ennen muita, ryhdy BETA-testaajaksi"
}
}

3
abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/fr.json

@ -431,6 +431,7 @@
"ErrorExceptionMessage": "Une erreur s'est produite lors du traitement de votre demande",
"WatchTakeCodeGeneration": "Regardez la vidéo « Explorez le potentiel de la génération de code : ABP Suite » !",
"ExtendNow": "Prolonger / Renouveler",
"RegisterDemo": "Registre"
"RegisterDemo": "Registre",
"AbpStudio_ComingSoon": "Si vous souhaitez tester ABP Studio avant tout le monde, devenez BETA testeur"
}
}

3
abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/hi.json

@ -430,6 +430,7 @@
"ErrorExceptionMessage": "आपका अनुरोध संसाधित करते समय एक त्रुटि पाई गई",
"WatchTakeCodeGeneration": "\"कोड जनरेशन की क्षमता का अन्वेषण करें: एबीपी सुइट\" वीडियो देखें!",
"ExtendNow": "विस्तार/नवीनीकरण",
"RegisterDemo": "पंजीकरण करवाना"
"RegisterDemo": "पंजीकरण करवाना",
"AbpStudio_ComingSoon": "यदि आप किसी और से पहले एबीपी स्टूडियो का परीक्षण करना चाहते हैं, तो बीटा परीक्षक बनें"
}
}

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

@ -915,7 +915,6 @@
"AbpStudio_Description": "ABP Studio je još uvijek u razvoju. Možete ispuniti obrazac ispod i biti jedan od prvih korisnika.",
"AbpStudio_Description1": "ABP Studio je <span class=\"text-highlight-white\">stolna aplikacija za više platformi</span> za ABP programere.",
"AbpStudio_Description2": "<span class=\"text-highlight-white\">Dobro je integriran</span> u ABP Framework i ima za cilj pružiti vam ugodno razvojno okruženje <span class=\"text-highlight-white\">automatiziranjem stvari, pružanjem uvida</span> u vaše rješenje, čineći <span class=\"text-highlight-white\">razvoj, pokretanje</span> i <span class=\"text-highlight-white\">implementaciju</span> vaših rješenja puno lakšim.",
"AbpStudio_ComingSoon": "Uskoro. <span class=\"opacity-50 ms-0 ms-md-3 d-block d-md-inline-block \">Planirani datum izdavanja beta verzije: 4. tromjesečje 2023.</span>",
"AbpStudio_PlannedPreviewDate": "Planirani datum izdavanja pregleda: 4. kvartal 2023.",
"BetaRequest": "Zahtjev za beta verziju",
"CreateNewSolutions": "Stvorite nova rješenja",
@ -1107,6 +1106,7 @@
"SendUsEmail": "Pošaljite nam e-mail",
"ErrorExceptionMessage": "Pojavila se greška prilikom obrade Vašeg zahtjeva",
"WatchTakeCodeGeneration": "Pogledajte video \"Istražite potencijal generiranja koda: ABP Suite\"!",
"ExtendNow": "Produži / obnovi"
"ExtendNow": "Produži / obnovi",
"AbpStudio_ComingSoon": "Ako želite testirati ABP Studio prije svih ostalih, postanite BETA tester"
}
}

3
abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/hu.json

@ -777,6 +777,7 @@
"SendUsEmail": "Küldjön nekünk e-mailt",
"ErrorExceptionMessage": "Hiba történt a kérése feldolgozása során",
"WatchTakeCodeGeneration": "Nézze meg a \"Fedezze fel a kódgenerálás lehetőségét: ABP Suite\" videót!",
"ExtendNow": "Bővítés / Megújítás"
"ExtendNow": "Bővítés / Megújítás",
"AbpStudio_ComingSoon": "Ha bárki más előtt szeretné tesztelni az ABP Studio-t, legyen BÉTA tesztelő"
}
}

3
abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/is.json

@ -408,6 +408,7 @@
"SendUsEmail": "Sendu okkur tölvupóst",
"ErrorExceptionMessage": "Villa kom upp við úrvinnslu beiðni þinnar",
"WatchTakeCodeGeneration": "Horfðu á \"Kannaðu möguleika kóðaframleiðslu: ABP Suite\" myndbandið!",
"ExtendNow": "Framlengja / endurnýja"
"ExtendNow": "Framlengja / endurnýja",
"AbpStudio_ComingSoon": "Ef þú vilt prófa ABP Studio á undan öllum öðrum skaltu gerast BETA prófari"
}
}

3
abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/it.json

@ -430,6 +430,7 @@
"ErrorExceptionMessage": "Si è verificato un errore durante l'elaborazione della richiesta",
"WatchTakeCodeGeneration": "Guarda il video \"Esplora il potenziale della generazione di codice: ABP Suite\"!",
"ExtendNow": "Estendi/Rinnova",
"RegisterDemo": "Registrati"
"RegisterDemo": "Registrati",
"AbpStudio_ComingSoon": "Se vuoi provare ABP Studio prima di chiunque altro, diventa un BETA tester"
}
}

3
abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/nl.json

@ -408,6 +408,7 @@
"SendUsEmail": "Stuur ons een e-mail",
"ErrorExceptionMessage": "Er is een fout opgetreden bij het verwerken van uw verzoek",
"WatchTakeCodeGeneration": "Bekijk de video 'Ontdek het potentieel van codegeneratie: ABP Suite'!",
"ExtendNow": "Verlengen / Verlengen"
"ExtendNow": "Verlengen / Verlengen",
"AbpStudio_ComingSoon": "Als u ABP Studio als eerste wilt testen, wordt dan BETA-tester"
}
}

3
abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/pl-PL.json

@ -409,6 +409,7 @@
"ErrorExceptionMessage": "Podczas przetwarzania żądania wystąpił błąd",
"WatchTakeCodeGeneration": "Obejrzyj film „Odkryj potencjał generowania kodu: pakiet ABP”!",
"ExtendNow": "Przedłuż/Odnów",
"RegisterDemo": "Rejestr"
"RegisterDemo": "Rejestr",
"AbpStudio_ComingSoon": "Jeśli chcesz przetestować ABP Studio zanim ktokolwiek inny, zostań testerem BETA"
}
}

3
abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/pt-BR.json

@ -431,6 +431,7 @@
"SendUsEmail": "Envie-nos um e-mail",
"ErrorExceptionMessage": "Um erro ocorreu durante o processamento do seu pedido",
"WatchTakeCodeGeneration": "Assista ao vídeo \"Explore o potencial de geração de código: ABP Suite\"!",
"ExtendNow": "Estender/Renovar"
"ExtendNow": "Estender/Renovar",
"AbpStudio_ComingSoon": "Se você quiser testar o ABP Studio antes de todo mundo, torne-se um testador BETA"
}
}

3
abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/ro-RO.json

@ -408,6 +408,7 @@
"SendUsEmail": "Trimite-ne e-mail",
"ErrorExceptionMessage": "A apărut o eroare în timpul procesării cererii dumneavoastră",
"WatchTakeCodeGeneration": "Urmărește videoclipul „Explorați potențialul generării codului: ABP Suite”!",
"ExtendNow": "Extinde/Reînnoiește"
"ExtendNow": "Extinde/Reînnoiește",
"AbpStudio_ComingSoon": "Dacă doriți să testați ABP Studio înaintea oricui, deveniți un tester BETA"
}
}

3
abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/sk.json

@ -427,6 +427,7 @@
"SendUsEmail": "Pošlite nám e-mail",
"ErrorExceptionMessage": "Nastala chyba pri spracovaní vašej žiadosti",
"WatchTakeCodeGeneration": "Pozrite si video „Preskúmajte potenciál generovania kódu: ABP Suite“!",
"ExtendNow": "Predĺžiť / obnoviť"
"ExtendNow": "Predĺžiť / obnoviť",
"AbpStudio_ComingSoon": "Ak chcete otestovať ABP Studio skôr ako ktokoľvek iný, staňte sa BETA testerom"
}
}

3
abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/sl.json

@ -409,6 +409,7 @@
"ErrorExceptionMessage": "Pri obdelavi vaše zahteve je prišlo do napake",
"WatchTakeCodeGeneration": "Oglejte si video »Raziščite potencial generiranja kode: zbirka ABP«!",
"ExtendNow": "Podaljšaj / obnovi",
"RegisterDemo": "Registrirajte se"
"RegisterDemo": "Registrirajte se",
"AbpStudio_ComingSoon": "Če želite preizkusiti ABP Studio pred vsemi drugimi, postanite BETA tester"
}
}

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

@ -1058,7 +1058,6 @@
"AbpStudio_Description": "ABP Studio hala geliştirme aşamasında. İlk kullanıcılardan biri olmak için aşağıdaki formu doldurabilirsiniz.",
"AbpStudio_Description1": "ABP Studio, ABP geliştiricileri için <span class=\"text-highlight-white\">çok platformlu masaüstü uygulamasıdır</span>.",
"AbpStudio_Description2": "ABP Studio, ABP Framework'e <span class=\"text-highlight-white\">iyi entegre edilmiştir</span> ve sizin için işleri <span class=\"text-highlight-white\">otomatikleştirerek, projeniz hakkında bilgi sağlayarak</span>, projelerinizi <span class=\"text-highlight-white\">geliştirmeyi, çalıştırmayı</span> ve <span class=\"text-highlight-white\">dağıtımını</span> çok daha kolay hale getirmeyi amaçlamaktadır.",
"AbpStudio_ComingSoon": "Yakında <span class=\"opacity-50 ms-0 ms-md-3 d-block d-md-inline-block \">Planlanan beta sürüm tarihi: 2023'ün 4. çeyreği.</span>",
"AbpStudio_PlannedPreviewDate": "Planlanan beta sürüm tarihi: 2023'ün 4. çeyreği.",
"BetaRequest": "Beta Talebi",
"CreateNewSolutions": "Yeni Projeler Oluştur",
@ -1140,6 +1139,7 @@
"RemoveBasket": "Sepetten kaldır",
"TrainingPack": "Eğitim paketi",
"TrainingPackDiscount": "Eğitim paketi indirimi",
"LinkExpiredMessage": "Ödeme bağlantısının süresi doldu! Bağlantıyı güncellemek için <a href='mailto:sales@volosoft.com'>sales@volosoft.com</a> adresinden bizimle iletişime geçin veya iletişim sayfasına gitmek için <a href='https://commercial.abp.io/contact'>buraya</a> tıklayın."
"LinkExpiredMessage": "Ödeme bağlantısının süresi doldu! Bağlantıyı güncellemek için <a href='mailto:sales@volosoft.com'>sales@volosoft.com</a> adresinden bizimle iletişime geçin veya iletişim sayfasına gitmek için <a href='https://commercial.abp.io/contact'>buraya</a> tıklayın.",
"AbpStudio_ComingSoon": "ABP Studio'yu herkesten önce test etmek istiyorsanız BETA test kullanıcısı olun"
}
}

3
abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/vi.json

@ -408,6 +408,7 @@
"SendUsEmail": "Gửi email cho chúng tôi",
"ErrorExceptionMessage": "Đã xảy ra lỗi trong khi xử lý yêu cầu của bạn",
"WatchTakeCodeGeneration": "Xem video \"Khám phá tiềm năng tạo mã: ABP Suite\"!",
"ExtendNow": "Gia hạn/Gia hạn"
"ExtendNow": "Gia hạn/Gia hạn",
"AbpStudio_ComingSoon": "Nếu bạn muốn thử nghiệm ABP Studio trước bất kỳ ai khác, hãy trở thành người thử nghiệm BETA"
}
}

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

@ -915,7 +915,6 @@
"AbpStudio_Description": "ABP Studio 仍在开发中。您可以填写下面的表单,成为首批用户之一。",
"AbpStudio_Description1": "ABP Studio 是专为 ABP 开发人员设计的<span class=\"text-highlight-white\">跨平台桌面应用程序</span>。",
"AbpStudio_Description2": "它<span class=\"text-highlight-white\">与 ABP 框架集成得很好</span>,旨在通过<span class=\"text-highlight-white\">自动化、提供有关解决方案的见解</span>,为您提供舒适的开发环境,使<span class=\"text-highlight-white\">开发、运行</span>和<span class=\"text-highlight-white\">部署</span>解决方案变得更加容易。",
"AbpStudio_ComingSoon": "即将发布 <span class=\"opacity-50 ms-0 ms-md-3 d-block d-md-inline-block \">计划测试版发布日期:</span>计划测试版发布日期:2023年第四季度。",
"AbpStudio_PlannedPreviewDate": "计划预览版发布日期:2023 年第四季度。",
"BetaRequest": "测试版请求",
"CreateNewSolutions": "创建新的解决方案",
@ -1110,6 +1109,7 @@
"ErrorExceptionMessage": "处理您的请求时发生错误",
"WatchTakeCodeGeneration": "观看“探索代码生成的潜力:ABP Suite”视频!",
"PreBuiltApplicationModulesTitle": "预构建应用程序 <span class=\"gradient-commercial\">模块</span>",
"RegisterDemo": "登记"
"RegisterDemo": "登记",
"AbpStudio_ComingSoon": "如果您想先于其他人测试 ABP Studio,请成为 BETA 测试员"
}
}

4
abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/zh-Hant.json

@ -897,7 +897,6 @@
"AbpStudio_Description": "ABP Studio 仍在開發中。您可以填寫下面的表单,成為第一批使用者之一。",
"AbpStudio_Description1": "ABP Studio 是一款針對 ABP 開發人員的<span class=\"text-highlight-white\">跨平台桌面應用程式</span>。",
"AbpStudio_Description2": "它與 ABP 框架<span class=\"text-highlight-white\">很好地集成</span>,旨在透過<span class=\"text-highlight-white\">自動化為您提供一個舒適的開發環境,提供有關您的解決方案的見解</span>,使<span class=\"text-highlight-white\">開發、運行</span>和<span class=\"text-highlight-white\">部署</span>您的解決方案變得更加容易。",
"AbpStudio_ComingSoon": "即將推出<span class=\"opacity-50 ms-0 ms-md-3 d-block d-md-inline-block \">計劃測試版發布日期:2023 年第四季。</span>",
"AbpStudio_PlannedPreviewDate": "計畫預覽版發布日期:2023 年第四季。",
"BetaRequest": "測試版請求",
"CreateNewSolutions": "建立新的解決方案",
@ -1100,6 +1099,7 @@
"WatchTakeCodeGeneration": "观看“探索代码生成的潜力:ABP Suite”视频!",
"ExtendNow": "延长 / 续订",
"PreBuiltApplicationModulesTitle": "预构建应用程序 <span class=\"gradient-commercial\">模块</span>",
"RegisterDemo": "登记"
"RegisterDemo": "登记",
"AbpStudio_ComingSoon": "如果您想先于其他人测试 ABP Studio,请成为 BETA 测试员"
}
}

5
abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/ar.json

@ -259,6 +259,9 @@
"MarkdownSupported": "<a href=\"https://www.markdownguide.org/basic-syntax/\">Markdown</a> أيد.",
"Preview": "معاينة",
"VisitVideoCourseDescription": "إذا كنت ترغب في تعلم أساسيات إطار عمل برنامج ABP، فاطلع على دورات الفيديو الخاصة ببرنامج ABP Essentials.",
"VisitPage": "زر الصفحة"
"VisitPage": "زر الصفحة",
"ConfirmEmailForPost": "لتتمكن من النشر، تحتاج إلى تأكيد بريدك الإلكتروني. انتقل إلى account.abp.io/Account/Manage وتحقق من بريدك الإلكتروني في علامة التبويب \"المعلومات الشخصية\".",
"DailyPostCreateLimitation": "لقد وصلت إلى الحد الأقصى اليومي لإنشاء المنشورات. يمكنك إنشاء مشاركة جديدة في {0}.",
"YourAccountDisabled": "تم تعطيل حساب المستخدم الخاص بك!"
}
}

4
abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/cs.json

@ -259,6 +259,8 @@
"MarkdownSupported": "<a href=\"https://www.markdownguide.org/basic-syntax/\">Markdown</a> podporováno.",
"Preview": "Náhled",
"VisitPage": "Navštivte stránku",
"VisitVideoCourseDescription": "Pokud se chcete naučit základy rámce ABP, podívejte se na videokurzy ABP Essentials."
"VisitVideoCourseDescription": "Pokud se chcete naučit základy rámce ABP, podívejte se na videokurzy ABP Essentials.",
"ConfirmEmailForPost": "Abyste mohli přidávat příspěvky, musíte potvrdit svůj e-mail. Přejděte na stránku account.abp.io/Account/Manage a ověřte svůj e-mail na kartě Osobní údaje.",
"DailyPostCreateLimitation": "Dosáhli jste denního limitu pro vytváření příspěvků. Nový příspěvek můžete vytvořit v {0}."
}
}

4
abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/de.json

@ -259,6 +259,8 @@
"MarkdownSupported": "<a href=\"https://www.markdownguide.org/basic-syntax/\">Markdown</a> unterstützt.",
"Preview": "Vorschau",
"VisitPage": "Seite besuchen",
"VisitVideoCourseDescription": "Wenn Sie die Grundlagen des ABP Framework erlernen möchten, schauen Sie sich die ABP Essentials-Videokurse an."
"VisitVideoCourseDescription": "Wenn Sie die Grundlagen des ABP Framework erlernen möchten, schauen Sie sich die ABP Essentials-Videokurse an.",
"ConfirmEmailForPost": "Um Beiträge verfassen zu können, müssen Sie Ihre E-Mail-Adresse bestätigen. Gehen Sie zu account.abp.io/Account/Manage und bestätigen Sie Ihre E-Mail-Adresse auf der Registerkarte „Persönliche Daten“.",
"DailyPostCreateLimitation": "Sie haben das tägliche Limit für die Erstellung von Beiträgen erreicht. Sie können in {0} einen neuen Beitrag erstellen."
}
}

2
abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/en-GB.json

@ -59,7 +59,7 @@
"MilestoneErrorMessage": "Couldn't get the current milestone details from Github.",
"QuestionItemErrorMessage": "Couldn't get the latest question details from Stackoverflow.",
"Oops": "Oops!",
"CreatePostSuccessMessage": "The Post has been successfully submitted. It will be published once it has been reviewed by the site admin.",
"CreatePostSuccessMessage": "Your post has been successfully submitted. It will be published after review by the site administrator.",
"ChooseCoverImage": "Choose a cover image...",
"CoverImage": "Cover Image",
"ShareYourExperiencesWithTheABPFramework": "Share your experiences with the ABP Framework!",

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

@ -16,7 +16,7 @@
"Title": "Title",
"CreationTime": "Creation time",
"Save": "Save",
"SameUrlAlreadyExist": "Same url already exists if you want to add this post, you should change the url!",
"SameUrlAlreadyExist": "Same URL already exists! You must change the URL!",
"UrlIsNotValid": "Url is not valid.",
"UrlNotFound": "Url not found.",
"UrlContentNotFound": "Url content not found.",
@ -33,7 +33,7 @@
"FeatureRequest": "Feature Request",
"CreatePostTitleInfo": "Title of the post to be shown on the post list.",
"CreatePostSummaryInfo": "A short summary of the post to be shown on the post list. Maximum length: <b>{0}</b>",
"CreatePostCoverInfo": "For creating an effective post, add a cover photo. Upload 16:9 aspect ratio pictures for the best view.<br/> Maximum file size: <b>1MB.</b>",
"CreatePostCoverInfo": "To create an effective post, add a cover photo. Upload <b>16:9 aspect ratio</b> pictures for the best view.<br/> Maximum file size is <b>1MB.</b>",
"ThisExtensionIsNotAllowed": "This extension is not allowed.",
"TheFileIsTooLarge": "The file is too large.",
"GoToThePost": "Go to the Post",
@ -56,7 +56,7 @@
"MilestoneErrorMessage": "Could not get the current milestone details from Github.",
"QuestionItemErrorMessage": "Could not get the latest question details from Stackoverflow.",
"Oops": "Oops!",
"CreatePostSuccessMessage": "The Post has been successfully submitted. It will be published after a review from the site admin.",
"CreatePostSuccessMessage": "Your post has been successfully submitted. It will be published after review by the site administrator.",
"Browse": "Browse",
"CoverImage": "Cover Image",
"ShareYourExperiencesWithTheABPFramework": "Share your experiences with the ABP Framework!",
@ -125,7 +125,7 @@
"YoutubeVideoSubmitStepTwo": "<span class=\"font-weight-bold\">2.</span> Submit the video URL using the form.",
"YoutubeVideoSubmitStepThree": "<span class=\"font-weight-bold\">3.</span> Visitors will be able to watch your video content directly on this website.",
"ExternalContent": "External Content",
"ExternalContentSubmitStepOne": "<span class=\"font-weight-bold\">1.</span> Create a content on any public platform (Medium, your own blog or anywhere you like).",
"ExternalContentSubmitStepOne": "<span class=\"font-weight-bold\">1.</span> Create content on any public platform (Medium, your own blog or anywhere you like).",
"ExternalContentSubmitStepTwo": "<span class=\"font-weight-bold\">2.</span> Submit your content URL using the form.",
"ExternalContentSubmitStepThree": "<span class=\"font-weight-bold\">3.</span> Visitors are redirected to the content on the original website.",
"ChooseYourContentType": "Please choose the way you want to add your content.",
@ -135,12 +135,12 @@
"GitHubUserNameValidationMessage": "Your Github username can not include whitespace, please make sure your Github username is correct.",
"PersonalSiteUrlValidationMessage": "Your personal site URL can not include whitespace, please make sure your personal site URL is correct.",
"TwitterUserNameValidationMessage": "Your Twitter username can not include whitespace, please make sure your Twitter username is correct.",
"LinkedinUrlValidationMessage": "Your Linkedin URL can not include whitespace, please make sure your Linkedin URL is correct.",
"LinkedinUrlValidationMessage": "Your LinkedIn URL can not include whitespace, please make sure your LinkedIn URL is correct.",
"NoPostsFound": "No posts found!",
"SearchInPosts": "Search in posts...",
"MinimumSearchContent": "You must enter at least 3 characters!",
"Volo.AbpIo.Domain:060001": "Source URL(\"{PostUrl}\") is not Github URL",
"Volo.AbpIo.Domain:060002": "Post Content is not available from Github(\"{PostUrl}\") resource.",
"Volo.AbpIo.Domain:060002": "Post Content is not available from GitHub(\"{PostUrl}\") resource.",
"Volo.AbpIo.Domain:060003": "No post content found!",
"SeeMore": "See More",
"JoinTheABPCommunity": "Join the ABP Community",
@ -171,14 +171,14 @@
"Discord_Page_Announce": "We are happy to announce ABP Community Discord Server!",
"Discord_Page_Description_1": "ABP Community has been growing since day one. We wanted to take it to the next step by creating an official ABP Discord server so the ABP Community can interact with each other using the wonders of instant messaging.",
"Discord_Page_Description_2": "ABP Community Discord Server is the place where you can showcase your creations using ABP Framework, share the tips that worked for you, catch up with the latest news and announcements about ABP Framework, just chat with community members to exchange ideas, and have fun!",
"Discord_Page_Description_3": "This ABP Community Discord Server is the official one with the ABP Core Team is present on the server to monitor.",
"Discord_Page_Description_3": "This ABP Community Discord Server is the official one with the ABP Core Team present on the server to monitor.",
"Discord_Page_JoinToServer": "Join ABP Discord Server",
"Events_Page_MetaTitle": "ABP Community Events",
"Events_Page_MetaDescription": "The live shows, hosted by the ABP Team, are casual sessions full of community content, demos, Q&A, and discussions around what's happening in ABP.",
"Events_Page_Title": "ABP<span class=\"gradient-community\"> Community</span> Talks",
"Members_Page_WritingFromUser": "Read writing from {0} on ABP Community.",
"Post_Create_Page_MetaTitle": "New Post",
"Post_Create_Page_MetaDescription": "Create your post for sharing your experiences about ABP framework and contributing the ABP Community.",
"Post_Create_Page_MetaDescription": "Create your post for sharing your experiences about the ABP framework and contributing to the ABP Community.",
"Post_Create_Page_CreateNewPost": "Create New Post",
"Post_Index_Page_MetaDescription": "ABP Community's purpose is to create a contribution environment for developers who use the ABP framework.",
"Layout_Title": "{0} | ABP Community",
@ -193,7 +193,7 @@
"AbpCommunityTitleContent": "ABP Community - Open Source ABP Framework",
"CommunitySlogan": "A unique community platform for <span class=\"{0}\">ABP Lovers</span>",
"RaffleIsNotActive": "Raffle is not active",
"YouAreAlreadyJoinedToThisRaffle": "You already joined to this raffle!",
"YouAreAlreadyJoinedToThisRaffle": "You already joined this raffle!",
"InvalidSubscriptionCode": "Invalid subscription code",
"Raffle:{0}": "Raffle: {0}",
"Join": "Join",
@ -261,6 +261,9 @@
"Preview": "Preview",
"VisitPage": "Visit Page",
"VisitVideoCourseDescription": "If you want to learn the basics of the ABP Framework, check out the ABP Essentials Video courses.",
"EditProfile": "Edit Profile"
"EditProfile": "Edit Profile",
"ConfirmEmailForPost": "To be able to post, you need to confirm your email. Go to account.abp.io/Account/Manage and verify your email in the Personal Info tab.",
"DailyPostCreateLimitation": "You have reached the daily post creation limit. You can create a new post in {0}.",
"YourAccountDisabled": "Your user account is disabled!"
}
}
}

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

@ -259,6 +259,8 @@
"MarkdownSupported": "<a href=\"https://www.markdownguide.org/basic-syntax/\">Markdown</a> soportado.",
"Preview": "Avance",
"VisitPage": "Visita la página",
"VisitVideoCourseDescription": "Si desea aprender los conceptos básicos del marco ABP, consulte los cursos en vídeo de ABP Essentials."
"VisitVideoCourseDescription": "Si desea aprender los conceptos básicos del marco ABP, consulte los cursos en vídeo de ABP Essentials.",
"ConfirmEmailForPost": "Para poder publicar, debe confirmar su correo electrónico. Vaya a account.abp.io/Account/Manage y verifique su correo electrónico en la pestaña Información personal.",
"DailyPostCreateLimitation": "Has alcanzado el límite diario de creación de publicaciones. Puedes crear una nueva publicación en {0}."
}
}

4
abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/fi.json

@ -259,6 +259,8 @@
"MarkdownSupported": "<a href=\"https://www.markdownguide.org/basic-syntax/\">Markdown</a> tuettu.",
"Preview": "Esikatselu",
"VisitPage": "Vieraile sivulla",
"VisitVideoCourseDescription": "Jos haluat oppia ABP Frameworkin perusteet, katso ABP Essentials Video -kurssit."
"VisitVideoCourseDescription": "Jos haluat oppia ABP Frameworkin perusteet, katso ABP Essentials Video -kurssit.",
"ConfirmEmailForPost": "Jotta voit lähettää viestejä, sinun on vahvistettava sähköpostiosoitteesi. Siirry osoitteeseen account.abp.io/Account/Manage ja vahvista sähköpostiosoitteesi Henkilökohtaiset tiedot -välilehdessä.",
"DailyPostCreateLimitation": "Olet saavuttanut päivittäisen viestien luomisrajan. Voit luoda uuden viestin kohteessa {0}."
}
}

4
abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/fr.json

@ -259,6 +259,8 @@
"MarkdownSupported": "<a href=\"https://www.markdownguide.org/basic-syntax/\">Markdown</a> prise en charge.",
"Preview": "Aperçu",
"VisitPage": "Page de visite",
"VisitVideoCourseDescription": "Si vous souhaitez apprendre les bases du framework ABP, consultez les cours vidéo ABP Essentials."
"VisitVideoCourseDescription": "Si vous souhaitez apprendre les bases du framework ABP, consultez les cours vidéo ABP Essentials.",
"ConfirmEmailForPost": "Pour pouvoir publier, vous devez confirmer votre e-mail. Accédez à account.abp.io/Account/Manage et vérifiez votre e-mail dans l'onglet Informations personnelles.",
"DailyPostCreateLimitation": "Vous avez atteint la limite quotidienne de création de publications. Vous pouvez créer une nouvelle publication dans {0}."
}
}

4
abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/hi.json

@ -259,6 +259,8 @@
"MarkdownSupported": "<a href=\"https://www.markdownguide.org/basic-syntax/\">Markdown</a> का समर्थन किया।",
"Preview": "पूर्व दर्शन",
"VisitPage": "यात्रा पेज",
"VisitVideoCourseDescription": "यदि आप एबीपी फ्रेमवर्क की मूल बातें सीखना चाहते हैं, तो एबीपी एसेंशियल वीडियो पाठ्यक्रम देखें।"
"VisitVideoCourseDescription": "यदि आप एबीपी फ्रेमवर्क की मूल बातें सीखना चाहते हैं, तो एबीपी एसेंशियल वीडियो पाठ्यक्रम देखें।",
"ConfirmEmailForPost": "पोस्ट करने में सक्षम होने के लिए, आपको अपने ईमेल की पुष्टि करनी होगी। account.abp.io/Account/Manage पर जाएं और व्यक्तिगत जानकारी टैब में अपना ईमेल सत्यापित करें।",
"DailyPostCreateLimitation": "आप दैनिक पोस्ट निर्माण सीमा तक पहुंच गए हैं। आप {0} में एक नई पोस्ट बना सकते हैं।"
}
}

4
abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/hr.json

@ -259,6 +259,8 @@
"MarkdownSupported": "<a href=\"https://www.markdownguide.org/basic-syntax/\">Markdown</a> podržan.",
"Preview": "Pregled",
"VisitPage": "Posjetite stranicu",
"VisitVideoCourseDescription": "Ako želite naučiti osnove ABP okvira, pogledajte video tečajeve ABP Essentials."
"VisitVideoCourseDescription": "Ako želite naučiti osnove ABP okvira, pogledajte video tečajeve ABP Essentials.",
"ConfirmEmailForPost": "Da biste mogli objavljivati, morate potvrditi svoju e-poštu. Idite na account.abp.io/Account/Manage i potvrdite svoju e-poštu na kartici Osobni podaci.",
"DailyPostCreateLimitation": "Dosegli ste dnevno ograničenje za izradu postova. Možete stvoriti novi post u {0}."
}
}

4
abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/hu.json

@ -259,6 +259,8 @@
"MarkdownSupported": "<a href=\"https://www.markdownguide.org/basic-syntax/\">Markdown</a> támogatott.",
"Preview": "Előnézet",
"VisitPage": "Látogassa meg az oldalt",
"VisitVideoCourseDescription": "Ha meg szeretné tanulni az ABP Framework alapjait, nézze meg az ABP Essentials Video tanfolyamokat."
"VisitVideoCourseDescription": "Ha meg szeretné tanulni az ABP Framework alapjait, nézze meg az ABP Essentials Video tanfolyamokat.",
"ConfirmEmailForPost": "A bejegyzések közzétételéhez meg kell erősítenie e-mail-címét. Nyissa meg az account.abp.io/Account/Manage oldalt, és ellenőrizze e-mail-címét a Személyes adatok lapon.",
"DailyPostCreateLimitation": "Elérte a napi bejegyzéslétrehozási korlátot. Új bejegyzést itt hozhat létre: {0}."
}
}

4
abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/is.json

@ -259,6 +259,8 @@
"MarkdownSupported": "<a href=\"https://www.markdownguide.org/basic-syntax/\">Markdown</a> stutt.",
"Preview": "Forskoðun",
"VisitPage": "Heimsæktu síðu",
"VisitVideoCourseDescription": "Ef þú vilt læra grunnatriði ABP Framework skaltu skoða ABP Essentials Video námskeiðin."
"VisitVideoCourseDescription": "Ef þú vilt læra grunnatriði ABP Framework skaltu skoða ABP Essentials Video námskeiðin.",
"ConfirmEmailForPost": "Til að geta sent færslur þarftu að staðfesta netfangið þitt. Farðu á account.abp.io/Account/Manage og staðfestu tölvupóstinn þinn á Persónulegum upplýsingum flipanum.",
"DailyPostCreateLimitation": "Þú hefur náð daglegu takmörkunum fyrir færslu færslu. Þú getur búið til nýja færslu í {0}."
}
}

4
abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/it.json

@ -259,6 +259,8 @@
"MarkdownSupported": "<a href=\"https://www.markdownguide.org/basic-syntax/\">Markdown</a> supportato.",
"Preview": "Anteprima",
"VisitPage": "Visita la pagina",
"VisitVideoCourseDescription": "Se vuoi apprendere le nozioni di base del Framework ABP, dai un'occhiata ai corsi video ABP Essentials."
"VisitVideoCourseDescription": "Se vuoi apprendere le nozioni di base del Framework ABP, dai un'occhiata ai corsi video ABP Essentials.",
"ConfirmEmailForPost": "Per poter pubblicare, devi confermare la tua email. Vai su account.abp.io/Account/Manage e verifica la tua email nella scheda Informazioni personali.",
"DailyPostCreateLimitation": "Hai raggiunto il limite giornaliero di creazione di post. Puoi creare un nuovo post in {0}."
}
}

4
abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/nl.json

@ -259,6 +259,8 @@
"MarkdownSupported": "<a href=\"https://www.markdownguide.org/basic-syntax/\">Markdown</a> ondersteund.",
"Preview": "Voorbeeld",
"VisitPage": "Bezoek pagina",
"VisitVideoCourseDescription": "Als je de basis van het ABP Framework wilt leren, bekijk dan de ABP Essentials Videocursussen."
"VisitVideoCourseDescription": "Als je de basis van het ABP Framework wilt leren, bekijk dan de ABP Essentials Videocursussen.",
"ConfirmEmailForPost": "Om te kunnen posten, moet u uw e-mailadres bevestigen. Ga naar account.abp.io/Account/Manage en verifieer uw e-mailadres op het tabblad Persoonlijke informatie.",
"DailyPostCreateLimitation": "Je hebt de dagelijkse limiet voor het maken van berichten bereikt. Je kunt een nieuw bericht maken in {0}."
}
}

4
abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/pl-PL.json

@ -259,6 +259,8 @@
"MarkdownSupported": "<a href=\"https://www.markdownguide.org/basic-syntax/\">Markdown</a> utrzymany.",
"Preview": "Zapowiedź",
"VisitPage": "Odwiedź stronę",
"VisitVideoCourseDescription": "Jeśli chcesz poznać podstawy ABP Framework, sprawdź kursy wideo ABP Essentials."
"VisitVideoCourseDescription": "Jeśli chcesz poznać podstawy ABP Framework, sprawdź kursy wideo ABP Essentials.",
"ConfirmEmailForPost": "Aby móc publikować, musisz potwierdzić swój adres e-mail. Przejdź do account.abp.io/Account/Manage i zweryfikuj swój adres e-mail w zakładce Dane osobowe.",
"DailyPostCreateLimitation": "Osiągnąłeś dzienny limit tworzenia postów. Możesz utworzyć nowy post w {0}."
}
}

4
abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/pt-BR.json

@ -259,6 +259,8 @@
"MarkdownSupported": "<a href=\"https://www.markdownguide.org/basic-syntax/\">Markdown</a> suportado.",
"Preview": "Visualização",
"VisitPage": "Visite a página",
"VisitVideoCourseDescription": "Se você quiser aprender o básico do ABP Framework, confira os cursos em vídeo ABP Essentials."
"VisitVideoCourseDescription": "Se você quiser aprender o básico do ABP Framework, confira os cursos em vídeo ABP Essentials.",
"ConfirmEmailForPost": "Para poder postar, você precisa confirmar seu e-mail. Acesse account.abp.io/Account/Manage e verifique seu e-mail na guia Informações pessoais.",
"DailyPostCreateLimitation": "Você atingiu o limite diário de criação de postagens. Você pode criar uma nova postagem em {0}."
}
}

4
abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/ro-RO.json

@ -259,6 +259,8 @@
"MarkdownSupported": "<a href=\"https://www.markdownguide.org/basic-syntax/\">Markdown</a> sprijinit.",
"Preview": "previzualizare",
"VisitPage": "Vizitați pagina",
"VisitVideoCourseDescription": "Dacă doriți să aflați elementele de bază ale cadrului ABP, consultați cursurile video ABP Essentials."
"VisitVideoCourseDescription": "Dacă doriți să aflați elementele de bază ale cadrului ABP, consultați cursurile video ABP Essentials.",
"ConfirmEmailForPost": "Pentru a putea posta, trebuie să vă confirmați adresa de e-mail. Accesați account.abp.io/Account/Manage și verificați e-mailul în fila Informații personale.",
"DailyPostCreateLimitation": "Ați atins limita zilnică de creare a postărilor. Puteți crea o postare nouă în {0}."
}
}

4
abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/sk.json

@ -259,6 +259,8 @@
"MarkdownSupported": "<a href=\"https://www.markdownguide.org/basic-syntax/\">Markdown</a> podporované.",
"Preview": "Náhľad",
"VisitPage": "Navštívte stránku",
"VisitVideoCourseDescription": "Ak sa chcete naučiť základy rámca ABP, pozrite si video kurzy ABP Essentials."
"VisitVideoCourseDescription": "Ak sa chcete naučiť základy rámca ABP, pozrite si video kurzy ABP Essentials.",
"ConfirmEmailForPost": "Aby ste mohli uverejňovať príspevky, musíte potvrdiť svoj e-mail. Prejdite na stránku account.abp.io/Account/Manage a overte svoj e-mail na karte Osobné informácie.",
"DailyPostCreateLimitation": "Dosiahli ste denný limit na vytváranie príspevkov. Nový príspevok môžete vytvoriť v {0}."
}
}

4
abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/sl.json

@ -259,6 +259,8 @@
"MarkdownSupported": "<a href=\"https://www.markdownguide.org/basic-syntax/\">Markdown</a> podprt.",
"Preview": "Predogled",
"VisitPage": "Obiščite stran",
"VisitVideoCourseDescription": "Če se želite naučiti osnov ogrodja ABP, si oglejte video tečaje ABP Essentials."
"VisitVideoCourseDescription": "Če se želite naučiti osnov ogrodja ABP, si oglejte video tečaje ABP Essentials.",
"ConfirmEmailForPost": "Če želite objavljati, morate potrditi svoj e-poštni naslov. Pojdite na account.abp.io/Account/Manage in potrdite svoj e-poštni naslov na zavihku Osebni podatki.",
"DailyPostCreateLimitation": "Dosegli ste dnevno omejitev za ustvarjanje objav. Novo objavo lahko ustvarite v {0}."
}
}

5
abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/tr.json

@ -244,6 +244,9 @@
"BuyTicket": "Bilet al",
"SeeEvent": "Etkinliği Gör",
"Cancel": "Vazgeç",
"Continue": "Devam"
"Continue": "Devam",
"ConfirmEmailForPost": "Gönderi paylaşabilmek için e-posta adresinizi onaylamanız gerekir. account.abp.io/Account/Manage adresine gidin ve Kişisel Bilgiler sekmesinden e-posta adresinizi doğrulayın.",
"DailyPostCreateLimitation": "Günlük gönderi paylaşma sınırına ulaştınız. {0}'da yeni bir gönderi paylaşabilirsiniz.",
"YourAccountDisabled": "Kullanıcı hesabınız devre dışı bırakıldı!"
}
}

4
abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/vi.json

@ -259,6 +259,8 @@
"MarkdownSupported": "<a href=\"https://www.markdownguide.org/basic-syntax/\">Markdown</a> được hỗ trợ.",
"Preview": "Xem trước",
"VisitPage": "Ghé thăm trang",
"VisitVideoCourseDescription": "Nếu bạn muốn tìm hiểu những kiến ​​thức cơ bản về Khung ABP, hãy xem các khóa học Video Cơ bản về ABP."
"VisitVideoCourseDescription": "Nếu bạn muốn tìm hiểu những kiến ​​thức cơ bản về Khung ABP, hãy xem các khóa học Video Cơ bản về ABP.",
"ConfirmEmailForPost": "Để có thể đăng bài, bạn cần xác nhận email của mình. Hãy truy cập account.abp.io/Account/Quản lý và xác minh email của bạn trong tab Thông tin cá nhân.",
"DailyPostCreateLimitation": "Bạn đã đạt đến giới hạn tạo bài đăng hàng ngày. Bạn có thể tạo bài đăng mới trong {0}."
}
}

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

@ -259,6 +259,8 @@
"MarkdownSupported": "<a href=\"https://www.markdownguide.org/basic-syntax/\">Markdown</a> 支持的。",
"Preview": "预览",
"VisitPage": "访问页面",
"VisitVideoCourseDescription": "如果您想学习 ABP 框架的基础知识,请查看 ABP Essentials 视频课程。"
"VisitVideoCourseDescription": "如果您想学习 ABP 框架的基础知识,请查看 ABP Essentials 视频课程。",
"ConfirmEmailForPost": "为了能够发帖,您需要确认您的电子邮件。转到 account.abp.io/Account/Manage 并在“个人信息”选项卡中验证您的电子邮件。",
"DailyPostCreateLimitation": "您已达到每日帖子创建限制。您可以在 {0} 中创建新帖子。"
}
}

4
abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/zh-Hant.json

@ -259,6 +259,8 @@
"MarkdownSupported": "<a href=\"https://www.markdownguide.org/basic-syntax/\">Markdown</a> 支持的。",
"Preview": "预览",
"VisitPage": "访问页面",
"VisitVideoCourseDescription": "如果您想学习 ABP 框架的基础知识,请查看 ABP Essentials 视频课程。"
"VisitVideoCourseDescription": "如果您想学习 ABP 框架的基础知识,请查看 ABP Essentials 视频课程。",
"ConfirmEmailForPost": "为了能够发帖,您需要确认您的电子邮件。转到 account.abp.io/Account/Manage 并在“个人信息”选项卡中验证您的电子邮件。",
"DailyPostCreateLimitation": "您已达到每日帖子创建限制。您可以在 {0} 中创建新帖子。"
}
}

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

@ -158,7 +158,7 @@
"IndexPageHeroSection": "<span class=\"first-line shine\"><strong>open source</strong></span><span class=\"second-line text-uppercase\">Web Application<br />Framework</span><span class=\"third-line shine2\"><strong>for asp.net core</strong></span>",
"UiFramework": "UI框架",
"EmailAddress": "电子邮件地址",
"Mobile": "移动电话",
"Mobile": "选择移动应用程序框架",
"ReactNative": "React Native",
"Strong": "强大",
"Complete": "完整",
@ -476,4 +476,4 @@
"ABPVideoCoursesPageDescription": "通过ABP团队创建的视频课程学习ABP框架的基础知识。在本视频系列中,您将学习ABP框架的基本主题。每个视频上的数字都是根据学习流程编写的。",
"ABPVideoCoursesTitle": "ABP 基本视频"
}
}
}

4
common.props

@ -1,8 +1,8 @@
<Project>
<PropertyGroup>
<LangVersion>latest</LangVersion>
<Version>8.2.3</Version>
<LeptonXVersion>3.2.3</LeptonXVersion>
<Version>8.3.0-rc.3</Version>
<LeptonXVersion>3.3.0-rc.3</LeptonXVersion>
<NoWarn>$(NoWarn);CS1591;CS0436</NoWarn>
<PackageIconUrl>https://abp.io/assets/abp_nupkg.png</PackageIconUrl>
<PackageProjectUrl>https://abp.io/</PackageProjectUrl>

4
docs/en/Blog-Posts/2024-05 ABP Unification/post.md

@ -51,7 +51,7 @@ You can easily download and install ABP Studio, login with your abp.io account a
### The New Pricing Page
Since the [ABP Commercial website](https://commercial.abp.io/) has merged with the main website, you will see the *Pricing* page located on the main menu of the abp.io website. We have completely revised the design and content of this page to better reflect which features are open source and free, and what is included in the commercial licenses.
Since the [ABP Commercial website](https://commercial.abp.io/) has merged with the main website, you will see the *Pricing* page located on the main menu of the abp.io website. We have completely revised the design and content of this page to better reflect which features are open source and free, and what is included in the paid licenses.
![new-pricing](new-pricing.png)
@ -68,7 +68,7 @@ Based on our and customers' experiences, there are some problems with that appro
* Getting started, development tutorials, release notes, road map and some other documents are duplicated (or very similar) among ABP Framework and ABP Commercial documents.
* For ABP Commercial users, it is not clear if they also need to read the ABP Framework (open source) documentation or not. Also, when they read the framework document, some parts are different for ABP Commercial users, and it is also not clear in some cases.
We are currently working to completely merge the ABP Framework (open source) and ABP Commercial documentation, remove duplications and revisit the contents. We will clearly indicate if a part of a document requires a commercial license.
We are currently working to completely merge the ABP Framework (open source) and ABP Commercial documentation, remove duplications and revisit the contents. We will clearly indicate if a part of a document requires a paid license.
The left navigation panel tree is also completely revisited and simplified:

14
docs/en/cli/index.md

@ -105,6 +105,8 @@ abp cli update
abp cli update --preview
abp cli update --version 1.0.0
abp cli remove
abp cli check-version
abp cli clear-cache
````
### new
@ -138,10 +140,10 @@ For more samples, go to [ABP CLI Create Solution Samples](new-command-samples.md
* `--tiered`: Creates a tiered solution where Web and Http API layers are physically separated. If not specified, it creates a layered solution which is less complex and suitable for most scenarios. (*Available for* ***Team*** *or higher licenses*)
* `angular`: Angular UI. There are some additional options for this template:
* `--tiered`: The Auth Server project comes as a separate project and runs at a different endpoint. It separates the Auth Server from the API Host application. If not specified, you will have a single endpoint in the server side. (*Available for* ***Team*** *or higher licenses*)
* `--pwa`: Specifies the project as Progressive Web Application.
* `--progressive-web-app` or `-pwa`: Specifies the project as Progressive Web Application.
* `blazor`: Blazor UI. There are some additional options for this template:
* `--tiered`The Auth Server project comes as a separate project and runs at a different endpoint. It separates the Auth Server from the API Host application. If not specified, you will have a single endpoint in the server side. (*Available for* ***Team*** *or higher licenses*)
* `--pwa`: Specifies the project as Progressive Web Application.
* `--progressive-web-app` or `-pwa`: Specifies the project as Progressive Web Application.
* `blazor-server`: Blazor Server UI. There are some additional options for this template:
* `--tiered`: The Auth Server and the API Host project comes as separate projects and run at different endpoints. It has 3 startup projects: *HttpApi.Host*, *AuthServer* and *Blazor* and and each runs on different endpoints. If not specified, you will have a single endpoint for your web project. (*Available for* ***Team*** *or higher licenses*)
* `maui-blazor`: Blazor Maui UI (*Available for* ***Team*** *or higher licenses*). There are some additional options for this template:
@ -156,8 +158,12 @@ For more samples, go to [ABP CLI Create Solution Samples](new-command-samples.md
* `ef`: Entity Framework Core.
* `mongodb`: MongoDB.
* `--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` 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](../framework/data/entity-framework-core/other-dbms.md) (after creating the solution).
* `--skip-migrations` or `-sm`: Skips the creating initial database migration step.
* `--skip-migrator` or `-smr`: Skips the run database migrator step.
* `--public-website`: Public Website is a front-facing website for describing your project, listing your products and doing SEO for marketing purposes. Users can login and register on your website with this website. This option is only included in PRO templates.
* `--without-cms-kit`: When you add a public website to your solution, it automatically includes the [CmsKit](./../modules/cms-kit-pro/index.md) module. If you don't want to include *CmsKit*, you can use this parameter.
* `--separate-tenant-schema`: Creates a different DbContext for tenant schema. If not specified, the tenant schema is shared with the host schema. This option is only included in PRO templates.
* `--sample-crud-page` or `-scp`: It adds the [BookStore](./../tutorials/book-store/index.md) sample to your solution.
* `--theme` or `-th`: Specifes the theme. Default theme is `leptonx`. Available themes:
* `leptonx`: LeptonX Theme. (*Available for* ***Team*** *or higher licenses*)
* `leptonx-lite`: LeptonX-Lite Theme.
@ -174,6 +180,9 @@ For more samples, go to [ABP CLI Create Solution Samples](new-command-samples.md
* `ef`: Entity Framework Core.
* `mongodb`: MongoDB.
* `--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` 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](../framework/data/entity-framework-core/other-dbms.md) (after creating the solution).
* `--skip-migrations` or `-sm`: Skips the creating initial database migration step.
* `--skip-migrator` or `-smr`: Skips the run database migrator step.
* `--sample-crud-page` or `-scp`: It adds the [BookStore](./../tutorials/book-store/index.md) sample to your solution.
* `--theme`: Specifes the theme. Default theme is `leptonx`. Available themes:
* `leptonx`: LeptonX Theme. (*Available for* ***Team*** *or higher licenses*)
* `leptonx-lite`: LeptonX-Lite Theme.
@ -211,6 +220,7 @@ For more samples, go to [ABP CLI Create Solution Samples](new-command-samples.md
* `--dont-run-install-libs`: Skip installing client side packages.
* `--dont-run-bundling`: Skip bundling for Blazor packages.
* `--no-kubernetes-configuration` or `-nkc`: Skips the Kubernetes configuration files.
* `--no-social-logins` or `-nsl`: Skipts the social login configuration.
* *Module Options*: You can skip some modules if you don't want to add them to your solution (*Available for* ***Team*** *or higher licenses*). Available commands:
* `-no-saas`: Skips the Saas module.
* `-no-gdpr`: Skips the GDPR module.

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

@ -10,8 +10,8 @@ Wikipedia [defines](https://en.wikipedia.org/wiki/Multitenancy) the multi-tenanc
There are two main side of a typical SaaS / Multi-tenant application:
* A **Tenant** is a customer of the SaaS application that pays money to use the service.
* **Host** is the company that owns the SaaS application and manages the system.
- A **Tenant** is a customer of the SaaS application that pays money to use the service.
- **Host** is the company that owns the SaaS application and manages the system.
The Host and the Tenant terms will be used for that purpose in the rest of the document.
@ -36,9 +36,9 @@ Configure<AbpMultiTenancyOptions>(options =>
ABP supports all the following approaches to store the tenant data in the database;
* **Single Database**: All tenants are stored in a single database.
* **Database per Tenant**: Every tenant has a separate, dedicated database to store the data related to that tenant.
* **Hybrid**: Some tenants share a single databases while some tenants may have their own databases.
- **Single Database**: All tenants are stored in a single database.
- **Database per Tenant**: Every tenant has a separate, dedicated database to store the data related to that tenant.
- **Hybrid**: Some tenants share a single database while some tenants may have their own databases.
[Tenant management module](../../../modules/tenant-management.md) (which comes pre-installed with the startup projects) allows you to set a connection string for any tenant (as optional), so you can achieve any of the approaches.
@ -50,9 +50,9 @@ Multi-tenancy system is designed to **work seamlessly** and make your applicatio
You should implement the `IMultiTenant` interface for your [entities](../domain-driven-design/entities.md) to make them **multi-tenancy ready**.
**Example: A multi-tenant *Product* entity**
**Example: A multi-tenant _Product_ entity**
````csharp
```csharp
using System;
using Volo.Abp.Domain.Entities;
using Volo.Abp.MultiTenancy;
@ -68,7 +68,7 @@ namespace MultiTenancyDemo.Products
public float Price { get; set; }
}
}
````
```
`IMultiTenant` interface just defines a `TenantId` property. When you implement this interface, ABP **automatically** [filters](../../infrastructure/data-filtering.md) entities for the current tenant when you query from database. So, you don't need to manually add `TenantId` condition while performing queries. A tenant can not access to data of another tenant by default.
@ -96,9 +96,9 @@ If you set the `TenantId` value for a specific entity object, it will override t
`ICurrentTenant` defines the following properties;
* `Id` (`Guid`): Id of the current tenant. Can be `null` if the current user is a host user or the tenant could not be determined from the request.
* `Name` (`string`): Name of the current tenant. Can be `null` if the current user is a host user or the tenant could not be determined from the request.
* `IsAvailable` (`bool`): Returns `true` if the `Id` is not `null`.
- `Id` (`Guid`): Id of the current tenant. Can be `null` if the current user is a host user or the tenant could not be determined from the request.
- `Name` (`string`): Name of the current tenant. Can be `null` if the current user is a host user or the tenant could not be determined from the request.
- `IsAvailable` (`bool`): Returns `true` if the `Id` is not `null`.
#### Change the Current Tenant
@ -108,7 +108,7 @@ ABP automatically filters the resources (database, cache...) based on the `ICurr
**Example: Get product count of a specific tenant**
````csharp
```csharp
using System;
using System.Threading.Tasks;
using Volo.Abp.Domain.Repositories;
@ -134,11 +134,11 @@ namespace MultiTenancyDemo.Products
}
}
}
````
```
* `Change` method can be used in a **nested way**. It restores the `CurrentTenant.Id` to the previous value after the `using` statement.
* When you use `CurrentTenant.Id` inside the `Change` scope, you get the `tenantId` provided to the `Change` method. So, the repository also get this `tenantId` and can filter the database query accordingly.
* Use `CurrentTenant.Change(null)` to change scope to the host context.
- `Change` method can be used in a **nested way**. It restores the `CurrentTenant.Id` to the previous value after the `using` statement.
- When you use `CurrentTenant.Id` inside the `Change` scope, you get the `tenantId` provided to the `Change` method. So, the repository also get this `tenantId` and can filter the database query accordingly.
- Use `CurrentTenant.Change(null)` to change scope to the host context.
> Always use the `Change` method with a `using` statement like done in this example.
@ -148,7 +148,7 @@ As mentioned before, ABP handles data isolation between tenants using the [Data
**Example: Get count of products in the database, including all the products of all the tenants.**
````csharp
```csharp
using System;
using System.Threading.Tasks;
using Volo.Abp.Data;
@ -181,7 +181,7 @@ namespace MultiTenancyDemo.Products
}
}
````
```
See the [Data Filtering document](../../infrastructure/data-filtering.md) for more.
@ -201,15 +201,15 @@ ABP provides an extensible **Tenant Resolving** system for that purpose. Tenant
The following resolvers are provided and configured by default;
* `CurrentUserTenantResolveContributor`: Gets the tenant id from claims of the current user, if the current user has logged in. **This should always be the first contributor for the security**.
* `QueryStringTenantResolveContributor`: Tries to find current tenant id from query string parameters. The parameter name is `__tenant` by default.
* `RouteTenantResolveContributor`: Tries to find current tenant id from route (URL path). The variable name is `__tenant` by default. If you defined a route with this variable, then it can determine the current tenant from the route.
* `HeaderTenantResolveContributor`: Tries to find current tenant id from HTTP headers. The header name is `__tenant` by default.
* `CookieTenantResolveContributor`: Tries to find current tenant id from cookie values. The cookie name is `__tenant` by default.
- `CurrentUserTenantResolveContributor`: Gets the tenant id from claims of the current user, if the current user has logged in. **This should always be the first contributor for the security**.
- `QueryStringTenantResolveContributor`: Tries to find current tenant id from query string parameters. The parameter name is `__tenant` by default.
- `RouteTenantResolveContributor`: Tries to find current tenant id from route (URL path). The variable name is `__tenant` by default. If you defined a route with this variable, then it can determine the current tenant from the route.
- `HeaderTenantResolveContributor`: Tries to find current tenant id from HTTP headers. The header name is `__tenant` by default.
- `CookieTenantResolveContributor`: Tries to find current tenant id from cookie values. The cookie name is `__tenant` by default.
###### Problems with the NGINX
You may have problems with the `__tenant` in the HTTP Headers if you're using the [nginx](https://www.nginx.com/) as the reverse proxy server. Because it doesn't allow to use underscore and some other special characters in the HTTP headers and you may need to manually configure it. See the following documents please:
You may have problems with the `__tenant` in the HTTP Headers if you're using the [nginx](https://www.nginx.com/) as the reverse proxy server. Because it doesn't allow to use underscore and some other special characters in the HTTP headers and you may need to manually configure it. See the following documents please:
http://nginx.org/en/docs/http/ngx_http_core_module.html#ignore_invalid_headers
http://nginx.org/en/docs/http/ngx_http_core_module.html#underscores_in_headers
@ -219,22 +219,24 @@ http://nginx.org/en/docs/http/ngx_http_core_module.html#underscores_in_headers
**Example:**
````csharp
```csharp
services.Configure<AbpAspNetCoreMultiTenancyOptions>(options =>
{
options.TenantKey = "MyTenantKey";
});
````
```
If you change the `TenantKey`, make sure to pass it to `CoreModule` in the Angular client as follows:
If you change the `TenantKey`, make sure to pass it to `provideAbpCore` via `withOptions` method in the Angular client as follows:
```js
@NgModule({
imports: [
CoreModule.forRoot({
// ...
tenantKey: 'MyTenantKey'
}),
providers: [
provideAbpCore(
withOptions({
// ...
tenantKey: "MyTenantKey",
})
),
],
// ...
})
@ -249,7 +251,7 @@ import { TENANT_KEY } from '@abp/ng.core';
class SomeComponent {
constructor(@Inject(TENANT_KEY) private tenantKey: string) {}
}
}
```
> However, we don't suggest to change this value since some clients may assume the the `__tenant` as the parameter name and they might need to manually configure then.
@ -277,12 +279,12 @@ In a real application, most of times you will want to determine the current tena
**Example: Add a subdomain resolver**
````csharp
```csharp
Configure<AbpTenantResolveOptions>(options =>
{
options.AddDomainTenantResolver("{0}.mydomain.com");
});
````
```
* `{0}` is the placeholder to determine the current tenant's unique name.
* Add this code to the `ConfigureServices` method of your [module](../modularity/basics.md).
@ -293,14 +295,14 @@ Openiddict is the default Auth Server in ABP (since v6.0). When you use OpenIddi
```csharp
// using Volo.Abp.OpenIddict.WildcardDomains
PreConfigure<AbpOpenIddictWildcardDomainOptions>(options =>
PreConfigure<AbpOpenIddictWildcardDomainOptions>(options =>
{
options.EnableWildcardDomainSupport = true;
options.WildcardDomainsFormat.Add("https://{0}.mydomain.com");
});
```
You must add this code to the `Configure` method as well.
You must add this code to the `Configure` method as well.
```csharp
// using Volo.Abp.MultiTenancy;
@ -312,7 +314,7 @@ Configure<AbpTenantResolveOptions>(options =>
```
> There is an [example](https://github.com/abpframework/abp-samples/tree/master/DomainTenantResolver) that uses the subdomain to determine the current tenant.
> There is an [example](https://github.com/abpframework/abp-samples/tree/master/DomainTenantResolver) that uses the subdomain to determine the current tenant.
If you use a sepereted Auth server, you must install `[Owl.TokenWildcardIssuerValidator](https://www.nuget.org/packages/Owl.TokenWildcardIssuerValidator)` on the `HTTPApi.Host` project
@ -332,7 +334,7 @@ context.Services
options.Authority = configuration["AuthServer:Authority"];
options.RequireHttpsMetadata = Convert.ToBoolean(configuration["AuthServer:RequireHttpsMetadata"]);
options.Audience = "ExampleProjectName";
// start of added block
options.TokenValidationParameters.IssuerValidator = TokenWildcardIssuerValidator.IssuerValidator;
options.TokenValidationParameters.ValidIssuers = new[]
@ -348,16 +350,16 @@ context.Services
You can add implement your custom tenant resolver and configure the `AbpTenantResolveOptions` in your module's `ConfigureServices` method as like below:
````csharp
```csharp
Configure<AbpTenantResolveOptions>(options =>
{
options.TenantResolvers.Add(new MyCustomTenantResolveContributor());
});
````
```
`MyCustomTenantResolveContributor` must inherit from the `TenantResolveContributorBase` (or implement the `ITenantResolveContributor`) as shown below:
````csharp
```csharp
using System.Threading.Tasks;
using Volo.Abp.MultiTenancy;
@ -373,7 +375,7 @@ namespace MultiTenancyDemo.Web
}
}
}
````
```
* A tenant resolver should set `context.TenantIdOrName` if it can determine it. If not, just leave it as is to allow the next resolver to determine it.
* `context.ServiceProvider` can be used if you need to additional services to resolve from the [dependency injection](../../fundamentals/dependency-injection.md) system.
@ -384,9 +386,9 @@ Multi-Tenancy middleware is an ASP.NET Core request pipeline [middleware](https:
Multi-Tenancy middleware is typically placed just under the [authentication](https://docs.microsoft.com/en-us/aspnet/core/security/authentication) middleware (`app.UseAuthentication()`):
````csharp
```csharp
app.UseMultiTenancy();
````
```
> This middleware is already configured in the startup templates, so you normally don't need to manually add it.
@ -406,7 +408,7 @@ The [tenant management module](../../../modules/tenant-management.md) is **inclu
**Example: Define tenants in appsettings.json**
````json
```json
"Tenants": [
{
"Id": "446a5211-3d72-4339-9adc-845151f8ada0",
@ -422,7 +424,7 @@ The [tenant management module](../../../modules/tenant-management.md) is **inclu
}
}
]
````
```
> It is recommended to **use the Tenant Management module**, which is already pre-configured when you create a new application with the ABP startup templates.

181
docs/en/framework/ui/angular/localization.md

@ -11,7 +11,7 @@ The Localization key format consists of 2 sections which are **Resource Name** a
const environment = {
//...
localization: {
defaultResourceName: 'MyProjectName',
defaultResourceName: "MyProjectName",
},
};
```
@ -38,7 +38,8 @@ You can also specify a default value as shown below:
```html
<h1>
{%{{{ { key: 'Resource::Key', defaultValue: 'Default Value' } | abpLocalization }}}%}
{%{{{ { key: 'Resource::Key', defaultValue: 'Default Value' } |
abpLocalization }}}%}
</h1>
```
@ -82,17 +83,17 @@ After that, you are able to use localization service.
```js
this.localizationService.instant(
'AbpIdentity::UserDeletionConfirmation',
'John'
"AbpIdentity::UserDeletionConfirmation",
"John"
);
// with fallback value
this.localizationService.instant(
{
key: 'AbpIdentity::UserDeletionConfirmation',
defaultValue: 'Default Value',
key: "AbpIdentity::UserDeletionConfirmation",
defaultValue: "Default Value",
},
'John'
"John"
);
// Output
@ -102,12 +103,12 @@ this.localizationService.instant(
To get a localized text as [_Observable_](https://rxjs.dev/guide/observable) use `get` method instead of `instant`:
```js
this.localizationService.get('Resource::Key');
this.localizationService.get("Resource::Key");
// with fallback value
this.localizationService.get({
key: 'Resource::Key',
defaultValue: 'Default Value',
key: "Resource::Key",
defaultValue: "Default Value",
});
```
@ -118,41 +119,46 @@ Localizations can be determined on backend side. Angular UI gets the localizatio
See an example:
```ts
// app.module.ts
import { provideAbpCore, withOptions } from '@abp/ng.core';
@NgModule({
imports: [
//...other imports
CoreModule.forRoot({
localizations: [
{
culture: 'en',
resources: [
{
resourceName: 'MyProjectName',
texts: {
Administration: 'Administration',
HomePage: 'Home',
providers: [
// ...
provideAbpCore(
withOptions({
...,
localizations: [
{
culture: 'en',
resources: [
{
resourceName: 'MyProjectName',
texts: {
Administration: 'Administration',
HomePage: 'Home',
},
},
},
],
},
{
culture: 'de',
resources: [
{
resourceName: 'MyProjectName',
texts: {
Administration: 'Verwaltung',
HomePage: 'Startseite',
],
},
{
culture: 'de',
resources: [
{
resourceName: 'MyProjectName',
texts: {
Administration: 'Verwaltung',
HomePage: 'Startseite',
},
},
},
],
},
],
}),
]
],
},
],
}),
),
...
],
})
export class AppModule {}
```
...or, you can determine the localizations in a feature module:
@ -256,10 +262,10 @@ Find [styles configuration in angular.json](https://angular.io/guide/workspace-c
If you have created and injected chunks for Fontawesome as seen above, you no longer need the lazy loading in the `AppComponent` which was implemented before v2.9. Simply remove them. The `AppComponent` in the template of the new version looks like this:
```js
import { Component } from '@angular/core';
import { Component } from "@angular/core";
@Component({
selector: 'app-root',
selector: "app-root",
template: `
<abp-loader-bar></abp-loader-bar>
<router-outlet></router-outlet>
@ -274,33 +280,32 @@ Since ABP has more than one language, Angular locale files loads lazily using [W
### registerLocaleFn
`registerLocale` function that exported from `@abp/ng.core/locale` package is a higher order function that accepts `cultureNameLocaleFileMap` object and `errorHandlerFn` function as params and returns Webpack `import` function. A `registerLocale` function must be passed to the `forRoot` of the `CoreModule` as shown below:
```js
// app.module.ts
`registerLocale` function that exported from `@abp/ng.core/locale` package is a higher order function that accepts `cultureNameLocaleFileMap` object and `errorHandlerFn` function as params and returns Webpack `import` function. A `registerLocale` function must be passed to the `withOptions` of the `provideAbpCore` as shown below:
```ts
import { provideAbpCore, withOptions } from '@abp/ng.core';
import { registerLocale } from '@abp/ng.core/locale';
// if you have commercial license and the language management module, add the below import
// import { registerLocale } from '@volo/abp.ng.language-management/locale';
@NgModule({
imports: [
// ...
CoreModule.forRoot({
// ...other options,
registerLocaleFn: registerLocale(
// you can pass the cultureNameLocaleFileMap and errorHandlerFn as optionally
{
cultureNameLocaleFileMap: { 'pt-BR': 'pt' },
errorHandlerFn: ({ resolve, reject, locale, error }) => {
// the error can be handled here
providers: [
provideAbpCore(
withOptions({
...,
registerLocaleFn: registerLocale(
// you can pass the cultureNameLocaleFileMap and errorHandlerFn as optionally
{
cultureNameLocaleFileMap: { 'pt-BR': 'pt' },
errorHandlerFn: ({ resolve, reject, locale, error }) => {
// the error can be handled here
},
},
},
)
}),
//...
]
),
}),
),
...
],
})
export class AppModule {}
```
### Mapping of Culture Name to Angular Locale File Name
@ -320,20 +325,23 @@ import { registerLocale } from '@abp/ng.core/locale';
@NgModule({
imports: [
providers: [
// ...
CoreModule.forRoot({
// ...other options,
registerLocaleFn: registerLocale(
{
cultureNameLocaleFileMap: {
"DotnetCultureName": "AngularLocaleFileName",
"pt-BR": "pt" // example
provideAbpCore(
withOptions({
...,
registerLocaleFn: registerLocale(
{
cultureNameLocaleFileMap: {
"DotnetCultureName": "AngularLocaleFileName",
"pt-BR": "pt" // example
},
},
},
)
}),
//...
)
}),
),
]
})
```
See [all locale files in Angular](https://github.com/angular/angular/tree/master/packages/common/locales).
@ -345,12 +353,12 @@ Add the below code to the `app.module.ts` by replacing `your-locale` placeholder
```js
//app.module.ts
import { storeLocaleData } from '@abp/ng.core/locale';
import { storeLocaleData } from "@abp/ng.core/locale";
import(
/* webpackChunkName: "_locale-your-locale-js"*/
/* webpackMode: "eager" */
'@angular/common/locales/your-locale.js'
).then((m) => storeLocaleData(m.default, 'your-locale'));
"@angular/common/locales/your-locale.js"
).then((m) => storeLocaleData(m.default, "your-locale"));
```
...or a custom `registerLocale` function can be passed to the `CoreModule`:
@ -373,14 +381,17 @@ export function registerLocale(locale: string) {
import { registerLocale } from './register-locale';
@NgModule({
imports: [
providers: [
// ...
CoreModule.forRoot({
// ...other options,
registerLocaleFn: registerLocale
}),
provideAbpCore(
withOptions({
...,
registerLocaleFn: registerLocale,
}),
),
//...
]
})
```
After this custom `registerLocale` function, since the en and fr added to the `webpackInclude`, only en and fr locale files will be created as chunks:
@ -392,4 +403,4 @@ Which locale files you add to `webpackInclude` magic comment, they will be inclu
## See Also
* [Localization in ASP.NET Core](../../fundamentals/localization.md)
* [Video tutorial](https://abp.io/video-courses/essentials/localization)
* [Video tutorial](https://abp.io/video-courses/essentials/localization)

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

@ -4,8 +4,8 @@
Please follow the steps below to prepare your development environment for Angular.
1. **Install Node.js:** Please visit [Node.js downloads page](https://nodejs.org/en/download/) and download proper Node.js v16 or v18 installer for your OS. An alternative is to install [NVM](https://github.com/nvm-sh/nvm) and use it to have multiple versions of Node.js in your operating system.
2. **[Optional] Install Yarn:** You may install Yarn v1 (not v2) following the instructions on [the installation page](https://classic.yarnpkg.com/en/docs/install). Yarn v1 delivers an arguably better developer experience compared to npm v6 and below. You may skip this step and work with npm, which is built-in in Node.js, instead.
1. **Install Node.js:** Please visit [Node.js downloads page](https://nodejs.org/en/download/) and download proper Node.js `v18.19+` installer for your OS. An alternative is to install [NVM](https://github.com/nvm-sh/nvm) and use it to have multiple versions of Node.js in your operating system.
2. **[Optional] Install Yarn:** You may install Yarn v1.22+ (not v2) following the instructions on [the installation page](https://classic.yarnpkg.com/en/docs/install). Yarn v1 delivers an arguably better developer experience compared to npm v10 and below. You may skip this step and work with npm, which is built-in in Node.js, instead.
3. **[Optional] Install VS Code:** [VS Code](https://code.visualstudio.com/) is a free, open-source IDE which works seamlessly with TypeScript. Although you can use any IDE including Visual Studio or Rider, VS Code will most likely deliver the best developer experience when it comes to Angular projects. ABP project templates even contain plugin recommendations for VS Code users, which VS Code will ask you to install when you open the Angular project folder. Here is a list of recommended extensions:
- [Angular Language Service](https://marketplace.visualstudio.com/items?itemName=angular.ng-template)
- [Prettier - Code formatter](https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode)

4
docs/en/get-started/layered-web-application.md

@ -22,8 +22,8 @@ The following tools should be installed on your development machine:
* [Visual Studio 2022](https://visualstudio.microsoft.com/vs/) (v17.3+) for Windows / [Visual Studio for Mac](https://visualstudio.microsoft.com/vs/mac/). <sup id="a-editor">[1](#f-editor)</sup>
* [.NET 8.0+](https://dotnet.microsoft.com/en-us/download/dotnet)
{{ if UI != "Blazor" }}
* [Node v16 or v18](https://nodejs.org/)
* [Yarn v1.20+ (not v2)](https://classic.yarnpkg.com/en/docs/install) <sup id="a-yarn">[2](#f-yarn)</sup> or npm v6+ (already installed with Node)
* [Node v18.19+](https://nodejs.org/)
* [Yarn v1.22+ (not v2)](https://classic.yarnpkg.com/en/docs/install) <sup id="a-yarn">[2](#f-yarn)</sup> or npm v10+ (already installed with Node)
{{ end }}
{{ if Tiered == "Yes" }}
* [Redis](https://redis.io/) (as the [distributed cache](../framework/fundamentals/caching.md)).

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

@ -125,6 +125,8 @@ In the *Solution Runner* section (on the left side) you can see all the runnable
> All the leaf items in the *Solution Runner* is called as an *Application* as they are executable applications.
> For a faster start process, first start the *Docker-Dependencies*, then you can start all applications.
As shown in the figure above, the executable applications are grouped into folders like `apps`, `gateways`, `infrastructure`, and `services`. You can start/stop them all, a group (folder) of them, or one by one.
Before running the applications, it is good to be sure that all applications are built. To do that, right-click the root item in the *Solution Runner* and select *Build* -> *Build All* action.

4
docs/en/get-started/single-layer-web-application.md

@ -21,8 +21,8 @@ The following tools should be installed on your development machine:
* [Visual Studio 2022](https://visualstudio.microsoft.com/vs/) (v17.3+) for Windows / [Visual Studio for Mac](https://visualstudio.microsoft.com/vs/mac/). <sup id="a-editor">[1](#f-editor)</sup>
* [.NET 8.0+](https://dotnet.microsoft.com/en-us/download/dotnet)
{{ if UI != "Blazor" }}
* [Node v16 or v18](https://nodejs.org/)
* [Yarn v1.20+ (not v2)](https://classic.yarnpkg.com/en/docs/install) <sup id="a-yarn">[2](#f-yarn)</sup> or npm v6+ (already installed with Node)
* [Node v18.19+](https://nodejs.org/)
* [Yarn v1.22+ (not v2)](https://classic.yarnpkg.com/en/docs/install) <sup id="a-yarn">[2](#f-yarn)</sup> or npm v10+ (already installed with Node)
{{ end }}
{{ if Tiered == "Yes" }}
* [Redis](https://redis.io/) (as the [distributed cache](../framework/fundamentals/caching.md)).

BIN
docs/en/images/cmskit-module-markedItems.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

BIN
docs/en/images/cmskit-module-markedItemsFilter.gif

Binary file not shown.

After

Width:  |  Height:  |  Size: 483 KiB

BIN
docs/en/images/docs-referencing.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

4
docs/en/modules/account/authority-delegation.md

@ -77,6 +77,8 @@ You can click the `Delegate New User` button to delegate a new user:
* You can specify a time range to ensure the delegation is only available within the time range.
* You can make multiple delegates to the same user and set different delegate time ranges.
> You have to enter the full username to query and delegate a user.
> The delegation has three states: `Expired`, `Active`, and `Future`. These states are set automatically by checking the specified time interval.
### My delegated users
@ -87,4 +89,4 @@ You can see a list of users who delegated you to login on their behalf of them,
You can click the `Login` button to log in to the application as a delegated user and go back to your account by clicking the `Back to my account` icon:
![account-pro-module-delegated-impersonate](../../images/account-pro-module-delegated-impersonate.jpg)
![account-pro-module-delegated-impersonate](../../images/account-pro-module-delegated-impersonate.jpg)

1
docs/en/modules/cms-kit/index.md

@ -17,6 +17,7 @@ The following features are currently available:
* Provides a [**menu**](./menus.md) system to manage public menus dynamically.
* Provides a [**global resources**](./global-resources.md) system to add global styles and scripts dynamically.
* Provides a [**Dynamic Widget**](./dynamic-widget.md) system to create dynamic widgets for page and blog posts.
* Provides a [**Marked Item**](./marked-items.md) system to mark any kind of resource, like a blog post or a product, as a favorite, starred, flagged, or bookmarked.
> You can click on the any feature links above to understand and learn how to use it.

123
docs/en/modules/cms-kit/marked-items.md

@ -0,0 +1,123 @@
# CMS Kit: Marked Item System
CMS kit provides a marking system to mark any kind of resource, like a blog post or a product, as a favorite, starred, flagged, or bookmarked.
Marked toggling component allows users to mark your items via pre-defined icons/emojis. Here how the marked toggling components may look like:
![markedItems](../../images/cmskit-module-markedItems.png)
you can also customize the marking icons shown in the toggling components.
## Enabling the Marked Item Feature
By default, CMS Kit features are disabled. Therefore, you need to enable the features you want, before starting to use it. You can use the [Global Feature](../../Global-Features.md) system to enable/disable CMS Kit features on development time. Alternatively, you can use the ABP Framework's [Feature System](https://docs.abp.io/en/abp/latest/Features) to disable a CMS Kit feature on runtime.
> Check the ["How to Install" section of the CMS Kit Module documentation](Index.md#how-to-install) to see how to enable/disable CMS Kit features on development time.
## Options
Marking system provides a simple approach to define your entity type with mark types like favorite or starred. For example, if you want to use the marking system for products, you need to define an entity type named `product` with the icon name.
`CmsKitMarkedItemOptions` can be configured in YourModule.cs, in the `ConfigureServices` method of your [module](https://docs.abp.io/en/abp/latest/Module-Development-Basics). Example:
```csharp
Configure<CmsKitMarkedItemOptions>(options =>
{
options.EntityTypes.Add(
new MarkedItemEntityTypeDefinition(
"product",
StandardMarkedItems.Favorite
)
);
});
```
`CmsKitMarkedItemOptions` properties:
- `EntityTypes`: List of defined entity types (`CmsKitMarkedItemOptions`) in the marking system.
`MarkedItemEntityTypeDefinition` properties:
- `EntityType`: Name of the entity type.
- `IconName`: The name of the icon.
## The Marked Item widget
The marking system provides a toggle widget to allow users to add/remove the marks from an item. You can place the widget with the item as shown below:
``` csharp
@await Component.InvokeAsync(typeof (MarkedItemToggleViewComponent), new
{
entityId = "...",
entityType = "product",
needsConfirmation = true // (optional)
})
```
* `entityType` was explained in the previous section.
* `entityId` should be the unique id of the product, in this example. If you have a Product entity, you can use its Id here.
* `needsConfirmation` An optional parameter to let the user confirm when removing the mark.
# Internals
## Domain Layer
#### Aggregates
This module follows the [Entity Best Practices & Conventions](https://docs.abp.io/en/abp/latest/Best-Practices/Entities) guide.
##### UserMarkedItem
A user markedItem represents a user has marking on the item.
- `UserMarkedItem` (aggregate root): Represents a marked item in the system.
#### Repositories
This module follows the [Repository Best Practices & Conventions](https://docs.abp.io/en/abp/latest/Best-Practices/Repositories) guide.
Following custom repositories are defined for this feature:
- `IUserMarkedItemRepository`
#### Domain services
This module follows the [Domain Services Best Practices & Conventions](https://docs.abp.io/en/abp/latest/Best-Practices/Domain-Services) guide.
##### Marked Item Manager
`MarkedItemManager` is used to perform some operations for the `UserMarkedItem` aggregate root.
### Application layer
#### Application services
- `MarkedItemPublicAppService` (implements `IMarkedItemPublicAppService`): Implements the use cases of marking system.
### Database providers
#### Common
##### Table / collection prefix & schema
All tables/collections use the `Cms` prefix by default. Set static properties on the `CmsKitDbProperties` class if you need to change the table prefix or set a schema name (if supported by your database provider).
##### Connection string
This module uses `CmsKit` for the connection string name. If you don't define a connection string with this name, it fallbacks to the `Default` connection string.
See the [connection strings](https://docs.abp.io/en/abp/latest/Connection-Strings) documentation for details.
#### Entity Framework Core
##### Tables
- CmsUserMarkedItems
#### MongoDB
##### Collections
- **CmsUserMarkedItems**

54
docs/en/modules/docs.md

@ -666,9 +666,61 @@ See the following examples:
```
```
---
## Referencing Next & Previous Documents
The **Docs Module** supports referencing previous and next documents. It's useful if you have a series of documents that are strictly related to each other and need to be followed one after the other.
To reference the previous and next documents from a document, you should specify the documentation titles and their paths as follows:
```
````json
//[doc-nav]
{
"Previous": {
"Name": "Overall",
"Path": "testing/overall"
},
"Next": {
"Name": "Integration tests",
"Path": "testing/integration-tests"
}
}
````
```
After you specify the next & previous documents, they will appear at the end of the current documentation like in the following figure:
![](../images/docs-referencing.png)
## Single Project Mode
The **single project mode** allows you to use a single name as a project name in your application. If you are not considering supporting multiple projects with their multiple docs and instead if you have a single project and want to have documentation only for it, it's especially useful for you.
You just need to configure the `DocsUiOptions`, set the single project mode as **enabled** and also define a constant project name:
```csharp
Configure<DocsUiOptions>(options =>
{
options.RoutePrefix = "docs";
options.SingleProjectMode.Enable = true;
options.SingleProjectMode.ProjectName = "abp";
});
```
## Multi Language Mode
The **multi language mode** allows you to show a combobox that lists and shows all documentation languages and configures the related languages in routes.
It's enabled by default and supports multiple languages, but if you are considering only supporting a single language, and don't want to show the language combobox in the sidebar of your docs system, you can configure the `DocsUiOptions` and set the multi language mode support as **false** to disable it:
```csharp
Configure<DocsUiOptions>(options =>
{
options.MultiLanguageMode = false;
});
```
## See Also

11
docs/en/modules/openiddict-pro.md

@ -415,6 +415,17 @@ public override void PreConfigureServices(ServiceConfigurationContext context)
}
```
### Disable Transport Security Requirement
By default, OpenIddict requires the use of HTTPS for all endpoints. You can disable it if it's needed. You just need to configure the `OpenIddictServerAspNetCoreOptions` and set `DisableTransportSecurityRequirement` as **true**:
```cs
Configure<OpenIddictServerAspNetCoreOptions>(options =>
{
options.DisableTransportSecurityRequirement = true;
});
```
https://documentation.openiddict.com/configuration/token-formats.html#disabling-jwt-access-token-encryption
### Request/Response Process

11
docs/en/modules/openiddict.md

@ -375,6 +375,17 @@ public override void PreConfigureServices(ServiceConfigurationContext context)
}
```
### Disable Transport Security Requirement
By default, OpenIddict requires the use of HTTPS for all endpoints. You can disable it if it's needed. You just need to configure the `OpenIddictServerAspNetCoreOptions` and set `DisableTransportSecurityRequirement` as **true**:
```cs
Configure<OpenIddictServerAspNetCoreOptions>(options =>
{
options.DisableTransportSecurityRequirement = true;
});
```
https://documentation.openiddict.com/configuration/token-formats.html#disabling-jwt-access-token-encryption
### Request/Response Process

68
docs/en/release-info/migration-guides/abp-8-3.md

@ -0,0 +1,68 @@
# ABP Version 8.3 Migration Guide
This document is a guide for upgrading ABP v8.x solutions to ABP v8.3. There are some changes in this version that may affect your applications, please read it carefully and apply the necessary changes to your application.
## Open-Source (Framework)
### Added `AdminUserName` parameter to `IIdentityDataSeeder.SeedAsync` method
Prior to this version, `IIdentityDataSeeder.SeedAsync` was used to seed the initial user data with the `admin` as the username, to be able to easily test all applications with all permissions granted.
In this version on, we allow you to set the default **adminUserName**. So, you can set the default user name to any name you want or leave it as it is and let the username be `admin` as before.
For example, in the `MyProjectNameDbMigrationService.SeedDataAsync` method (under the domain project's **Data** folder), you can pass the username as below:
```diff
private async Task SeedDataAsync(Tenant? tenant = null)
{
Logger.LogInformation($"Executing {(tenant == null ? "host" : tenant.Name + " tenant")} database seed...");
await _dataSeeder.SeedAsync(new DataSeedContext(tenant?.Id)
.WithProperty(IdentityDataSeedContributor.AdminEmailPropertyName, IdentityDataSeedContributor.AdminEmailDefaultValue)
.WithProperty(IdentityDataSeedContributor.AdminPasswordPropertyName, IdentityDataSeedContributor.AdminPasswordDefaultValue)
+ .WithProperty(IdentityDataSeedContributor.AdminUserNamePropertyName, "your-admin-user-name")
);
}
```
Normally, you don't need to make any changes in your code related to this change. However, if you used the `IIdentityDataSeeder.SeedAsync` method in your application, now also gets additional (and optional) `adminUserName` parameter that you can pass the value on.
See the PR for more info: https://github.com/abpframework/abp/pull/20131/
### Docs Module: Improvements & Single Project Mode Support
In this version, we made some improvements in the [Docs Module](../../modules/docs.md) and introduced single project mode, which allows you to use a single project name for all of your documents.
While implementing this new feature, we made some small changes to the existing classes. For example, the constructor methods of the following classes have been changed, and need to be updated in your code, if you use them:
* `TreeTagHelper.cs`: https://github.com/abpframework/abp/pull/19419/files#diff-e0fb91c1b564d61dedf9dfc60d08e7e0af57b433797fcb3bd664f3fd4768ea0d
* `MarkdownDocumentToHtmlConverter.cs`: https://github.com/abpframework/abp/pull/19419/files#diff-948e25b2d8851576888f8053b5f2c9416e23576aff95a88ef8ec8ca2841b3622
See the PR for more info: https://github.com/abpframework/abp/pull/19419
### Updated `datatables.net` to 2.0.2
In this version, the `datatables.net` library version was updated from v1.11.4 to v2.0.2. We made all related changes at the framework level and updated the dependency and its resource mapping configurations. Also, we made it backward compatible so it should not directly affect your application.
However, notice this package is used by the `@abp/aspnetcore.mvc.ui.theme.shared` package, which is used by the official themes. Therefore, if you used any methods from the **datatables.net** library it might be already deprecated or removed.
See the PR for more info: https://github.com/abpframework/abp/pull/19340
### Angular UI
We wish to formally inform you that ABP version 8.3 has been upgraded to incorporate Angular version 18. Consequently, we recommend migrating your application to [Angular v18](https://angular.dev/update-guide) to ensure compatibility.
## PRO
> Please check the **Open-Source (Framework)** section before reading this section. The listed topics might affect your application and you might need to take care of them.
If you are a paid-license owner and using the ABP's paid version, then please follow the following sections to get informed about the breaking changes and apply the necessary ones:
### Added RegEx Support to CMS Kit's (PRO) URL Forwarding System
ABP provides a [URL Forwarding System](../../modules/cms-kit-pro/url-forwarding.md), which allows you to create URLs that redirect to other pages or external websites. Prior to this version, the URL Forwarding System was only working for static URLs and didn't support RegEx. In this version, we introduced the RegEx support for the URL Forwarding System and now you can pass regular expressions for not static URLs.
Since a new property has been added to the `CmsShortenedUrl` entity, you should create a new migration and apply it to your database.
> After creating a new migration and applying it to your database, typically you don't need to make any changes, however, if you have overridden a page/method or class related to the URL Forwarding System, you might need to update it accordingly. For this purpose, you can get the source code of the [CMS Kit Module's](../../modules/cms-kit-pro/index.md) and update the related parts in your application.

1
docs/en/release-info/migration-guides/index.md

@ -2,6 +2,7 @@
The following documents explain how to migrate your existing ABP applications. We write migration documents only if you need to take an action while upgrading your solution. Otherwise, you can easily upgrade your solution using the [abp update command](../upgrading.md).
- [8.x to 8.3](abp-8-3.md)
- [8.1 to 8.2](abp-8-2.md)
- [8.0 to 8.1](abp-8-1.md)
- [7.x to 8.0](abp-8-0.md)

15
docs/en/release-info/release-notes.md

@ -4,11 +4,20 @@ This document contains **brief release notes** for each release. Release notes o
> If you want to read detailed release posts for each version, please see the [official ABP blog](https://abp.io/blog).
## 8.2 (2024-05-25)
## 8.3.0-rc.1 (2024-07-31)
> This version is currently in preview. The final release date is planned for July, 2024.
> This version is currently in preview. The final release date is planned for August, 2024.
See the detailed **[blog post / announcement](https://abp.io/blog/announcing-abp-8-2-release-candidate)** for the v8.2 release.
See the detailed **[blog post / announcement](https://abp.io/blog/announcing-abp-8-3-release-candidate)** for the v8.3 release.
* CMS Kit: Marked Items & Approvement System for Commenting Feature
* Enhancements on the Docs Module (Google Translation support & new single project mode)
* Using DbFunction for generating more precise SQL commands for Global Query Filters
* CMS Kit (Pro): FAQ System
## 8.2 (2024-06-26)
See the detailed **[blog post / announcement](https://abp.io/blog/announcing-abp-8-2-stable-release)** for the v8.2 release.
* Blazor Full-Stack Web App UI.
* Introducing the `IBlockUiService` for Blazor UI (disables/blocks the page or a part of the page).

136
docs/en/release-info/road-map.md

@ -4,55 +4,119 @@ This document provides a road map, release schedule, and planned features for th
## Next Versions
### v8.3
The next version will be 8.3 and we will be mostly working on the following topics:
* CMS Kit: Marked Items/Favorites & Approvement System for Comments
* Docs Module: Added Google Translation Support & Introducing the Single Project Mode
* Using DBFunction for Global Query Filters
* Upgrade Angular Version to v18.1.x
* Improvements on the existing features and provide more guides...
See the [8.3 milestone](https://github.com/abpframework/abp/milestone/106) for all the issues we've planned to work on.
### v9.0
The next version will be 9.0 and planned to release the stable 9.0 version in November 2024. We will be mostly working on the following topics:
* Framework
* Upgrading to .NET 9.0
* Google Cloud Storage BLOB Provider
* Better handling localization resources in a microservice scenario
* SSR support for the Angular UI
* Upgrading 3rd-party dependencies
* ABP Suite
* Multiple navigation properties to the same target entity
* Define navigation properties without target string property dependency
* Improvements one-to-many scenarios
* Access to default code generation templates for customized templates
* ABP Studio
* Blazor WebApp UI option for the new startup templates
* Execution order (dependency management) for Solution Runner
* Automate more details on new service creation for a microservice solution
* Support multiple concurrent Kubernetes deployment/integration scenarios
* Show the README file when you create a new solution or open an existing solution
* Improve ABP Suite code-generation possibilities for microservice solutions
* Improve the module installation experience
* Auto-install 3rd-party dependencies
* Better handle long log files
* Allow to directly create new solutions with ABP's RC (Release Candidate) versions
* Support Intel processors for Mac computers, support ARM chipset for Windows and support Linux OS
* Improve client proxy generation experience
* Application modules
* Account module: Support mixed social/local login scenarios
* UI/UX improvements on existing application modules
* New tutorials
* Modular monolith development
* Microservice development
## Backlog Items
The *Next Versions* section above shows the main focus of the planned versions. However, in each release, we add new features to the core framework and the [application modules](../modules).
Here is a list of major items in the backlog we are considering working on in the next versions.
The *Next Versions* section above shows the main focus of the planned versions. However, in each release, we add new features to the ABP platform.
### Framework
* [#86](https://github.com/abpframework/abp/issues/86) / GrapQL Integration
The ABP framework is [open source](https://github.com/abpframework/abp) and free for everyone. You can see its [public backlog](https://github.com/abpframework/abp/milestone/2). Here, are some of the important features you can expect from next versions:
* [#236](https://github.com/abpframework/abp/issues/236) / Resource based authorization system
* [#2882](https://github.com/abpframework/abp/issues/2882) / Providing a gRPC integration infrastructure (while it is [already possible](https://github.com/abpframework/abp-samples/tree/master/GrpcDemo) to create or consume gRPC endpoints for your application, we plan to create endpoints for the [standard application modules](../modules))
* [#2882](https://github.com/abpframework/abp/issues/2882) / Providing a gRPC integration infrastructure (while it is [already possible](https://github.com/abpframework/abp-samples/tree/master/GrpcDemo) to create or consume gRPC endpoints for your application, we plan to create endpoints for the [standard application modules](../modules/index.md))
* [#57](https://github.com/abpframework/abp/issues/57) / Built-in CQRS infrastructure
* [#58](https://github.com/abpframework/abp/issues/58) / Content localization system (multilingual entities)
* [#4223](https://github.com/abpframework/abp/issues/4223) / WebHook system
* [#162](https://github.com/abpframework/abp/issues/162) / Azure ElasticDB Integration for multitenancy
* [#2296](https://github.com/abpframework/abp/issues/2296) / Feature toggling infrastructure
* [#16342](https://github.com/abpframework/abp/issues/16342) / CMS Kit: Meta information for SEO
* [#16260](https://github.com/abpframework/abp/issues/16260) / GCP Blob Storage Provider
* [#15932](https://github.com/abpframework/abp/issues/15932) / Introduce ABP Diagnostics Module
* [#16756](https://github.com/abpframework/abp/issues/16756) / Blob Storing - Provider configuration UI
* [#16744](https://github.com/abpframework/abp/issues/16744) / State Management API
### Modules / Themes
* New styles, components and features for the LeptonX theme.
* Payment module: Invoice system.
* Dynamic dashboard system.
* User guiding module.
* gRPC integration and implementation for all the pre-built modules.
* Chat Module: Deleting messages & conversations
### Tooling
* Suite: File, DateOnly and TimeOnly types
* Suite: Export child/detail entity records
* CMS Kit features, including FAQ, spam protection, social media feeds, multi-language support, and so on.
You can always check the milestone planning and the prioritized backlog issues on [the GitHub repository](https://github.com/abpframework/abp/milestones) for a detailed road map. The backlog items are subject to change. We are adding new items and changing priorities based on the community feedbacks and goals of the project.
* [#17815](https://github.com/abpframework/abp/issues/17815) / Operation Rate Limiting
### Application Modules / UI Themes
ABP Platform provides many (free and commercial) [pre-built application modules](../modules/index.md) and modern [UI themes](../ui-themes/index.md). In every release, many enhancements and bugfixes are already done on the existing modules. In addition, here some of the planned features for next versions:
* LeptonX theme: New layouts, styles and components
* CMS Kit module: Meta information for SEO, media gallery, RSS feed, content versioning, social media streams
* Identity module: Idle session warning
* Payment module: Invoice system
* New module: User notification
* New module: Dynamic dashboard
* New module: User guiding
* New module: Keycloak integration
### ABP Studio
[ABP Studio](../studio/index.md) is a cross-platform desktop application for ABP and .NET developers to simplify and automate daily tasks of developers. It has a community (free) edition as well as commercial editions. It is released and versioned independently from the ABP platform and frequently released.
Here, are some of the important planned features for next ABP Studio versions:
* Theme builder for the LeptonX theme
* Analyze user solutions to explore entities, domain services, application services, pages and other fundamental objects.
* Add status bar to the built-in browser to easily see errors
* Swagger authentication support for the built-in browser
* Show related requests/events (traces) together in the solution runner panel
* Integrate common tool dashboards into ABP Studio (such a Garana, Redis, RabbitMQ, Kibana, etc)
* Built-in command terminal
* Automate all steps of new service creation for microservice solutions
* Container application type support for Solution Runner (to individually control docker dependencies)
* More options while creating new solutions
* Downloading samples in ABP studio
* Built-in ABP documentation experience
* Auto-execute terminal commands in markdown files
* Compare changed on the startup templates when a new ABP version is published
* Remove unused projects while downloading source code of an existing module
* Testing/hosting applications for module templates
* Easily explore all module and package dependencies of a large solution
* Built-in deployment options
* Rapid application development features
* ABP support integration
### ABP Suite
[ABP Suite](../suite/index.md) is a GUI application that is mainly used to generate CRUD style pages in your application. You define your entity and it can generate all the code from the database layer to the UI layer. The generated code is clean and a perfect starting point to implement your custom requirements on top of it.
Here, are some of the important planned features for next ABP Suite versions:
* Handle image properties for entities
* Allow to define extra properties for DTOs those are not a part of the entity
* Allow to create pages instead of modals for CRUD page generation
* View-only (detail view) modal/page for an entity
* Export child/detail entity records as a part of export operation for a main (master) entity
* Allow to accept attachments (files) for an entity
* Allow to add custom entity actions for an entity
* Allow to inherit from an existing entity class
* Custom form layouts on CRUD page generation
## Feature Requests

6
docs/en/solution-templates/microservice/adding-new-api-gateways.md

@ -155,12 +155,6 @@ We should configure the AuthServer for **CORS** and **RedirectAllowedUrls**.
}
```
### Add the New Gateway to the Solution Runner
We should add the new gateway to the solution runner [profile](../../studio/running-applications.md#profile) for running applications in the ABP Studio. You can follow the steps explained in the [Solution Runner](../../studio/running-applications.md#c-application) document to add the new gateway to the solution runner profile. Afterwards, you can start the new gateway by selecting it in the solution runner.
![public-gateway-solution-runner](images/public-gateway-solution-runner.png)
## Creating Helm Chart for the New Gateway
If you want to deploy the new gateway to Kubernetes, you should create a Helm chart for the new application.

6
docs/en/solution-templates/microservice/adding-new-applications.md

@ -120,12 +120,6 @@ Add the new application URL to the `appsettings.json` file in the `Identity` ser
}
```
### Add the New Application to the Solution Runner
We should add the new application to the solution runner [profile](../../studio/running-applications.md#profile) for running applications in the ABP Studio. You can follow the steps explained in the [Solution Runner](../../studio/running-applications.md#c-application) document to add the new application to the solution runner profile. Afterwards, you can start the new application by selecting it in the solution runner.
![web-public-solution-runner](images/web-public-solution-runner.png)
## Docker Configuration for Prometheus
If you want to monitor the new application with Prometheus when you debug the solution, you should add the new application to the `prometheus.yml` file in the `etc/docker/prometheus` folder. You can copy the configurations from the existing applications and modify them according to the new application. Below is an example of the `prometheus.yml` file for the `WebPublic` application.

372
docs/en/solution-templates/microservice/adding-new-microservices.md

@ -16,6 +16,8 @@ This document explains how to add new microservices to the microservice solution
Additionally, there is a folder named `_templates` in the root directory. This folder contains templates you can use to create new microservices, API gateways, and applications. These templates can be customized according to your needs.
![folder-structure](images/folder-structure.png)
## Adding a New Microservice
To add a new microservice to the solution, you can use the `service_nolayers` template. This template creates a new ASP.NET Core application with the necessary configurations and dependencies. Follow the steps below to add a new microservice:
@ -40,29 +42,34 @@ The new microservice is created and added to the solution. You can see the new m
The new microservice is created with the necessary configurations and dependencies. We should configure several sections by modifying the `appsettings.json` file:
* Set the `Administration` & `AbpBlobStoring` connection strings.
* Set the correct `StringEncryption` key.
* Set the `CorsOrigins` to allow the web gateway to access the microservice.
* Set the `AuthServer` configurations to enable the microservice to authenticate and authorize users.
* Set the correct `StringEncryption` key.
You can copy the configurations from the existing microservices and modify them according to the new microservice. Below is an example of the `appsettings.json` file for the `ProductService` microservice.
```json
```diff
{
"ConnectionStrings": {
"Administration": "Server=localhost,1434; User Id=sa; Password=myPassw@rd; Database=Bookstore_Administration; TrustServerCertificate=true",
"AbpBlobStoring": "Server=localhost,1434; User Id=sa; Password=myPassw@rd; Database=Bookstore_BlobStoring; TrustServerCertificate=true",
- "Administration": "Administration_Database",
- "AbpBlobStoring": "BlobStoring_Database",
+ "Administration": "Server=localhost,1434; User Id=sa; Password=myPassw@rd; Database=Bookstore_Administration; TrustServerCertificate=true",
+ "AbpBlobStoring": "Server=localhost,1434; User Id=sa; Password=myPassw@rd; Database=Bookstore_BlobStoring; TrustServerCertificate=true",
"ProductService": "Server=localhost,1434; User Id=sa; Password=myPassw@rd; Database=Bookstore_ProductService; TrustServerCertificate=true"
},
"App": {
"CorsOrigins": "http://localhost:44333",
- "CorsOrigins": "http://localhost:webgateway_port",
+ "CorsOrigins": "http://localhost:44333",
"EnablePII": false
},
"Swagger": {
"IsEnabled": true
},
"AuthServer": {
"Authority": "http://localhost:44387",
"MetaAddress": "http://localhost:44387",
- "Authority": "http://localhost:authserver_port",
- "MetaAddress": "http://localhost:authserver_port",
+ "Authority": "http://localhost:44387",
+ "MetaAddress": "http://localhost:44387",
"RequireHttpsMetadata": "false",
"SwaggerClientId": "SwaggerTestUI",
"Audience": "ProductService"
@ -93,24 +100,25 @@ You can copy the configurations from the existing microservices and modify them
"Url": "http://localhost:9200"
},
"StringEncryption": {
"DefaultPassPhrase": "PDAWjbshpwlOwNB6"
- "DefaultPassPhrase": "string_encrryption_key"
+ "DefaultPassPhrase": "PDAWjbshpwlOwNB6"
}
}
```
### Configuring the OpenId Options
We should configure the OpenId options by modifying the `OpenIddictDataSeeder` in the `Identity` service. Below is an example of the `OpenIddictDataSeeder` options for the `ProductService` microservice.
We should configure the OpenId options by modifying the `OpenIddictDataSeeder` in the `Identity` service. Below is an example of the `OpenIddictDataSeeder` options for the `Product` microservice.
Create API scopes and add the required API scope for Swagger clients in the `CreateApiScopesAsync` and `CreateSwaggerClientsAsync` methods in the `OpenIddictDataSeeder` class.
```csharp
```diff
private async Task CreateApiScopesAsync()
{
await CreateScopesAsync("AuthServer");
await CreateScopesAsync("IdentityService");
await CreateScopesAsync("AdministrationService");
await CreateScopesAsync("ProductService"); // new service
+ await CreateScopesAsync("ProductService");
}
private async Task CreateSwaggerClientsAsync()
@ -120,21 +128,21 @@ private async Task CreateSwaggerClientsAsync()
"AuthServer",
"IdentityService",
"AdministrationService",
"ProductService" // new service
+ "ProductService"
});
}
```
Add the redirect URL for the new service in the `CreateSwaggerClientAsync` method.
```csharp
```diff
private async Task CreateSwaggerClientAsync(string clientId, string[] scopes)
{
...
...
...
var administrationServiceRootUrl = _configuration["OpenIddict:Resources:AdministrationService:RootUrl"]!.TrimEnd('/');
var productServiceServiceRootUrl = _configuration["OpenIddict:Resources:ProductService:RootUrl"]!.TrimEnd('/'); // new service
+ var productServiceRootUrl = _configuration["OpenIddict:Resources:ProductService:RootUrl"]!.TrimEnd('/');
await CreateOrUpdateApplicationAsync(
name: clientId,
@ -152,15 +160,15 @@ private async Task CreateSwaggerClientAsync(string clientId, string[] scopes)
$"{authServerRootUrl}/swagger/oauth2-redirect.html",
$"{identityServiceRootUrl}/swagger/oauth2-redirect.html",
$"{administrationServiceRootUrl}/swagger/oauth2-redirect.html",
$"{productServiceServiceRootUrl}/swagger/oauth2-redirect.html", // new service
+ $"{productServiceRootUrl}/swagger/oauth2-redirect.html"
}
);
}
```
Add the allowed scope for the web (front-end) application(s) in the `CreateClientsAsync` method. You might have different clients for different UI applications such as web, Angular, React, etc. Ensure you add the new service to the allowed scopes of these clients.
Add the allowed scope for the web (front-end) application(s) in the `CreateClientsAsync` method. You might have different clients for different UI applications such as web, Angular, React, etc. Ensure you add the new microservice to the allowed scopes of these clients.
```csharp
```diff
private async Task CreateClientsAsync()
{
var commonScopes = new List<string>
@ -192,7 +200,7 @@ private async Task CreateClientsAsync()
"SaasService",
"AuditLoggingService",
"AdministrationService",
"ProductService" // new service
+ "ProductService"
}).ToList(),
redirectUris: new List<string> { $"{webClientRootUrl}signin-oidc" },
postLogoutRedirectUris: new List<string>() { $"{webClientRootUrl}signout-callback-oidc" },
@ -202,110 +210,130 @@ private async Task CreateClientsAsync()
}
```
Add the new service URL to the `appsettings.json` file in the `Identity` service.
Add the new service URL to the `appsettings.json` file in the `Identity` microservice. In this example we're gonna edit the *Acme.Bookstore.IdentityService* project `appsettings.json` file.
```json
```diff
"OpenIddict": {
"Applications": {
...
},
"Resources": {
...
"ProductService": {
"RootUrl": "http://localhost:44350"
}
+ "ProductService": {
+ "RootUrl": "http://localhost:44350"
+ }
}
}
```
### Configuring the AuthServer
We should configure the AuthServer for **CORS** and **RedirectAllowedUrls**.
We should configure the *AuthServer* application `appsettings.json` file for the **CorsOrigins** and **RedirectAllowedUrls** sections.
```json
```diff
...
"App": {
"SelfUrl": "http://localhost:***",
"CorsOrigins": "...... ,http://localhost:44350",
- "CorsOrigins": "http://localhost:44358,..",
+ "CorsOrigins": "http://localhost:44358,..,http://localhost:44350",
"EnablePII": false,
"RedirectAllowedUrls": "...... ,http://localhost:44350"
}
- "RedirectAllowedUrls": "http://localhost:44358,..",
+ "RedirectAllowedUrls": "http://localhost:44358,..,http://localhost:44350"
},
...
```
### Configuring the API Gateway
We should configure the API Gateway to allow the web gateway to access the new microservice. First, we should add the **ProductService** sections to the `appsettings.json` file in the `WebGateway` project.
We should configure the API Gateway to access the new microservice. First, add the **Product** sections to the `appsettings.json` file in the `WebGateway` project. In this example we're gonna edit the *Acme.Bookstore.WebGateway* project `appsettings.json` file.
```json
```diff
"ReverseProxy": {
"Routes": {
...
"ProductService": {
"ClusterId": "ProductService",
"Match": {
"Path": "/api/productservice/{**catch-all}"
}
},
"ProductServiceSwagger": {
"ClusterId": "ProductService",
"Match": {
"Path": "/swagger-json/ProductService/swagger/v1/swagger.json"
},
"Transforms": [
{ "PathRemovePrefix": "/swagger-json/ProductService" }
]
}
+ "Product": {
+ "ClusterId": "Product",
+ "Match": {
+ "Path": "/api/product/{**catch-all}"
+ }
+ },
+ "ProductSwagger": {
+ "ClusterId": "Product",
+ "Match": {
+ "Path": "/swagger-json/Product/swagger/v1/swagger.json"
+ },
+ "Transforms": [
+ { "PathRemovePrefix": "/swagger-json/Product" }
+ ]
+ }
},
"Clusters": {
...
"ProductService": {
"Destinations": {
"ProductService": {
"Address": "http://localhost:44350/"
}
}
}
+ "Product": {
+ "Destinations": {
+ "Product": {
+ "Address": "http://localhost:44350/"
+ }
+ }
+ }
}
}
```
Afterwards, open the `ProjectNameWebGatewayModule` class in the `WebGateway` and add the `ProductService` to the `ConfigureSwaggerUI` method.
Afterwards, open the `ProjectNameWebGatewayModule` class in the `WebGateway` project and add the `ProductService` to the `ConfigureSwaggerUI` method. In this example we're gonna edit the `BookstoreWebGatewayModule` file.
```diff
private static void ConfigureSwaggerUI(
IProxyConfig proxyConfig,
SwaggerUIOptions options,
IConfiguration configuration)
{
foreach (var cluster in proxyConfig.Clusters)
{
options.SwaggerEndpoint($"/swagger-json/{cluster.ClusterId}/swagger/v1/swagger.json", $"{cluster.ClusterId} API");
}
```csharp
options.OAuthScopes(
"AdministrationService",
"AuthServer",
"IdentityService",
"ProductService" // new service
);
options.OAuthClientId(configuration["AuthServer:SwaggerClientId"]);
options.OAuthScopes(
"AdministrationService",
"AuthServer",
...,
+ "ProductService"
);
}
```
### Configuring the UI Services
We should configure the UI application(s) to allow the new microservice to access through the web gateway. To do this, we should add the new service scope to the `ConfigureAuthentication` method in the `ProjectName...Module` class in the `Web` or `Blazor` application.
We should configure the UI application(s) to allow the new microservice to access through the web gateway. To do this, we should add the new microservice scope to the `ConfigureAuthentication` method in the `ProjectName...Module` class in the `Web` or `Blazor` application. In this example we're gonna edit the `BookstoreWebModule` file.
```csharp
context.Services.AddAuthentication(options =>
{
options.DefaultScheme = "Cookies";
options.DefaultChallengeScheme = "oidc";
})
.AddCookie("Cookies", options =>
{
options.ExpireTimeSpan = TimeSpan.FromDays(365);
})
.AddAbpOpenIdConnect("oidc", options =>
```diff
private void ConfigureAuthentication(ServiceConfigurationContext context, IConfiguration configuration)
{
...
options.Scope.Add("AuthServer");
options.Scope.Add("IdentityService");
options.Scope.Add("AdministrationService");
options.Scope.Add("ProductService"); // new servie
});
context.Services.AddAuthentication(options =>
{
options.DefaultScheme = "Cookies";
options.DefaultChallengeScheme = "oidc";
})
.AddCookie("Cookies", options =>
{
options.ExpireTimeSpan = TimeSpan.FromDays(365);
})
.AddAbpOpenIdConnect("oidc", options =>
{
...
options.Scope.Add("AuthServer");
options.Scope.Add("IdentityService");
options.Scope.Add("AdministrationService");
+ options.Scope.Add("ProductService");
});
...
}
```
Similarly, if you have an Angular application, you should add the new service scope to the `oAuthConfig` in `environment.ts`:
```typescript
```diff
const baseUrl = 'http://localhost:4200';
const oAuthConfig = {
@ -313,69 +341,83 @@ const oAuthConfig = {
redirectUri: baseUrl,
clientId: 'Angular',
responseType: 'code',
scope: 'openid profile email roles AuthServer IdentityService AdministrationService ProductService', // new service
- scope: 'openid profile email roles AuthServer IdentityService AdministrationService',
+ scope: 'openid profile email roles AuthServer IdentityService AdministrationService ProductService',
requireHttps: false
};
```
### Add the New Microservice to the Solution Runner
We should add the new microservice to the solution runner [profile](../../studio/running-applications.md#profile) for running applications in the ABP Studio. You can follow the steps explained in the [Solution Runner](../../studio/running-applications.md#c-application) document to add the new microservice to the solution runner profile. Afterwards, you can start the new microservice by selecting it in the solution runner.
![product-service-solution-runner](images/product-service-solution-runner.png)
## Docker Configuration for Prometheus
If you want to monitor the new microservice with Prometheus when you debug the solution, you should add the new microservice to the `prometheus.yml` file in the `etc/docker/prometheus` folder. You can copy the configurations from the existing microservices and modify them according to the new microservice. Below is an example of the `prometheus.yml` file for the `ProductService` microservice.
If you want to monitor the new microservice with Prometheus when you debug the solution, you should add the new microservice to the `prometheus.yml` file in the `etc/docker/prometheus` folder. You can copy the configurations from the existing microservices and modify them according to the new microservice. Below is an example of the `prometheus.yml` file for the `Product` microservice.
```yml
- job_name: 'product'
```diff
- job_name: 'authserver'
scheme: http
metrics_path: 'metrics'
static_configs:
- targets: ['host.docker.internal:44350']
- targets: ['host.docker.internal:44398']
...
+ - job_name: 'product'
+ scheme: http
+ metrics_path: 'metrics'
+ static_configs:
+ - targets: ['host.docker.internal:44350']
```
## Creating Helm Chart for the New Microservice
If you want to deploy the new microservice to Kubernetes, you should create a Helm chart for the new microservice.
First, we need to add the new microservice to the `build-all-images.ps1` script in the `etc/helm` folder. You can copy the configurations from the existing microservices and modify them according to the new microservice. Below is an example of the `build-all-images.ps1` script for the `ProductService` microservice.
First, we need to add the new microservice to the `build-all-images.ps1` script in the `etc/helm` folder. You can copy the configurations from the existing microservices and modify them according to the new microservice. Below is an example of the `build-all-images.ps1` script for the `Product` microservice.
```powershell
./build-image.ps1 -ProjectPath "../../services/product/Acme.Bookstore.ProductService/Acme.Bookstore.ProductService.csproj" -ImageName bookstore/productservice
```diff
...
./build-image.ps1 -ProjectPath "../../apps/auth-server/Acme.Bookstore.AuthServer/Acme.Bookstore.AuthServer.csproj" -ImageName bookstore/authserver
+ ./build-image.ps1 -ProjectPath "../../services/product/Acme.Bookstore.ProductService/Acme.Bookstore.ProductService.csproj" -ImageName bookstore/product
```
Then, we need to add the connection string to the `values.projectname-local.yaml` file in the `etc/helm/projectname` folder. Below is an example of the `values.bookstore-local.yaml` file for the `ProductService` microservice.
Then, we need to add the connection string to the `values.projectname-local.yaml` file in the `etc/helm/projectname` folder. Below is an example of the `values.bookstore-local.yaml` file for the `Product` microservice.
```yaml
```diff
global:
...
connectionStrings:
...
productService: "Server=[RELEASE_NAME]-sqlserver,1433; Database=Bookstore_ProductService; User Id=sa; Password=myPassw@rd; TrustServerCertificate=True"
+ product: "Server=[RELEASE_NAME]-sqlserver,1433; Database=Bookstore_ProductService; User Id=sa; Password=myPassw@rd; TrustServerCertificate=True"
```
Afterwards, we need to create a new Helm chart for the new microservice. You can copy the configurations from the existing microservices and modify them according to the new microservice. Below is an example of the `productservice` Helm chart for the `ProductService` microservice.
Afterwards, we need to create a new Helm chart for the new microservice. You can copy the configurations from the existing microservices and modify them according to the new microservice. Below is an example of the `product` Helm chart for the `Product` microservice.
Product microservice `values.yaml` file.
{%{
```yaml
# values.yaml
image:
repository: "bookstore/productservice"
repository: "bookstore/product"
tag: "latest"
pullPolicy: IfNotPresent
swagger:
isEnabled: "true"
```
}%}
# Chart.yaml
Product microservice `Chart.yaml` file.
{%{
```yaml
apiVersion: v2
name: productservice
name: product
version: 1.0.0
appVersion: "1.0"
description: Bookstore Product Service
```
}%}
Product microservice `product.yaml` file.
# product.yaml
{%{
```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
@ -404,10 +446,15 @@ spec:
- name: "ConnectionStrings__AbpBlobStoring"
value: "{{ .Values.global.connectionStrings.blobStoring | replace "[RELEASE_NAME]" .Release.Name }}"
- name: "ConnectionStrings__ProductService"
value: "{{ .Values.global.connectionStrings.productService | replace "[RELEASE_NAME]" .Release.Name }}"
value: "{{ .Values.global.connectionStrings.product | replace "[RELEASE_NAME]" .Release.Name }}"
...
```
}%}
# product-service.yaml
Product microservice `product-service.yaml` file.
{%{
```yaml
apiVersion: v1
kind: Service
metadata:
@ -427,32 +474,113 @@ After creating the Helm chart, you can *Refresh Sub Charts* in the ABP Studio.
![kubernetes-refresh-sub-charts](images/kubernetes-refresh-sub-charts.png)
Then, update *Metadata* information right-click the *microservicename* [sub-chart](../../studio/kubernetes.md#subchart), select *Properties* it open *Chart Properties* window. You can edit in the *Metadata* tab.
Then, update *Metadata* information right-click the *microservicename* [sub-chart](../../studio/kubernetes.md#subchart), select *Properties* it open *Chart Properties* window. You should add the following keys in the *Metadata* tab.
![microservice-chart-properties](images/microservice-chart-properties-metadata.png)
- `projectPath`: The path to the microservice host application project. In the bookstore example, this value is `../../services/product/Acme.Bookstore.ProductService/Acme.Bookstore.ProductService.csproj`.
- `imageName`: When we build the Docker image, it uses this value as the Docker image name. We're going to use it in the Helm chart values.
- `projectType`: You can add a Helm chart for Angular and .NET projects, which is why we should explicitly specify the project type.
Add the *Kubernetes Services* in the *Chart Properties* -> *Kubernetes Services* tab.
![microservice-chart-properties-kubernetes-services](images/microservice-chart-properties-kubernetes-services.png)
> This value should be the same as the [solution runner application](./../../studio/running-applications.md#properties) *Kubernetes service* value. It's necessary for browsing because when we connect to the Kubernetes cluster, we should browse the Kubernetes services instead of using the Launch URL.
Last but not least, we need to configure the helm chart environments for identity, auth-server, and gateway applications.
Below is an example of the *Identity* microservice `identity.yaml` file.
{%{
```yaml
# identity.yaml
# Add this line to the "env:" section
- name: "OpenIddict__Resources__ProductService__RootUrl"
value: "http://{{ .Release.Name }}-productservice"
# authserver.yaml
# Concat the following lines for "App__CorsOrigins" section
- name: "App__CorsOrigins"
value: "...,http://{{ .Release.Name }}-administration,http://{{ .Release.Name }}-productservice"
# webapigateway.yaml
# Add this line to the "env:" section
- name: "ReverseProxy__Clusters__ProductService__Destinations__ProductService__Address"
value: "http://{{ .Release.Name }}-productservice"
```diff
apiVersion: apps/v1
kind: Deployment
metadata:
name: "{{ .Release.Name }}-{{ .Chart.Name }}"
spec:
selector:
matchLabels:
app: "{{ .Release.Name }}-{{ .Chart.Name }}"
template:
metadata:
labels:
app: "{{ .Release.Name }}-{{ .Chart.Name }}"
spec:
containers:
- image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
imagePullPolicy: "{{ .Values.image.pullPolicy }}"
name: "{{ .Release.Name }}-{{ .Chart.Name }}"
ports:
- name: "http"
containerPort: 80
env:
...
+ - name: "OpenIddict__Resources__ProductService__RootUrl"
+ value: "http://{{ .Release.Name }}-product"
```
}%}
Below is an example of the *AuthServer* application `authserver.yaml` file.
{%{
```diff
apiVersion: apps/v1
kind: Deployment
metadata:
name: "{{ .Release.Name }}-{{ .Chart.Name }}"
spec:
selector:
matchLabels:
app: "{{ .Release.Name }}-{{ .Chart.Name }}"
template:
metadata:
labels:
app: "{{ .Release.Name }}-{{ .Chart.Name }}"
spec:
containers:
- image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
imagePullPolicy: "{{ .Values.image.pullPolicy }}"
name: "{{ .Release.Name }}-{{ .Chart.Name }}"
ports:
- name: "http"
containerPort: 80
env:
...
- name: "App__CorsOrigins"
- value: "...,http://{{ .Release.Name }}-administration"
+ value: "...,http://{{ .Release.Name }}-administration,http://{{ .Release.Name }}-product"
```
}%}
Below is an example of the *WebApiGateway* application `webapigateway.yaml` file.
{%{
```diff
apiVersion: apps/v1
kind: Deployment
metadata:
name: "{{ .Release.Name }}-{{ .Chart.Name }}"
spec:
selector:
matchLabels:
app: "{{ .Release.Name }}-{{ .Chart.Name }}"
template:
metadata:
labels:
app: "{{ .Release.Name }}-{{ .Chart.Name }}"
spec:
containers:
- image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
imagePullPolicy: "{{ .Values.image.pullPolicy }}"
name: "{{ .Release.Name }}-{{ .Chart.Name }}"
ports:
- name: "http"
containerPort: 80
env:
...
+ - name: "ReverseProxy__Clusters__Product__Destinations__Product__Address"
+ value: "http://{{ .Release.Name }}-product"
```
}%}
@ -465,11 +593,11 @@ You can customize the microservice template if needed. Add new configurations, d
After adding the new microservice to the solution, you can develop the UI for the new microservice. For .NET applications, you can add the microservice *Contracts* package to the UI application(s) to access the services provided by the new microservice. Afterwards, you can use the [generate-proxy](../../cli/index.md#generate-proxy) command to generate the proxy classes for the new microservice.
```bash
abp generate-proxy -t csharp -url http://localhost:44333/ -m productService --without-contracts
abp generate-proxy -t csharp -url http://localhost:44333/ -m product --without-contracts
```
Next, start creating *Pages* and *Components* for the new microservice in the UI application(s). Similarly, if you have an Angular application, you can use the [generate-proxy](../../cli/index.md#generate-proxy) command to generate the proxy classes for the new microservice and start developing the UI.
```bash
abp generate-proxy -t ng -url http://localhost:44333/ -m productService
abp generate-proxy -t ng -url http://localhost:44333/ -m product
```

BIN
docs/en/solution-templates/microservice/images/folder-structure.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

2
docs/en/studio/installation.md

@ -8,7 +8,7 @@
Before you begin the installation process for ABP Studio, ensure that your system meets the following pre-requirements:
### Node
Make sure [Node.js](https://nodejs.org/en) is installed on your system. If you have not installed Node.js, you can download the `v16` or `v18` version from the official [Node.js website](https://nodejs.org/en/download/prebuilt-installer).
Make sure [Node.js](https://nodejs.org/en) is installed on your system. If you have not installed Node.js, you can download the `v18.19+` version from the official [Node.js website](https://nodejs.org/en/download/prebuilt-installer).
### WireGuard (Optional)
ABP Studio needs [WireGuard](https://www.wireguard.com/) for Kubernetes operations. You can find the installation instructions for your specific operating system below:

2
docs/en/tutorials/todo/layered/index.md

@ -53,7 +53,7 @@ This documentation has a video tutorial on **YouTube**!! You can watch it here:
## Pre-Requirements
* An IDE (e.g. [Visual Studio](https://visualstudio.microsoft.com/vs/)) that supports [.NET 8.0+](https://dotnet.microsoft.com/download/dotnet) development.
* [Node v16.x](https://nodejs.org/)
* [Node v18.19+](https://nodejs.org/)
{{if DB=="Mongo"}}

2
docs/en/tutorials/todo/single-layer/index.md

@ -49,7 +49,7 @@ This documentation has a video tutorial on **YouTube**!! You can watch it here:
## Pre-Requirements
* An IDE (e.g. [Visual Studio](https://visualstudio.microsoft.com/vs/)) that supports [.NET 8.0+](https://dotnet.microsoft.com/download/dotnet) development.
* [Node v16.x](https://nodejs.org/)
* [Node v18.19+](https://nodejs.org/)
{{if DB=="Mongo"}}

12
framework/src/Volo.Abp.AspNetCore.Abstractions/Volo/Abp/AspNetCore/Authentication/AbpAspNetCoreTokenUnauthorizedErrorInfo.cs

@ -0,0 +1,12 @@
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.AspNetCore.Authentication;
public class AbpAspNetCoreTokenUnauthorizedErrorInfo : IScopedDependency
{
public string? Error { get; set; }
public string? ErrorDescription { get; set; }
public string? ErrorUri { get; set; }
}

28
framework/src/Volo.Abp.AspNetCore.Authentication.JwtBearer/Microsoft/Extensions/DependencyInjection/AbpJwtBearerExtensions.cs

@ -1,6 +1,7 @@
using System;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Volo.Abp.AspNetCore.Authentication;
using Volo.Abp.Security.Claims;
namespace Microsoft.Extensions.DependencyInjection;
@ -31,6 +32,33 @@ public static class AbpJwtBearerExtensions
return builder.AddJwtBearer(authenticationScheme, displayName, options =>
{
configureOptions?.Invoke(options);
options.Events ??= new JwtBearerEvents();
var previousOnChallenge = options.Events.OnChallenge;
options.Events.OnChallenge = async eventContext =>
{
await previousOnChallenge(eventContext);
if (eventContext.Handled ||
!string.IsNullOrEmpty(eventContext.Error) ||
!string.IsNullOrEmpty(eventContext.ErrorDescription) ||
!string.IsNullOrEmpty(eventContext.ErrorUri))
{
return;
}
var tokenUnauthorizedErrorInfo = eventContext.HttpContext.RequestServices.GetRequiredService<AbpAspNetCoreTokenUnauthorizedErrorInfo>();
if (string.IsNullOrEmpty(tokenUnauthorizedErrorInfo.Error) &&
string.IsNullOrEmpty(tokenUnauthorizedErrorInfo.ErrorDescription) &&
string.IsNullOrEmpty(tokenUnauthorizedErrorInfo.ErrorUri))
{
return;
}
eventContext.Error = tokenUnauthorizedErrorInfo.Error;
eventContext.ErrorDescription = tokenUnauthorizedErrorInfo.ErrorDescription;
eventContext.ErrorUri = tokenUnauthorizedErrorInfo.ErrorUri;
};
});
}
}

1
framework/src/Volo.Abp.AspNetCore.Authentication.JwtBearer/Volo.Abp.AspNetCore.Authentication.JwtBearer.csproj

@ -19,6 +19,7 @@
<ItemGroup>
<ProjectReference Include="..\Volo.Abp.Security\Volo.Abp.Security.csproj" />
<ProjectReference Include="..\Volo.Abp.Caching\Volo.Abp.Caching.csproj" />
<ProjectReference Include="..\Volo.Abp.AspNetCore.Abstractions\Volo.Abp.AspNetCore.Abstractions.csproj" />
</ItemGroup>
<ItemGroup>

3
framework/src/Volo.Abp.AspNetCore.Authentication.JwtBearer/Volo/Abp/AspNetCore/Authentication/JwtBearer/AbpAspNetCoreAuthenticationJwtBearerModule.cs

@ -7,7 +7,7 @@ using Volo.Abp.Security.Claims;
namespace Volo.Abp.AspNetCore.Authentication.JwtBearer;
[DependsOn(typeof(AbpSecurityModule), typeof(AbpCachingModule))]
[DependsOn(typeof(AbpSecurityModule), typeof(AbpCachingModule), typeof(AbpAspNetCoreAbstractionsModule))]
public class AbpAspNetCoreAuthenticationJwtBearerModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
@ -21,5 +21,6 @@ public class AbpAspNetCoreAuthenticationJwtBearerModule : AbpModule
context.Services.AddTransient<WebRemoteDynamicClaimsPrincipalContributor>();
context.Services.AddTransient<WebRemoteDynamicClaimsPrincipalContributorCache>();
}
}
}

2
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardBodyTagHelperService.cs

@ -32,7 +32,7 @@ public class AbpCardBodyTagHelperService : AbpTagHelperService<AbpCardBodyTagHel
if (!TagHelper.Subtitle.IsNullOrWhiteSpace())
{
var cardSubtitle = new TagBuilder(AbpCardSubtitleTagHelper.DefaultHeading.ToHtmlTag());
cardSubtitle.AddCssClass("card-subtitle text-muted mb-2");
cardSubtitle.AddCssClass("card-subtitle mb-2");
cardSubtitle.InnerHtml.AppendHtml(TagHelper.Subtitle!);
output.PreContent.AppendHtml(cardSubtitle);
}

2
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpSelectTagHelperService.cs

@ -250,7 +250,7 @@ public class AbpSelectTagHelperService : AbpTagHelperService<AbpSelectTagHelper>
var small = new TagBuilder("small");
small.Attributes.Add("id", idAttr?.Value?.ToString() + "InfoText");
small.AddCssClass("form-text text-muted");
small.AddCssClass("form-text");
small.InnerHtml.Append(localizedText);
return small.ToHtmlString();

15
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/Volo/Abp/AspNetCore/Mvc/UI/Bundling/AbpAspNetCoreMvcUiBundlingModule.cs

@ -1,4 +1,6 @@
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap;
using Volo.Abp.AspNetCore.Mvc.Libs;
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap;
using Volo.Abp.Data;
using Volo.Abp.Minify;
using Volo.Abp.Modularity;
@ -11,5 +13,14 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bundling;
)]
public class AbpAspNetCoreMvcUiBundlingModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
if (!context.Services.IsDataMigrationEnvironment())
{
Configure<AbpMvcLibsOptions>(options =>
{
options.CheckLibs = true;
});
}
}
}

10
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Packages/Volo/Abp/AspNetCore/Mvc/UI/Packages/DatatablesNet/DatatablesNetScriptContributor.cs

@ -10,6 +10,14 @@ public class DatatablesNetScriptContributor : BundleContributor
{
public override void ConfigureBundle(BundleConfigurationContext context)
{
context.Files.AddIfNotContains("/libs/datatables.net/js/jquery.dataTables.js");
if (context.FileProvider.GetFileInfo("/libs/datatables.net/js/dataTables.min.js").Exists)
{
context.Files.AddIfNotContains("/libs/datatables.net/js/dataTables.min.js");
}
else
{
//TODO: Compatible code, Remove it after 8.3 rc1.
context.Files.AddIfNotContains("/libs/datatables.net/js/jquery.dataTables.js");
}
}
}

19
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/datatables/datatables-extensions.js

@ -90,7 +90,7 @@ var abp = abp || {};
return "";
}
var $button = $('<button type="button" class="btn btn-primary abp-action-button"></button>');
var $button = $('<button type="button" class="btn btn-primary btn-sm abp-action-button"></button>');
if (firstItem.displayNameHtml) {
$button.html(abp.utils.isFunction(firstItem.text) ? firstItem.text(record, tableInstance) : firstItem.text);
@ -240,10 +240,17 @@ var abp = abp || {};
if (tableInstance.aoColumns) {
columns = tableInstance.aoColumns;
} else {
} else if (abp.utils.isFunction(tableInstance.fnSettings)) {
columns = tableInstance.fnSettings().aoColumns;
}
if (!columns && abp.utils.isFunction(tableInstance.api)) {
var settings = tableInstance.api().settings();
if (settings.length === 1 && settings[0].aoColumns) {
columns = settings[0].aoColumns;
}
}
if (!columns) {
return;
}
@ -271,8 +278,9 @@ var abp = abp || {};
}
};
var _existingApiRenderRowActionsFunction = $.fn.dataTableExt.oApi.renderRowActions;
$.fn.dataTableExt.oApi.renderRowActions =
if ($.fn.dataTableExt.oApi) {
var _existingApiRenderRowActionsFunction = $.fn.dataTableExt.oApi.renderRowActions;
$.fn.dataTableExt.oApi.renderRowActions =
function (tableInstance, nRow, aData, iDisplayIndex, iDisplayIndexFull) {
if (_existingApiRenderRowActionsFunction) {
_existingApiRenderRowActionsFunction(tableInstance, nRow, aData, iDisplayIndex, iDisplayIndexFull);
@ -280,7 +288,8 @@ var abp = abp || {};
renderRowActions(tableInstance, nRow, aData, iDisplayIndex, iDisplayIndexFull);
};
}
if (!$.fn.dataTable) {
return;
}

7
framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcModule.cs

@ -32,6 +32,7 @@ using Volo.Abp.AspNetCore.Mvc.DataAnnotations;
using Volo.Abp.AspNetCore.Mvc.DependencyInjection;
using Volo.Abp.AspNetCore.Mvc.Infrastructure;
using Volo.Abp.AspNetCore.Mvc.Json;
using Volo.Abp.AspNetCore.Mvc.Libs;
using Volo.Abp.AspNetCore.Mvc.Localization;
using Volo.Abp.AspNetCore.VirtualFileSystem;
using Volo.Abp.DependencyInjection;
@ -231,6 +232,7 @@ public class AbpAspNetCoreMvcModule : AbpModule
public override void OnApplicationInitialization(ApplicationInitializationContext context)
{
AddApplicationParts(context);
CheckLibs(context);
}
private static void AddApplicationParts(ApplicationInitializationContext context)
@ -277,4 +279,9 @@ public class AbpAspNetCoreMvcModule : AbpModule
partManager.ApplicationParts.AddIfNotContains(moduleAssembly);
}
}
private static void CheckLibs(ApplicationInitializationContext context)
{
context.ServiceProvider.GetRequiredService<IAbpMvcLibsService>().CheckLibs(context);
}
}

16
framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ExceptionHandling/AbpExceptionFilter.cs

@ -75,10 +75,18 @@ public class AbpExceptionFilter : IAsyncExceptionFilter, IAbpFilter, ITransientD
}
else
{
context.HttpContext.Response.Headers.Add(AbpHttpConsts.AbpErrorFormat, "true");
context.HttpContext.Response.StatusCode = (int)context
.GetRequiredService<IHttpExceptionStatusCodeFinder>()
.GetStatusCode(context.HttpContext, context.Exception);
if (!context.HttpContext.Response.HasStarted)
{
context.HttpContext.Response.Headers.Add(AbpHttpConsts.AbpErrorFormat, "true");
context.HttpContext.Response.StatusCode = (int)context
.GetRequiredService<IHttpExceptionStatusCodeFinder>()
.GetStatusCode(context.HttpContext, context.Exception);
}
else
{
var logger = context.GetService<ILogger<AbpExceptionFilter>>(NullLogger<AbpExceptionFilter>.Instance)!;
logger.LogWarning("HTTP response has already started, cannot set headers and status code!");
}
context.Result = new ObjectResult(new RemoteServiceErrorResponse(remoteServiceErrorInfo));
}

15
framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ExceptionHandling/AbpExceptionPageFilter.cs

@ -103,10 +103,17 @@ public class AbpExceptionPageFilter : IAsyncPageFilter, IAbpFilter, ITransientDe
}
else
{
context.HttpContext.Response.Headers.Add(AbpHttpConsts.AbpErrorFormat, "true");
context.HttpContext.Response.StatusCode = (int)context
.GetRequiredService<IHttpExceptionStatusCodeFinder>()
.GetStatusCode(context.HttpContext, context.Exception!);
if (!context.HttpContext.Response.HasStarted)
{
context.HttpContext.Response.Headers.Add(AbpHttpConsts.AbpErrorFormat, "true");
context.HttpContext.Response.StatusCode = (int)context
.GetRequiredService<IHttpExceptionStatusCodeFinder>()
.GetStatusCode(context.HttpContext, context.Exception!);
}
else
{
logger.LogWarning("HTTP response has already started, cannot set headers and status code!");
}
context.Result = new ObjectResult(new RemoteServiceErrorResponse(remoteServiceErrorInfo));
}

6
framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Libs/AbpMvcLibsOptions.cs

@ -0,0 +1,6 @@
namespace Volo.Abp.AspNetCore.Mvc.Libs;
public class AbpMvcLibsOptions
{
public bool CheckLibs { get; set; }
}

93
framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Libs/AbpMvcLibsService.cs

@ -0,0 +1,93 @@
using System;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Microsoft.Extensions.FileProviders;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.AspNetCore.Mvc.Libs;
public class AbpMvcLibsService : IAbpMvcLibsService, ITransientDependency
{
private Task<bool>? _checkLibsTask;
public virtual void CheckLibs(ApplicationInitializationContext context)
{
var options = context.ServiceProvider.GetRequiredService<IOptions<AbpMvcLibsOptions>>().Value;
if (options.CheckLibs)
{
var app = context.GetApplicationBuilderOrNull();
if (app == null)
{
var logger = context.ServiceProvider.GetRequiredService<ILogger<AbpMvcLibsService>>();
logger.LogWarning($"The {nameof(IApplicationBuilder)} is not available. The 'CheckLibs' feature is disabled!");
return;
}
app.Use(async (httpContext, next) =>
{
if (!await CheckLibsAsyncOnceAsync(httpContext))
{
httpContext.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
httpContext.Response.ContentType = "text/html";
await httpContext.Response.WriteAsync(
"<html>" +
" <head>" +
" <title>Error - The Libs folder is missing!</title>" +
" </head>" +
" <body>" +
" <h1> &#9888;&#65039; The Libs folder under the <code style='background-color: #e7e7e7;'>wwwroot/libs</code> directory is empty!</h1>" +
" <p>The Libs folder contains mandatory NPM Packages for running the project.</p>" +
" <p>Make sure you run the <code style='background-color: #e7e7e7;'>abp install-libs</code> CLI tool command.</p>" +
" <p>For more information, check out the <a href='https://abp.io/docs/latest/CLI#install-libs'>ABP CLI documentation</a></p>" +
" </body>" +
"</html>",
Encoding.UTF8
);
return;
}
await next(httpContext);
});
}
}
protected virtual Task<bool> CheckLibsAsyncOnceAsync(HttpContext httpContext)
{
if (_checkLibsTask == null)
{
_checkLibsTask = CheckLibsAsync(httpContext);
}
return _checkLibsTask;
}
protected virtual Task<bool> CheckLibsAsync(HttpContext httpContext)
{
var logger = httpContext.RequestServices.GetRequiredService<ILogger<AbpMvcLibsService>>();
try
{
var fileProvider = new PhysicalFileProvider(httpContext.RequestServices.GetRequiredService<IWebHostEnvironment>().WebRootPath);
var libsFolder = fileProvider.GetDirectoryContents("/libs");
if (!libsFolder.Exists || !libsFolder.Any())
{
logger.LogError("The 'wwwroot/libs' folder does not exist or empty!");
return Task.FromResult(false);
}
}
catch (Exception e)
{
// In case of any exception, log it and return true to prevent crashing the application.
logger.LogError(e, "An error occurred while checking the libs folder!");
}
return Task.FromResult(true);
}
}

6
framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Libs/IAbpMvcLibsService.cs

@ -0,0 +1,6 @@
namespace Volo.Abp.AspNetCore.Mvc.Libs;
public interface IAbpMvcLibsService
{
void CheckLibs(ApplicationInitializationContext context);
}

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

@ -102,6 +102,7 @@ public static class AbpApplicationBuilderExtensions
return app.UseMiddleware<AbpExceptionHandlingMiddleware>();
}
[Obsolete("Replace with AbpClaimsTransformation")]
public static IApplicationBuilder UseAbpClaimsMap(this IApplicationBuilder app)
{
return app.UseMiddleware<AbpClaimsMapMiddleware>();

8
framework/src/Volo.Abp.AspNetCore/Microsoft/Extensions/DependencyInjection/AbpAspNetCoreServiceCollectionExtensions.cs

@ -1,6 +1,7 @@
using System.Linq;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Hosting;
using Volo.Abp.AspNetCore.Security.Claims;
namespace Microsoft.Extensions.DependencyInjection;
@ -20,4 +21,9 @@ public static class AbpAspNetCoreServiceCollectionExtensions
return hostingEnvironment;
}
public static IServiceCollection TransformAbpClaims(this IServiceCollection services)
{
return services.AddTransient<IClaimsTransformation, AbpClaimsTransformation>();
}
}

9
framework/src/Volo.Abp.AspNetCore/Volo/Abp/ApplicationInitializationContextExtensions.cs

@ -12,7 +12,14 @@ public static class ApplicationInitializationContextExtensions
{
public static IApplicationBuilder GetApplicationBuilder(this ApplicationInitializationContext context)
{
return context.ServiceProvider.GetRequiredService<IObjectAccessor<IApplicationBuilder>>().Value!;
var applicationBuilder = context.ServiceProvider.GetRequiredService<IObjectAccessor<IApplicationBuilder>>().Value;
Check.NotNull(applicationBuilder, nameof(applicationBuilder));
return applicationBuilder;
}
public static IApplicationBuilder? GetApplicationBuilderOrNull(this ApplicationInitializationContext context)
{
return context.ServiceProvider.GetRequiredService<IObjectAccessor<IApplicationBuilder>>().Value;
}
public static IWebHostEnvironment GetEnvironment(this ApplicationInitializationContext context)

4
framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Security/Claims/AbpClaimsMapMiddleware.cs

@ -1,4 +1,5 @@
using System.Linq;
using System;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
@ -10,6 +11,7 @@ using Volo.Abp.Security.Claims;
namespace Volo.Abp.AspNetCore.Security.Claims;
[Obsolete("Replace with AbpClaimsTransformation")]
public class AbpClaimsMapMiddleware : AbpMiddlewareBase, ITransientDependency
{
public async override Task InvokeAsync(HttpContext context, RequestDelegate next)

35
framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Security/Claims/AbpClaimsTransformation.cs

@ -0,0 +1,35 @@
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication;
using Microsoft.Extensions.Options;
namespace Volo.Abp.AspNetCore.Security.Claims;
public class AbpClaimsTransformation : IClaimsTransformation
{
protected IOptions<AbpClaimsMapOptions> AbpClaimsMapOptions { get; }
public AbpClaimsTransformation(IOptions<AbpClaimsMapOptions> abpClaimsMapOptions)
{
AbpClaimsMapOptions = abpClaimsMapOptions;
}
public virtual Task<ClaimsPrincipal> TransformAsync(ClaimsPrincipal principal)
{
var mapClaims = principal.Claims.Where(claim => AbpClaimsMapOptions.Value.Maps.Keys.Contains(claim.Type));
principal.AddIdentity(new ClaimsIdentity(mapClaims.Select(
claim => new Claim(
AbpClaimsMapOptions.Value.Maps[claim.Type](),
claim.Value,
claim.ValueType,
claim.Issuer
)
)
)
);
return Task.FromResult(principal);
}
}

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

Loading…
Cancel
Save