Browse Source

Merge branch 'dev' into maliming/Auditing

pull/2652/head
Halil İbrahim Kalkan 7 years ago
parent
commit
d9b7e3aef0
  1. 2
      abp_io/AbpIoLocalization/AbpIoLocalization/AbpIoLocalization.csproj
  2. 13
      abp_io/AbpIoLocalization/AbpIoLocalization/Account/Localization/Resources/zh-Hant.json
  3. 32
      abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json
  4. 29
      abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/zh-Hans.json
  5. 60
      abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/zh-Hant.json
  6. 31
      abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/zh-Hant.json
  7. 5
      abp_io/AbpIoLocalization/AbpIoLocalization/Blog/Localization/Resources/zh-Hant.json
  8. 3
      abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json
  9. 30
      abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/zh-Hant.json
  10. 5
      abp_io/AbpIoLocalization/AbpIoLocalization/Docs/Localization/Resources/zh-Hant.json
  11. 5
      abp_io/AbpIoLocalization/AbpIoLocalization/Support/Localization/Resources/zh-Hant.json
  12. 159
      abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/zh-Hant.json
  13. 40
      build-all-release.ps1
  14. 40
      build-all.ps1
  15. 16
      build/build-all-release.ps1
  16. 16
      build/build-all.ps1
  17. 34
      build/common.ps1
  18. 16
      build/test-all.ps1
  19. 2
      common.props
  20. 9
      configureawait.props
  21. 18
      docs/cs/CLI.md
  22. 77
      docs/cs/Entity-Framework-Core-PostgreSQL.md
  23. 59
      docs/cs/docs-nav.json
  24. BIN
      docs/cs/images/docs-section-ui.png
  25. 3
      docs/en/Ambient-Context-Pattern.md
  26. 87
      docs/en/Audit-Logging.md
  27. 42
      docs/en/Background-Jobs-Hangfire.md
  28. 58
      docs/en/Blog-Posts/2020-01-15 v2_0_Release/Post.md
  29. BIN
      docs/en/Blog-Posts/2020-01-15 v2_0_Release/abp-commercial-demo.png
  30. BIN
      docs/en/Blog-Posts/2020-01-15 v2_0_Release/abp-io-abpcommercial-release.png
  31. BIN
      docs/en/Blog-Posts/2020-01-15 v2_0_Release/lepton-theme-material.png
  32. BIN
      docs/en/Blog-Posts/2020-01-15 v2_0_Release/ndc-2020-volosoft-booth-wall.png
  33. BIN
      docs/en/Blog-Posts/2020-01-15 v2_0_Release/ndc-london-volosoft.png
  34. 29
      docs/en/Contribution/Localization-Text-Files.md
  35. 173
      docs/en/Entities.md
  36. 6
      docs/en/Modules/Audit-Logging.md
  37. 6
      docs/en/Modules/Docs.md
  38. 20
      docs/en/Modules/Index.md
  39. 2
      docs/en/Modules/Setting-Management.md
  40. 2
      docs/en/Tutorials/Angular/Part-I.md
  41. 18
      docs/en/Tutorials/AspNetCore-Mvc/Part-I.md
  42. 3
      docs/en/Tutorials/AspNetCore-Mvc/Part-II.md
  43. 18
      docs/en/Tutorials/AspNetCore-Mvc/Part-III.md
  44. 3
      docs/pt-BR/Tutorials/AspNetCore-Mvc/Part-II.md
  45. 164
      docs/zh-Hans/Blog-Posts/2020-01-15 v2_0_Release/Post.md
  46. BIN
      docs/zh-Hans/Blog-Posts/2020-01-15 v2_0_Release/abp-commercial-demo.png
  47. BIN
      docs/zh-Hans/Blog-Posts/2020-01-15 v2_0_Release/lepton-theme-material.png
  48. BIN
      docs/zh-Hans/Blog-Posts/2020-01-15 v2_0_Release/ndc-2020-volosoft-booth-wall.png
  49. BIN
      docs/zh-Hans/Blog-Posts/2020-01-15 v2_0_Release/ndc-london-volosoft.png
  50. 3
      docs/zh-Hans/Tutorials/AspNetCore-Mvc/Part-II.md
  51. 3
      framework/src/Volo.Abp.ApiVersioning.Abstractions/FodyWeavers.xml
  52. 30
      framework/src/Volo.Abp.ApiVersioning.Abstractions/FodyWeavers.xsd
  53. 1
      framework/src/Volo.Abp.ApiVersioning.Abstractions/Volo.Abp.ApiVersioning.Abstractions.csproj
  54. 3
      framework/src/Volo.Abp.AspNetCore.Authentication.JwtBearer/FodyWeavers.xml
  55. 30
      framework/src/Volo.Abp.AspNetCore.Authentication.JwtBearer/FodyWeavers.xsd
  56. 4
      framework/src/Volo.Abp.AspNetCore.Authentication.JwtBearer/Microsoft/AspNetCore/Builder/JwtTokenMiddleware.cs
  57. 3
      framework/src/Volo.Abp.AspNetCore.Authentication.JwtBearer/Volo.Abp.AspNetCore.Authentication.JwtBearer.csproj
  58. 3
      framework/src/Volo.Abp.AspNetCore.Authentication.OAuth/FodyWeavers.xml
  59. 30
      framework/src/Volo.Abp.AspNetCore.Authentication.OAuth/FodyWeavers.xsd
  60. 5
      framework/src/Volo.Abp.AspNetCore.Authentication.OAuth/Volo.Abp.AspNetCore.Authentication.OAuth.csproj
  61. 3
      framework/src/Volo.Abp.AspNetCore.MultiTenancy/FodyWeavers.xml
  62. 30
      framework/src/Volo.Abp.AspNetCore.MultiTenancy/FodyWeavers.xsd
  63. 3
      framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo.Abp.AspNetCore.MultiTenancy.csproj
  64. 8
      framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/MultiTenancyMiddleware.cs
  65. 3
      framework/src/Volo.Abp.AspNetCore.Mvc.Client/FodyWeavers.xml
  66. 30
      framework/src/Volo.Abp.AspNetCore.Mvc.Client/FodyWeavers.xsd
  67. 3
      framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo.Abp.AspNetCore.Mvc.Client.csproj
  68. 4
      framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/CachedApplicationConfigurationClient.cs
  69. 2
      framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/RemoteFeatureChecker.cs
  70. 2
      framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/RemoteLanguageProvider.cs
  71. 4
      framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/RemotePermissionChecker.cs
  72. 4
      framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/RemoteSettingProvider.cs
  73. 12
      framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/RemoteTenantStore.cs
  74. 3
      framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/FodyWeavers.xml
  75. 30
      framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/FodyWeavers.xsd
  76. 3
      framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo.Abp.AspNetCore.Mvc.Contracts.csproj
  77. 3
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/FodyWeavers.xml
  78. 30
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/FodyWeavers.xsd
  79. 2
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Breadcrumb/AbpBreadcrumbTagHelperService.cs
  80. 2
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Carousel/AbpCarouselTagHelperService.cs
  81. 2
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Collapse/AbpAccordionItemTagHelperService.cs
  82. 2
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Collapse/AbpAccordionTagHelperService.cs
  83. 2
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Collapse/AbpCollapseBodyTagHelperService.cs
  84. 12
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Dropdown/AbpDropdownButtonTagHelperService.cs
  85. 4
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Extensions/TagHelperExtensions.cs
  86. 20
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpDynamicformTagHelperService.cs
  87. 16
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpInputTagHelperService.cs
  88. 16
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpSelectTagHelperService.cs
  89. 2
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Grid/AbpColumnTagHelperService.cs
  90. 18
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Pagination/AbpPaginationTagHelperService.cs
  91. 2
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Tab/AbpTabDropdownTagHelperService.cs
  92. 2
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Tab/AbpTabTagHelperService.cs
  93. 10
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Tab/AbpTabsTagHelperService.cs
  94. 3
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.csproj
  95. 3
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/FodyWeavers.xml
  96. 30
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/FodyWeavers.xsd
  97. 3
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/Volo.Abp.AspNetCore.Mvc.UI.Bundling.csproj
  98. 12
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/Volo/Abp/AspNetCore/Mvc/UI/Bundling/BundleManager.cs
  99. 2
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/Volo/Abp/AspNetCore/Mvc/UI/Bundling/TagHelpers/AbpBundleItemTagHelperService.cs
  100. 6
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/Volo/Abp/AspNetCore/Mvc/UI/Bundling/TagHelpers/AbpBundleTagHelperService.cs

2
abp_io/AbpIoLocalization/AbpIoLocalization/AbpIoLocalization.csproj

@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>

13
abp_io/AbpIoLocalization/AbpIoLocalization/Account/Localization/Resources/zh-Hant.json

@ -0,0 +1,13 @@
{
"culture": "zh-Hant",
"texts": {
"Account": "帳號",
"Welcome": "歡迎",
"UseOneOfTheFollowingLinksToContinue": "使用下面的連結繼續",
"FrameworkHomePage": "框架首頁",
"FrameworkDocumentation": "框架文件",
"OfficialBlog": "官方部落格",
"CommercialHomePage": "商業版首頁",
"CommercialSupportWebSite": "商業版支援網站"
}
}

32
abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json

@ -1,6 +1,8 @@
{
"culture": "en",
"texts": {
"Permission:Organizations": "Organizations",
"Permission:Manage": "Manage Organizations",
"Permission:NpmPackages": "NPM Packages",
"Permission:NugetPackages": "Nuget Packages",
"Permission:Maintenance": "Maintenance",
@ -11,6 +13,7 @@
"Permission:Edit": "Edit",
"Permission:Delete": "Delete",
"Permission:Create": "Create",
"Menu:Organizations": "Organizations",
"Menu:Packages": "Packages",
"NpmPackageDeletionWarningMessage": "This NPM Package will be deleted. Do you confirm that?",
"NugetPackageDeletionWarningMessage": "This Nuget Package will be deleted. Do you confirm that?",
@ -34,7 +37,7 @@
"NugetPackageTarget.HttpApi": "Http Api",
"NugetPackageTarget.HttpApiClient": "Http Api Client",
"NugetPackageTarget.Web": "Web",
"NugetPackageTarget.EntityFrameworkCore": "EntityFramework Core",
"NugetPackageTarget.EntityFrameworkCore": "DeleteAllEntityFramework Core",
"NugetPackageTarget.MongoDB": "MongoDB",
"Edit": "Edit",
"Delete": "Delete",
@ -55,6 +58,31 @@
"Menu:NpmPackages": "NPM Packages",
"Menu:Modules": "Modules",
"Menu:Maintenance": "Maintenance",
"Menu:NugetPackages": "Nuget Packages"
"Menu:NugetPackages": "Nuget Packages",
"CreateAnOrganization": "Create an organization",
"Organizations": "Organizations",
"LongName": "Long name",
"LicenseType": "License type",
"LicenseStartTime": "License start time",
"LicenseEndTime": "License end time",
"AllowedDeveloperCount": "Allowed developer count",
"UserNameOrEmailAddress": "Username or email address",
"AddOwner": "Add owner",
"UserName": "Username",
"Email": "Email",
"Developers": "Developers",
"AddDeveloper": "Add developer",
"Create": "Create",
"UserNotFound": "User not found",
"{0}WillBeRemovedFromMembers": "{0} Will be removed from members",
"Computers": "Computers",
"UniqueComputerId": "Unique computer id",
"LastSeenDate": "Last seen date",
"{0}Computer{1}WillBeRemovedFromRecords": "Computer of {0} ({1}) will be removed from records",
"OrganizationDeletionWarningMessage": "Organization will be deleted",
"This{0}AlreadyExistInThisOrganization": "This {0} already exist in this organization",
"AreYouSureYouWantToDeleteAllComputers": "Are you sure you want to delete all computers?",
"DeleteAll": "Delete all",
"DoYouWantToCreateNewUser": "Do you want to create new user?"
}
}

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

@ -1,6 +1,8 @@
{
"culture": "zh-Hans",
"texts": {
"Permission:Organizations": "组织",
"Permission:Manage": "管理组织",
"Permission:NpmPackages": "NPM包",
"Permission:NugetPackages": "Nuget包",
"Permission:Maintenance": "维护",
@ -11,6 +13,7 @@
"Permission:Edit": "编辑",
"Permission:Delete": "删除",
"Permission:Create": "创建",
"Menu:Organizations": "组织",
"Menu:Packages": "包",
"NpmPackageDeletionWarningMessage": "该NPM包将会被删除. 你确定吗?",
"NugetPackageDeletionWarningMessage": "该Nuget包将会被删除. 你确定吗?",
@ -55,6 +58,30 @@
"Menu:NpmPackages": "NPM包",
"Menu:Modules": "模块",
"Menu:Maintenance": "维护",
"Menu:NugetPackages": "Nuget包"
"Menu:NugetPackages": "Nuget包",
"CreateAnOrganization": "创建新组织",
"Organizations": "组织",
"LongName": "完整名称",
"LicenseType": "授权类型",
"LicenseStartTime": "授权开始时间",
"LicenseEndTime": "授权结束时间",
"AllowedDeveloperCount": "允许的开发人员数量",
"UserNameOrEmailAddress": "用户名或电子邮件地址",
"AddOwner": "添加所有者",
"UserName": "用户名",
"Email": "电子邮件地址",
"Developers": "开发者",
"AddDeveloper": "添加开发者",
"Create": "创建",
"UserNotFound": "用户不存在",
"{0}WillBeRemovedFromMembers": "{0} 将从成员中删除",
"Computers": "计算机",
"UniqueComputerId": "计算机唯一ID",
"LastSeenDate": "上次查看日期",
"{0}Computer{1}WillBeRemovedFromRecords": "计算机 {0} ({1}) 将从记录中删除",
"OrganizationDeletionWarningMessage": "组织将被删除",
"This{0}AlreadyExistInThisOrganization": "该组织中已经存在此 {0}",
"AreYouSureYouWantToDeleteAllComputers": "您确定要删除所有计算机吗?",
"DeleteAll": "删除所有"
}
}

60
abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/zh-Hant.json

@ -0,0 +1,60 @@
{
"culture": "zh-Hant",
"texts": {
"Permission:NpmPackages": "NPM套件",
"Permission:NugetPackages": "Nuget套件",
"Permission:Maintenance": "維護",
"Permission:Maintain": "維護",
"Permission:ClearCaches": "清除快取",
"Permission:Modules": "模組",
"Permission:Packages": "套件",
"Permission:Edit": "編輯",
"Permission:Delete": "刪除",
"Permission:Create": "建立",
"Menu:Packages": "套件",
"NpmPackageDeletionWarningMessage": "該NPM套件將會被刪除. 你確定嗎?",
"NugetPackageDeletionWarningMessage": "該Nuget套件將會被刪除. 你確定嗎?",
"ModuleDeletionWarningMessage": "該模組將會被刪除. 你確定嗎?",
"Name": "名稱",
"DisplayName": "顯示名稱",
"ShortDescription": "簡述",
"NameFilter": "名稱",
"CreationTime": "建立時間",
"IsPro": "是否為專業版",
"EfCoreConfigureMethodName": "設定方法",
"IsProFilter": "是否為專業版",
"ApplicationType": "應用程式類型",
"Target": "目標",
"TargetFilter": "目標",
"ModuleClass": "模組分類",
"NugetPackageTarget.DomainShared": "Domain Shared",
"NugetPackageTarget.Domain": "Domain",
"NugetPackageTarget.Application": "Application",
"NugetPackageTarget.ApplicationContracts": "Application Contracts",
"NugetPackageTarget.HttpApi": "Http Api",
"NugetPackageTarget.HttpApiClient": "Http Api Client",
"NugetPackageTarget.Web": "Web",
"NugetPackageTarget.EntityFrameworkCore": "EntityFramework Core",
"NugetPackageTarget.MongoDB": "MongoDB",
"Edit": "編輯",
"Delete": "刪除",
"Refresh": "刷新",
"NpmPackages": "NPM套件",
"NugetPackages": "Nuget套件",
"NpmPackageCount": "NPM套件數量",
"NugetPackageCount": "Nuget套件數量",
"Module": "模組",
"ModuleInfo": "模組信息",
"CreateANpmPackage": "建立NPM套件",
"CreateAModule": "建立模組",
"CreateANugetPackage": "建立Nuget套件",
"AddNew": "建立",
"PackageAlreadyExist{0}": "\"{0}\"已經被添加.",
"ClearCache": "清除快取",
"SuccessfullyCleared": "清除成功",
"Menu:NpmPackages": "NPM套件",
"Menu:Modules": "模組",
"Menu:Maintenance": "維護",
"Menu:NugetPackages": "Nuget套件"
}
}

31
abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/zh-Hant.json

@ -0,0 +1,31 @@
{
"culture": "zh-Hant",
"texts": {
"Volo.AbpIo.Domain:010004": "超過最大成員數!",
"Volo.AbpIo.Domain:010005": "超過最大擁有者數!",
"Volo.AbpIo.Domain:010006": "使用者已經是該組織的擁有者!",
"Volo.AbpIo.Domain:010007": "該使用者已經是該組織的開發者!",
"Volo.AbpIo.Domain:010008": "允許的開發者數量不能低於當前開發者數量!",
"Volo.AbpIo.Domain:010009": "允許的開發者數量不能小於零!",
"Volo.AbpIo.Domain:010010": "超出了最大mac地址數!",
"Volo.AbpIo.Domain:010011": "個人許可不允許超過1個開發者!",
"Volo.AbpIo.Domain:010012": "許可過期後許可不可延長1個月!",
"Volo.AbpIo.Domain:020001": "不能刪除該NPM套件因為\"{NugetPackages}\"Nuget套件依賴此套件.",
"Volo.AbpIo.Domain:020002": "不能刪除該NPM套件因為\"{Modules}\"模組正在使用此套件.",
"Volo.AbpIo.Domain:020003": "不能刪除該NPM套件因為\"{Modules}\"模組正在使用此套件並且\"{NugetPackages}\"Nuget套件依賴此套件.",
"Volo.AbpIo.Domain:020004": "不能刪除該Nuget套件因為\"{Modules}\"模組正在使用此套件.",
"WantToLearn?": "想學習嗎?",
"ReadyToGetStarted?": "準備開始了嗎?",
"JoinOurCommunity": "加入我們的社群",
"GetStartedUpper": "開始",
"ForkMeOnGitHub": "Fork me on GitHub",
"Features": "功能",
"GetStarted": "開始",
"Documents": "文件",
"Community": "社群",
"ContributionGuide": "貢獻指南",
"Blog": "部落格",
"Commercial": "商業版",
"SeeDocuments": "查看文件"
}
}

5
abp_io/AbpIoLocalization/AbpIoLocalization/Blog/Localization/Resources/zh-Hant.json

@ -0,0 +1,5 @@
{
"culture": "zh-Hant",
"texts": {
}
}

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

@ -26,6 +26,7 @@
"MyOrganizations": "My organizations",
"ApiKey": "API key",
"UserNameNotFound": "There is no user with username {0}",
"SuccessfullyAddedToNewsletter": "Thanks you for subscribing to our newsletter!"
"SuccessfullyAddedToNewsletter": "Thanks you for subscribing to our newsletter!",
"ManageProfile": "Manage your profile"
}
}

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

@ -0,0 +1,30 @@
{
"culture": "zh-Hant",
"texts": {
"OrganizationManagement": "組織管理",
"OrganizationList": "組織列表",
"Volo.AbpIo.Commercial:010003": "您不是該組織的擁有者!",
"OrganizationNotFoundMessage": "找不到任何組織!",
"DeveloperCount": "開發者數量",
"Owners": "擁有者",
"AddMember": "加入成員",
"AddOwner": "加入擁有者",
"AddDeveloper": "加入開發者",
"UserName": "使用者名稱",
"Name": "名稱",
"EmailAddress": "電子信箱地址",
"Developers": "開發者",
"LicenseType": "許可證類型",
"Manage": "管理",
"StartDate": "開始日期",
"EndDate": "結束日期",
"Modules": "模組",
"LicenseExtendMessage": "您的許可已經延長至{0}",
"LicenseUpgradeMessage": "您的許可已升級為{0}",
"LicenseAddDeveloperMessage": "{0}個開發者已加入到您的許可",
"Volo.AbpIo.Commercial:010004": "不能找到指定的使用者! 使用者必須已經註冊.",
"MyOrganizations": "我的組織",
"ApiKey": "API key",
"UserNameNotFound": "沒有使用者名稱為{0}的使用者"
}
}

5
abp_io/AbpIoLocalization/AbpIoLocalization/Docs/Localization/Resources/zh-Hant.json

@ -0,0 +1,5 @@
{
"culture": "zh-Hant",
"texts": {
}
}

5
abp_io/AbpIoLocalization/AbpIoLocalization/Support/Localization/Resources/zh-Hant.json

@ -0,0 +1,5 @@
{
"culture": "zh-Hant",
"texts": {
}
}

159
abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/zh-Hant.json

@ -0,0 +1,159 @@
{
"culture": "zh-Hant",
"texts": {
"GetStarted": "開始",
"Create": "建立",
"NewProject": "新專案",
"DirectDownload": "直接下載",
"ProjectName": "專案名稱",
"ProjectType": "專案類型",
"DatabaseProvider": "資料庫提供者",
"NTier": "N層",
"IncludeUserInterface": "包含使用者介面",
"CreateNow": "現在建立",
"TheStartupProject": "起始專案",
"Tutorial": "教學",
"UsingCLI": "使用CLI",
"SeeDetails": "看詳細",
"AbpShortDescription": "ABP是用於建立現代Web應用程式的完整架構和強大的基礎設施! 遵循最佳實作和約定,為您提供SOLID開發經驗.",
"SourceCodeUpper": "原始碼",
"LatestReleaseLogs": "最新發佈日誌",
"Infrastructure": "基礎設施",
"Architecture": "架構",
"Modular": "模組化",
"DontRepeatYourself": "不要重複工作",
"DeveloperFocused": "專注於開發者",
"FullStackApplicationInfrastructure": "全端應用程式基礎設施",
"DomainDrivenDesign": "領域驅動設計",
"DomainDrivenDesignExplanation": "依據DDD模式和準則進行設計和開發. 為您的應用程式提供分層模型.",
"Authorization": "授權",
"AuthorizationExplanation": "具有使用者,角色和細膩度權限系統的高級授權. 建立於Microsoft Identity套件上.",
"MultiTenancy": "多租戶",
"MultiTenancyExplanationShort": "SaaS應用程式變得簡單! 從資料庫到UI的多租戶整合.",
"CrossCuttingConcerns": "橫切關注點",
"CrossCuttingConcernsExplanationShort": "完整的基礎架構,用於授權,驗證,異常處理,快取,稽核日誌,交易管理等.",
"BuiltInBundlingMinification": "內建Bundling & Minification",
"BuiltInBundlingMinificationExplanation": "無須使用外部工具進行Bundling & Minification. ABP提供了一種更簡單,動態,功能強大,模組化和內建的方式!",
"VirtualFileSystem": "虛擬文件系統",
"VirtualFileSystemExplanation": "將檢視,腳本,樣式,圖片...嵌入到套件/類別庫中,並在不同的應用程式中重複使用.",
"Theming": "主題",
"ThemingExplanationShort": "使用和訂製基於bootstrap的標準UI主題,或建立自己的主題.",
"BootstrapTagHelpersDynamicForms": "Bootstrap Tag Helpers和動態表單",
"BootstrapTagHelpersDynamicFormsExplanation": "內建的背景作業系統可以整合到Hangfire,RabbitMQ或您喜歡的任何工具中.", //TODO explanation doesn't match.
"HTTPAPIsDynamicProxies": "HTTP APIs和動態代理",
"HTTPAPIsDynamicProxiesExplanation": "自動將應用程式服務公開為REST樣式的HTTP API,並與動態JavaScript和C#代理一起使用.",
"CompleteArchitectureInfo": "現在架構用來建立可維護的軟體解決方案.",
"DomainDrivenDesignBasedLayeringModelExplanation": "幫助您實現基於DDD的分層架構並建構可維護的程式碼.",
"DomainDrivenDesignBasedLayeringModelExplanationCont": "提供啟動模板,抽象,基礎類別,服務,文件和指南以幫助您開發基於DDD模式和準則的應用程式.",
"MicroserviceCompatibleModelExplanation": "核心框架和預先建構模組在設計時就考慮了微服務架構.",
"MicroserviceCompatibleModelExplanationCont": "提供基礎結構,整合,範例和文件,以更輕鬆地實現微服務解決方案,而如果您要使用整體應用程式,也不會帶來額外的複雜性.",
"ModularInfo": "ABP提供了完整的模組化系統,使您能夠開發可重複使用的應用程式模組.",
"PreBuiltModulesThemes": "預先建構模組和主題",
"PreBuiltModulesThemesExplanation": "開源和商業模組和主題已準備好在您的業務應用程式中使用.",
"NuGetNPMPackages": "NuGet和NPM套件",
"NuGetNPMPackagesExplanation": "作為NuGet和NPM套件發佈.易於安裝和升級.",
"ExtensibleReplaceable": "可擴展/可替換",
"ExtensibleReplaceableExplanation": "所有服務和模組在設計時都考慮了可擴展性.您可以替換服務,頁面,樣式,組件...",
"CrossCuttingConcernsExplanation2": "保持原始碼整潔,專注於您自己的業務邏輯.",
"CrossCuttingConcernsExplanation3": "不要浪費時間一次又一次地實作共通用的應用程式需求.",
"AuthenticationAuthorization": "認證與授權",
"ExceptionHandling": "異常處理",
"Validation": "驗證",
"DatabaseConnection": "資料庫連接",
"TransactionManagement": "交易管理",
"AuditLogging": "稽核日誌",
"Caching": "快取",
"Multitenancy": "多租戶",
"DataFiltering": "資料過濾",
"ConventionOverConfiguration": "習慣優於設定",
"ConventionOverConfigurationExplanation": "預設情況下,ABP使用最小或零設定實現共通用的應用程式.",
"ConventionOverConfigurationExplanationList1": "自動註冊已知服務以進行依賴注入.",
"ConventionOverConfigurationExplanationList2": "通過命名習慣將應用程式服務公開為HTTP API.",
"ConventionOverConfigurationExplanationList3": "為C#和JavaScript建立動態HTTP客戶端代理.",
"ConventionOverConfigurationExplanationList4": "為您的實體提供預設Repository.",
"ConventionOverConfigurationExplanationList5": "根據Web請求或應用程式服務方法管理工作單元.",
"ConventionOverConfigurationExplanationList6": "為實體發佈建立,更新和刪除事件.",
"BaseClasses": "基礎類別",
"BaseClassesExplanation": "共通用應用程式模式的預先建構基礎類別.",
"DeveloperFocusedExplanation": "ABP是為了開發者",
"DeveloperFocusedExplanationCont": "它旨在簡化您的日常軟體開發,同時又不限制您在需要時進行底層工作。",
"SeeAllFeatures": "瀏覽所有功能",
"CLI_CommandLineInterface": "CLI (命令列介面)",
"CLI_CommandLineInterfaceExplanation": "CLI會自動建立新專案並將模組添加到您的應用程式.",
"StartupTemplates": "起始模板",
"StartupTemplatesExplanation": "各種起始模板為您提供了完整設定的解結方案,以快速啟動您的開發.",
"BasedOnFamiliarTools": "基於熟悉的工具",
"BasedOnFamiliarToolsExplanation": "建立在您已經知道的主流工具上並與其整合.學習曲線低,適應性強,舒適的開發.",
"ORMIndependent": "ORM獨立",
"ORMIndependentExplanation": "核心框架獨立於ORM/資料庫,並且可以與任何資料庫一起使用.Entity Framework Core和MongoDB提供者已經可用.",
"Features": "功能",
"ABPCLI": "ABP CLI",
"Modularity": "模組化",
"BootstrapTagHelpers": "Bootstrap Tag Helpers",
"DynamicForms": "動態表單",
"BundlingMinification": "Bundling & Minification",
"BackgroundJobs": "背景作業",
"DDDInfrastructure": "DDD基礎設施",
"DomainDrivenDesignInfrastructure": "Domain Driven Design基礎設施",
"AutoRESTAPIs": "自動REST APIs",
"DynamicClientProxies": "動態客戶端代理",
"DistributedEventBus": "分散式事件匯流排",
"DistributedEventBusWithRabbitMQIntegration": "具有RabbitMQ整合的分散式事件匯流排",
"TestInfrastructure": "測試基礎設施",
"AuditLoggingEntityHistories": "稽核日誌和實體歷史",
"ObjectToObjectMapping": "物件對應",
"EmailSMSAbstractions": "電子郵件和簡訊抽象",
"EmailSMSAbstractionsWithTemplatingSupport": "具有模板支援的電子郵件和簡訊抽象",
"Localization": "本地化",
"SettingManagement": "設定管理",
"ExtensionMethods": "擴充方法",
"ExtensionMethodsHelpers": "擴充方法和助手",
"AspectOrientedProgramming": "切面導向設計",
"DependencyInjection": "依賴注入",
"DependencyInjectionByConventions": "依照習慣的依賴注入",
"ABPCLIExplanation": "ABP CLI(命令列介面)是用於對ABP解決方案執行常見操作的命令列工具.",
"ModularityExplanation": "ABP提供了一個完整的基礎設施來建構您自己的應用程式模組,這些模組可能具有實體,服務,資料庫整合,API,UI組件等.", //TODO: strong "your own application modules",-
"MultiTenancyExplanation": "ABP框建不僅支援開發多租戶應用程式,而且使您的程式碼幾乎無須知道多租戶.",
"MultiTenancyExplanation2": "可以自動確定當前租戶,將不同租戶的資料互相隔離.",
"MultiTenancyExplanation3": "支援單一資料庫,或每個租戶單獨資料庫或者混合方式.",
"MultiTenancyExplanation4": "您專注於業務邏輯,並讓該框架為您處理多租戶.",
"BootstrapTagHelpersExplanation": "與其手動撰寫重複細節的bootstrap組件,不如使用ABP的tag helper來簡化它並利用自動完成.您當然也可以在需要時直接使用Bootstrap.",
"DynamicFormsExplanation": "動態表單和tag helpers可以利用C#類別做為模型來建立完整的表單.",
"AuthenticationAuthorizationExplanation": "整合到ASP.NET Core Identity和IdentityServer4的豐富身份驗證和授權選項.提供可擴展且詳細的權限系統.",
"CrossCuttingConcernsExplanation": "部要重複資幾一次又一次地實作所有這寫常見的東西.專注於您的業務邏輯,並讓ABP按照習慣自動執行.",
"DatabaseConnectionTransactionManagement": "資料庫連接和交易管理",
"CorrelationIdTracking": "關聯ID追蹤",
"BundlingMinificationExplanation": "ABP提供了一個簡單,動態,功能強大,模組化的內建Bundling & Minification系統.",
"VirtualFileSystemnExplanation": "虛擬文件系統使管理文件系統(硬碟)上不存在的文件成為可能.它主要用於將(js,css,image,cshtml...)文件嵌入到組件(Assembly)中,並在運行時像實體文件一樣使用他們.",
"ThemingExplanation": "主題系統允許通過基於最新的Bootstrap框架定義一組通用基礎類別庫和佈局來獨立開發應用程式和模組主題.",
"DomainDrivenDesignInfrastructureExplanation": "基於領域驅動設計模式和準則建構分層應用程式的完整基礎設施;",
"Specification": "規範",
"Repository": "倉儲",
"DomainService": "領域服務",
"ValueObject": "值對象",
"ApplicationService": "應用服務",
"DataTransferObject": "資料傳輸對象",
"AggregateRootEntity": "聚合根, 實體",
"AutoRESTAPIsExplanation": "ABP可以依照習慣自動將您的應用服務設定為API控制器.",
"DynamicClientProxiesExplanation": "從JavaScript和C#客戶端輕鬆使用您的API.",
"DistributedEventBusWithRabbitMQIntegrationExplanation": "使用帶有RabbitMQ整合的內建分散式事件匯流排,可以輕鬆發佈和使用分散式事件.",
"TestInfrastructureExplanation": "框架已經考慮了單元和整合測試.為您提供基礎類別,使其更容易.起始模板已預先設定用於測試.",
"AuditLoggingEntityHistoriesExplanation": "針對關鍵業務應用的內建稽核日誌紀錄.請求,服務,方法級別的稽核日誌紀錄以及具有屬性級別詳細資訊的實體歷史紀錄.",
"EmailSMSAbstractionsWithTemplatingSupportExplanation": "IEmailSender和ISmsSender抽象使您的應用程式邏輯與基礎設施解耦.先進的電子郵件模板系統允許建立和在地化電子郵件模板,並在需要實輕鬆使用.",
"LocalizationExplanation": "在地化系統允許在純JSON文件中建立資源,並使用它們來在地化UI.它支援繼承,擴展和JavaScript整合等高級方案,同時與AspNet Core的在地化系統完全兼容.",
"SettingManagementExplanation": "定義應用程式的設定,並根據當前設定,租戶和使用者在運行時獲取值.",
"ExtensionMethodsHelpersExplanation": "即使式瑣碎的程式碼部分,也不要重複.標準類型的擴展方法和助手使您的程式碼更加清晰和易於撰寫.",
"AspectOrientedProgrammingExplanation": "提供合適的基礎設施來建立動態代理並實現切面導向設計.攔截任何類別,並在每次方法執行之前和之後執行程式碼.",
"DependencyInjectionByConventionsExplanation": "無須手動註冊類別以進行依賴注入.按照習慣自動註冊常用服務類型.對於其他類型的服務,您可以使用介面和屬性來使其變得更輕鬆.",
"DataFilteringExplanation": "定義和使用資料過濾器,這些過濾器在您從資料庫中查詢實體時會自動應用.當您實現簡單的介面時,可立即使用軟刪除功能和多租戶過濾器.",
"PublishEvents": "發佈事件",
"HandleEvents": "處理事件",
"AndMore": "更多...",
"Code": "編碼",
"Result": "結果",
"SeeTheDocumentForMoreInformation": "查看<a href=\"{1}\">{0} 文件</a>獲得更多訊息",
"IndexPageHeroSection": "<span class=\"third-line shine2\"><strong>asp.net core的</strong></span><span class=\"first-line shine\"><strong>開源</strong></span><span class=\"second-line text-uppercase\">Web應用程式<br />框架 </span>",
"UiFramework": "UI框架",
"EmailAddress": "電子信箱地址"
}
}

40
build-all-release.ps1

@ -1,40 +0,0 @@
# COMMON PATHS
$rootFolder = (Get-Item -Path "./" -Verbose).FullName
# List of solutions
$solutionPaths = (
"framework",
"modules/users",
"modules/permission-management",
"modules/setting-management",
"modules/feature-management",
"modules/identity",
"modules/identityserver",
"modules/tenant-management",
"modules/account",
"modules/docs",
"modules/blogging",
"modules/audit-logging",
"modules/background-jobs",
"modules/client-simulation",
"templates/module/aspnet-core",
"templates/app/aspnet-core",
"abp_io/AbpIoLocalization"
)
# Build all solutions
foreach ($solutionPath in $solutionPaths) {
$solutionAbsPath = (Join-Path $rootFolder $solutionPath)
Set-Location $solutionAbsPath
dotnet build --configuration Release
if (-Not $?) {
Write-Host ("Build failed for the solution: " + $solutionPath)
Set-Location $rootFolder
exit $LASTEXITCODE
}
}
Set-Location $rootFolder

40
build-all.ps1

@ -1,40 +0,0 @@
# COMMON PATHS
$rootFolder = (Get-Item -Path "./" -Verbose).FullName
# List of solutions
$solutionPaths = (
"framework",
"modules/users",
"modules/permission-management",
"modules/setting-management",
"modules/feature-management",
"modules/identity",
"modules/identityserver",
"modules/tenant-management",
"modules/account",
"modules/docs",
"modules/blogging",
"modules/audit-logging",
"modules/background-jobs",
"modules/client-simulation",
"templates/module/aspnet-core",
"templates/app/aspnet-core",
"abp_io/AbpIoLocalization"
)
# Build all solutions
foreach ($solutionPath in $solutionPaths) {
$solutionAbsPath = (Join-Path $rootFolder $solutionPath)
Set-Location $solutionAbsPath
dotnet build
if (-Not $?) {
Write-Host ("Build failed for the solution: " + $solutionPath)
Set-Location $rootFolder
exit $LASTEXITCODE
}
}
Set-Location $rootFolder

16
build/build-all-release.ps1

@ -0,0 +1,16 @@
. ".\common.ps1"
# Build all solutions
foreach ($solutionPath in $solutionPaths) {
$solutionAbsPath = (Join-Path $rootFolder $solutionPath)
Set-Location $solutionAbsPath
dotnet build --configuration Release
if (-Not $?) {
Write-Host ("Build failed for the solution: " + $solutionPath)
Set-Location $rootFolder
exit $LASTEXITCODE
}
}
Set-Location $rootFolder

16
build/build-all.ps1

@ -0,0 +1,16 @@
. ".\common.ps1"
# Build all solutions
foreach ($solutionPath in $solutionPaths) {
$solutionAbsPath = (Join-Path $rootFolder $solutionPath)
Set-Location $solutionAbsPath
dotnet build
if (-Not $?) {
Write-Host ("Build failed for the solution: " + $solutionPath)
Set-Location $rootFolder
exit $LASTEXITCODE
}
}
Set-Location $rootFolder

34
build/common.ps1

@ -0,0 +1,34 @@
# COMMON PATHS
$rootFolder = (Get-Item -Path "./" -Verbose).FullName
# List of solutions
$solutionPaths = (
"../framework",
"../modules/users",
"../modules/permission-management",
"../modules/setting-management",
"../modules/feature-management",
"../modules/identity",
"../modules/identityserver",
"../modules/tenant-management",
"../modules/account",
"../modules/docs",
"../modules/blogging",
"../modules/audit-logging",
"../modules/background-jobs",
"../modules/client-simulation",
"../templates/module/aspnet-core",
"../templates/app/aspnet-core",
"../samples/BasicAspNetCoreApplication",
"../samples/BasicConsoleApplication",
"../samples/BookStore",
"../samples/BookStore-Angular-MongoDb/aspnet-core",
"../samples/BookStore-Modular/modules/book-management",
"../samples/BookStore-Modular/application",
"../samples/DashboardDemo",
"../samples/MicroserviceDemo",
"../samples/RabbitMqEventBus",
"../abp_io/AbpIoLocalization"
)

16
build/test-all.ps1

@ -0,0 +1,16 @@
. ".\common.ps1"
# Test all solutions
foreach ($solutionPath in $solutionPaths) {
$solutionAbsPath = (Join-Path $rootFolder $solutionPath)
Set-Location $solutionAbsPath
dotnet test --no-build --no-restore
if (-Not $?) {
Write-Host ("Test failed for the solution: " + $solutionPath)
Set-Location $rootFolder
exit $LASTEXITCODE
}
}
Set-Location $rootFolder

2
common.props

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

9
configureawait.props

@ -0,0 +1,9 @@
<Project>
<ItemGroup>
<PackageReference Include="ConfigureAwait.Fody" Version="3.3.1" />
<PackageReference Include="Fody" Version="6.0.6">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
</ItemGroup>
</Project>

18
docs/cs/CLI.md

@ -129,6 +129,24 @@ abp update [možnosti]
* `--npm`: Aktualizuje pouze balíčky NPM.
* `--nuget`: Aktualizuje pouze balíčky NuGet.
### login
Některé funkce CLI vyžadují přihlášení k platformě abp.io. Chcete-li se přihlásit pomocí svého uživatelského jména, napište
```bash
abp login <username>
```
Všimněte si, že nové přihlášení s již aktivní relací ukončí předchozí relaci a vytvoří novou.
### logout
Odhlásí vás odebráním tokenu relace z počítače.
```
abp logout
```
### help
Vypíše základní informace k používání CLI.

77
docs/cs/Entity-Framework-Core-PostgreSQL.md

@ -1,74 +1,39 @@
## Entity Framework Core PostgreSQL integrace
# Přepnutí na EF Core PostgreSQL providera
> Podívejte se na [Entity Framework Core integrační dokument](../Entity-Framework-Core.md) pro základy integrace EF Core.
Tento dokument vysvětluje, jak přepnout na poskytovatele databáze **PostgreSQL** pro **[spouštěcí šablonu aplikace](Startup-Templates/Application.md)**, která je dodávána s předem nakonfigurovaným SQL poskytovatelem.
### Aktualizace projektu EntityFrameworkCore
## Výměna balíku Volo.Abp.EntityFrameworkCore.SqlServer
- V projektu `Acme.BookStore.EntityFrameworkCore` nahraďte balík `Volo.Abp.EntityFrameworkCore.SqlServer` za `Volo.Abp.EntityFrameworkCore.PostgreSql`
- Aktualizace pro použití PostgreSQL v `BookStoreEntityFrameworkCoreModule`
- Nahraďte `AbpEntityFrameworkCoreSqlServerModule` za `AbpEntityFrameworkCorePostgreSqlModule`
- Nahraďte `options.UseSqlServer()` za `options.UsePostgreSql()`
- V jiných projektech aktualizujte PostgreSQL connection string v nezbytných `appsettings.json` souborech
- Více informací v [PostgreSQL connection strings](https://www.connectionstrings.com/postgresql/), v tomto dokumentu věnujte pozornost sekci `Npgsql`
Projekt `.EntityFrameworkCore` v řešení závisí na NuGet balíku [Volo.Abp.EntityFrameworkCore.SqlServer](https://www.nuget.org/packages/Volo.Abp.EntityFrameworkCore.SqlServer). Odstraňte tento balík a přidejte stejnou verzi balíku [Volo.Abp.EntityFrameworkCore.PostgreSql](https://www.nuget.org/packages/Volo.Abp.EntityFrameworkCore.PostgreSql).
### Aktualizace projektu EntityFrameworkCore.DbMigrations
- Aktualizace pro použití PostgreSQL v `XXXMigrationsDbContextFactory`
- Nahraďte `new DbContextOptionsBuilder<XXXMigrationsDbContext>().UseSqlServer()` za `new DbContextOptionsBuilder<XXXMigrationsDbContext>().UseNpgsql()`
## Nahrazení závislosti modulu
Najděte třídu ***YourProjectName*EntityFrameworkCoreModule** v projektu `.EntityFrameworkCore`, odstraňte `typeof(AbpEntityFrameworkCoreSqlServerModule)` z atributu `DependsOn`, přidejte `typeof(AbpEntityFrameworkCorePostgreSqlModule)` (také nahraďte `using Volo.Abp.EntityFrameworkCore.SqlServer;` za `using Volo.Abp.EntityFrameworkCore.PostgreSql;`).
### Odstranění stávajících migrací
## UsePostgreSql()
Smažte všechny stavající migrační soubory (včetně `DbContextModelSnapshot`)
Najděte volání `UseSqlServer()` v *YourProjectName*EntityFrameworkCoreModule.cs uvnitř projektu `.EntityFrameworkCore` a nahraďte za `UsePostgreSql()`.
![postgresql-delete-initial-migrations](images/postgresql-delete-initial-migrations.png)
Najděte volání `UseSqlServer()` v *YourProjectName*MigrationsDbContextFactory.cs uvnitř projektu `.EntityFrameworkCore.DbMigrations` a nahraďte za `UseNpgsql()`.
### Znovu vygenerujte počáteční migraci
> V závislosti na struktuře řešení můžete najít více volání `UseSqlServer()`, které je třeba změnit.
Nastavte správný spouštěcí projekt (obvykle web projekt)
## Změna connection stringů
![set-as-startup-project](../images/set-as-startup-project.png)
PostgreSql connection stringy se od těch pro SQL Server liší. Je proto potřeba zkontrolovat všechny soubory `appsettings.json` v řešení a connection stringy v nich nahradit. Podívejte se na [connectionstrings.com](https://www.connectionstrings.com/postgresql/) pro více detailů o možnostech PostgreSql connection stringů.
Otevřete **Package Manager Console** (Tools -> Nuget Package Manager -> Package Manager Console), zvolte `.EntityFrameworkCore.DbMigrations` jako **Default project** a proveďte následující příkaz:
Typicky je potřeba změnit `appsettings.json` v projektech `.DbMigrator` a `.Web` projects, ale to záleží na vaší struktuře řešení.
Proveďte příkaz `Add-Migration`:
````
PM> Add-Migration Initial
````
## Regenerace migrací
### Aktualizace databáze
Startovací šablona používá [Entity Framework Core Code First migrace](https://docs.microsoft.com/en-us/ef/core/managing-schemas/migrations/). EF Core migrace závisí na zvoleném DBMS poskytovateli. Tudíž změna DBMS poskytovatele způsobí selhání migrace.
* Smažte složku Migrations v projektu `.EntityFrameworkCore.DbMigrations` and znovu sestavte řešení.
* Spusťte `Add-Migration "Initial"` v Package Manager Console (je nutné zvolit `.DbMigrator` (nebo `.Web`) projekt jako startovací projekt v Solution Explorer a zvolit projekt `.EntityFrameworkCore.DbMigrations` jako výchozí v Package Manager Console).
K vytvoření databáze máte dvě možnosti.
Tímto vytvoříte migraci databáze se všemi nakonfigurovanými databázovými objekty (tabulkami).
#### Použití DbMigrator aplikace
Spusťte projekt `.DbMigrator` k vytvoření databáze a vložení počátečních dat.
Řešení obsahuje konzolovou aplikaci (v tomto příkladu nazvanou `Acme.BookStore.DbMigrator`), která může vytvářet databáze, aplikovat migrace a vkládat seed data. Je užitečná jak pro vývojové, tak pro produkční prostředí.
## Spuštění aplikace
> Projekt `.DbMigrator` má vlastní `appsettings.json`. Takže pokud jste změnili connection string uvedený výše, musíte změnit také tento.
Klikněte pravým na projekt `.DbMigrator` a vyberte **Set as StartUp Project**:
![set-as-startup-project](images/set-as-startup-project.png)
Zmáčkněte F5 (nebo Ctrl+F5) ke spuštění aplikace. Výstup bude vypadat následovně:
![set-as-startup-project](images/db-migrator-app.png)
#### Použití EF Core Update-Database příkazu
Ef Core má `Update-Database` příkaz, který v případě potřeby vytvoří databázi a aplikuje čekající migrace.
Nastavte správný spouštěcí projekt (obvykle web projekt)
![set-as-startup-project](../images/set-as-startup-project.png)
Otevřete **Package Manager Console** (Tools -> Nuget Package Manager -> Package Manager Console), vyberte projekt `.EntityFrameworkCore.DbMigrations` jako **Default Project** and spusťte následující příkaz:
````
PM> Update-Database
````
Dojde k vytvoření nové databáze na základě nakonfigurovaného connection stringu.
![postgresql-update-database](images/postgresql-update-database.png)
> Použití nástroje `.DbMigrator` je doporučený způsob, jelikož zároveň vloží seed data nutné k správnému běhu webové aplikace.
Vše je připraveno. Stačí už jen spustit aplikaci a užívat si kódování.

59
docs/cs/docs-nav.json

@ -60,6 +60,10 @@
"text": "Konfigurace",
"path": "Configuration.md"
},
{
"text": "Možnosti",
"path": "Options.md"
},
{
"text": "Vkládání závislostí",
"path": "Dependency-Injection.md",
@ -83,7 +87,14 @@
"path": "Exception-Handling.md"
},
{
"text": "Validace"
"text": "Validace",
"path": "Validation.md",
"items": [
{
"text": "FluentValidation integrace",
"path": "FluentValidation.md"
}
]
},
{
"text": "Autorizace",
@ -257,24 +268,46 @@
},
{
"text": "Přístup k datům",
"path": "Data-Access.md",
"items": [
{
"text": "Entity Framework Core integrace",
"path": "Entity-Framework-Core.md",
"text": "Connection stringy",
"path": "Connection-Strings.md"
},
{
"text": "Poskytovatelé databází",
"items": [
{
"text": "PostgreSQL integrace",
"path": "Entity-Framework-Core-PostgreSQL.md"
"text": "Entity Framework Core",
"path": "Entity-Framework-Core.md",
"items": [
{
"text": "Přepnutí na MySQL",
"path": "Entity-Framework-Core-MySQL.md"
},
{
"text": "Přepnutí na PostgreSQL",
"path": "Entity-Framework-Core-PostgreSQL.md"
},
{
"text": "Přepnutí na SQLite",
"path": "Entity-Framework-Core-SQLite.md"
},
{
"text": "Přepnutí na jiný DBMS",
"path": "Entity-Framework-Core-Other-DBMS.md"
}
]
},
{
"text": "MongoDB",
"path": "MongoDB.md"
},
{
"text": "Dapper",
"path": "Dapper.md"
}
]
},
{
"text": "MongoDB integrace",
"path": "MongoDB.md"
},
{
"text": "Dapper integrace",
"path": "Dapper.md"
}
]
},

BIN
docs/cs/images/docs-section-ui.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

3
docs/en/Ambient-Context-Pattern.md

@ -0,0 +1,3 @@
## Ambient Context Pattern
TODO

87
docs/en/Audit-Logging.md

@ -14,6 +14,11 @@ An **audit log object** (see the Audit Log Object section below) is typically cr
> [Startup templates](Startup-Templates/Index.md) are configured for the audit logging system which is suitable for most of the applications. Use this document for a detailed control over the audit log system.
### Database Provider Support
* Fully supported by the [Entity Framework Core](Entity-Framework-Core.md) provider.
* Entity change logging is not supported by the [MongoDB](MongoDB.md) provider. Other features work as expected.
## UseAuditing()
`UseAuditing()` middleware should be added to the ASP.NET Core request pipeline in order to create and save the audit logs. If you've created your applications using [the startup templates](Startup-Templates/Index.md), it is already added.
@ -199,7 +204,7 @@ public class MyUser : Entity<Guid>
## Audit Log Object
An **audit log object** is created for each **web request** is by default. An audit log object can be represented by the following relation diagram:
An **audit log object** is created for each **web request** by default. An audit log object can be represented by the following relation diagram:
![**auditlog-object-diagram**](images/auditlog-object-diagram.png)
@ -214,7 +219,7 @@ An **audit log object** is created for each **web request** is by default. An au
* `ClientId`: Id of the current client, if the client has been authenticated. A client is generally a 3rd-party application using the system over an HTTP API.
* `ClientName`: Name of the current client, if available.
* `ClientIpAddress`: IP address of the client/user device.
* `CorrelationId`: Current [Correlation Id]((CorrelationId.md)). Correlation Id is used to relate the audit logs written by different applications (or microservices) in a single logical operation.
* `CorrelationId`: Current [Correlation Id](CorrelationId.md). Correlation Id is used to relate the audit logs written by different applications (or microservices) in a single logical operation.
* `BrowserInfo`: Browser name/version info of the current user, if available.
* `HttpMethod`: HTTP method of the current request (GET, POST, PUT, DELETE... etc.).
* `HttpStatusCode`: HTTP response status code for this request.
@ -282,6 +287,84 @@ Configure<AbpAuditingOptions>(options =>
});
````
## IAuditLogScope & IAuditingManager
This section explains the `IAuditLogScope` & `IAuditingManager` services for advanced use cases.
An **audit log scope** is an [ambient scope](Ambient-Context-Pattern.md) that **builds** and **saves** an audit log object (explained before). By default, an audit log scope is created for a web request by the Audit Log Middleware (see `UseAuditing()` section above).
### Access to the Current Audit Log Scope
Audit log contributors, was explained above, is a global way of manipulating the audit log object. It is good if you can get a value from a service.
If you need to manipulate the audit log object in an arbitrary point of your application, you can access to the current audit log scope and get the current audit log object (independent of how the scope is managed). Example:
````csharp
public class MyService : ITransientDependency
{
private readonly IAuditingManager _auditingManager;
public MyService(IAuditingManager auditingManager)
{
_auditingManager = auditingManager;
}
public async Task DoItAsync()
{
var currentAuditLogScope = _auditingManager.Current;
if (currentAuditLogScope != null)
{
currentAuditLogScope.Log.Comments.Add(
"Executed the MyService.DoItAsync method :)"
);
currentAuditLogScope.Log.SetProperty("MyCustomProperty", 42);
}
}
}
````
Always check if `_auditingManager.Current` is null or not, because it is controlled in an outer scope and you can't know if an audit log scope was created before calling your method.
### Manually Create an Audit Log Scope
You rarely need to create a manual audit log scope, but if you need, you can create an audit log scope using the `IAuditingManager` as like in the following example:
````csharp
public class MyService : ITransientDependency
{
private readonly IAuditingManager _auditingManager;
public MyService(IAuditingManager auditingManager)
{
_auditingManager = auditingManager;
}
public async Task DoItAsync()
{
using (var auditingScope = _auditingManager.BeginScope())
{
try
{
//Call other services...
}
catch (Exception ex)
{
//Add exceptions
_auditingManager.Current.Log.Exceptions.Add(ex);
}
finally
{
//Always save the log
await auditingScope.SaveAsync();
}
}
}
}
````
You can call other services, they may call others, they may change entities and so on. All these interactions are saved as a single audit log object in the finally block.
## The Audit Logging Module
The Audit Logging Module basically implements the `IAuditingStore` to save the audit log objects to a database. It supports multiple database providers. This module is added to the startup templates by default.

42
docs/en/Background-Jobs-Hangfire.md

@ -1,3 +1,43 @@
# Hangfire Background Job Manager
TODO
[Hangfire](https://www.hangfire.io/) is an advanced background job manager. You can integrate Hangfire with the ABP Framework to use it instead of the [default background job manager](Background-Jobs.md). In this way, you can use the same background job API for Hangfire and your code will be independent of Hangfire. If you like, you can directly use Hangfire's API, too.
> See the [background jobs document](Background-Jobs.md) to learn how to use the background job system. This document only shows how to install and configure the Hangfire integration.
## Installation
It is suggested to use the [ABP CLI](CLI.md) to install this package.
### Using the ABP CLI
Open a command line window in the folder of the project (.csproj file) and type the following command:
````bash
abp add-package Volo.Abp.BackgroundJobs.HangFire
````
### Manual Installation
If you want to manually install;
1. Add the [Volo.Abp.BackgroundJobs.HangFire](https://www.nuget.org/packages/Volo.Abp.BackgroundJobs.HangFire) NuGet package to your project:
````
Install-Package Volo.Abp.BackgroundJobs.HangFire
````
2. Add the `AbpBackgroundJobsHangfireModule` to the dependency list of your module:
````csharp
[DependsOn(
//...other dependencies
typeof(AbpBackgroundJobsHangfireModule) //Add the new module dependency
)]
public class YourModule : AbpModule
{
}
````
## Configuration
TODO...

58
docs/en/Blog-Posts/2020-01-15 v2_0_Release/Post.md

@ -1,8 +1,8 @@
# ABP Framework v2.0 and the ABP Commercial
ABP Framework v2.0 has been released this week. This post explains why we have released an **early major version** and what is changed with version 2.0.
ABP Framework v2.0 has been released in this week. This post explains why we have released an **early major version** and what is changed with version 2.0.
In addition to the v2.0 release, we have also announced **ABP Commercial** which is a set of professional modules, tools, themes, and services built on top of the open-source ABP framework.
In addition to the v2.0 release, we are excited to announce the **ABP Commercial**, which is a set of professional modules, tools, themes, and services built on top of the open-source ABP framework.
## ABP Framework v2.0
@ -12,7 +12,7 @@ It was planned to release v1.2 after the [v1.1.2](https://github.com/abpframewor
We have investigated the problem deeply and have seen that the root cause of the problem was related to the implementation of **intercepting `async` methods**. Besides, there were some **`async` over `sync`** usages that effected the thread pool optimization.
Finally, we **solved all the problems** with the great help of the **community**. But we also had some important **design decisions** which cause some **breaking changes** and we had to change the major version number of the framework because of the **semantic versioning**.
Finally, we **solved all the problems** with the great help of the **community**. But we also had some important **design decisions** which cause some **breaking changes** and we had to change the major version number of the framework because of the [semantic versioning](https://semver.org/).
Most of the applications won't be affected by [the breaking changes](https://github.com/abpframework/abp/releases), or it will be trivial to make these necessary changes.
@ -74,15 +74,15 @@ See [the release notes](https://github.com/abpframework/abp/releases/tag/2.0.0)
### Documentation
We have completed some missing documentation with the v2.0 release. In the following weeks, we will mostly focus on the basic documentation and tutorials.
We have completed some missing documentation with the v2.0 release. In the following weeks, we will mostly focus on the documentation and tutorials.
## ABP Commercial
[ABP Commercial](https://commercial.abp.io/) is a set of professional **modules, tools, themes, and services** built on top of the open-source ABP framework.
- It provides [professional modules](https://commercial.abp.io/modules) in addition to the ABP Framework's free & [open source modules](https://docs.abp.io/en/abp/latest/Modules/Index).
- It includes a beautiful a [UI theme](https://commercial.abp.io/themes).
- It provides [ABP Suite](https://commercial.abp.io/tools/suite); A tool to assist your development to make you more productive. It currently can create full-stack CRUD pages in a few seconds by configuring your entity properties. More functionalities will be added over time.
- It includes a beautiful a [UI theme](https://commercial.abp.io/themes) with 5 different styles.
- It provides the [ABP Suite](https://commercial.abp.io/tools/suite); A tool to assist your development to make you more productive. It currently can create full-stack CRUD pages in a few seconds by configuring your entity properties. More functionalities will be added over time.
- [Premium support](https://commercial.abp.io/support) for enterprise companies.
In addition to these standard set of features, we will provide customer basis services. See the [commercial.abp.io](https://commercial.abp.io/) web site for other details.
@ -91,11 +91,25 @@ In addition to these standard set of features, we will provide customer basis se
The ABP Commercial **is not a paid version** of the ABP Framework. You can consider it as **set of additional benefits** for professional companies. You can use it to save your time and develop your product faster.
ABP Framework is open source & free and will always be free!
ABP Framework is **open source & free** and will always be like that!
As a principle, we build the main infrastructure as open-source and sell additional pre-built application features, themes, and tools. The main idea similar to the [ASP.NET Boilerplate](https://aspnetboilerplate.com/) & the [ASP.NET Zero](https://aspnetzero.com/) products.
Buying a commercial license saves you significant time and effort and you can focus on your own business, besides you get dedicated and high priority support. Also, you will be supporting the ABP core team since we are spending most of our time to develop, maintain and support the open-source ABP Framework.
Buying a commercial license saves your significant time and effort and you can focus on your own business, besides you get dedicated and high priority support. Also, you will be supporting the ABP core team since we are spending most of our time to develop, maintain and support the open-source ABP Framework.
With the introduction of the ABP Commercial, now ABP becomes a platform. We call it as the **ABP.IO Platform** which consists of the open source ABP Framework and the ABP Commercial.
### Demo
If you are wondering how exactly looks like the ABP Commercial application startup template, you can easily [create a demo](https://commercial.abp.io/demo) and see it in action. The demo includes all the pre-built modules and the theme.
Here, a screenshot from the IdentityServer management module UI:
![abp-commercial-demo](abp-commercial-demo.png)
This is another screenshot from a demo application using the material design style of the theme:
![lepton-theme-material](lepton-theme-material.png)
### Pricing
@ -105,7 +119,7 @@ You can build **unlimited projects/products**, sell to **unlimited customers**,
- **Business license**: Allows downloading the source code of all the modules and the themes. Also, it includes 5 developer licenses by default. You can buy additional developer licenses.
- **Enterprise license**: Provides unlimited and private support in addition to the benefits of the business license.
See the [pricing page](https://commercial.abp.io/pricing) for details. In addition to the standard packages, we are also providing custom services and custom licensing. [Contact us](https://commercial.abp.io/contact) if you have further questions.
See the [pricing page](https://commercial.abp.io/pricing) for details. In addition to the standard packages, we are also providing custom services and custom licensing. [Contact us](https://commercial.abp.io/contact) if you have any questions.
#### License Comparison
@ -113,11 +127,11 @@ The license price changes based on your developer count, support level and sourc
##### The Source-Code
Team license doesn't include the source-code of the pre-built modules & themes. It uses all these modules as `NuGet` & `NPM` packages. In this way, you can easily get new features and bug fixes by just updating the package dependencies. But you can't access their source-code. So you don't have the possibility to embed a module's source code into your application and freely change the source-code.
Team license doesn't include the source-code of the pre-built modules & themes. It uses all these modules as **NuGet & NPM packages**. In this way, you can easily **get new features and bug fixes** by just updating the package dependencies. But you can't access their source-code. So you don't have the possibility to embed a module's source code into your application and freely change the source-code.
Pre-built modules provide some level of customization and extensibility and allow you to override services, UI parts and so on. We are working on to make them much more customizable and extensible. If you don't need to make major changes in the pre-built modules, the team license will be ideal for you, because it is cheaper and allows you to easily get new features and bug fixes.
Pre-built modules provide some level of **customization** and **extensibility** and allow you to override services, UI parts and so on. We are working on to make them much more customizable and extensible. If you don't need to make major changes in the pre-built modules, the team license will be ideal for you, because it is cheaper and allows you to easily get new features and bug fixes.
Business and Enterprise licenses allow you to download the source-code of any module or the theme when you need it. They also use the same startup template with the team license, so all modules are used as `NuGet` & `NPM` packages. But in case of need, you can remove the package dependencies for a module and embed its source-code into your own solution to completely customize it. In this case, upgrading the module will not be as easy as before when a new version is available. You don't have to upgrade it, surely! But if you want, you should do it yourself using some merge tool or `Git` branch system.
Business and Enterprise licenses allow you to **download the source-code** of any module or the theme when you need it. They also use the same startup template with the team license, so all modules are used as `NuGet` & `NPM` packages by default. But in case of need, you can remove the package dependencies for a module and embed its source-code into your own solution to completely customize it. In this case, upgrading the module will not be as easy as before when a new version is available. You don't have to upgrade it, surely! But if you want, you should do it yourself using some merge tool or Git branch system.
#### License Lifetime
@ -129,4 +143,22 @@ However, the following services are covered for one year:
- You can not get **updates** of the modules & the themes after one year. You can continue to use the last obtained version. You can even get bug fixes and enhancements for your current major version.
- You can use the **ABP Suite** tool for one year.
If you want to continue to get these benefits, you can extend your license period. Renewing price is 20% less than the regular price.
If you want to continue to get these benefits, you can extend your license period. Renewing price is 20% less than the regular price.
## NDC London 2020
Just like the [previous year](https://medium.com/volosoft/impressions-of-ndc-london-2019-f8f391bb7a9c), we are a partner of the famous software development conference: [NDC London](https://ndc-london.com/)! In the previous year, we were there with the [ASP.NET Boilerplate](https://aspnetboilerplate.com/) & [ASP.NET Zero](https://aspnetzero.com/) theme:
![ndc-london-volosoft](ndc-london-volosoft.png)
This year, we will be focusing on the **ABP.IO Platform** (The Open Source ABP Framework and the ABP Commercial). Our booth wall will be like that:
![ndc-london-volosoft](ndc-2020-volosoft-booth-wall.png)
If you attend to the conference, remember to visit our booth. We would be glad to talk about the ABP platform features, goals and software development in general.
### Would you like to meet the ABP Team?
If you are in London and want to have a coffee with us, we will be available at February 1st afternoon. [@hibrahimkalkan](https://twitter.com/hibrahimkalkan) and [@ismcagdas](https://twitter.com/ismcagdas) will be there.
Just write to info@abp.io if you want to meet :)

BIN
docs/en/Blog-Posts/2020-01-15 v2_0_Release/abp-commercial-demo.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 134 KiB

BIN
docs/en/Blog-Posts/2020-01-15 v2_0_Release/abp-io-abpcommercial-release.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 75 KiB

BIN
docs/en/Blog-Posts/2020-01-15 v2_0_Release/lepton-theme-material.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 148 KiB

BIN
docs/en/Blog-Posts/2020-01-15 v2_0_Release/ndc-2020-volosoft-booth-wall.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 236 KiB

BIN
docs/en/Blog-Posts/2020-01-15 v2_0_Release/ndc-london-volosoft.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 MiB

29
docs/en/Contribution/Localization-Text-Files.md

@ -3,7 +3,7 @@
Here, a list of localization text files for anyone wants to contribute to localization of the texts coming from the framework. We will keep this list up to date:
* https://github.com/abpframework/abp/tree/master/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/en.json
* https://github.com/abpframework/abp/tree/master/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/Resources/AbpValidation/en.json
* https://github.com/abpframework/abp/blob/master/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/Localization/en.json
* https://github.com/abpframework/abp/tree/master/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/Localization/Resource/en.json
* https://github.com/abpframework/abp/tree/master/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/en.json
* https://github.com/abpframework/abp/tree/master/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Localization/Resource/en.json
@ -12,29 +12,20 @@ Here, a list of localization text files for anyone wants to contribute to locali
* https://github.com/abpframework/abp/tree/master/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/Validation/en.json
* https://github.com/abpframework/abp/tree/master/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Source/en.json
* https://github.com/abpframework/abp/tree/master/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/SourceExt/en.json
* https://github.com/abpframework/abp/tree/master/modules/account/src/Volo.Abp.Account.Web/Localization/Resources/AbpAccount/Web/en.json
* https://github.com/abpframework/abp/blob/master/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/en.json
* https://github.com/abpframework/abp/tree/master/modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Localization/Resources/Blogging/ApplicationContracts/en.json
* https://github.com/abpframework/abp/tree/master/modules/blogging/src/Volo.Blogging.Web/Localization/Resources/Blogging/Web/en.json
* https://github.com/abpframework/abp/tree/master/modules/blogging/src/Volo.Blogging.Domain.Shared/Volo/Blogging/Localization/Resources/en.json
* https://github.com/abpframework/abp/tree/master/modules/docs/app/VoloDocs.Web/Localization/Resources/VoloDocs/Web/en.json
* https://github.com/abpframework/abp/tree/master/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/en.json
* https://github.com/abpframework/abp/tree/master/modules/docs/src/Volo.Docs.Admin.Web/Localization/Resources/Docs/Web/en.json
* https://github.com/abpframework/abp/tree/master/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/en.json
* https://github.com/abpframework/abp/tree/master/modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/Localization/ApplicationContracts/en.json
* https://github.com/abpframework/abp/tree/master/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/Localization/Domain/en.json
* https://github.com/abpframework/abp/tree/master/modules/feature-management/src/Volo.Abp.FeatureManagement.Web/Localization/Resources/FeatureManagement/en.json
* https://github.com/abpframework/abp/tree/master/modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/Localization/ApplicationContracts/en.json
* https://github.com/abpframework/abp/tree/master/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Localization/Domain/en.json
* https://github.com/abpframework/abp/tree/master/modules/identity/src/Volo.Abp.Identity.Web/Localization/Resources/AbpIdentity/en.json
* https://github.com/abpframework/abp/tree/master/modules/permission-management/src/Volo.Abp.PermissionManagement.Web/Localization/Resources/AbpPermissionManagement/en.json
* https://github.com/abpframework/abp/tree/master/modules/setting-management/src/Volo.Abp.SettingManagement.Web/Localization/Resources/AbpSettingManagement/en.json
* https://github.com/abpframework/abp/tree/master/modules/tenant-management/src/Volo.Abp.TenantManagement.Application.Contracts/Volo/Abp/TenantManagement/Localization/ApplicationContracts/en.json
* https://github.com/abpframework/abp/tree/master/modules/tenant-management/src/Volo.Abp.TenantManagement.Web/Localization/Resources/AbpTenantManagement/Web/en.json
* https://github.com/abpframework/abp/tree/master/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/en.json
* https://github.com/abpframework/abp/tree/master/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/en.json
* https://github.com/abpframework/abp/tree/master/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/en.json
* https://github.com/abpframework/abp/tree/master/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/en.json
* https://github.com/abpframework/abp/tree/master/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain.Shared/Volo/Abp/TenantManagement/Localization/Resources/en.json
* https://github.com/abpframework/abp/tree/master/samples/BookStore/src/Acme.BookStore.Domain.Shared/Localization/BookStore/en.json
* https://github.com/abpframework/abp/tree/master/samples/DashboardDemo/src/DashboardDemo.Domain/Localization/DashboardDemo/en.json
* https://github.com/abpframework/abp/tree/master/samples/DashboardDemo/src/DashboardDemo.Domain.Shared/Localization/DashboardDemo/en.json
* https://github.com/abpframework/abp/tree/master/samples/MicroserviceDemo/modules/product/src/ProductManagement.Application.Contracts/ProductManagement/Localization/ApplicationContracts/en.json
* https://github.com/abpframework/abp/tree/master/samples/MicroserviceDemo/modules/product/src/ProductManagement.Domain/ProductManagement/Localization/Domain/en.json
* https://github.com/abpframework/abp/tree/master/samples/MicroserviceDemo/modules/product/src/ProductManagement.Web/Localization/Resources/ProductManagement/en.json
* https://github.com/abpframework/abp/tree/master/templates/mvc-module/src/MyCompanyName.MyProjectName.Application.Contracts/Localization/MyProjectName/ApplicationContracts/en.json
* https://github.com/abpframework/abp/tree/master/templates/mvc-module/src/MyCompanyName.MyProjectName.Domain.Shared/Localization/MyProjectName/DomainShared/en.json
* https://github.com/abpframework/abp/tree/master/templates/mvc-module/src/MyCompanyName.MyProjectName.Web/Localization/MyProjectName/Web/en.json
* https://github.com/abpframework/abp/tree/master/templates/mvc/src/MyCompanyName.MyProjectName.Domain.Shared/Localization/MyProjectName/en.json
* https://github.com/abpframework/abp/tree/master/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Domain.Shared/Localization/MyProjectName/en.json

173
docs/en/Entities.md

@ -1,34 +1,87 @@
## Entities
# Entities
Entities are one of the core concepts of DDD (Domain Driven Design). Eric Evans describe it as "*An object that is not fundamentally defined by its attributes, but rather by a thread of continuity and identity*".
An entity is generally mapped to a table in a relational database.
### Entity Class
## Entity Class
Entities are derived from `Entity<TKey>` class as shown below:
Entities are derived from the `Entity<TKey>` class as shown below:
```C#
public class Person : Entity<int>
public class Book : Entity<Guid>
{
public string Name { get; set; }
public DateTime CreationTime { get; set; }
public float Price { get; set; }
}
```
> If you do not want to derive your entity from the base `Entity<TKey>` class, you can directly implement `IEntity<TKey>` interface.
`Entity<TKey>` class just defines an `Id` property with the given primary **key type**, which is `Guid` in the example above. It can be other types like `string`, `int`, `long` or whatever you need.
### Entities with GUID Keys
If your entity's Id type is `Guid`, there are some good practices to implement:
* Create a constructor that gets the Id as a parameter and passes to the base class.
* If you don't set a GUID Id, ABP Framework sets it on save, but it is good to have a valid Id on the entity even before saving it to the database.
* If you create an entity with a constructor that takes parameters, also create a `protected` empty constructor. This is used while your database provider reads your entity from the database (on deserialization).
* Don't use the `Guid.NewGuid()` to set the Id! Use [the `IGuidGenerator` service](Guid-Generation.md) while passing the Id from the code that creates the entity. `IGuidGenerator` optimized to generate sequential GUIDs, which is critical for clustered indexes in the relational databases.
An example entity:
public Person()
````csharp
public class Book : Entity<Guid>
{
public string Name { get; set; }
public float Price { get; set; }
protected Book()
{
CreationTime = DateTime.Now;
}
public Book(Guid id)
: base(id)
{
}
}
```
````
> If you do not want to derive your entity from the base `Entity<TKey>` class, you can directly implement `IEntity<TKey>` interface.
Example usage in an [application service](Application-Services.md):
`Entity<TKey>` class just defines an `Id` property with the given primary **key type**, which is `int` in the sample above. It can be other types like `string`, `Guid`, `long` or whatever you need.
````csharp
public class BookAppService : ApplicationService, IBookAppService
{
private readonly IRepository<Book> _bookRepository;
Entity class also overrides the **equality** operator (==) to easily check if two entities are equal (they are equals if they are same entity type and their Ids are equals).
public BookAppService(IRepository<Book> bookRepository)
{
_bookRepository = bookRepository;
}
#### Entities with Composite Keys
public async Task CreateAsync(CreateBookDto input)
{
await _bookRepository.InsertAsync(
new Book(GuidGenerator.Create())
{
Name = input.Name,
Price = input.Price
}
);
}
}
````
* `BookAppService` injects the default [repository](Repositories.md) for the book entity and uses its `InsertAsync` method to insert a `Book` to the database.
* `GuidGenerator` is type of `IGuidGenerator` which is a property defined in the `ApplicationService` base class. ABP defines such frequently used base properties as pre-injected for you, so you don't need to manually [inject](Dependency-Injection.md) them.
* If you want to follow the DDD best practices, see the *Aggregate Example* section below.
### Entities with Composite Keys
Some entities may need to have **composite keys**. In that case, you can derive your entity from the non-generic `Entity` class. Example:
@ -53,31 +106,31 @@ public class UserRole : Entity
}
````
For the example above, the composite key is composed of `UserId` and `RoleId`. For a relational database, it is the composite primary key of the related table.
Entities with composite keys should implement the `GetKeys()` method as shown above.
For the example above, the composite key is composed of `UserId` and `RoleId`. For a relational database, it is the composite primary key of the related table. Entities with composite keys should implement the `GetKeys()` method as shown above.
Notice that you also need to define keys of the entity in your **object-relational mapping** (ORM) configuration.
> Notice that you also need to define keys of the entity in your **object-relational mapping** (ORM) configuration. See the [Entity Framework Core](Entity-Framework-Core.md) integration document for example.
> Also note that Entities with Composite Primary Keys cannot utilize the `IRepository<TEntity, TKey>` interface since it requires a single unique Id property. However, you can always use `IRepository<TEntity>`. See [repositories documentation](Repositories.md) for more.
> Also note that Entities with Composite Primary Keys cannot utilize the `IRepository<TEntity, TKey>` interface since it requires a single Id property. However, you can always use `IRepository<TEntity>`. See [repositories documentation](Repositories.md) for more.
### AggregateRoot Class
## AggregateRoot Class
"*Aggregate is a pattern in Domain-Driven Design. A DDD aggregate is a cluster of domain objects that can be treated as a single unit. An example may be an order and its line-items, these will be separate objects, but it's useful to treat the order (together with its line items) as a single aggregate.*" (see the [full description](http://martinfowler.com/bliki/DDD_Aggregate.html))
`AggregateRoot` class extends the `Entity` class. So, it also has an `Id` property by default.
`AggregateRoot<TKey>` class extends the `Entity<TKey>` class. So, it also has an `Id` property by default.
> Notice that ABP creates default repositories only for aggregate roots by default. However, it's possible to include all entities. See [repositories documentation](Repositories.md) for more.
> Notice that ABP creates default repositories only for aggregate roots by default. However, it's possible to include all entities. See the [repositories documentation](Repositories.md) for more.
ABP does not force you to use aggregate roots, you can in fact use the `Entity` class as defined before. However, if you want to implement DDD and want to create aggregate root classes, there are some best practices you may want to consider:
ABP does not force you to use aggregate roots, you can in fact use the `Entity` class as defined before. However, if you want to implement the [Domain Driven Design](Domain-Driven-Design.md) and want to create aggregate root classes, there are some best practices you may want to consider:
* An aggregate root is responsible to preserve it's own integrity. This is also true for all entities, but aggregate root has responsibility for it's sub entities too. So, the aggregate root must always be in a valid state.
* An aggregate root can be referenced by it's Id. Do not reference it by it's navigation property.
* An aggregate root is treated as a single unit. It's retrieved and updated as a single unit. It's generally considered as a transaction boundary.
* Work with sub-entities over the aggregate root- do not modify them independently.
#### Aggregate Example
See the [entity design best practice guide](Best-Practices/Entities.md) if you want to implement DDD in your application.
### Aggregate Example
This is a full sample of an aggregate root with a related sub-entity collection:
@ -156,6 +209,11 @@ public class OrderLine : Entity
{
Count = newCount;
}
public override object[] GetKeys()
{
return new Object[] {OrderId, ProductId};
}
}
````
@ -163,15 +221,80 @@ public class OrderLine : Entity
`Order` is an **aggregate root** with `Guid` type `Id` property. It has a collection of `OrderLine` entities. `OrderLine` is another entity with a composite primary key (`OrderId` and ` ProductId`).
While this example may not implement all the best practices of an aggregate root, it still follows good practices:
While this example may not implement all the best practices of an aggregate root, it still follows some good practices:
* `Order` has a public constructor that takes **minimal requirements** to construct an `Order` instance. So, it's not possible to create an order without an id and reference number. The **protected/private** constructor is only necessary to **deserialize** the object while reading from a data source.
* `OrderLine` constructor is internal, so it is only allowed to be created by the domain layer. It's used inside of the `Order.AddProduct` method.
* `Order.AddProduct` implements the business rule to add a product to an order.
* All properties have `protected` setters. This is to prevent the entity from arbitrary changes from outside of the entity. For exmple, it would be dangerous to set `TotalItemCount` without adding a new product to the order. It's value is maintained by the `AddProduct` method.
ABP does not force you to apply any DDD rule or patterns. However, it tries to make it possible and easier when you do want to apply them. The documentation also follows the same principle.
ABP Framework does not force you to apply any DDD rule or patterns. However, it tries to make it possible and easier when you do want to apply them. The documentation also follows the same principle.
#### Aggregate Roots with Composite Keys
### Aggregate Roots with Composite Keys
While it's not common (and not suggested) for aggregate roots, it is in fact possible to define composite keys in the same way as defined for the mentioned entities above. Use non-generic `AggregateRoot` base class in that case.
## Base Classes & Interfaces for Audit Properties
There are some properties like `CreationTime`, `CreatorId`, `LastModificationTime`... which are very common in all applications. ABP Framework provides some interfaces and base classes to **standardize** these properties and also **sets their values automatically**.
### Auditing Interfaces
There are a lot of auditing interfaces, so you can implement the one that you need.
> While you can manually implement these interfaces, you can use **the base classes** defined in the next section to simplify it.
* `IHasCreationTime` defines the following properties:
* `CreationTime`
* `IMayHaveCreator` defines the following properties:
* `CreatorId`
* `ICreationAuditedObject` inherits from the `IHasCreationTime` and the `IMayHaveCreator`, so it defines the following properties:
* `CreationTime`
* `CreatorId`
* `IHasModificationTime` defines the following properties:
* `LastModificationTime`
* `IModificationAuditedObject` extends the `IHasModificationTime` and adds the `LastModifierId` property. So, it defines the following properties:
* `LastModificationTime`
* `LastModifierId`
* `IAuditedObject` extends the `ICreationAuditedObject` and the `IModificationAuditedObject`, so it defines the following properties:
* `CreationTime`
* `CreatorId`
* `LastModificationTime`
* `LastModifierId`
* `ISoftDelete` (see the [data filtering document](Data-Filtering.md)) defines the following properties:
* `IsDeleted`
* `IHasDeletionTime` extends the `ISoftDelete` and adds the `DeletionTime` property. So, it defines the following properties:
* `IsDeleted`
* `DeletionTime`
* `IDeletionAuditedObject` extends the `IHasDeletionTime` and adds the `DeleterId` property. So, it defines the following properties:
* `IsDeleted`
* `DeletionTime`
* `DeleterId`
* `IFullAuditedObject` inherits from the `IAuditedObject` and the `IDeletionAuditedObject`, so it defines the following properties:
* `CreationTime`
* `CreatorId`
* `LastModificationTime`
* `LastModifierId`
* `IsDeleted`
* `DeletionTime`
* `DeleterId`
Once you implement any of the interfaces, or derive from a class defined in the next section, ABP Framework automatically manages these properties wherever possible.
> Implementing `ISoftDelete`, `IDeletionAuditedObject` or `IFullAuditedObject` makes your entity **soft-delete**. See the [data filtering document](Data-Filtering.md) to learn about the soft-delete pattern.
### Auditing Base Classes
While you can manually implement any of the interfaces defined above, it is suggested to inherit from the base classes defined here:
* `CreationAuditedEntity<TKey>` and `CreationAuditedAggregateRoot<TKey>` implement the `ICreationAuditedObject` interface.
* `AuditedEntity<TKey>` and `AuditedAggregateRoot<TKey>` implement the `IAuditedObject` interface.
* `FullAuditedEntity<TKey>` and `FullAuditedAggregateRoot<TKey>` implement the `IFullAuditedObject` interface.
All these base classes also have non-generic versions to take `AuditedEntity` and `FullAuditedAggregateRoot` to support the composite primary keys.
All these base classes also have `...WithUser` pairs, like `FullAuditedAggregateRootWithUser<TUser>` and`FullAuditedAggregateRootWithUser<TKey, TUser>`. This makes possible to add a navigation property to your user entity. However, it is not a good practice to add navigation properties between aggregate roots, so this usage is not suggested (unless you are using an ORM, like EF Core, that well supports this scenario and you really need it - otherwise remember that this approach doesn't work for NoSQL databases like MongoDB where you must truly implement the aggregate pattern).
## See Also
* [Best practice guide to design the entities](Best-Practices/Entities.md)

6
docs/en/Modules/Audit-Logging.md

@ -1,3 +1,7 @@
# Audit Logging Module
TODO
The Audit Logging Module basically implements the `IAuditingStore` to save the audit log objects to a database.
> Audit Logging module is already installed and configured for [the startup templates](../Startup-Templates/Index.md). So, most of the times you don't need to manually add this module to your application.
See [the audit logging system](../Audit-Logging.md) document for more about the audit logging.

6
docs/en/Modules/Docs.md

@ -16,7 +16,7 @@ Docs module is an application module and does not offer any hosting solution. Yo
When you use GitHub to store your docs, Docs Module supports versioning. If you have multiple versions for your docs, there will be a combo-box on the UI to switch between versions. If you choose file system to store your docs, it does not support multiple versions.
[The documents](https://abp.io/documents/) for ABP framework is also using this module.
[The documents](docs.abp.io) for ABP framework is also using this module.
> Docs module follows the [module architecture best practices](../Best-Practices/Module-Architecture.md) guide.
@ -447,7 +447,7 @@ For example, [en/docs-params.json](https://github.com/abpio/abp-commercial-docs/
Since not every single document in your projects may not have sections or may not need all of those parameters, you have to declare which of those parameters will be used for sectioning the document, as a JSON block anywhere on the document.
For example [Getting-Started.md](https://github.com/abpio/abp-commercial-docs/blob/master/en/Getting-Started.md):
For example [Getting-Started.md](https://github.com/abpio/abp-commercial-docs/blob/master/en/getting-started.md):
```
.....
@ -466,7 +466,7 @@ For example [Getting-Started.md](https://github.com/abpio/abp-commercial-docs/bl
This section will be automatically deleted during render. And f course, those key values must match with the ones in **Parameter document**.
![Interface](..\images\docs-section-ui.png)
![Interface](../images/docs-section-ui.png)
Now you can use **Scriban** syntax to create sections in your document.

20
docs/en/Modules/Index.md

@ -11,16 +11,20 @@ There are **two types of modules.** They don't have any structural difference bu
There are some **free and open source** application modules developed and maintained by the ABP community:
* **Account**: Used to make user login/register to the application.
* **Audit Logging**: Used to persist audit logs to a database.
* **Background Jobs**: Used to persist background jobs when using default background job manager.
* **Blogging**: Used to create fancy blogs. ABP's [own blog](https://abp.io/blog/abp/) already using this module.
* **Account**: Provides UI for the account management and allows user to login/register to the application.
* [**Audit Logging**](Audit-Logging.md): Persists audit logs to a database.
* **Background Jobs**: Persist background jobs when using the default background job manager.
* **Blogging**: Used to create fancy blogs. ABP's [own blog](https://blog.abp.io/) already using this module.
* [**Docs**](Docs.md): Used to create technical documentation pages. ABP's [own documentation](https://docs.abp.io) already using this module.
* **Identity**: Used to manage roles, users and their permissions.
* **Identity**: Manages roles, users and their permissions, based on the Microsoft Identity library.
* **IdentityServer**: Integrates to IdentityServer4.
* **Permission Management**: Used to persist permissions.
* **[Setting Management](Setting-Management.md)**: Used to persist and manage the [settings](../Settings.md).
* **Tenant Management**: Used to manage tenants for a [multi-tenant](../Multi-Tenancy.md) application.
* **Users**: Used to abstract users, so other modules can depend on this instead of the Identity module.
* **Tenant Management**: Manages tenants for a [multi-tenant](../Multi-Tenancy.md) application.
* **Users**: Abstract users, so other modules can depend on this module instead of the Identity module.
Documenting the modules is in the progress. See [this repository](https://github.com/abpframework/abp/tree/master/modules) for source code of all modules.
See [the GitHub repository](https://github.com/abpframework/abp/tree/master/modules) for source code of all modules.
## Commercial Application Modules
[ABP Commercial](https://commercial.abp.io/) license provides additional pre-built application modules on top of the ABP framework. See the [module list](https://commercial.abp.io/modules) provided by the ABP Commercial.

2
docs/en/Modules/Setting-Management.md

@ -67,6 +67,8 @@ namespace Demo
So, you can get or set a setting value for different setting value providers (Default, Global, User, Tenant... etc).
> Use the `ISettingProvider` instead of the `ISettingManager` if you only need to read the setting values, because it implements caching and supports all deployment scenarios. You can use the `ISettingManager` if you are creating a setting management UI.
### Setting Cache
Setting values are cached using the [distributed cache](../Caching.md) system. Always use the `ISettingManager` to change the setting values which manages the cache for you.

2
docs/en/Tutorials/Angular/Part-I.md

@ -343,7 +343,7 @@ Run `yarn start`, wait Angular to run the application and open `http://localhost
Open the `app-routing.module.ts` and replace `books` as shown below:
```js
import { ApplicationLayoutComponent } from '@abp/ng.theme.basic';-
import { ApplicationLayoutComponent } from '@abp/ng.theme.basic';
//...
{

18
docs/en/Tutorials/AspNetCore-Mvc/Part-I.md

@ -50,6 +50,20 @@ namespace Acme.BookStore
public DateTime PublishDate { get; set; }
public float Price { get; set; }
protected Book()
{
}
public Book(Guid id, string name, BookType type, DateTime publishDate, float price)
:base(id)
{
Name = name;
Type = type;
PublishDate = publishDate;
Price = price;
}
}
}
````
@ -345,7 +359,7 @@ Open the `Index.cshtml` and change the content as shown below:
````
* This code changes the default inheritance of the Razor View Page Model so it **inherits** from the `BookStorePage` class (instead of `PageModel`). The `BookStorePage` class which comes with the startup template and provides some shared properties/methods used by all pages.
* Ensure that the `IndexModel` (*Index.cshtml.cs)* has the `Acme.BookStore.Pages.Books` namespace, or update it in the `Index.cshtml`.
* Ensure that the `IndexModel` (*Index.cshtml.cs)* has the `Acme.BookStore.Web.Pages.Books` namespace, or update it in the `Index.cshtml`.
#### Add Books Page to the Main Menu
@ -422,7 +436,7 @@ Change the `Pages/Books/Index.cshtml` as following:
````
* `abp-script` [tag helper](https://docs.microsoft.com/en-us/aspnet/core/mvc/views/tag-helpers/intro) is used to add external **scripts** to the page. It has many additional features compared to standard `script` tag. It handles **minification** and **versioning** for example. See the [bundling & minification document](../../AspNetCore/Bundling-Minification.md) for details.
* `abp-card` and `abp-table` are **tag helpers** for Twitter Bootstrap's [card component](http://getbootstrap.com/docs/4.1/components/card/). There are many tag helpers in ABP to easily use most of the [bootstrap](https://getbootstrap.com/) components. You can also use regular HTML tags instead of these tag helpers, but using tag helpers reduces HTML code and prevents errors by help of the intellisense and compile time type checking. See the [tag helpers document](../../AspNetCore/Tag-Helpers.md).
* `abp-card` and `abp-table` are **tag helpers** for Twitter Bootstrap's [card component](http://getbootstrap.com/docs/4.1/components/card/). There are many tag helpers in ABP to easily use most of the [bootstrap](https://getbootstrap.com/) components. You can also use regular HTML tags instead of these tag helpers, but using tag helpers reduces HTML code and prevents errors by help of the intellisense and compile time type checking. See the [tag helpers document](../../AspNetCore/Tag-Helpers/Index.md).
* You can **localize** the column names in the localization file as you did for the menu items above.
##### Add a Script File

3
docs/en/Tutorials/AspNetCore-Mvc/Part-II.md

@ -421,7 +421,8 @@ $(function () {
Open the `en.json` in the `Acme.BookStore.Domain.Shared` project and add the following line:
````json
"BookDeletionConfirmationMessage": "Are you sure to delete the book {0}?"
"BookDeletionConfirmationMessage": "Are you sure to delete the book {0}?",
"SuccessfullyDeleted": "Successfully deleted"
````
Run the application and try to delete a book.

18
docs/en/Tutorials/AspNetCore-Mvc/Part-III.md

@ -57,25 +57,11 @@ namespace Acme.BookStore
public async Task SeedAsync(DataSeedContext context)
{
await _bookRepository.InsertAsync(
new Book
{
Id = _guidGenerator.Create(),
Name = "Test book 1",
Type = BookType.Fantastic,
PublishDate = new DateTime(2015, 05, 24),
Price = 21
}
new Book(_guidGenerator.Create(), "Test book 1", BookType.Fantastic, new DateTime(2015, 05, 24), 21)
);
await _bookRepository.InsertAsync(
new Book
{
Id = _guidGenerator.Create(),
Name = "Test book 2",
Type = BookType.Science,
PublishDate = new DateTime(2014, 02, 11),
Price = 15
}
new Book(_guidGenerator.Create(), "Test book 2", BookType.Science, new DateTime(2014, 02, 11), 15)
);
}
}

3
docs/pt-BR/Tutorials/AspNetCore-Mvc/Part-II.md

@ -454,7 +454,8 @@ $(function () {
Abra o `en.json`no `Acme.BookStore.Domain.Shared`projeto e adicione a seguinte linha:
```json
"BookDeletionConfirmationMessage": "Are you sure to delete the book {0}?"
"BookDeletionConfirmationMessage": "Are you sure to delete the book {0}?",
"SuccessfullyDeleted": "Successfully deleted"
```

164
docs/zh-Hans/Blog-Posts/2020-01-15 v2_0_Release/Post.md

@ -0,0 +1,164 @@
# ABP框架v2.0 和 ABP商业版
ABP框架2.0版已经在本周公布.这篇文章解释了为什么我们发布了一个**抢先主版本**,和2.0版本中的变化.
除了v2.0版本,我们很高兴地宣布**ABP商业版**,这是建立在开源ABP框架的之上的一套专业的模块,工具,主题和服务.
## ABP框架V2.0
### 为什么2.0,而不是1.2?
本来在[V1.1.2](https://github.com/abpframework/abp/releases/tag/1.1.2)发布后计划发布1.2版.然而,[有报告](https://github.com/abpframework/abp/issues/2026)称1.x版在Linux上有一些**性能**和**稳定性**问题,尤其是当应用程序部署在**低配CPU和内存**的**Linux**容器上.
我们深入研究了这一问题,并已查明问题的根本原因与**拦截`async`方法**的实现有关.此外,也有一些 **`async`套`sync`** 的用法影响了线程池的优化.
最后,在**社区**在大力协助下我们**解决了所有的问题**.但是,我们也有一些重要的**设计决策**导致了一些**破坏性变更**,因为[语义版本](https://semver.org/),我们不得不改变框架的主版号.
大多数的应用程序不会受到[破坏性变更](https://github.com/abpframework/abp/releases)的影响,或者只需要做一些微小的修改.
### 破坏性变更
#### 删除了一些同步的API
一些拦截器需要使用`async`的API.当他们拦截`sync`方法时,他们需要调用`async`套`sync`.这最终导致了`async`套`sync`的问题.这就是为什么我们[删除了一些同步的API](https://github.com/abpframework/abp/pull/2464).
当你需要**在`async`方法中调用`sync`方法**时, **`async`套`sync`** 这种模式是`C#`一个经典问题.虽然有一些解决方法,但是都有相应的**缺点**,并建议**不要写**这样的代码.你可以在网上找到关于这一话题的许多文档.
为了避免这个问题,我们已经移除:
- `sync`[仓储](https://docs.abp.io/en/abp/latest/Repositories)方法 (如`insert`, `update`, 等...),
- `sync`[工作单元](https://docs.abp.io/en/abp/latest/Unit-Of-Work)API,
- `sync`[后台作业](https://docs.abp.io/en/abp/latest/Background-Jobs)API,
- `sync`[审计日志](https://docs.abp.io/en/abp/latest/Audit-Logging)API,
- 其他一些很少使用的`sync`API.
如果你遇到了编译错误,只需使用这些API的`async`版本.
#### 始终async!
从v2.0开始,ABP框架假设你以`async`方式编写你的应用程序代码.否则,一些框架的功能可能无法正常工作.
建议你的所有[应用服务](https://docs.abp.io/en/abp/latest/Application-Services), [仓储方法](https://docs.abp.io/en/abp/latest/Repositories), 控制器动作(ontroller actions), 页面处理器(page handlers)都是`async`.
即使你的应用服务方法并不需要是`async`,也将其设置为`async`,因为拦截器需要执行`async`操作(授权,工作单元等).你可以在不调用`async`的方法中返回`Task.Completed`.
示例:
````csharp
public Task<int> GetValueAsync()
{
//这个方法没有任何async调用
return Task.CompletedTask(42);
}
````
上述例子通常并不需要是`async`因为它不执行`async`调用.然而,将它设置为`async`,这样可以帮助ABP框架运行拦截器时避免出现`async`套sync的调用.
此规则不强制你写的每一个方法都是`async`.这样并不好而且很乏味.只在拦截的服务上需要(特别是[应用服务](https://docs.abp.io/en/abp/latest/Application-Services)和[仓库方法](https://docs.abp.io/en/abp/latest/Repositories))
#### 其他破坏性变更
查看[发行说明](https://github.com/abpframework/abp/releases/tag/2.0.0)中的破坏性变更.他们中的大多数都不会影响你的应用程序代码.
### 新功能
本次发布还包含一些新的功能和一堆改进:
- [#2597](https://github.com/abpframework/abp/pull/2597) 新的`Volo.Abp.AspNetCore.Serilog`包.
- [#2526](https://github.com/abpframework/abp/issues/2526) `C#`客户端代理的客户端验证.
- [#2374](https://github.com/abpframework/abp/issues/2374) `async`后台作业.
- [#265](https://github.com/abpframework/abp/issues/265) 管理应用程序关闭.
- [#2472](https://github.com/abpframework/abp/issues/2472) `IdentityServer`模块实现`DeviceFlowCodes`和`TokenCleanupService`.
功能,改进和BUG修复的完整列表, 请查看[发布说明](https://github.com/abpframework/abp/releases/tag/2.0.0).
### 文档
随着v2.0的发布,我们也完成了一些缺少的文档.在接下来的几周内,我们将主要关注文档和教程.
## ABP商业版
[ABP商业版](https://commercial.abp.io/)是建立在开源ABP框架之上的一套专业的**模块,工具,主题和服务**.
- 除了ABP框架免费和[开源模块](https://docs.abp.io/en/abp/latest/Modules/Index)之外, 提供[专业模块](https://commercial.abp.io/modules).
- 包含一个漂亮的[UI主题](https://commercial.abp.io/themes), 具有5种不同的样式.
- 提供[ABP套件](https://commercial.abp.io/tools/suite); 一个让开发更具有生产力的工具. 通过配置实体属性, 它可以在几秒内创建全栈的CRUD页面. 更多的功能陆续开发中.
- 为企业提供[高级支持](ttps://commercial.abp.io/support).
除了这些标准的功能,我们会将提供定制服务.更多细节请参见[commercial.abp.io](https://commercial.abp.io/)网站.
### ABP框架 vs ABP商业版
ABP商业版**不是付费版本**的ABP框架.可以把它当作为专业公司提供的**附加套餐**.你可以用它来节省时间和更快地开发产品.
ABP框架将永远是**开源免费**的!
一个原则是,我们创建的主要基础设施作为开源产品, 然后销售额外的预制应用程序功能,主题和工具.类似于[ASP.NET Boilerplate](https://aspnetboilerplate.com/)和[ASP.NET Zero](https://aspnetzero.com/)产品.
购买商业版许可极大地节省你的时间和精力,你可以专注于自己的业务,此外也可获得专门的和优先的支持.同时,你也在支持ABP核心团队,因为我们花了大部分时间来开发,维护和支持开源的ABP框架.
有了ABP商业版,ABP现在变为一个平台.我们称之为**ABP.IO平台**, 其中包括开源ABP框架和ABP商业版.
### 演示
如果你想知道ABP商业版应用程序的启动模板是什么样,你可以很容易地[创建一个演示](https://commercial.abp.io/demo),并看到它的实际效果.该演示包括所有的预制模块和主题.
下面是一张IdentityServer管理模块UI的截图:
![abp-commercial-demo](abp-commercial-demo.png)
这是一张来自使用material设计风格主题的演示应用程序的截图:
![lepton-theme-material](lepton-theme-material.png)
### 价格
你可以创建**无限个工程/产品**, 销售给**无限个客户**, 部署在**无限台服务器上**, 不受任何限制. 定价主要是基于**开发人员个数**,**支持等级**和**源代码**需求上.有三个标准包;
- **团队许可**: 包括所有的模块,主题和工具.允许最多3个开发者开发产品.可购买额外的开发者许可.
- **商业许可**: 允许下载所有的模块和主题的源代码.此外,默认包含了5个开发者许可.可购买额外的开发者许可.
- **企业许可**: 在商业许可上, 提供无限的专属支持.
请查看[价格页面](https://commercial.abp.io/pricing)了解详细信息.除了标准包以外,我们也提供定制服务和定制许可.如有任何问题,请[联系我们](https://commercial.abp.io/contact).
#### 许可比较
许可价格是根据开发者数量,支持等级和源代码访问而变化的.
##### 源代码
团队许可证不包括预制模块和主题的源代码.以**NuGet和NPM包**的方式使用所有这些模块.通过这种方式,你可以很容易地通过更新包的依赖得到**新功能和bug修复**仅.但是不能访问其源代码.所以不能嵌入模块的源代码到你的应用程序里,和随意修改源代码.
预制模块提供一定等级的**定制**和**扩展**,并允许你覆盖服务,UI部分等.我们正在努力使他们更加可定制和可扩展.如果你无需在预制模块中做很大修改的话,团队许可是你理想的选择,因为它更便宜,并且可轻松获得新的功能和bug修复.
商业和企业许可允许你在需要时**下载任何模块和主题的源代码**.它们使用与团队许可相同的启动模板,所以所有的模块都默认使用`NuGet`和`NPM`包.但是,在需要的情况下,你可以从一个模块中删除包的依赖,并嵌入它的源代码到你自己的解决方案中,然后完全定制它.在这种情况下,当一个新版本可用时, 升级模块将不会那么容易.当然, 你不必升级!但是,如果你愿意,你也可以使用一些合并工具或Git的分支系统来做到这一点.
#### 许可周期
ABP商业版许可是**永久的**,这意味着你可以**永远使用**它继续开发应用程序.
但是,下面的服务周期为一年:
- 高级**支持**一年后结束.你可以继续得到社区支持.
- 一年后将不会得到模块和主题的**更新**.你可以继续使用最后获得的版本.甚至可以在主版本内得到BUG修复和改进.
- 你可使用**ABP套件**一年.
如果想继续获得这些好处,可延长许可期限.续订价格比正常价格低20%.
## NDC London 2020
与[去年](https://medium.com/volosoft/impressions-of-ndc-london-2019-f8f391bb7a9c)一样, 我们是著名的软件开发会议[NDC London](https://ndc-london.com/)的合作伙伴! 去年, 我们开展了[ASP.NET Boilerplate](https://aspnetboilerplate.com/)和[ASP.NET Zero](https://aspnetzero.com/)主题:
![ndc-london-volosoft](ndc-london-volosoft.png)
今年,我们将着重于**ABP.IO平台**(开源ABP框架和ABP商业版).我们的展位会是这样的:
![ndc-london-volosoft](ndc-2020-volosoft-booth-wall.png)
如果你参加会议,记得要参观我们的展位.我们将很高兴来谈一谈ABP平台的功能,目标和软件开发.
### 你想见ABP团队吗?
如果你在伦敦, 而且想和我们喝杯咖啡的话, 在2月1日的下午[@hibrahimkalkan](https://twitter.com/hibrahimkalkan)和[@ismcagdas](https://twitter.com/ismcagdas)会在那.
想见面就给info@abp.io写个邮件 :)

BIN
docs/zh-Hans/Blog-Posts/2020-01-15 v2_0_Release/abp-commercial-demo.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 134 KiB

BIN
docs/zh-Hans/Blog-Posts/2020-01-15 v2_0_Release/lepton-theme-material.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 148 KiB

BIN
docs/zh-Hans/Blog-Posts/2020-01-15 v2_0_Release/ndc-2020-volosoft-booth-wall.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 236 KiB

BIN
docs/zh-Hans/Blog-Posts/2020-01-15 v2_0_Release/ndc-london-volosoft.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 MiB

3
docs/zh-Hans/Tutorials/AspNetCore-Mvc/Part-II.md

@ -421,7 +421,8 @@ $(function () {
打开`Acme.BookStore.Domain.Shared`项目中的`en.json`并添加以下行:
````json
"BookDeletionConfirmationMessage": "Are you sure to delete the book {0}?"
"BookDeletionConfirmationMessage": "Are you sure to delete the book {0}?",
"SuccessfullyDeleted": "Successfully deleted"
````
运行程序并尝试删除一个book实体.

3
framework/src/Volo.Abp.ApiVersioning.Abstractions/FodyWeavers.xml

@ -0,0 +1,3 @@
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
<ConfigureAwait ContinueOnCapturedContext="false" />
</Weavers>

30
framework/src/Volo.Abp.ApiVersioning.Abstractions/FodyWeavers.xsd

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. -->
<xs:element name="Weavers">
<xs:complexType>
<xs:all>
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" />
</xs:complexType>
</xs:element>
</xs:all>
<xs:attribute name="VerifyAssembly" type="xs:boolean">
<xs:annotation>
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="VerifyIgnoreCodes" type="xs:string">
<xs:annotation>
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="GenerateXsd" type="xs:boolean">
<xs:annotation>
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:complexType>
</xs:element>
</xs:schema>

1
framework/src/Volo.Abp.ApiVersioning.Abstractions/Volo.Abp.ApiVersioning.Abstractions.csproj

@ -1,5 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\configureawait.props" />
<Import Project="..\..\..\common.props" />
<PropertyGroup>

3
framework/src/Volo.Abp.AspNetCore.Authentication.JwtBearer/FodyWeavers.xml

@ -0,0 +1,3 @@
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
<ConfigureAwait ContinueOnCapturedContext="false" />
</Weavers>

30
framework/src/Volo.Abp.AspNetCore.Authentication.JwtBearer/FodyWeavers.xsd

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. -->
<xs:element name="Weavers">
<xs:complexType>
<xs:all>
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" />
</xs:complexType>
</xs:element>
</xs:all>
<xs:attribute name="VerifyAssembly" type="xs:boolean">
<xs:annotation>
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="VerifyIgnoreCodes" type="xs:string">
<xs:annotation>
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="GenerateXsd" type="xs:boolean">
<xs:annotation>
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:complexType>
</xs:element>
</xs:schema>

4
framework/src/Volo.Abp.AspNetCore.Authentication.JwtBearer/Microsoft/AspNetCore/Builder/JwtTokenMiddleware.cs

@ -11,14 +11,14 @@ namespace Microsoft.AspNetCore.Builder
{
if (ctx.User.Identity?.IsAuthenticated != true)
{
var result = await ctx.AuthenticateAsync(schema).ConfigureAwait(false);
var result = await ctx.AuthenticateAsync(schema);
if (result.Succeeded && result.Principal != null)
{
ctx.User = result.Principal;
}
}
await next().ConfigureAwait(false);
await next();
});
}
}

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

@ -1,5 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\configureawait.props" />
<Import Project="..\..\..\common.props" />
<PropertyGroup>

3
framework/src/Volo.Abp.AspNetCore.Authentication.OAuth/FodyWeavers.xml

@ -0,0 +1,3 @@
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
<ConfigureAwait ContinueOnCapturedContext="false" />
</Weavers>

30
framework/src/Volo.Abp.AspNetCore.Authentication.OAuth/FodyWeavers.xsd

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. -->
<xs:element name="Weavers">
<xs:complexType>
<xs:all>
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" />
</xs:complexType>
</xs:element>
</xs:all>
<xs:attribute name="VerifyAssembly" type="xs:boolean">
<xs:annotation>
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="VerifyIgnoreCodes" type="xs:string">
<xs:annotation>
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="GenerateXsd" type="xs:boolean">
<xs:annotation>
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:complexType>
</xs:element>
</xs:schema>

5
framework/src/Volo.Abp.AspNetCore.Authentication.OAuth/Volo.Abp.AspNetCore.Authentication.OAuth.csproj

@ -1,5 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<Project Sdk="Microsoft.NET.Sdk.Web">
<Import Project="..\..\..\configureawait.props" />
<Import Project="..\..\..\common.props" />
<PropertyGroup>
@ -19,4 +20,4 @@
<ProjectReference Include="..\Volo.Abp.Security\Volo.Abp.Security.csproj" />
</ItemGroup>
</Project>
</Project>

3
framework/src/Volo.Abp.AspNetCore.MultiTenancy/FodyWeavers.xml

@ -0,0 +1,3 @@
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
<ConfigureAwait ContinueOnCapturedContext="false" />
</Weavers>

30
framework/src/Volo.Abp.AspNetCore.MultiTenancy/FodyWeavers.xsd

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. -->
<xs:element name="Weavers">
<xs:complexType>
<xs:all>
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" />
</xs:complexType>
</xs:element>
</xs:all>
<xs:attribute name="VerifyAssembly" type="xs:boolean">
<xs:annotation>
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="VerifyIgnoreCodes" type="xs:string">
<xs:annotation>
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="GenerateXsd" type="xs:boolean">
<xs:annotation>
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:complexType>
</xs:element>
</xs:schema>

3
framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo.Abp.AspNetCore.MultiTenancy.csproj

@ -1,5 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<Project Sdk="Microsoft.NET.Sdk.Web">
<Import Project="..\..\..\configureawait.props" />
<Import Project="..\..\..\common.props" />
<PropertyGroup>

8
framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/MultiTenancyMiddleware.cs

@ -33,7 +33,7 @@ namespace Volo.Abp.AspNetCore.MultiTenancy
TenantConfiguration tenant = null;
if (resolveResult.TenantIdOrName != null)
{
tenant = await FindTenantAsync(resolveResult.TenantIdOrName).ConfigureAwait(false);
tenant = await FindTenantAsync(resolveResult.TenantIdOrName);
if (tenant == null)
{
//TODO: A better exception?
@ -45,7 +45,7 @@ namespace Volo.Abp.AspNetCore.MultiTenancy
using (_currentTenant.Change(tenant?.Id, tenant?.Name))
{
await next(context).ConfigureAwait(false);
await next(context);
}
}
@ -53,11 +53,11 @@ namespace Volo.Abp.AspNetCore.MultiTenancy
{
if (Guid.TryParse(tenantIdOrName, out var parsedTenantId))
{
return await _tenantStore.FindAsync(parsedTenantId).ConfigureAwait(false);
return await _tenantStore.FindAsync(parsedTenantId);
}
else
{
return await _tenantStore.FindAsync(tenantIdOrName).ConfigureAwait(false);
return await _tenantStore.FindAsync(tenantIdOrName);
}
}
}

3
framework/src/Volo.Abp.AspNetCore.Mvc.Client/FodyWeavers.xml

@ -0,0 +1,3 @@
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
<ConfigureAwait ContinueOnCapturedContext="false" />
</Weavers>

30
framework/src/Volo.Abp.AspNetCore.Mvc.Client/FodyWeavers.xsd

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. -->
<xs:element name="Weavers">
<xs:complexType>
<xs:all>
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" />
</xs:complexType>
</xs:element>
</xs:all>
<xs:attribute name="VerifyAssembly" type="xs:boolean">
<xs:annotation>
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="VerifyIgnoreCodes" type="xs:string">
<xs:annotation>
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="GenerateXsd" type="xs:boolean">
<xs:annotation>
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:complexType>
</xs:element>
</xs:schema>

3
framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo.Abp.AspNetCore.Mvc.Client.csproj

@ -1,5 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<Project Sdk="Microsoft.NET.Sdk.Web">
<Import Project="..\..\..\configureawait.props" />
<Import Project="..\..\..\common.props" />
<PropertyGroup>

4
framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/CachedApplicationConfigurationClient.cs

@ -43,12 +43,12 @@ namespace Volo.Abp.AspNetCore.Mvc.Client
configuration = await Cache.GetOrAddAsync(
cacheKey,
async () => await Proxy.Service.GetAsync().ConfigureAwait(false),
async () => await Proxy.Service.GetAsync(),
() => new DistributedCacheEntryOptions
{
AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(120) //TODO: Should be configurable. Default value should be higher (5 mins would be good).
}
).ConfigureAwait(false);
);
if (httpContext != null)
{

2
framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/RemoteFeatureChecker.cs

@ -15,7 +15,7 @@ namespace Volo.Abp.AspNetCore.Mvc.Client
public override async Task<string> GetOrNullAsync(string name)
{
var configuration = await ConfigurationClient.GetAsync().ConfigureAwait(false);
var configuration = await ConfigurationClient.GetAsync();
return configuration.Features.Values.GetOrDefault(name);
}
}

2
framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/RemoteLanguageProvider.cs

@ -16,7 +16,7 @@ namespace Volo.Abp.AspNetCore.Mvc.Client
public async Task<IReadOnlyList<LanguageInfo>> GetLanguagesAsync()
{
var configuration = await ConfigurationClient.GetAsync().ConfigureAwait(false);
var configuration = await ConfigurationClient.GetAsync();
return configuration.Localization.Languages;
}
}

4
framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/RemotePermissionChecker.cs

@ -16,7 +16,7 @@ namespace Volo.Abp.AspNetCore.Mvc.Client
public async Task<bool> IsGrantedAsync(string name)
{
var configuration = await ConfigurationClient.GetAsync().ConfigureAwait(false);
var configuration = await ConfigurationClient.GetAsync();
return configuration.Auth.GrantedPolicies.ContainsKey(name);
}
@ -24,7 +24,7 @@ namespace Volo.Abp.AspNetCore.Mvc.Client
public async Task<bool> IsGrantedAsync(ClaimsPrincipal claimsPrincipal, string name)
{
/* This provider always works for the current principal. */
return await IsGrantedAsync(name).ConfigureAwait(false);
return await IsGrantedAsync(name);
}
}
}

4
framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/RemoteSettingProvider.cs

@ -17,13 +17,13 @@ namespace Volo.Abp.AspNetCore.Mvc.Client
public async Task<string> GetOrNullAsync(string name)
{
var configuration = await ConfigurationClient.GetAsync().ConfigureAwait(false);
var configuration = await ConfigurationClient.GetAsync();
return configuration.Setting.Values.GetOrDefault(name);
}
public async Task<List<SettingValue>> GetAllAsync()
{
var configuration = await ConfigurationClient.GetAsync().ConfigureAwait(false);
var configuration = await ConfigurationClient.GetAsync();
return configuration
.Setting.Values
.Select(s => new SettingValue(s.Key, s.Value))

12
framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/RemoteTenantStore.cs

@ -39,13 +39,13 @@ namespace Volo.Abp.AspNetCore.Mvc.Client
tenantConfiguration = await Cache.GetOrAddAsync(
cacheKey,
async () => CreateTenantConfiguration(await Proxy.Service.FindTenantByNameAsync(name).ConfigureAwait(false)),
async () => CreateTenantConfiguration(await Proxy.Service.FindTenantByNameAsync(name)),
() => new DistributedCacheEntryOptions
{
AbsoluteExpirationRelativeToNow =
TimeSpan.FromMinutes(5) //TODO: Should be configurable.
}
).ConfigureAwait(false);
);
if (httpContext != null)
{
@ -67,13 +67,13 @@ namespace Volo.Abp.AspNetCore.Mvc.Client
tenantConfiguration = await Cache.GetOrAddAsync(
cacheKey,
async () => CreateTenantConfiguration(await Proxy.Service.FindTenantByIdAsync(id).ConfigureAwait(false)),
async () => CreateTenantConfiguration(await Proxy.Service.FindTenantByIdAsync(id)),
() => new DistributedCacheEntryOptions
{
AbsoluteExpirationRelativeToNow =
TimeSpan.FromMinutes(5) //TODO: Should be configurable.
}
).ConfigureAwait(false);
);
if (httpContext != null)
{
@ -95,7 +95,7 @@ namespace Volo.Abp.AspNetCore.Mvc.Client
tenantConfiguration = Cache.GetOrAdd(
cacheKey,
() => AsyncHelper.RunSync(async () => CreateTenantConfiguration(await Proxy.Service.FindTenantByNameAsync(name).ConfigureAwait(false))),
() => AsyncHelper.RunSync(async () => CreateTenantConfiguration(await Proxy.Service.FindTenantByNameAsync(name))),
() => new DistributedCacheEntryOptions
{
AbsoluteExpirationRelativeToNow =
@ -123,7 +123,7 @@ namespace Volo.Abp.AspNetCore.Mvc.Client
tenantConfiguration = Cache.GetOrAdd(
cacheKey,
() => AsyncHelper.RunSync(async () => CreateTenantConfiguration(await Proxy.Service.FindTenantByIdAsync(id).ConfigureAwait(false))),
() => AsyncHelper.RunSync(async () => CreateTenantConfiguration(await Proxy.Service.FindTenantByIdAsync(id))),
() => new DistributedCacheEntryOptions
{
AbsoluteExpirationRelativeToNow =

3
framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/FodyWeavers.xml

@ -0,0 +1,3 @@
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
<ConfigureAwait ContinueOnCapturedContext="false" />
</Weavers>

30
framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/FodyWeavers.xsd

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. -->
<xs:element name="Weavers">
<xs:complexType>
<xs:all>
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" />
</xs:complexType>
</xs:element>
</xs:all>
<xs:attribute name="VerifyAssembly" type="xs:boolean">
<xs:annotation>
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="VerifyIgnoreCodes" type="xs:string">
<xs:annotation>
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="GenerateXsd" type="xs:boolean">
<xs:annotation>
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:complexType>
</xs:element>
</xs:schema>

3
framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo.Abp.AspNetCore.Mvc.Contracts.csproj

@ -1,5 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\configureawait.props" />
<Import Project="..\..\..\common.props" />
<PropertyGroup>

3
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/FodyWeavers.xml

@ -0,0 +1,3 @@
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
<ConfigureAwait ContinueOnCapturedContext="false" />
</Weavers>

30
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/FodyWeavers.xsd

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. -->
<xs:element name="Weavers">
<xs:complexType>
<xs:all>
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" />
</xs:complexType>
</xs:element>
</xs:all>
<xs:attribute name="VerifyAssembly" type="xs:boolean">
<xs:annotation>
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="VerifyIgnoreCodes" type="xs:string">
<xs:annotation>
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="GenerateXsd" type="xs:boolean">
<xs:annotation>
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:complexType>
</xs:element>
</xs:schema>

2
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Breadcrumb/AbpBreadcrumbTagHelperService.cs

@ -12,7 +12,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Breadcrumb
{
var list = InitilizeFormGroupContentsContext(context, output);
await output.GetChildContentAsync().ConfigureAwait(false);
await output.GetChildContentAsync();
SetInnerOlTag(context, output);
SetInnerList(context, output, list);

2
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Carousel/AbpCarouselTagHelperService.cs

@ -19,7 +19,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Carousel
var itemList = InitilizeCarouselItemsContentsContext(context, output);
await output.GetChildContentAsync().ConfigureAwait(false);
await output.GetChildContentAsync();
SetOneItemAsActive(context, output, itemList);
SetItems(context, output, itemList);

2
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Collapse/AbpAccordionItemTagHelperService.cs

@ -12,7 +12,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Collapse
{
SetRandomIdIfNotProvided();
var innerContent = (await output.GetChildContentAsync().ConfigureAwait(false)).GetContent();
var innerContent = (await output.GetChildContentAsync()).GetContent();
var html = GetAccordionHeaderItem(context, output) + GetAccordionContentItem(context, output, innerContent);

2
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Collapse/AbpAccordionTagHelperService.cs

@ -20,7 +20,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Collapse
var items = InitilizeFormGroupContentsContext(context, output);
await output.GetChildContentAsync().ConfigureAwait(false);
await output.GetChildContentAsync();
var content = GetContent(items);

2
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Collapse/AbpCollapseBodyTagHelperService.cs

@ -22,7 +22,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Collapse
output.Attributes.AddClass("multi-collapse");
}
var innerContent = (await output.GetChildContentAsync().ConfigureAwait(false)).GetContent();
var innerContent = (await output.GetChildContentAsync()).GetContent();
output.Content.SetHtmlContent(innerContent);
}

12
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Dropdown/AbpDropdownButtonTagHelperService.cs

@ -26,9 +26,9 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Dropdown
public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
{
var content = await output.GetChildContentAsync().ConfigureAwait(false);
var content = await output.GetChildContentAsync();
var buttonsAsHtml = await GetButtonsAsHtmlAsync(context, output, content).ConfigureAwait(false);
var buttonsAsHtml = await GetButtonsAsHtmlAsync(context, output, content);
output.PreElement.SetHtmlContent(buttonsAsHtml);
@ -43,13 +43,13 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Dropdown
{
var buttonBuilder = new StringBuilder("");
var mainButton = await GetMainButtonAsync(context, output, content).ConfigureAwait(false);
var mainButton = await GetMainButtonAsync(context, output, content);
buttonBuilder.AppendLine(mainButton);
if (TagHelper.DropdownStyle == DropdownStyle.Split)
{
var splitButton = await GetSplitButtonAsync(context, output).ConfigureAwait(false);
var splitButton = await GetSplitButtonAsync(context, output);
buttonBuilder.AppendLine(splitButton);
}
@ -68,7 +68,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Dropdown
abpButtonTagHelper.ButtonType = TagHelper.ButtonType;
var attributes = GetAttributesForMainButton(context, output);
var buttonTag = await abpButtonTagHelper.ProcessAndGetOutputAsync(attributes, context, "button", TagMode.StartTagAndEndTag).ConfigureAwait(false);
var buttonTag = await abpButtonTagHelper.ProcessAndGetOutputAsync(attributes, context, "button", TagMode.StartTagAndEndTag);
buttonTag.PreContent.SetHtmlContent(content.GetContent());
@ -89,7 +89,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Dropdown
abpButtonTagHelper.ButtonType = TagHelper.ButtonType;
var attributes = GetAttributesForSplitButton(context, output);
return await abpButtonTagHelper.RenderAsync(attributes, context, _htmlEncoder, "button", TagMode.StartTagAndEndTag).ConfigureAwait(false);
return await abpButtonTagHelper.RenderAsync(attributes, context, _htmlEncoder, "button", TagMode.StartTagAndEndTag);
}
protected virtual TagHelperAttributeList GetAttributesForMainButton(TagHelperContext context, TagHelperOutput output)

4
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Extensions/TagHelperExtensions.cs

@ -19,14 +19,14 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Extensions
tagHelper.Init(context);
await tagHelper.ProcessAsync(innerContext, innerOutput).ConfigureAwait(false);
await tagHelper.ProcessAsync(innerContext, innerOutput);
return innerOutput;
}
public static async Task<string> RenderAsync(this TagHelper tagHelper, TagHelperAttributeList attributeList, TagHelperContext context, HtmlEncoder htmlEncoder, string tagName = "div", TagMode tagMode = TagMode.SelfClosing)
{
var innerOutput = await tagHelper.ProcessAndGetOutputAsync(attributeList, context, tagName, tagMode).ConfigureAwait(false);
var innerOutput = await tagHelper.ProcessAndGetOutputAsync(attributeList, context, tagName, tagMode);
return innerOutput.Render(htmlEncoder);
}

20
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpDynamicformTagHelperService.cs

@ -37,11 +37,11 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form
NormalizeTagMode(context, output);
var childContent = (await output.GetChildContentAsync().ConfigureAwait(false)).GetContent();
var childContent = (await output.GetChildContentAsync()).GetContent();
await ConvertToMvcForm(context, output).ConfigureAwait(false);
await ConvertToMvcForm(context, output);
await ProcessFieldsAsync(context, output).ConfigureAwait(false);
await ProcessFieldsAsync(context, output);
SetContent(context, output, list, childContent);
@ -67,9 +67,9 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form
ViewContext = TagHelper.ViewContext
};
var formTagOutput = await formTagHelper.ProcessAndGetOutputAsync(output.Attributes, context, "form", TagMode.StartTagAndEndTag).ConfigureAwait(false);
var formTagOutput = await formTagHelper.ProcessAndGetOutputAsync(output.Attributes, context, "form", TagMode.StartTagAndEndTag);
await formTagOutput.GetChildContentAsync().ConfigureAwait(false);
await formTagOutput.GetChildContentAsync();
output.PostContent.SetHtmlContent(output.PostContent.GetContent() + formTagOutput.PostContent.GetContent());
output.PreContent.SetHtmlContent(output.PreContent.GetContent() + formTagOutput.PreContent.GetContent());
@ -134,11 +134,11 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form
{
if (IsSelectGroup(context, model))
{
await ProcessSelectGroupAsync(context, output, model).ConfigureAwait(false);
await ProcessSelectGroupAsync(context, output, model);
}
else
{
await ProcessInputGroupAsync(context, output, model).ConfigureAwait(false);
await ProcessInputGroupAsync(context, output, model);
}
}
}
@ -147,7 +147,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form
{
var abpSelectTagHelper = GetSelectGroupTagHelper(context, output, model);
await abpSelectTagHelper.RenderAsync(new TagHelperAttributeList(), context, _htmlEncoder, "div", TagMode.StartTagAndEndTag).ConfigureAwait(false);
await abpSelectTagHelper.RenderAsync(new TagHelperAttributeList(), context, _htmlEncoder, "div", TagMode.StartTagAndEndTag);
}
protected virtual AbpTagHelper GetSelectGroupTagHelper(TagHelperContext context, TagHelperOutput output, ModelExpression model)
@ -185,7 +185,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form
abpButtonTagHelper.Text = "Submit";
abpButtonTagHelper.ButtonType = AbpButtonType.Primary;
return await abpButtonTagHelper.RenderAsync(attributes, context, _htmlEncoder, "button", TagMode.StartTagAndEndTag).ConfigureAwait(false);
return await abpButtonTagHelper.RenderAsync(attributes, context, _htmlEncoder, "button", TagMode.StartTagAndEndTag);
}
protected virtual async Task ProcessInputGroupAsync(TagHelperContext context, TagHelperOutput output, ModelExpression model)
@ -195,7 +195,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form
abpInputTagHelper.ViewContext = TagHelper.ViewContext;
abpInputTagHelper.DisplayRequiredSymbol = TagHelper.RequiredSymbols ?? true;
await abpInputTagHelper.RenderAsync(new TagHelperAttributeList(), context, _htmlEncoder, "div", TagMode.StartTagAndEndTag).ConfigureAwait(false);
await abpInputTagHelper.RenderAsync(new TagHelperAttributeList(), context, _htmlEncoder, "div", TagMode.StartTagAndEndTag);
}
protected virtual List<ModelExpression> GetModels(TagHelperContext context, TagHelperOutput output)

16
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpInputTagHelperService.cs

@ -27,7 +27,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form
public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
{
var (innerHtml, isCheckBox) = await GetFormInputGroupAsHtmlAsync(context, output).ConfigureAwait(false);
var (innerHtml, isCheckBox) = await GetFormInputGroupAsHtmlAsync(context, output);
var order = TagHelper.AspFor.ModelExplorer.GetDisplayOrder();
@ -57,12 +57,12 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form
protected virtual async Task<(string, bool)> GetFormInputGroupAsHtmlAsync(TagHelperContext context, TagHelperOutput output)
{
var (inputTag, isCheckBox) = await GetInputTagHelperOutputAsync(context, output).ConfigureAwait(false);
var (inputTag, isCheckBox) = await GetInputTagHelperOutputAsync(context, output);
var inputHtml = inputTag.Render(_encoder);
var label = await GetLabelAsHtmlAsync(context, output, inputTag, isCheckBox).ConfigureAwait(false);
var label = await GetLabelAsHtmlAsync(context, output, inputTag, isCheckBox);
var info = GetInfoAsHtml(context, output, inputTag, isCheckBox);
var validation = isCheckBox ? "" : await GetValidationAsHtmlAsync(context, output, inputTag).ConfigureAwait(false);
var validation = isCheckBox ? "" : await GetValidationAsHtmlAsync(context, output, inputTag);
return (GetContent(context, output, label, inputHtml, validation, info, isCheckBox), isCheckBox);
}
@ -82,7 +82,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form
var attributeList = new TagHelperAttributeList { { "class", "text-danger" } };
return await validationMessageTagHelper.RenderAsync(attributeList, context, _encoder, "span", TagMode.StartTagAndEndTag).ConfigureAwait(false);
return await validationMessageTagHelper.RenderAsync(attributeList, context, _encoder, "span", TagMode.StartTagAndEndTag);
}
protected virtual string GetContent(TagHelperContext context, TagHelperOutput output, string label, string inputHtml, string validation, string infoHtml, bool isCheckbox)
@ -125,7 +125,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form
{
var tagHelper = GetInputTagHelper(context, output);
var inputTagHelperOutput = await tagHelper.ProcessAndGetOutputAsync(GetInputAttributes(context, output), context, "input").ConfigureAwait(false);
var inputTagHelperOutput = await tagHelper.ProcessAndGetOutputAsync(GetInputAttributes(context, output), context, "input");
ConvertToTextAreaIfTextArea(inputTagHelperOutput);
AddDisabledAttribute(inputTagHelperOutput);
@ -227,7 +227,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form
if (string.IsNullOrEmpty(TagHelper.Label))
{
return await GetLabelAsHtmlUsingTagHelperAsync(context, output, isCheckbox).ConfigureAwait(false) + GetRequiredSymbol(context, output);
return await GetLabelAsHtmlUsingTagHelperAsync(context, output, isCheckbox) + GetRequiredSymbol(context, output);
}
var checkboxClass = isCheckbox ? "class=\"custom-control-label\" " : "";
@ -301,7 +301,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form
attributeList.AddClass("custom-control-label");
}
return await labelTagHelper.RenderAsync(attributeList, context, _encoder, "label", TagMode.StartTagAndEndTag).ConfigureAwait(false);
return await labelTagHelper.RenderAsync(attributeList, context, _encoder, "label", TagMode.StartTagAndEndTag);
}
protected virtual void ConvertToTextAreaIfTextArea(TagHelperOutput tagHelperOutput)

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

@ -30,7 +30,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form
public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
{
var innerHtml = await GetFormInputGroupAsHtmlAsync(context, output).ConfigureAwait(false);
var innerHtml = await GetFormInputGroupAsHtmlAsync(context, output);
var order = TagHelper.AspFor.ModelExplorer.GetDisplayOrder();
@ -52,10 +52,10 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form
protected virtual async Task<string> GetFormInputGroupAsHtmlAsync(TagHelperContext context, TagHelperOutput output)
{
var selectTag = await GetSelectTagAsync(context, output).ConfigureAwait(false);
var selectTag = await GetSelectTagAsync(context, output);
var selectAsHtml = selectTag.Render(_encoder);
var label = await GetLabelAsHtmlAsync(context, output, selectTag).ConfigureAwait(false);
var validation = await GetValidationAsHtmlAsync(context, output, selectTag).ConfigureAwait(false);
var label = await GetLabelAsHtmlAsync(context, output, selectTag);
var validation = await GetValidationAsHtmlAsync(context, output, selectTag);
var infoText = GetInfoAsHtml(context, output, selectTag);
return label + Environment.NewLine + selectAsHtml + Environment.NewLine + infoText + Environment.NewLine + validation;
@ -75,7 +75,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form
ViewContext = TagHelper.ViewContext
};
var selectTagHelperOutput = await selectTagHelper.ProcessAndGetOutputAsync(GetInputAttributes(context, output), context, "select", TagMode.StartTagAndEndTag).ConfigureAwait(false);
var selectTagHelperOutput = await selectTagHelper.ProcessAndGetOutputAsync(GetInputAttributes(context, output), context, "select", TagMode.StartTagAndEndTag);
selectTagHelperOutput.Attributes.AddClass("form-control");
selectTagHelperOutput.Attributes.AddClass(GetSize(context, output));
@ -123,7 +123,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form
return "<label " + GetIdAttributeAsString(selectTag) + ">" + TagHelper.Label + "</label>" + GetRequiredSymbol(context, output);
}
return await GetLabelAsHtmlUsingTagHelperAsync(context, output).ConfigureAwait(false) + GetRequiredSymbol(context, output);
return await GetLabelAsHtmlUsingTagHelperAsync(context, output) + GetRequiredSymbol(context, output);
}
protected virtual string GetRequiredSymbol(TagHelperContext context, TagHelperOutput output)
@ -242,7 +242,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form
ViewContext = TagHelper.ViewContext
};
return await labelTagHelper.RenderAsync(new TagHelperAttributeList(), context, _encoder, "label", TagMode.StartTagAndEndTag).ConfigureAwait(false);
return await labelTagHelper.RenderAsync(new TagHelperAttributeList(), context, _encoder, "label", TagMode.StartTagAndEndTag);
}
protected virtual async Task<string> GetValidationAsHtmlAsync(TagHelperContext context, TagHelperOutput output, TagHelperOutput inputTag)
@ -255,7 +255,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form
var attributeList = new TagHelperAttributeList { { "class", "text-danger" } };
return await validationMessageTagHelper.RenderAsync(attributeList, context, _encoder, "span", TagMode.StartTagAndEndTag).ConfigureAwait(false);
return await validationMessageTagHelper.RenderAsync(attributeList, context, _encoder, "span", TagMode.StartTagAndEndTag);
}
protected virtual string GetSize(TagHelperContext context, TagHelperOutput output)

2
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Grid/AbpColumnTagHelperService.cs

@ -8,6 +8,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Grid
public override void Process(TagHelperContext context, TagHelperOutput output)
{
output.TagName = "div";
output.Attributes.AddClass("col");
ProcessSizeClasses(context, output);
@ -52,6 +53,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Grid
classString += "-" + size.ToString("D");
}
output.Attributes.RemoveClass("col");
output.Attributes.AddClass(classString);
}

18
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Pagination/AbpPaginationTagHelperService.cs

@ -31,7 +31,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Pagination
}
ProcessMainTag(context, output);
await SetContentAsHtmlAsync(context, output).ConfigureAwait(false);
await SetContentAsHtmlAsync(context, output);
}
protected virtual async Task SetContentAsHtmlAsync(TagHelperContext context, TagHelperOutput output)
@ -39,9 +39,9 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Pagination
var html = new StringBuilder("");
html.AppendLine(GetOpeningTags(context, output));
html.AppendLine(await GetPreviousButtonAsync(context, output).ConfigureAwait(false));
html.AppendLine(await GetPagesAsync(context, output).ConfigureAwait(false));
html.AppendLine(await GetNextButton(context, output).ConfigureAwait(false));
html.AppendLine(await GetPreviousButtonAsync(context, output));
html.AppendLine(await GetPagesAsync(context, output));
html.AppendLine(await GetNextButton(context, output));
html.AppendLine(GetClosingTags(context, output));
output.Content.SetHtmlContent(html.ToString());
@ -61,7 +61,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Pagination
foreach (var page in TagHelper.Model.Pages)
{
pagesHtml.AppendLine(await GetPageAsync(context, output, page).ConfigureAwait(false));
pagesHtml.AppendLine(await GetPageAsync(context, output, page));
}
return pagesHtml.ToString();
@ -86,7 +86,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Pagination
}
else
{
pageHtml.AppendLine(await RenderAnchorTagHelperLinkHtmlAsync(context, output, page.Index.ToString(), page.Index.ToString()).ConfigureAwait(false));
pageHtml.AppendLine(await RenderAnchorTagHelperLinkHtmlAsync(context, output, page.Index.ToString(), page.Index.ToString()));
}
pageHtml.AppendLine("</li>");
@ -102,7 +102,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Pagination
: (TagHelper.Model.CurrentPage - 1).ToString();
return
"<li class=\"page-item " + (TagHelper.Model.CurrentPage == 1 ? "disabled" : "") + "\">\r\n" +
(await RenderAnchorTagHelperLinkHtmlAsync(context, output, currentPage, localizationKey).ConfigureAwait(false)) + " </li>";
(await RenderAnchorTagHelperLinkHtmlAsync(context, output, currentPage, localizationKey)) + " </li>";
}
protected virtual async Task<string> GetNextButton(TagHelperContext context, TagHelperOutput output)
@ -111,7 +111,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Pagination
var currentPage = (TagHelper.Model.CurrentPage + 1).ToString();
return
"<li class=\"page-item " + (TagHelper.Model.CurrentPage >= TagHelper.Model.TotalPageCount ? "disabled" : "") + "\">\r\n" +
(await RenderAnchorTagHelperLinkHtmlAsync(context, output, currentPage, localizationKey).ConfigureAwait(false)) +
(await RenderAnchorTagHelperLinkHtmlAsync(context, output, currentPage, localizationKey)) +
" </li>";
}
@ -121,7 +121,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Pagination
var anchorTagHelper = GetAnchorTagHelper(currentPage, out var attributeList);
var tagHelperOutput = await anchorTagHelper.ProcessAndGetOutputAsync(attributeList, context, "a", TagMode.StartTagAndEndTag).ConfigureAwait(false);
var tagHelperOutput = await anchorTagHelper.ProcessAndGetOutputAsync(attributeList, context, "a", TagMode.StartTagAndEndTag);
tagHelperOutput.Content.SetHtmlContent(localizer[localizationKey]);

2
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Tab/AbpTabDropdownTagHelperService.cs

@ -15,7 +15,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Tab
throw new Exception("Name of tab dropdown tag can not bu null or empty.");
}
await output.GetChildContentAsync().ConfigureAwait(false);
await output.GetChildContentAsync();
var tabHeader = GetTabHeaderItem(context, output);
var tabHeaderItems = context.GetValue<List<TabItem>>(TabItems);

2
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Tab/AbpTabTagHelperService.cs

@ -12,7 +12,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Tab
{
SetPlaceholderForNameIfNotProvided();
var innerContent = await output.GetChildContentAsync().ConfigureAwait(false);
var innerContent = await output.GetChildContentAsync();
var tabHeader = GetTabHeaderItem(context, output);
var tabContent = GetTabContentItem(context, output, innerContent.GetContent());

10
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Tab/AbpTabsTagHelperService.cs

@ -17,7 +17,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Tab
var items = InitilizeFormGroupContentsContext(context, output);
await output.GetChildContentAsync().ConfigureAwait(false);
await output.GetChildContentAsync();
var headers = GetHeaders(context, output, items);
var contents = GetConents(context, output, items);
@ -45,8 +45,8 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Tab
var headerColumnSize = GetHeaderColumnSize();
var contentColumnSize = 12 - headerColumnSize;
headers = PlaceInsideColunm(headers, headerColumnSize);
contents = PlaceInsideColunm(contents, contentColumnSize);
headers = PlaceInsideColumn(headers, headerColumnSize);
contents = PlaceInsideColumn(contents, contentColumnSize);
}
@ -79,9 +79,9 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Tab
return surroundedContents;
}
protected virtual string PlaceInsideColunm(string contents, int columnSize)
protected virtual string PlaceInsideColumn(string contents, int columnSize)
{
var surroundedContents = "<div class=\"col-" + columnSize + "\">" + Environment.NewLine +
var surroundedContents = "<div class=\"col-md-" + columnSize + "\">" + Environment.NewLine +
contents +
" </div>";

3
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.csproj

@ -1,5 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk.Razor">
<Project Sdk="Microsoft.NET.Sdk.Razor">
<Import Project="..\..\..\configureawait.props" />
<Import Project="..\..\..\common.props" />
<PropertyGroup>

3
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/FodyWeavers.xml

@ -0,0 +1,3 @@
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
<ConfigureAwait ContinueOnCapturedContext="false" />
</Weavers>

30
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/FodyWeavers.xsd

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. -->
<xs:element name="Weavers">
<xs:complexType>
<xs:all>
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" />
</xs:complexType>
</xs:element>
</xs:all>
<xs:attribute name="VerifyAssembly" type="xs:boolean">
<xs:annotation>
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="VerifyIgnoreCodes" type="xs:string">
<xs:annotation>
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="GenerateXsd" type="xs:boolean">
<xs:annotation>
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:complexType>
</xs:element>
</xs:schema>

3
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/Volo.Abp.AspNetCore.Mvc.UI.Bundling.csproj

@ -1,5 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk.Razor">
<Project Sdk="Microsoft.NET.Sdk.Razor">
<Import Project="..\..\..\configureawait.props" />
<Import Project="..\..\..\common.props" />
<PropertyGroup>

12
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/Volo/Abp/AspNetCore/Mvc/UI/Bundling/BundleManager.cs

@ -61,12 +61,12 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bundling
public virtual async Task<IReadOnlyList<string>> GetStyleBundleFilesAsync(string bundleName)
{
return await GetBundleFilesAsync(Options.StyleBundles, bundleName, StyleBundler).ConfigureAwait(false);
return await GetBundleFilesAsync(Options.StyleBundles, bundleName, StyleBundler);
}
public virtual async Task<IReadOnlyList<string>> GetScriptBundleFilesAsync(string bundleName)
{
return await GetBundleFilesAsync(Options.ScriptBundles, bundleName, ScriptBundler).ConfigureAwait(false);
return await GetBundleFilesAsync(Options.ScriptBundles, bundleName, ScriptBundler);
}
protected virtual async Task<IReadOnlyList<string>> GetBundleFilesAsync(BundleConfigurationCollection bundles, string bundleName, IBundler bundler)
@ -185,17 +185,17 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bundling
foreach (var contributor in contributors)
{
await contributor.PreConfigureBundleAsync(context).ConfigureAwait(false);
await contributor.PreConfigureBundleAsync(context);
}
foreach (var contributor in contributors)
{
await contributor.ConfigureBundleAsync(context).ConfigureAwait(false);
await contributor.ConfigureBundleAsync(context);
}
foreach (var contributor in contributors)
{
await contributor.PostConfigureBundleAsync(context).ConfigureAwait(false);
await contributor.PostConfigureBundleAsync(context);
}
return context.Files;
@ -207,7 +207,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bundling
foreach (var contributor in contributors)
{
await contributor.ConfigureDynamicResourcesAsync(context).ConfigureAwait(false);
await contributor.ConfigureDynamicResourcesAsync(context);
}
return context.Files;

2
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/Volo/Abp/AspNetCore/Mvc/UI/Bundling/TagHelpers/AbpBundleItemTagHelperService.cs

@ -33,7 +33,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bundling.TagHelpers
TagHelper.CreateBundleTagHelperItem()
},
TagHelper.GetNameOrNull()
).ConfigureAwait(false);
);
}
}
}

6
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/Volo/Abp/AspNetCore/Mvc/UI/Bundling/TagHelpers/AbpBundleTagHelperService.cs

@ -20,16 +20,16 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bundling.TagHelpers
await ResourceService.ProcessAsync(
context,
output,
await GetBundleItems(context, output).ConfigureAwait(false),
await GetBundleItems(context, output),
TagHelper.GetNameOrNull()
).ConfigureAwait(false);
);
}
protected virtual async Task<List<BundleTagHelperItem>> GetBundleItems(TagHelperContext context, TagHelperOutput output)
{
var bundleItems = new List<BundleTagHelperItem>();
context.Items[AbpTagHelperConsts.ContextBundleItemListKey] = bundleItems;
await output.GetChildContentAsync().ConfigureAwait(false); //TODO: Is there a way of executing children without getting content?
await output.GetChildContentAsync(); //TODO: Is there a way of executing children without getting content?
return bundleItems;
}
}

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

Loading…
Cancel
Save