Browse Source

Merge branch 'issue-17077' of https://github.com/abpframework/abp into issue-17077

pull/17258/head
Gizem Mutu Kurt 3 years ago
parent
commit
d1cf3396ad
  1. 2
      Directory.Build.props
  2. 23
      abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json
  3. 20
      abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/tr.json
  4. 7
      abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/en.json
  5. 2
      abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/ar.json
  6. 118
      abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json
  7. 2
      abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/fi.json
  8. 2
      abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/hu.json
  9. 3
      abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/tr.json
  10. 2
      abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/zh-Hans.json
  11. 10
      docs/en/Best-Practices/Entities.md
  12. 125
      docs/en/Community-Articles/2023-08-07-Basic-Theme-Dark-Mode/POST.md
  13. BIN
      docs/en/Community-Articles/2023-08-07-Basic-Theme-Dark-Mode/basictheme-dark-login.png
  14. BIN
      docs/en/Community-Articles/2023-08-07-Basic-Theme-Dark-Mode/basictheme-dark-settings.png
  15. BIN
      docs/en/Community-Articles/2023-08-07-Basic-Theme-Dark-Mode/basictheme-dark-users.png
  16. BIN
      docs/en/Community-Articles/2023-08-07-Basic-Theme-Dark-Mode/basictheme-toggle-demo.gif
  17. 148
      docs/en/Community-Articles/2023-08-12-ABP-Commercial-GDPR-Module-Overview/POST.md
  18. BIN
      docs/en/Community-Articles/2023-08-12-ABP-Commercial-GDPR-Module-Overview/cover-image.png
  19. BIN
      docs/en/Community-Articles/2023-08-12-ABP-Commercial-GDPR-Module-Overview/gdpr-personal-data-menu.png
  20. BIN
      docs/en/Community-Articles/2023-08-12-ABP-Commercial-GDPR-Module-Overview/gdpr-personal-data-page.png
  21. BIN
      docs/en/Community-Articles/2023-08-12-ABP-Commercial-GDPR-Module-Overview/personal-data-download.png
  22. BIN
      docs/en/Community-Articles/2023-08-12-ABP-Commercial-GDPR-Module-Overview/personal-data-files.png
  23. 94
      docs/en/Migration-Guides/Abp-7_4.md
  24. 1
      docs/en/Migration-Guides/Index.md
  25. 12
      docs/en/Modules/Docs.md
  26. 6
      docs/en/Modules/Index.md
  27. 6
      docs/en/Modules/Setting-Management.md
  28. 27
      docs/en/Modules/Tenant-Management.md
  29. 80
      docs/en/UI/Angular/CapsLock.directive.md
  30. 6
      docs/en/UI/Angular/Entity-Action-Extensions.md
  31. 30
      docs/en/UI/Angular/Internet-Connection-Service.md
  32. 77
      docs/en/UI/Angular/Show-Password-Directive.md
  33. 46
      docs/en/UI/Angular/Sorting-Navigation-Elements.md
  34. BIN
      docs/en/UI/Angular/images/CapsLockDirective1.png
  35. BIN
      docs/en/UI/Angular/images/CapsLockDirective2.png
  36. BIN
      docs/en/UI/Angular/images/showPasswordDirective1.png
  37. BIN
      docs/en/UI/Angular/images/showPasswordDirective2.png
  38. 8
      docs/en/docs-nav.json
  39. 6
      docs/zh-Hans/Modules/Setting-Management.md
  40. 2
      framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/Layout/PageHeader.razor
  41. 5
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpInputTagHelperService.cs
  42. 59
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpSelectTagHelperService.cs
  43. 2
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ExceptionHandling/AbpExceptionPageFilter.cs
  44. 2
      framework/src/Volo.Abp.Auditing.Contracts/Volo/Abp/Auditing/IDeletionAuditedObject.cs
  45. 3
      framework/src/Volo.Abp.Auditing.Contracts/Volo/Abp/Auditing/IMayHaveCreator.cs
  46. 2
      framework/src/Volo.Abp.Auditing.Contracts/Volo/Abp/Auditing/IModificationAuditedObject.cs
  47. 2
      framework/src/Volo.Abp.BlazoriseUI/Components/ObjectExtending/LookupExtensionProperty.razor
  48. 20
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/VoloNugetPackagesVersionUpdater.cs
  49. 20
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Version/PackageVersionCheckerService.cs
  50. 2
      framework/src/Volo.Abp.Core/Microsoft/Extensions/Hosting/AbpHostingHostBuilderExtensions.cs
  51. 2
      framework/src/Volo.Abp.Dapper/Volo.Abp.Dapper.csproj
  52. 6
      framework/src/Volo.Abp.Dapper/Volo/Abp/Domain/Repositories/Dapper/DapperRepository.cs
  53. 4
      framework/src/Volo.Abp.Dapper/Volo/Abp/Domain/Repositories/Dapper/IDapperRepository.cs
  54. 2
      framework/src/Volo.Abp.Dapr/Volo.Abp.Dapr.csproj
  55. 8
      framework/src/Volo.Abp.Dapr/Volo/Abp/Dapr/AbpDaprClientFactory.cs
  56. 8
      framework/src/Volo.Abp.Dapr/Volo/Abp/Dapr/AbpDaprModule.cs
  57. 8
      framework/src/Volo.Abp.Dapr/Volo/Abp/Dapr/AbpDaprOptions.cs
  58. 4
      framework/src/Volo.Abp.Dapr/Volo/Abp/Dapr/DaprApiTokenProvider.cs
  59. 8
      framework/src/Volo.Abp.Dapr/Volo/Abp/Dapr/IAbpDaprClientFactory.cs
  60. 4
      framework/src/Volo.Abp.Dapr/Volo/Abp/Dapr/IDaprApiTokenProvider.cs
  61. 2
      framework/src/Volo.Abp.Ddd.Application.Contracts/Volo.Abp.Ddd.Application.Contracts.csproj
  62. 8
      framework/src/Volo.Abp.Ddd.Application.Contracts/Volo/Abp/Application/Dtos/AuditedEntityWithUserDto.cs
  63. 4
      framework/src/Volo.Abp.Ddd.Application.Contracts/Volo/Abp/Application/Dtos/CreationAuditedEntityWithUserDto.cs
  64. 2
      framework/src/Volo.Abp.Ddd.Application.Contracts/Volo/Abp/Application/Dtos/EntityDto.cs
  65. 8
      framework/src/Volo.Abp.Ddd.Application.Contracts/Volo/Abp/Application/Dtos/ExtensibleAuditedEntityWithUserDto.cs
  66. 4
      framework/src/Volo.Abp.Ddd.Application.Contracts/Volo/Abp/Application/Dtos/ExtensibleCreationAuditedEntityWithUserDto.cs
  67. 2
      framework/src/Volo.Abp.Ddd.Application.Contracts/Volo/Abp/Application/Dtos/ExtensibleEntityDto.cs
  68. 12
      framework/src/Volo.Abp.Ddd.Application.Contracts/Volo/Abp/Application/Dtos/ExtensibleFullAuditedEntityWithUserDto.cs
  69. 12
      framework/src/Volo.Abp.Ddd.Application.Contracts/Volo/Abp/Application/Dtos/FullAuditedEntityWithUserDto.cs
  70. 2
      framework/src/Volo.Abp.Ddd.Application.Contracts/Volo/Abp/Application/Dtos/ISortedResultRequest.cs
  71. 4
      framework/src/Volo.Abp.Ddd.Application.Contracts/Volo/Abp/Application/Dtos/LimitedResultRequestDto.cs
  72. 4
      framework/src/Volo.Abp.Ddd.Application.Contracts/Volo/Abp/Application/Dtos/ListResultDto.cs
  73. 4
      framework/src/Volo.Abp.Ddd.Application.Contracts/Volo/Abp/Application/Dtos/PagedAndSortedResultRequestDto.cs
  74. 2
      framework/src/Volo.Abp.Ddd.Application/Volo.Abp.Ddd.Application.csproj
  75. 6
      framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/AbstractKeyCrudAppService.cs
  76. 6
      framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/AbstractKeyReadOnlyAppService.cs
  77. 20
      framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/ApplicationService.cs
  78. 2
      framework/src/Volo.Abp.Ddd.Domain.Shared/Volo.Abp.Ddd.Domain.Shared.csproj
  79. 6
      framework/src/Volo.Abp.Ddd.Domain.Shared/Volo/Abp/Domain/Entities/Events/Distributed/EntityEto.cs
  80. 2
      framework/src/Volo.Abp.Ddd.Domain.Shared/Volo/Abp/Domain/Entities/Events/Distributed/EtoMappingDictionary.cs
  81. 4
      framework/src/Volo.Abp.Ddd.Domain.Shared/Volo/Abp/Domain/Entities/Events/Distributed/EtoMappingDictionaryItem.cs
  82. 3
      framework/src/Volo.Abp.Ddd.Domain.Shared/Volo/Abp/Domain/Entities/Events/Distributed/IEntityToEtoMapper.cs
  83. 2
      framework/src/Volo.Abp.Ddd.Domain/Volo.Abp.Ddd.Domain.csproj
  84. 10
      framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/DependencyInjection/AbpCommonDbContextRegistrationOptions.cs
  85. 2
      framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/DependencyInjection/IAbpCommonDbContextRegistrationOptionsBuilder.cs
  86. 2
      framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/DependencyInjection/MultiTenantDbContextType.cs
  87. 8
      framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Auditing/AuditedAggregateRootWithUser.cs
  88. 8
      framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Auditing/AuditedEntityWithUser.cs
  89. 4
      framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Auditing/CreationAuditedAggregateRootWithUser.cs
  90. 4
      framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Auditing/CreationAuditedEntityWithUser.cs
  91. 12
      framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Auditing/FullAuditedAggregateRootWithUser.cs
  92. 12
      framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Auditing/FullAuditedEntityWithUser.cs
  93. 12
      framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Caching/EntityCacheBase.cs
  94. 6
      framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Caching/EntityCacheServiceCollectionExtensions.cs
  95. 2
      framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Caching/EntityCacheWithObjectMapper.cs
  96. 2
      framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Caching/EntityCacheWithoutCacheItem.cs
  97. 3
      framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Caching/IEntityCache.cs
  98. 8
      framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Entity.cs
  99. 16
      framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/EntityHelper.cs
  100. 7
      framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Events/Distributed/EntitySynchronizer.cs

2
Directory.Build.props

@ -43,7 +43,7 @@
<IsTestProject Condition="$(MSBuildProjectFullPath.Contains('test')) and ($(MSBuildProjectName.EndsWith('.Tests')) or $(MSBuildProjectName.EndsWith('.TestBase')))">true</IsTestProject> <IsTestProject Condition="$(MSBuildProjectFullPath.Contains('test')) and ($(MSBuildProjectName.EndsWith('.Tests')) or $(MSBuildProjectName.EndsWith('.TestBase')))">true</IsTestProject>
<!-- OpenIddict https://www.nuget.org/packages/OpenIddict.Core --> <!-- OpenIddict https://www.nuget.org/packages/OpenIddict.Core -->
<OpenIddictPackageVersion>4.6.0</OpenIddictPackageVersion> <OpenIddictPackageVersion>4.7.0</OpenIddictPackageVersion>
</PropertyGroup> </PropertyGroup>

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

@ -470,19 +470,18 @@
"SubTotal": "Sub Total", "SubTotal": "Sub Total",
"TotalDue": "Total Due", "TotalDue": "Total Due",
"QuotationNo": "Quotation no", "QuotationNo": "Quotation no",
"ValidFor": "Valid for", "ValidTill": "Valid till",
"QuotationNote": "Quotation note", "QuotationNote": "Quotation note",
"QuotationTemplate.Address": "Address",
"QuotationTemplate.Address:": "Address:", "QuotationTemplate.Address:": "Address:",
"QuotationTemplate.VATNo": "VAT No", "QuotationTemplate.VATNo:": "VAT No:",
"QuotationTemplate.Phone": "Phone", "QuotationTemplate.Phone:": "Phone:",
"QuotationTemplate.E-mail": "E-mail", "QuotationTemplate.E-mail:": "E-mail:",
"QuotationTemplate.Quotation": "Quotation", "QuotationTemplate.Quotation": "Quotation",
"QuotationTemplate.To": "To", "QuotationTemplate.To": "To",
"QuotationTemplate.Details": "Details", "QuotationTemplate.Details": "Details",
"QuotationTemplate.QuotationNo:": "Quotation:", "QuotationTemplate.QuotationNo:": "Quotation #:",
"QuotationTemplate.IssueDate:": "Issue Date:", "QuotationTemplate.IssueDate:": "Issue Date:",
"QuotationTemplate.ValidFor:": "Valid For:", "QuotationTemplate.ValidTill:": "Valid Till:",
"QuotationTemplate.ValidDays": "{0} Days", "QuotationTemplate.ValidDays": "{0} Days",
"QuotationTemplate.Description": "Description", "QuotationTemplate.Description": "Description",
"QuotationTemplate.UnitPrice": "Unit Price", "QuotationTemplate.UnitPrice": "Unit Price",
@ -490,10 +489,10 @@
"QuotationTemplate.Discount": "Discount", "QuotationTemplate.Discount": "Discount",
"QuotationTemplate.Total": "Total", "QuotationTemplate.Total": "Total",
"QuotationTemplate.Notes": "Notes", "QuotationTemplate.Notes": "Notes",
"QuotationTemplate.SubTotal": "Sub Total", "QuotationTemplate.SubTotal:": "Sub Total :",
"QuotationTemplate.Tax/VAT": "Tax / VAT (%{0})", "QuotationTemplate.Tax/VAT:": "Tax / Vat (%{0}) :",
"QuotationTemplate.TotalDiscount": "Total Discount", "QuotationTemplate.TotalDiscount:": "Total Discount :",
"QuotationTemplate.TotalDue": "Total Due", "QuotationTemplate.TOTALDUE:": "TOTAL DUE :",
"QuotationTemplate.ThanksForYourBusiness": "Thanks for your business!" "QuotationTemplate.BankAccount": "Our bank account information can be found at {0}"
} }
} }

20
abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/tr.json

@ -423,28 +423,26 @@
"SubTotal": "Ara Toplam", "SubTotal": "Ara Toplam",
"TotalDue": "NET TOPLAM", "TotalDue": "NET TOPLAM",
"DiscountAmount": "İndirim Tutarı", "DiscountAmount": "İndirim Tutarı",
"QuotationTemplate.Address": "Adres",
"QuotationTemplate.Address:": "Adres:", "QuotationTemplate.Address:": "Adres:",
"QuotationTemplate.VATNo": "Vergi Dairesi/No", "QuotationTemplate.VATNo:": "Vergi Dairesi/No:",
"QuotationTemplate.Phone": "Telefon", "QuotationTemplate.Phone:": "Telefon:",
"QuotationTemplate.E-mail": "E-posta", "QuotationTemplate.E-mail:": "E-posta:",
"QuotationTemplate.Quotation": "Fiyat Teklifi", "QuotationTemplate.Quotation": "Fiyat Teklifi",
"QuotationTemplate.To": "Müşteri", "QuotationTemplate.To": "Müşteri",
"QuotationTemplate.Details": "Detay", "QuotationTemplate.Details": "Detay",
"QuotationTemplate.QuotationNo:": "Teklif No:", "QuotationTemplate.QuotationNo:": "Teklif No:",
"QuotationTemplate.IssueDate:": "Teklif Tarihi:", "QuotationTemplate.IssueDate:": "Teklif Tarihi:",
"QuotationTemplate.ValidFor:": "Geçerlilik Süresi:", "QuotationTemplate.ValidTill:": "Geçerlilik Tarihi:",
"QuotationTemplate.ValidDays": "{0} Gün",
"QuotationTemplate.Description": "Açıklama", "QuotationTemplate.Description": "Açıklama",
"QuotationTemplate.UnitPrice": "Birim Fiyat", "QuotationTemplate.UnitPrice": "Birim Fiyat",
"QuotationTemplate.Qty": "Adet", "QuotationTemplate.Qty": "Adet",
"QuotationTemplate.Discount": "İndirim", "QuotationTemplate.Discount": "İndirim",
"QuotationTemplate.Total": "Tutar", "QuotationTemplate.Total": "Tutar",
"QuotationTemplate.Notes": "Notlar", "QuotationTemplate.Notes": "Notlar",
"QuotationTemplate.SubTotal": "Alt Toplam", "QuotationTemplate.SubTotal:": "Alt Toplam :",
"QuotationTemplate.Tax/VAT": "Vergiler (%{0})", "QuotationTemplate.Tax/VAT:": "Vergiler (%{0}) :",
"QuotationTemplate.TotalDiscount": "Toplam İndirim", "QuotationTemplate.TotalDiscount:": "Toplam İndirim :",
"QuotationTemplate.TotalDue": "NET TOPLAM", "QuotationTemplate.TOTALDUE:": "NET TOPLAM :",
"QuotationTemplate.ThanksForYourBusiness": "Değerli siparişlerinizi bekleriz." "QuotationTemplate.BankAccount": "Banka hesabı bilgilerimiz {0} adresinde bulunabilir."
} }
} }

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

@ -213,12 +213,13 @@
"SpringCampaign": "Welcome <br>Spring Sale!", "SpringCampaign": "Welcome <br>Spring Sale!",
"SpringCampaign2": "<span>Limited <br> Time Offer!</span>", "SpringCampaign2": "<span>Limited <br> Time Offer!</span>",
"AboutUs": "About Us", "AboutUs": "About Us",
"HowItWorks": "How it works?", "HowItWorks": "How it Works?",
"ReleaseNotes": "Release Notes", "ReleaseNotes": "Release Notes",
"DetailedChangeNotes" : "Detailed Change Notes", "DetailedChangeNotes" : "Detailed Change Notes",
"SeeTrainings": "See Trainings", "SeeTrainings": "See Trainings",
"NoContent": "No content", "NoContent": "No content",
"ABPStudioBeta": "ABP Studio <span class=\"badge border rounded fw--5\" style=\"border-color: #B84297 !important;\">BETA</span>", "More": "More",
"More": "More" "WhyABPIOPlatform": "Why ABP.IO Platform?",
"AbpStudio": "ABP Studio"
} }
} }

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

@ -618,7 +618,7 @@
"TrialLicensePaymentInfoSection_Description": "<strong>شراء رخصة:</strong> بشراء رخصة، ستستمر في الحصول على <a href=\"{0}\" target=\"_blank\" rel=\"noopener\">الدعم المتميز</a>. ستتمكن أيضًا من الحصول على تحديثات رئيسية أو ثانوية للوحدات والسمات. ستتمكن من الاستمرار في إنشاء مشاريع جديدة. وستظل قادرًا على استخدام <a href=\"{1}\" target=\"_blank\" rel=\"noopener\">ABP Suite</a> مما يسرع من تطويرك.<br> راجع <a href=\"{2}\" target=\"_blank\" rel=\"noopener\">جدول مقارنة الرخصة</a> للتحقق من الاختلافات بين أنواع الرخص.", "TrialLicensePaymentInfoSection_Description": "<strong>شراء رخصة:</strong> بشراء رخصة، ستستمر في الحصول على <a href=\"{0}\" target=\"_blank\" rel=\"noopener\">الدعم المتميز</a>. ستتمكن أيضًا من الحصول على تحديثات رئيسية أو ثانوية للوحدات والسمات. ستتمكن من الاستمرار في إنشاء مشاريع جديدة. وستظل قادرًا على استخدام <a href=\"{1}\" target=\"_blank\" rel=\"noopener\">ABP Suite</a> مما يسرع من تطويرك.<br> راجع <a href=\"{2}\" target=\"_blank\" rel=\"noopener\">جدول مقارنة الرخصة</a> للتحقق من الاختلافات بين أنواع الرخص.",
"SelectTargetLicense": "حدد الرخصة المرادة", "SelectTargetLicense": "حدد الرخصة المرادة",
"UpgradePaymentInfoSection_ExtendMyLicenseForOneYear": "نعم، قم بتمديد تاريخ انتهاء رخصتي لمدة عام واحد.", "UpgradePaymentInfoSection_ExtendMyLicenseForOneYear": "نعم، قم بتمديد تاريخ انتهاء رخصتي لمدة عام واحد.",
"UpgradePaymentInfoSection_WantToExtendLicense": "هل تريد تمديد ترخيصك لمدة {0} سنة (سنوات) أخرى؟", "UpgradePaymentInfoSection_WantToExtendLicense": "هل تريد تمديد ترخيصك لمدة 1 سنة (سنوات) أخرى؟",
"UpgradePaymentInfoSection_UpgradingWillNotExtendLicense": "لن تؤدي الترقية إلى تمديد تاريخ انتهاء رخصتك!", "UpgradePaymentInfoSection_UpgradingWillNotExtendLicense": "لن تؤدي الترقية إلى تمديد تاريخ انتهاء رخصتك!",
"UpgradePaymentInfoSection_LicenseUpgradeDescription": "من خلال ترقية رخصتك، ستقوم بالترقية إلى نوع رخصة أعلى مما سيتيح لك الحصول على مزايا إضافية. راجع <a href=\"/Pricing\" target=\"_blank\">جدول مقارنة الرخص</a> للتحقق من الاختلافات بين أنواع الرخص.", "UpgradePaymentInfoSection_LicenseUpgradeDescription": "من خلال ترقية رخصتك، ستقوم بالترقية إلى نوع رخصة أعلى مما سيتيح لك الحصول على مزايا إضافية. راجع <a href=\"/Pricing\" target=\"_blank\">جدول مقارنة الرخص</a> للتحقق من الاختلافات بين أنواع الرخص.",
"Landing_Page_CustomerStories": "قصص العملاء", "Landing_Page_CustomerStories": "قصص العملاء",

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

@ -501,6 +501,7 @@
"DoYouNeedTraining": "Do you need {0} training?", "DoYouNeedTraining": "Do you need {0} training?",
"GetInTouchUs": "Get in touch with us", "GetInTouchUs": "Get in touch with us",
"ForMoreInformationClickHere": "For more information, click <a href='{0}'>here.</a>", "ForMoreInformationClickHere": "For more information, click <a href='{0}'>here.</a>",
"ForMoreInformationClickHereByClass": "<span class=\"{1}\">For more information, click</span> <a href='{0}'>here.</a>",
"IsGetOnboardingTraining": "Would you like to get onboarding & web application development training?", "IsGetOnboardingTraining": "Would you like to get onboarding & web application development training?",
"OnboardingWebApplicationDevelopmentTrainingMessage": "To schedule your training calendar, please contact {0} after creating the organization", "OnboardingWebApplicationDevelopmentTrainingMessage": "To schedule your training calendar, please contact {0} after creating the organization",
"CustomPurchaseMessage": "For the next step, click {0} to contact us.", "CustomPurchaseMessage": "For the next step, click {0} to contact us.",
@ -600,7 +601,7 @@
"TotalDeveloperPrice": "Total Developer Price", "TotalDeveloperPrice": "Total Developer Price",
"Purchase_PricePerDeveloper": "<span>{0} {1}</span> per developer", "Purchase_PricePerDeveloper": "<span>{0} {1}</span> per developer",
"Purchase_IncludedDeveloperInfo": "{0} {1} included.", "Purchase_IncludedDeveloperInfo": "{0} {1} included.",
"Purchase_LicenseExtraDeveloperPurchaseMessage": "The <span class=\"fw-6\">{0} license</span> contains {1} developer(s). You can add additional developers now or later.", "Purchase_LicenseExtraDeveloperPurchaseMessage": "The <span class=\"fw-bold\">{0} License</span> includes {1} developers. You can add additional developers.",
"StartupTemplates_Page_Title": "ABP Startup Templates", "StartupTemplates_Page_Title": "ABP Startup Templates",
"StartupTemplates_Page_Description": "ABP Commercial allows you to build solutions with any level of complexity. It provides two main pre-built startup solutions. You can select the one close to your requirements and build your own custom solution on top of it.", "StartupTemplates_Page_Description": "ABP Commercial allows you to build solutions with any level of complexity. It provides two main pre-built startup solutions. You can select the one close to your requirements and build your own custom solution on top of it.",
"MicroserviceStartupSolutionForDotnet": "Microservice Startup Solution for .NET", "MicroserviceStartupSolutionForDotnet": "Microservice Startup Solution for .NET",
@ -643,7 +644,7 @@
"TrialLicensePaymentInfoSection_Description": "<strong>Purchase license:</strong> By purchasing a license, you will continue to get <a href=\"{0}\" target=\"_blank\" rel=\"noopener\">premium support</a>. You will also be able to get major or minor updates for modules and themes. You will be able to continue creating new projects. And you will still be able to use <a href=\"{1}\" target=\"_blank\" rel=\"noopener\">ABP Suite</a> which speeds up your development.<br>See the <a href=\"{2}\" target=\"_blank\" rel=\"noopener\">license comparison table</a> to check the differences between the license types.", "TrialLicensePaymentInfoSection_Description": "<strong>Purchase license:</strong> By purchasing a license, you will continue to get <a href=\"{0}\" target=\"_blank\" rel=\"noopener\">premium support</a>. You will also be able to get major or minor updates for modules and themes. You will be able to continue creating new projects. And you will still be able to use <a href=\"{1}\" target=\"_blank\" rel=\"noopener\">ABP Suite</a> which speeds up your development.<br>See the <a href=\"{2}\" target=\"_blank\" rel=\"noopener\">license comparison table</a> to check the differences between the license types.",
"SelectTargetLicense": "Select Target License", "SelectTargetLicense": "Select Target License",
"UpgradePaymentInfoSection_ExtendMyLicenseForOneYear": "Yes, extend my license expiration date for 1 year.", "UpgradePaymentInfoSection_ExtendMyLicenseForOneYear": "Yes, extend my license expiration date for 1 year.",
"UpgradePaymentInfoSection_WantToExtendLicense": "Do you want to extend your license for {0} more year(s)?", "UpgradePaymentInfoSection_WantToExtendLicense": "Do you want to extend your license for 1 more year?",
"UpgradePaymentInfoSection_UpgradingWillNotExtendLicense": "Upgrading will not extend your license expiration date!", "UpgradePaymentInfoSection_UpgradingWillNotExtendLicense": "Upgrading will not extend your license expiration date!",
"UpgradePaymentInfoSection_LicenseUpgradeDescription": "By upgrading your license, you will promote to a higher license type which will allow you to get additional benefits. See the <a href=\"/Pricing\" target=\"_blank\">license comparison table</a> to check the differences between the license types.", "UpgradePaymentInfoSection_LicenseUpgradeDescription": "By upgrading your license, you will promote to a higher license type which will allow you to get additional benefits. See the <a href=\"/Pricing\" target=\"_blank\">license comparison table</a> to check the differences between the license types.",
"Landing_Page_CustomerStories": "Customer Stories", "Landing_Page_CustomerStories": "Customer Stories",
@ -825,7 +826,7 @@
"ExpirationDate": "Expiration Date", "ExpirationDate": "Expiration Date",
"SpringCampaignDiscount": "Spring Campaign Discount", "SpringCampaignDiscount": "Spring Campaign Discount",
"WhyUseAbpIoPlatform": "Why should I use the ABP.IO Platform instead of creating a new solution from scratch?", "WhyUseAbpIoPlatform": "Why should I use the ABP.IO Platform instead of creating a new solution from scratch?",
"WhyUseAbpIoPlatformFaqExplanation": "See <a href=\"https://docs.abp.io/en/commercial/latest/why-abp-io-platform \"> that document </a> for a detailed explanation of why using ABP.IO Platform has a significant advantage over doing everything yourself.", "WhyUseAbpIoPlatformFaqExplanation": "See <a href=\"/why-abp-io \"> that page </a> for a detailed explanation of why using ABP.IO Platform has a significant advantage over doing everything yourself.",
"EulaPageTitle": "End User License Agreement (EULA)", "EulaPageTitle": "End User License Agreement (EULA)",
"PrivacyPolicyPageTitle": "Privacy Policy - Cookie Policy", "PrivacyPolicyPageTitle": "Privacy Policy - Cookie Policy",
"TermsConditionsPageTitle": "Terms and Conditions", "TermsConditionsPageTitle": "Terms and Conditions",
@ -907,8 +908,12 @@
"ExtraQuestionCreditsFaqExplanation": "Yes, you can. To buy extra question credits, send an e-mail to <a href=\"mailto:info@abp.io\">info@abp.io</a> with your organization's name. Here's the price list for the extra question credits: <ul><li>50 questions pack $999</li><li>25 questions pack $625</li><li>15 questions pack $450</li></ul>", "ExtraQuestionCreditsFaqExplanation": "Yes, you can. To buy extra question credits, send an e-mail to <a href=\"mailto:info@abp.io\">info@abp.io</a> with your organization's name. Here's the price list for the extra question credits: <ul><li>50 questions pack $999</li><li>25 questions pack $625</li><li>15 questions pack $450</li></ul>",
"AlreadyBetaTester": "You have already joined the beta tester program.", "AlreadyBetaTester": "You have already joined the beta tester program.",
"AbpStudio": "ABP Studio", "AbpStudio": "ABP Studio",
"AbpStudio_Description": "ABP Studio is still under development. You can fill out the form below to be one of the first users.",
"AbpStudio_Description1": "ABP Studio is a <span class=\"text-highlight-white\">cross-platform desktop application</span> for ABP developers.", "AbpStudio_Description1": "ABP Studio is a <span class=\"text-highlight-white\">cross-platform desktop application</span> for ABP developers.",
"AbpStudio_Description2": "It is <span class=\"text-highlight-white\">well integrated</span> to the ABP Framework and aims to provide a comfortable development environment for you by <span class=\"text-highlight-white\">automating things, providing insights</span> about your solution, making <span class=\"text-highlight-white\">develop, run</span> and <span class=\"text-highlight-white\">deploy</span> your solutions much easier.", "AbpStudio_Description2": "It is <span class=\"text-highlight-white\">well integrated</span> to the ABP Framework and aims to provide a comfortable development environment for you by <span class=\"text-highlight-white\">automating things, providing insights</span> about your solution, making <span class=\"text-highlight-white\">develop, run</span> and <span class=\"text-highlight-white\">deploy</span> your solutions much easier.",
"AbpStudio_ComingSoon": "Coming Soon <span class=\"opacity-50 ms-0 ms-md-3 d-block d-md-inline-block \">Planned beta release date: Q4 of 2023.</span>",
"AbpStudio_PlannedPreviewDate": "Planned preview release date: Q4 of 2023.",
"BetaRequest": "Beta Request",
"CreateNewSolutions": "Create New Solutions", "CreateNewSolutions": "Create New Solutions",
"CreateNewSolutions_Description1": "You can create from simple applications to modular monolith or microservice solutions easily with a lot of options. You get a full production-ready base software solution for your business.", "CreateNewSolutions_Description1": "You can create from simple applications to modular monolith or microservice solutions easily with a lot of options. You get a full production-ready base software solution for your business.",
"ArchitectYourSolutions": "Architect Your Solutions", "ArchitectYourSolutions": "Architect Your Solutions",
@ -963,6 +968,111 @@
"OneCodeBaseMultipleDevices": "One Code-Base Multiple Devices", "OneCodeBaseMultipleDevices": "One Code-Base Multiple Devices",
"OneCodeBaseMultipleDevices_Description": "ABP Mobile applications are cross-platform. They are ready to be installed and run on iOS and Android devices, and they adapt to different form-factors using a single code base. Developers only need to create the UI and front-end code once, there is no need to adapt the code for each device you want to support.", "OneCodeBaseMultipleDevices_Description": "ABP Mobile applications are cross-platform. They are ready to be installed and run on iOS and Android devices, and they adapt to different form-factors using a single code base. Developers only need to create the UI and front-end code once, there is no need to adapt the code for each device you want to support.",
"ComesWithTheSourceCode": "Comes with the Source-Code", "ComesWithTheSourceCode": "Comes with the Source-Code",
"ComesWithTheSourceCode_Description": "The mobile apps are provided with the source-code. Easily customize the UX/UI of your apps to meet branding guidelines." "ComesWithTheSourceCode_Description": "The mobile apps are provided with the source-code. Easily customize the UX/UI of your apps to meet branding guidelines.",
"Purchase_OneYearPrice": "1 Year Price",
"Purchase_DeveloperSeatCount": "Developer Seat Count",
"Purchase_DevelopersAlreadyIncluded": "{0} developers already included",
"1Year": "1 year",
"{0}Years": "{0} years",
"1YearLicense": "1 year license",
"{0}YearsLicense": "{0} years license",
"1AdditionalDeveloper": "1 additional developer",
"{0}AdditionalDevelopers": "{0} additional developers",
"Discount": "Discount ({0}%)",
"Summary": "Summary",
"TrainingPack": "Training pack",
"TrainingPackDiscount": "Training pack discount",
"Purchase_OnboardingTraining_Description": "This live training package is discounted when purchase with the new license. This discounted price is valid only for new license purchases. <a href=\"{0}\" class=\"text-white\">Learn more <i class=\"fa fa-external-link ms-1\"></i></a>",
"Purchase_Save": "{0}% <span class=\"save ms-1\">Save {1} {2}</span>",
"RemoveBasket": "Remove from basket",
"WhyABPIOPlatform?": "Why <span class=\"gradient-commercial\">ABP.IO Platform</span>?",
"DocumentAim": "This document aims to answer the big question:",
"DocumentAim_Description": "\"Why should you use the ABP.IO Platform instead of creating a new solution from scratch?\"",
"DocumentAim_Description2": "The document introduces the challenges of building a modern software solution and explains how ABP addresses these challenges.",
"CreatingANewSolution": "Creating a New Solution",
"CreatingANewSolution_Description": "When you need to start a new solution, there are a lot of questions you need to ask yourself, and you should spend a lot of time before starting to write your very first business code.",
"CreatingAnEmptySolution": "Creating an Empty Solution",
"THEPROBLEM": "THE PROBLEM",
"CreatingAnEmptySolution_THEPROBLEM_Description": "Even creating an almost-empty solution is challenging;",
"CreatingAnEmptySolution_THEPROBLEM_Description2": "How do you organize your codebase across projects?",
"CreatingAnEmptySolution_THEPROBLEM_Description3": "What are the layers and how do they interact?",
"CreatingAnEmptySolution_THEPROBLEM_Description4": "How do you integrate to 3rd-party library and systems?",
"CreatingAnEmptySolution_THEPROBLEM_Description5": "How to set up the automated tests?",
"ABPSOLUTION": "ABP SOLUTION",
"CreatingAnEmptySolution_ABPSOLUTION_Description": "ABP provides a well-architected, layered and production-ready <a href=\"https://docs.abp.io/en/abp/latest/Startup-Templates/Application\" target=\"_blank\">startup solution</a> based on the <a href=\"https://docs.abp.io/en/abp/latest/Domain-Driven-Design\" target=\"_blank\">Domain Driven Design</a> principles. The solution also includes a pre-configured unit and integration <a href=\"https://docs.abp.io/en/abp/latest/Testing\" target=\"_blank\">test</a> projects for each layer.",
"CommonLibraries": "Common Libraries",
"CommonLibraries_THEPROBLEM_Description": "Which libraries should you use to implement common requirements? The software development ecosystem is highly dynamic and it is hard to follow the latest tools, libraries, trends and approaches.",
"CommonLibraries_ABPSOLUTION_Description": "ABP pre-integrates the popular, mature and up-to-date libraries into the solution. You don't spend time integrating them and talking to each other. They properly work out of the box.",
"UITheme&Layout": "UI Theme & Layout",
"UITheme&Layout_THEPROBLEM_Description": "When it comes to the UI, there are a lot of challenges, including preparing a foundation to create a responsive, modern and flexible UI kit with a consistent look & feel and tons of features (like left/top navigation menu, header, toolbar, footer, widgets and so.).",
"UITheme&Layout_THEPROBLEM_Description2": "Even if you buy a pre-built theme, integrating it into your solution may take days of development. Upgrading such a theme is another problem. Most of the time, the theme's HTML/CSS structure is mixed with your UI code, and it is not easy to upgrade or change the theme later.",
"UITheme&Layout_ABPSOLUTION_Description": "ABP Framework provides a <a href=\"https://docs.abp.io/en/abp/latest/UI/AspNetCore/Theming\" target=\"_blank\"> theming</a> system that makes your UI code independent from the theme. Themes are isolated, and they are NuGet/NPM packages. Installing or upgrading a theme is just a minute. While you can build your theme (or integrate an existing theme), ABP Commercial offers professional and modern <a href=\"/themes\">themes</a>.",
"UITheme&Layout_ABPSOLUTION_Description2": "There are also UI component providers (like Telerik and DevExpress). But they only provide individual components. You are responsible for creating your own layout system. You can use such libraries in your ABP-based solutions just like in any other project.",
"TestInfrastructure": "Test Infrastructure",
"TestInfrastructure_THEPROBLEM_Description": "Preparing a robust test environment takes time. You need to setup test projects in your solution, select the tools, mock the services and database, create the required base classes and utility services to reduce repeating code in the tests and so on.",
"TestInfrastructure_ABPSOLUTION_Description": "ABP Startup Templates comes with the test projects already configured for you, and you can immediately write your first unit or integration test code on day 1.",
"CodingStandards&Training": "Coding Standards & Training",
"CodingStandards&Training_THEPROBLEM_Description": "Once you create the development-ready solution, you typically need to train the developers to explain the system and develop it with the same conventions in a standard and consistent way. Even if you train the developers, it is hard to prepare and maintain your documentation. Over time, every developer will write the code differently, and coding standards will begin to diverge.",
"CodingStandards&Training_ABPSOLUTION_Description": "ABP solution is already well-defined and well-documented. <a href=\"https://docs.abp.io/en/abp/latest/Tutorials/Part-1\" target=\"_blank\">Tutorials</a> and <a href=\"https://docs.abp.io/en/abp/latest/Best-Practices/Index\" target=\"_blank\">best practice guides</a> clearly explain how to make development on an ABP project.",
"KeepingYourSolutionUpToDate": "Keeping Your Solution Up to Date",
"KeepingYourSolutionUpToDate_THEPROBLEM_Description": "After you start your development, you must keep track of the new versions of the libraries you use for upgrades & patches.",
"KeepingYourSolutionUpToDate_ABPSOLUTION_Description": "We regularly update all packages to the latest versions and test them before the stable release. When you update the ABP Framework, all its dependencies are upgraded to edge technology.",
"KeepingYourSolutionUpToDate_ABPSOLUTION_Description2": "<a class=\"text-primary\">Abp update</span> <a href=\"https://docs.abp.io/en/abp/latest/CLI\" target=\"_blank\">CLI </a> command automatically discovers and upgrades all ABP-dependant NuGet and NPM packages in a solution. With ABP, it is easier to stay with the latest versions.",
"DRY": "Don't Repeat Yourself!",
"DRY_Description": "Creating a base solution takes significant time and requires well architectural experience. However, this is just the beginning! As you start developing, you will likely have to write lots of repetitive code; that would be great if all this could be handled automatically.",
"DRY_Description2": "ABP automates and simplifies repeating code as much as possible by following the convention over configuration principle. However, it doesn't restrict you when you need to switch to manual gear. The control is always in your hands.",
"Authentication": "Authentication",
"Authentication_THEPROBLEM_Description": "Single Sign On, Active Directory / LDAP Integration, OpenIddict integration, social logins, two-factor authentication, forgot/reset password, email activation, new user registration, password complexity control, locking account on failed attempts, showing failed login attemps ... etc. We know that all these generic requirements are familiar to you. You are not alone!",
"Authentication_ABPSOLUTION_Description": "ABP Framework and the commercial version provide all these standard stuff pre-implemented for you as a re-usable account module. You just enable and configure what you need.",
"CrossCuttingConcerns": "Cross-Cutting Concerns",
"CrossCuttingConcerns_THEPROBLEM_Description": "Cross-Cutting Concerns are the fundamental repeating logic that should be implementedfor each use case. Some examples;",
"CrossCuttingConcerns_THEPROBLEM_Description2": "Starting transactions, committing on success and rollback on errors.",
"CrossCuttingConcerns_THEPROBLEM_Description3": "Handling and reporting exceptions, returning a proper error response to the clients and handling error cases on the client-side.",
"CrossCuttingConcerns_THEPROBLEM_Description4": "Implementing authorization and validation, returning proper responses and handling these on the client-side.",
"CrossCuttingConcerns_ABPSOLUTION_Description": "ABP Framework automates or simplifies all the common cross-cutting concerns. You only write code that matters for your business and ABP handles the rest by conventions.",
"ArchitecturalInfrastructure": "Architectural Infrastructure",
"ArchitecturalInfrastructure_THEPROBLEM_Description": "You typically need to build infrastructure to implement your architecture properly. For example, you generally implement the Repository pattern. You define some base classes to simplify and standardize to create entities, services, controllers and other objects.",
"ArchitecturalInfrastructure_ABPSOLUTION_Description": "ABP Framework provides all these and more out of the box. It is mature and well-documented.",
"EnterpriseApplicationRequirements": "Enterprise Application Requirements",
"EnterpriseApplicationRequirements_THEPROBLEM_Description": "There are a lot of requirements you repeatedly implement in every business application;",
"EnterpriseApplicationRequirements_THEPROBLEM_Description2": "Detailed permission system and managing permissions on the UI based on roles and users.",
"EnterpriseApplicationRequirements_THEPROBLEM_Description3": "Writing audit logs and entity histories to track when a user modifies a database record.",
"EnterpriseApplicationRequirements_THEPROBLEM_Description4": "Make your entities soft delete, so they are marked as deleted instead of physically deleting from the database and automatically filtering deleted entities on your queries.",
"EnterpriseApplicationRequirements_THEPROBLEM_Description5": "Creating abstractions and wrappers to consume your backend APIs from the frontend code.",
"EnterpriseApplicationRequirements_THEPROBLEM_Description6": "Enqueuing and executing background jobs.",
"EnterpriseApplicationRequirements_THEPROBLEM_Description7": "Handling multiple time zones in a global system.",
"EnterpriseApplicationRequirements_THEPROBLEM_Description8": "Sharing validation, localization, authorization logic between server and client.",
"EnterpriseApplicationRequirements_ABPSOLUTION_Description": "ABP provides infrastructure to implement such requirements easily. Again, you don't spend your valuable time to re-implement all these again and again.",
"GeneratingInitialCode&Tooling": "Generating Initial Code & Tooling",
"GeneratingInitialCode&Tooling_THEPROBLEM_Description": "You will build many similar pages in a typical web application. Most of them will perform similar CRUD operations. It is very tedious and also error prone to repeatedly create such pages.",
"GeneratingInitialCode&Tooling_ABPSOLUTION_Description": "<a href=\"/tools/suite\">ABP Suite</a> can generate a full-stack CRUD page for your entities in seconds. The generated code is layered and clean. All the standard validation and authorization requirements are implemented. Plus, unit test classes are generated. Once you get a fully running page, you can modify it according to your business requirements.",
"IntegratingTo3rdPartyLibrariesAndSystems": "Integrating to 3rd-Party Libraries and Systems",
"IntegratingTo3rdPartyLibrariesAndSystems_THEPROBLEM_Description": "Most libraries are designed as low level, and you typically do some work to integrate them properly without repeating the same integration and configuration code everywhere in your solution. For example, assume you must use RabbitMQ to implement your distributed event bus. All you want to do is; send a message to a queue and handle the incoming messages. But you need to understand messaging patterns, queue and exchange details. To write an efficient code, you must create a pool to manage connections, clients and channels. You also must deal with exceptions, ACK messages, re-connecting to RabbitMQ on failures and more.",
"IntegratingTo3rdPartyLibrariesAndSystems_ABPSOLUTION_Description": "For example, ABP's RabbitMQ Distributed Event Bus integration abstracts all these details. You send and receive messages without the hustle and bustle. Do you need to write low-level code? No problem, you can always do that. ABP doesn't restrict you when you need to use low-level features of the library you are using.",
"WhyNotBuildYourOwnFramework?": "Why Not Build Your Own Framework?",
"WhyNotBuildYourOwnFramework_THEPROBLEM_Description": "All the infrastructure, even in the most simple way, takes a lot of time to build, maintain and document. It gets bigger over time, and it becomes hard to maintain it in your solution. Separating these into a re-usable project is the starting point for building your own internal framework.",
"WhyNotBuildYourOwnFramework_THEPROBLEM_Description2": "Building, documenting, training and maintaining an internal framework is really hard. If you don't have an experienced, dedicated framework team, your internal framework rapidly becomes an undocumented legacy code that no one can understand and maintain anymore. On the other hand, these frameworks are generally developed by one or two developers in the team. And these fellows are becoming a knowledge silo. It is good for them but bad for the company because they are the project's single point of failure <a href=\"https://en.wikipedia.org/wiki/Single_point_of_failure\">-SPOF-</a>. Once they leave the company, the project dramatically goes down.",
"WhyNotBuildYourOwnFramework_ABPSOLUTION_Description": "ABP Framework is a community-driven, well-documented, mature and generic application framework. A team of highly experienced developers are working hard to keep it up-to-date, easy to understand and comfortable to use. Using such a stable framework makes you focus on your own business code and get help with the framework from experts whenever you need it.",
"ArchitecturalInfrastructure_Description": "SaaS applications, modular or microservice systems are most used enterprise software models. Building such systems not only requires a good understanding and experience, but also requires a strong software infrastructure. Otherwise, you will find yourself spending a great effort to support these architectural details in your codebase.",
"Modularity": "Modularity",
"Modularity_THEPROBLEM_Description": "Building a truly modular system is not easy! All the aspects of the system (database, entities, APIs, UI pages/components) can be split into modules, and each module can be re-usable without others. The plain ASP.NET Core doesn't provide such a modular architecture. If you need it, you should think about it from scratch.",
"Modularity_ABPSOLUTION_Description": "The ABP Framework is born to be a modular application development structure. Every feature in the framework is developed to be compatible with modularity. Documentation and guides explain how to develop re-usable modules in a standard way.",
"SaaSMultiTenancy": "SaaS / Multi-Tenancy",
"SaaSMultiTenancy_THEPROBLEM_Description": "<a href=\"https://docs.abp.io/en/abp/latest/Multi-Tenancy\">Multi-Tenancy</a> is a common way to implement SaaS systems. However, implementing a consistent multi-tenant infrastructure may become complicated.",
"SaaSMultiTenancy_ABPSOLUTION_Description": "ABP Framework provides a complete multi-tenant infrastructure and abstract complexity from your business code. Your application code will be mostly multi-tenancy aware while the ABP Framework automatically isolates the database, cache and other details of the tenants from each other. It supports single database, per tenant database and hybrid approaches. It properly configures the libraries like Microsoft Identity and OpenIddict, which are not normally multi-tenancy compatible.",
"Microservices": "Microservices",
"Microservices_THEPROBLEM_Description": "Building a microservice system requires many infrastructure details: Authenticating and authorizing applications and microservices and implementing asynchronous messaging and synchronous (Rest/GRPC) communication patterns between microservices are the most fundamental issues.",
"Microservices_ABPSOLUTION_Description": "The ABP Framework provides services, <a href=\"https://docs.abp.io/en/abp/latest/Microservice-Architecture\" target=\"_blank\">guides</a>, and samples to help you implement your microservice solution using the industry standard tools.",
"Microservices_ABPSOLUTION_Description2": "ABP Commercial even goes one step further and provides a complete <a href=\"https://docs.abp.io/en/commercial/latest/startup-templates/microservice/index\" target=\"_blank\">startup template</a> to kick-start your microservice solution.",
"PreBuiltModules": "Pre-Built Modules",
"PreBuiltModules_THEPROBLEM_Description": "All of us have similar but slightly different business requirements. However, we all should re-invent the wheel since no one's code can directly work in our solution. They are all embedded parts of a larger solution.",
"PreBuiltModules_ABPSOLUTION_Description":"ABP Commercial <a href=\"/modules\">modules</a> provides a lot of re-usable application modules like payment, chat, file management, audit log reporting... etc. All of these modules are easily installed into your solution and directly work. We are constantly adding more modules.",
"PreBuiltModules_ABPSOLUTION_Description2": "All modules are designed as customizable for your business requirements. If you need complete control, you can download the full source code of any module and completely customize based on your specific business requirements.",
"ABPCommunity": "ABP Community",
"ABPCommunity_Description": "Finally, Being in a big community where everyone follows similar coding styles and principles and shares a common infrastructure brings power when you have troubles or need help with design decisions. Since we write code similarly, we can help each other much better. ABP is a community-backed project with more then 10K stars on GitHub.",
"ABPCommunity_Description2": "It is easy to share code or even re-usable libraries between ABP developers. A code snippet that works for you will also work for others. There are a lot of samples and tutorials that you can directly implement for your application.",
"ABPCommunity_Description3": "When you hire a developer who worked before with the ABP architecture will immediately understand your solution and start development in a very short time.",
"WhyAbpIo_Page_Title": "Why ABP.IO Platform?",
"AbpStudio_Page_Title": "ABP Studio"
} }
} }

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

@ -642,7 +642,7 @@
"TrialLicensePaymentInfoSection_Description": "<strong>Osta käyttölupa:</strong> Ostamalla lisenssin saat edelleen <a href=\"{0}\" target=\"_blank\" rel=\"noopener\">premium-tuen</a>. Voit myös saada suurempia tai pieniä päivityksiä moduuleille ja teemoille. Voit jatkaa uusien projektien luomista. Voit edelleen käyttää <a href=\"{1}\" target=\"_blank\" rel=\"noopener\">ABP Suitea</a>, joka nopeuttaa kehitystäsi.<br>Katso <a href=\" {2}\" target=\"_blank\" rel=\"noopener\">käyttölupien vertailutaulukko</a>, jolla voit tarkistaa lisenssityyppien väliset erot.", "TrialLicensePaymentInfoSection_Description": "<strong>Osta käyttölupa:</strong> Ostamalla lisenssin saat edelleen <a href=\"{0}\" target=\"_blank\" rel=\"noopener\">premium-tuen</a>. Voit myös saada suurempia tai pieniä päivityksiä moduuleille ja teemoille. Voit jatkaa uusien projektien luomista. Voit edelleen käyttää <a href=\"{1}\" target=\"_blank\" rel=\"noopener\">ABP Suitea</a>, joka nopeuttaa kehitystäsi.<br>Katso <a href=\" {2}\" target=\"_blank\" rel=\"noopener\">käyttölupien vertailutaulukko</a>, jolla voit tarkistaa lisenssityyppien väliset erot.",
"SelectTargetLicense": "Valitse kohdelisenssi", "SelectTargetLicense": "Valitse kohdelisenssi",
"UpgradePaymentInfoSection_ExtendMyLicenseForOneYear": "Kyllä, jatka lisenssini voimassaolopäivää 1 vuodella.", "UpgradePaymentInfoSection_ExtendMyLicenseForOneYear": "Kyllä, jatka lisenssini voimassaolopäivää 1 vuodella.",
"UpgradePaymentInfoSection_WantToExtendLicense": "Haluatko jatkaa lisenssiäsi vielä {0} vuodella?", "UpgradePaymentInfoSection_WantToExtendLicense": "Haluatko jatkaa lisenssiäsi vielä 1 vuodella?",
"UpgradePaymentInfoSection_UpgradingWillNotExtendLicense": "Päivitys ei pidennä lisenssisi vanhenemispäivää!", "UpgradePaymentInfoSection_UpgradingWillNotExtendLicense": "Päivitys ei pidennä lisenssisi vanhenemispäivää!",
"UpgradePaymentInfoSection_LicenseUpgradeDescription": "Päivittämällä lisenssisi ylennät korkeampaan lisenssityyppiin, mikä antaa sinulle lisäetuja. Katso lisenssityyppien väliset erot <a href=\"/Pricing\" target=\"_blank\">lisenssivertailutaulukosta</a>.", "UpgradePaymentInfoSection_LicenseUpgradeDescription": "Päivittämällä lisenssisi ylennät korkeampaan lisenssityyppiin, mikä antaa sinulle lisäetuja. Katso lisenssityyppien väliset erot <a href=\"/Pricing\" target=\"_blank\">lisenssivertailutaulukosta</a>.",
"Landing_Page_CustomerStories": "Asiakkaiden tarinoita", "Landing_Page_CustomerStories": "Asiakkaiden tarinoita",

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

@ -642,7 +642,7 @@
"TrialLicensePaymentInfoSection_Description": "<strong>Licensz vásárlása: licensz</strong> megvásárlásával továbbra is <a href=\"{0}\" target=\"_blank\" rel=\"noopener\">prémium támogatást</a> kap . Emellett kisebb-nagyobb frissítéseket is kaphat a modulokhoz és témákhoz. Folytathatja új projektek létrehozását. És továbbra is használhatja az <a href=\"{1}\" target=\"_blank\" rel=\"noopener\">ABP Suite</a> -ot, amely felgyorsítja a fejlesztést.<br> Tekintse meg a <a href=\"{2}\" target=\"_blank\" rel=\"noopener\">licensz-összehasonlító táblázatot</a> a licensztípusok közötti különbségek ellenőrzéséhez.", "TrialLicensePaymentInfoSection_Description": "<strong>Licensz vásárlása: licensz</strong> megvásárlásával továbbra is <a href=\"{0}\" target=\"_blank\" rel=\"noopener\">prémium támogatást</a> kap . Emellett kisebb-nagyobb frissítéseket is kaphat a modulokhoz és témákhoz. Folytathatja új projektek létrehozását. És továbbra is használhatja az <a href=\"{1}\" target=\"_blank\" rel=\"noopener\">ABP Suite</a> -ot, amely felgyorsítja a fejlesztést.<br> Tekintse meg a <a href=\"{2}\" target=\"_blank\" rel=\"noopener\">licensz-összehasonlító táblázatot</a> a licensztípusok közötti különbségek ellenőrzéséhez.",
"SelectTargetLicense": "Válassza a Target License lehetőséget", "SelectTargetLicense": "Válassza a Target License lehetőséget",
"UpgradePaymentInfoSection_ExtendMyLicenseForOneYear": "Igen, meghosszabbítom az engedélyem lejárati dátumát 1 évvel.", "UpgradePaymentInfoSection_ExtendMyLicenseForOneYear": "Igen, meghosszabbítom az engedélyem lejárati dátumát 1 évvel.",
"UpgradePaymentInfoSection_WantToExtendLicense": "Szeretné meghosszabbítani licenszét további {0} évre?", "UpgradePaymentInfoSection_WantToExtendLicense": "Szeretné meghosszabbítani licenszét további 1 évre?",
"UpgradePaymentInfoSection_UpgradingWillNotExtendLicense": "A frissítés nem hosszabbítja meg a licensz lejárati dátumát!", "UpgradePaymentInfoSection_UpgradingWillNotExtendLicense": "A frissítés nem hosszabbítja meg a licensz lejárati dátumát!",
"UpgradePaymentInfoSection_LicenseUpgradeDescription": "Licenszének frissítésével magasabb licensztípusra lép, amely további előnyökhöz juttatja Önt. Tekintse meg a <a href=\"/Pricing\" target=\"_blank\">licensz-összehasonlító táblázatot</a> a licensztípusok közötti különbségek ellenőrzéséhez.", "UpgradePaymentInfoSection_LicenseUpgradeDescription": "Licenszének frissítésével magasabb licensztípusra lép, amely további előnyökhöz juttatja Önt. Tekintse meg a <a href=\"/Pricing\" target=\"_blank\">licensz-összehasonlító táblázatot</a> a licensztípusok közötti különbségek ellenőrzéséhez.",
"Landing_Page_CustomerStories": "Ügyféltörténetek", "Landing_Page_CustomerStories": "Ügyféltörténetek",

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

@ -511,6 +511,7 @@
"DoYouNeedTraining": "{0} eğitimine ihtiyacınız var mı?", "DoYouNeedTraining": "{0} eğitimine ihtiyacınız var mı?",
"GetInTouchUs": "Bize Ulaşın", "GetInTouchUs": "Bize Ulaşın",
"ForMoreInformationClickHere": "Daha fazla bilgi için <a href='{0}'>buraya tıklayın.</a>", "ForMoreInformationClickHere": "Daha fazla bilgi için <a href='{0}'>buraya tıklayın.</a>",
"ForMoreInformationClickHereByClass": "<span class=\"{1}\">Daha fazla bilgi için</span> <a href='{0}'>buraya tıklayın.</a>",
"IsGetOnboardingTraining": "İşe alım ve web uygulaması geliştirme eğitimi almak ister misiniz?", "IsGetOnboardingTraining": "İşe alım ve web uygulaması geliştirme eğitimi almak ister misiniz?",
"OnboardingWebApplicationDevelopmentTrainingMessage": "Eğitim takviminizi planlamak için lütfen organizasyonu oluşturduktan sonra {0} ile iletişime geçin", "OnboardingWebApplicationDevelopmentTrainingMessage": "Eğitim takviminizi planlamak için lütfen organizasyonu oluşturduktan sonra {0} ile iletişime geçin",
"CustomPurchaseMessage": "Bir sonraki adım için, bizimle iletişime geçmek üzere {0}'a tıklayın.", "CustomPurchaseMessage": "Bir sonraki adım için, bizimle iletişime geçmek üzere {0}'a tıklayın.",
@ -650,7 +651,7 @@
"TrialLicensePaymentInfoSection_Description": "<strong>Lisans satın alma:</strong> Bir lisans satın alarak <a href=\"{0}\" target=\"_blank\" rel=\"noopener\">premium destek</a> almaya devam edeceksiniz. Ayrıca modüller ve temalar için büyük veya küçük güncellemeler alabileceksiniz. Yeni projeler oluşturmaya devam edebileceksiniz. Ve gelişiminizi hızlandıran <a href=\"{1}\" target=\"_blank\" rel=\"noopener\">ABP Suite</a>'i kullanmaya devam edebileceksiniz. Lisans türleri arasındaki farkları kontrol etmek için <a href=\"{2}\" target=\"_blank\" rel=\"noopener\">lisans karşılaştırma tablosu</a>na bakın.", "TrialLicensePaymentInfoSection_Description": "<strong>Lisans satın alma:</strong> Bir lisans satın alarak <a href=\"{0}\" target=\"_blank\" rel=\"noopener\">premium destek</a> almaya devam edeceksiniz. Ayrıca modüller ve temalar için büyük veya küçük güncellemeler alabileceksiniz. Yeni projeler oluşturmaya devam edebileceksiniz. Ve gelişiminizi hızlandıran <a href=\"{1}\" target=\"_blank\" rel=\"noopener\">ABP Suite</a>'i kullanmaya devam edebileceksiniz. Lisans türleri arasındaki farkları kontrol etmek için <a href=\"{2}\" target=\"_blank\" rel=\"noopener\">lisans karşılaştırma tablosu</a>na bakın.",
"SelectTargetLicense": "Hedef Lisansı Seçin", "SelectTargetLicense": "Hedef Lisansı Seçin",
"UpgradePaymentInfoSection_ExtendMyLicenseForOneYear": "Evet, lisansımın geçerlilik süresini 1 yıl uzatın.", "UpgradePaymentInfoSection_ExtendMyLicenseForOneYear": "Evet, lisansımın geçerlilik süresini 1 yıl uzatın.",
"UpgradePaymentInfoSection_WantToExtendLicense": "Lisansınızı {0} yıl daha uzatmak istiyor musunuz?", "UpgradePaymentInfoSection_WantToExtendLicense": "Lisansınızı 1 yıl daha uzatmak istiyor musunuz?",
"UpgradePaymentInfoSection_UpgradingWillNotExtendLicense": "Yükseltme işlemi lisansınızın son kullanma tarihini uzatmayacaktır!", "UpgradePaymentInfoSection_UpgradingWillNotExtendLicense": "Yükseltme işlemi lisansınızın son kullanma tarihini uzatmayacaktır!",
"UpgradePaymentInfoSection_LicenseUpgradeDescription": "Lisansınızı yükselterek, ek avantajlar elde etmenizi sağlayacak daha yüksek bir lisans türüne terfi edeceksiniz. Lisans türleri arasındaki farkları kontrol etmek için <a href=\"/Pricing\" target=\"_blank\">lisans karşılaştırma tablosuna</a> bakın.", "UpgradePaymentInfoSection_LicenseUpgradeDescription": "Lisansınızı yükselterek, ek avantajlar elde etmenizi sağlayacak daha yüksek bir lisans türüne terfi edeceksiniz. Lisans türleri arasındaki farkları kontrol etmek için <a href=\"/Pricing\" target=\"_blank\">lisans karşılaştırma tablosuna</a> bakın.",
"Landing_Page_CustomerStories": "Müşteri Hikayeleri", "Landing_Page_CustomerStories": "Müşteri Hikayeleri",

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

@ -641,7 +641,7 @@
"TrialLicensePaymentInfoSection_Description": "<strong>购买许可证:</strong>通过购买许可证,您将继续获得<a href=\"{0}\" target=\"_blank\" rel=\"noopener\">高级支持</a>。 您还将能够获得模块和主题的重大更新。 您将能够继续创建新项目。 而且您仍然可以使用 <a href=\"{1}\" target=\"_blank\" rel=\"noopener\">ABP 套件</a> 加速您的开发。<br>请参阅 <a href=\"{2}\" target=\"_blank\" rel=\"noopener\">许可证比较表</a>来查看许可证类型之间的差异。", "TrialLicensePaymentInfoSection_Description": "<strong>购买许可证:</strong>通过购买许可证,您将继续获得<a href=\"{0}\" target=\"_blank\" rel=\"noopener\">高级支持</a>。 您还将能够获得模块和主题的重大更新。 您将能够继续创建新项目。 而且您仍然可以使用 <a href=\"{1}\" target=\"_blank\" rel=\"noopener\">ABP 套件</a> 加速您的开发。<br>请参阅 <a href=\"{2}\" target=\"_blank\" rel=\"noopener\">许可证比较表</a>来查看许可证类型之间的差异。",
"SelectTargetLicense": "选择目标许可证", "SelectTargetLicense": "选择目标许可证",
"UpgradePaymentInfoSection_ExtendMyLicenseForOneYear": "是的,将我的许可证到期日期延长 1 年。", "UpgradePaymentInfoSection_ExtendMyLicenseForOneYear": "是的,将我的许可证到期日期延长 1 年。",
"UpgradePaymentInfoSection_WantToExtendLicense": "您想将许可证再延长 {0} 年吗?", "UpgradePaymentInfoSection_WantToExtendLicense": "您想将许可证再延长 1 年吗?",
"UpgradePaymentInfoSection_UpgradingWillNotExtendLicense": "升级不会延长您的许可证到期日期!", "UpgradePaymentInfoSection_UpgradingWillNotExtendLicense": "升级不会延长您的许可证到期日期!",
"UpgradePaymentInfoSection_LicenseUpgradeDescription": "通过升级您的许可证,您将升级到更高的许可证类型,这将使您获得额外的好处。 请参阅<a href=\"/Pricing\" target=\"_blank\">许可证比较表</a>以查看许可证类型之间的差异。", "UpgradePaymentInfoSection_LicenseUpgradeDescription": "通过升级您的许可证,您将升级到更高的许可证类型,这将使您获得额外的好处。 请参阅<a href=\"/Pricing\" target=\"_blank\">许可证比较表</a>以查看许可证类型之间的差异。",
"Landing_Page_CustomerStories": "客户故事", "Landing_Page_CustomerStories": "客户故事",

10
docs/en/Best-Practices/Entities.md

@ -28,6 +28,7 @@ Every aggregate root is also an entity. So, these rules are valid for aggregate
- **Do** keep the entity as always **valid** and **consistent** within its own boundary. - **Do** keep the entity as always **valid** and **consistent** within its own boundary.
- **Do** define properties with `private`, `protected`, `internal ` or `protected internal` setter where it is needed to protect the entity consistency and validity. - **Do** define properties with `private`, `protected`, `internal ` or `protected internal` setter where it is needed to protect the entity consistency and validity.
- **Do** define `public `, `internal` or `protected internal` (virtual) **methods** to change the properties (with non-public setters) if necessary. - **Do** define `public `, `internal` or `protected internal` (virtual) **methods** to change the properties (with non-public setters) if necessary.
- **Do** return the entity object (`this`) from the setter methods.
### Aggregate Roots ### Aggregate Roots
@ -86,15 +87,16 @@ public class Issue : FullAuditedAggregateRoot<Guid> //Using Guid as the key/iden
Labels = new Collection<IssueLabel>(); //Always initialize the collection Labels = new Collection<IssueLabel>(); //Always initialize the collection
} }
public virtual void SetTitle([NotNull] string title) public virtual Issue SetTitle([NotNull] string title)
{ {
Title = Check.NotNullOrWhiteSpace(title, nameof(title)); //Validate Title = Check.NotNullOrWhiteSpace(title, nameof(title)); //Validate
return this;
} }
/* AddLabel & RemoveLabel methods manages the Labels collection /* AddLabel & RemoveLabel methods manages the Labels collection
* in a safe way (prevents adding the same label twice) */ * in a safe way (prevents adding the same label twice) */
public virtual void AddLabel(Guid labelId) public virtual Issue AddLabel(Guid labelId)
{ {
if (Labels.Any(l => l.LabelId == labelId)) if (Labels.Any(l => l.LabelId == labelId))
{ {
@ -102,11 +104,13 @@ public class Issue : FullAuditedAggregateRoot<Guid> //Using Guid as the key/iden
} }
Labels.Add(new IssueLabel(Id, labelId)); Labels.Add(new IssueLabel(Id, labelId));
return this;
} }
public virtual void RemoveLabel(Guid labelId) public virtual Issue RemoveLabel(Guid labelId)
{ {
Labels.RemoveAll(l => l.LabelId == labelId); Labels.RemoveAll(l => l.LabelId == labelId);
return this;
} }
/* Close & ReOpen methods protect the consistency /* Close & ReOpen methods protect the consistency

125
docs/en/Community-Articles/2023-08-07-Basic-Theme-Dark-Mode/POST.md

@ -0,0 +1,125 @@
# Adding Dark Mode Support to the Basic Theme
Basic Theme uses plain bootstrap and does not have any custom colors & styles. This article will show you how to add dark mode support to the [Basic Theme](https://docs.abp.io/en/abp/latest/UI/AspNetCore/Basic-Theme).
Bootstrap brings the [Color Modes](https://getbootstrap.com/docs/5.3/customize/color-modes/#dark-mode) feature with version **5.3**. This feature allows you to add dark mode support to your website with a single line of code. Adding the `data-bs-theme="dark"` attribute changes the color mode of the element to dark mode.
## Instructions
1. Create a new project with the following command:
```bash
abp new BasicThemeDarkMode -t app --theme basic
```
2. Create a component that toggles the color mode.
- Create a new file named `Components/ChangeTheme/Default.cshtml`:
```html
<div class="text-light mt-1">
<button class="btn text-light" href="#" id="ToolbarChangeTheme">
<i class="fas fa-sun"></i>
</button>
</div>
```
- Create a new file named `Components/ChangeTheme/ChangeThemeViewComponent.cs`:
```csharp
using Microsoft.AspNetCore.Mvc;
using Volo.Abp.AspNetCore.Mvc;
namespace BasicThemeDarkMode.Web.Components.ChangeTheme;
[Widget(ScriptFiles = new[]{"/Components/ChangeTheme/ChangeTheme.js"})]
public class ChangeThemeViewComponent : AbpViewComponent
{
public IViewComponentResult Invoke()
{
return View("~/Components/ChangeTheme/Default.cshtml");
}
}
```
- Create a JavaScript that manages the last selected theme and toggles the color mode. It stores the last selected theme in the *local storage*. So, you don't need to store it in the database.
- Create a new file named `Components/ChangeTheme/ChangeTheme.js`:
```js
$(function () {
function changeTheme(theme) {
window.localStorage.setItem('theme', theme);
document.getElementsByTagName('body')[0].setAttribute('data-bs-theme', theme);
}
function toggleTheme(){
getTheme() == 'light' ? changeTheme('dark') : changeTheme('light');
}
function getTheme(){
return window.localStorage.getItem('theme') ?? 'dark';
}
function init(){
let theme = getTheme();
if(theme){
changeTheme(theme);
}
}
document.getElementById('ToolbarChangeTheme').addEventListener('click', () => {
toggleTheme();
});
init();
});
```
3. Create a new [Toolbar Contributor](https://docs.abp.io/en/abp/latest/UI/AspNetCore/Toolbars) and add a newly created view component to the application toolbar.
- Create a new class named `BasicThemeDarkModeToolbarContributor.cs`:
```csharp
using BasicThemeDarkMode.Web.Components.ChangeTheme;
using System.Threading.Tasks;
using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Toolbars;
namespace BasicThemeDarkMode.Web;
public class BasicThemeDarkModeToolbarContributor : IToolbarContributor
{
public Task ConfigureToolbarAsync(IToolbarConfigurationContext context)
{
if (context.Toolbar.Name == StandardToolbars.Main)
{
context.Toolbar.Items
.Add(new ToolbarItem(typeof(ChangeThemeViewComponent)));
}
return Task.CompletedTask;
}
}
```
- Configure [Toolbar Options](https://docs.abp.io/en/abp/latest/UI/AspNetCore/Toolbars) and add a newly created contributor:
```csharp
Configure<AbpToolbarOptions>(options =>
{
options.Contributors.Add(new BasicThemeDarkModeToolbarContributor());
});
```
That's it! Now, you can toggle the color mode by clicking the sun icon in the toolbar:
![Dark Mode](basictheme-toggle-demo.gif)
- Users Page in Dark Mode:
![Users Page in Dark Mode](basictheme-dark-users.png)
- Settings Page in Dark Mode:
![Settings Page in Dark Mode](basictheme-dark-settings.png)
- Login Page in Dark Mode:
![Login Page in Dark Mode](basictheme-dark-login.png)
## Conclusion
The theme is stored in **local storage** and it's initialized on the client-side. You can use **Cookies** to render the page in the last selected theme on **server-side** to prevent the flash effect while navigating pages. This document shows the concept of adding dark mode support of bootstrap to the Basic Theme.

BIN
docs/en/Community-Articles/2023-08-07-Basic-Theme-Dark-Mode/basictheme-dark-login.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

BIN
docs/en/Community-Articles/2023-08-07-Basic-Theme-Dark-Mode/basictheme-dark-settings.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

BIN
docs/en/Community-Articles/2023-08-07-Basic-Theme-Dark-Mode/basictheme-dark-users.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

BIN
docs/en/Community-Articles/2023-08-07-Basic-Theme-Dark-Mode/basictheme-toggle-demo.gif

Binary file not shown.

After

Width:  |  Height:  |  Size: 189 KiB

148
docs/en/Community-Articles/2023-08-12-ABP-Commercial-GDPR-Module-Overview/POST.md

@ -0,0 +1,148 @@
# ABP Commercial - GDPR Module Overview
In this article, I will highlight ABP Commercial's [GDPR Module](https://commercial.abp.io/modules/Volo.Gdpr) and show you how to provide personal data to the GDPR Module that is collected by your application and make it aligned with personal data download results.
## GDPR Module
[GDPR Module](https://docs.abp.io/en/commercial/latest/modules/gdpr) allows users to download and delete the data collected by the application. It's used for Personal Data Management obligating by the GDPR regulation and provides the following features:
* Allows users to request their personal data.
* Lists the personal data requests and users can download their personal data by the listed request times.
* Allows users to delete their personal data and their accounts permanently.
The GDPR module is pre-installed in the [Application](https://docs.abp.io/en/commercial/latest/startup-templates/application/index) and [Application (Single Layer)](https://docs.abp.io/en/commercial/latest/startup-templates/application-single-layer/index) Pro Startup templates for ABP Commercial customers. Therefore, most of the time you don't need to manually install it.
> If you need to install the GDPR Module manually, you can refer to the [GDPR Module documentation](https://docs.abp.io/en/commercial/latest/modules/gdpr#how-to-install).
Let's create an Application template with the following command and see the UI for the GDPR module:
```csharp
abp new GdprDemo -t app-pro
```
After the application is created, we can run the application and login to the application. Then, when we check the user menu, we should be able to see the "Personal Data" menu item:
![](./gdpr-personal-data-menu.png)
We can click this menu item to navigate to the "Personal Data Management" page:
![](./gdpr-personal-data-page.png)
This page is used to manage personal data requests. You can view past requests, the current status of the latest request, create a new personal data download request, download the prepared personal data or delete all your personal data (makes the data anonymized) and account from the application.
### Downloading Personal Data
After a quick overview of the GDPR module, now we can deep dive into the Personal Data Download process.
The GDPR module requests information from the other modules that reference the `Volo.Abp.Gdpr.Abstractions` package and merges the response data into a single JSON file and the personal data can be downloaded later by the user from the "Personal Data Management" page when it's prepared (when the specified preparation time has been passed).
Currently, only the [Identity Pro module](https://docs.abp.io/en/commercial/latest/modules/identity) provides some personal data to the GDPR Module because it's the only module that can be considered as collecting personal data, such as the user's name, surname, email address, and so on. Therefore, ABP makes everything that is needed such as getting all data collected when the personal data download request has been made or deleting/anonymizing the personal data when the personal data delete request has been made.
This might be enough for some of your applications and you would not need to collect any other sensitive data from a user. However, most of the time you would probably need to collect some personal data from users for certain reasons.
In that case, you should provide the personal data that you collected for a certain user in your application/module or provider to the GPDR module. So, when the personal data download request has been made, the GDPR module can request the information from the different part of your application and merges the response data into a single JSON file to be downloaded. In other words, the data provided by you will be considered as personal data and whenever a user requests his/her personal data, it'll be included in the result.
In the next section, we will see how to provide personal data from a different module/provider.
## Providing Personal Data
Let's assume that we have an e-commerce application and we need to get the address from a user to send their order. Address information is considered as personal data according to GDPR regulations. Therefore, we need to provide the address information to the GDPR Module.
For this purpose, we need to subscribe to the `GdprUserDataDeletionRequestedEto` and `GdprUserDataRequestEto` distributed events. These ETOs (event transfer objects) come from the `Volo.Abp.Gdpr.Abstractions` package, which is used to start deleting/anonymizing and downloading personal data requests. `Volo.Abp.Gdpr.Domain` package is pre-installed in the domain layer and has reference to that package, so most of the time you don't need to reference to the `Volo.Abp.Gdpr.Abstractions` package.
But, if you want to use these ETOs in a different project, you should add the `Volo.Abp.Gdpr.Abstractions` package. You can use the following command to add it to your project:
```bash
abp add-package Volo.Abp.Gdpr.Abstractions
```
After we have ensured that we have reference to the package, then we can create a new event handler class named `AddressGdprEventHandler` and subscribe to the `GdprUserDataDeletionRequestedEto` and `GdprUserDataRequestEto` distributed events:
```csharp
public class AddressGdprEventHandler :
IDistributedEventHandler<GdprUserDataDeletionRequestedEto>,
IDistributedEventHandler<GdprUserDataRequestedEto>,
ITransientDependency
{
//inject your services
protected IDistributedEventBus EventBus { get; }
public AddressGdprEventHandler(IDistributedEventBus eventBus)
{
EventBus = eventBus;
}
public Task HandleEventAsync(GdprUserDataDeletionRequestedEto eventData)
{
//anonymize the personal data
return Task.CompletedTask;
}
public async Task HandleEventAsync(GdprUserDataRequestedEto eventData)
{
//assume we have retrieved the address for a certain user
//by querying eventData.UserId
var address = new Address
{
City = "Istanbul",
Postcode = "...",
//other properties...
};
var gdprDataInfo = new GdprDataInfo
{
{ "City", address.City },
{ "Postcode", address.Postcode }
};
await EventBus.PublishAsync(
new GdprUserDataPreparedEto
{
RequestId = eventData.RequestId,
Data = gdprDataInfo, //collected personal data
Provider = GetType().FullName //your module/provider name
});
}
}
```
* Here, we have subscribed to the `GdprUserDataDeletionRequestedEto` and `GdprUserDataRequestEto` distributed events.
* When a user made a personal data preparation request, then the `GdprUserDataRequestEto` is published by the GDPR module and the data preparation process starts. Modules/providers provide sensitive personal data by subscribing to this event and publishing a `GdprUserDataPreparedEto` distributed event, with the data and the provider information. Thanks to this, you can distinguish the personal data by the collected provider/module.
* Then, the GDPR module subscribes to the `GdprUserDataPreparedEto` distributed events that are published by multiple modules/providers and merge the response data into a single JSON file, and the personal data can be downloaded later by the user when the data preparation is done.
* On the other hand, when a user made a request to delete his/her personal data from the application, the `GdprUserDataDeletionRequestedEto` is published, so we can subscribe to the event and anonymize the personal data in our application.
* Also, the Identity Pro module deletes the user's account permanently.
Now, let's run the application once again and make a personal data download request. But before that, we can configure the `AbpGdprOptions` as follows to not wait for long and show our personal data result:
```csharp
Configure<AbpGdprOptions>(options =>
{
options.MinutesForDataPreparation = 5; //wait 5 minutes for data-preperation
});
```
After we have made a personal data preparation request, we need to wait for 5 minutes for personal data to be collected and then we can download it. After 5 minutes have passed, we can see the "Download" action button for the request on the "Personal Data Management" page:
![](./personal-data-download.png)
Then, when we clicked the download button, a zip file will be downloaded. We can unzip the file and examine the JSON files that contain our personal data. If you have followed and applied the steps from now, you should be seeing two JSON files. One of them is for user-specific information provided by the Identity Pro module and the other one is the address information provided by us (our application-specific personal data).
![](./personal-data-files.png)
*Basic information for the user:*
```json
{"Username":"admin","Name":"admin","Surname":null,"Email":"admin@abp.io","Phone Number":null}
```
*Address information that we provided in this article:*
```json
{"City":"Istanbul","Postcode":"..."}
```
## Conclusion
In this article, I've explained the GDPR Module's data collection system and given you a brief overview of the module. GDPR Module allows you to request to download personal data, delete/anonymize your own personal data and delete your account permanently. It's pre-installed in the Application and Application(single layer) Pro Startup templates, but you can easily configure it to your existing application.

BIN
docs/en/Community-Articles/2023-08-12-ABP-Commercial-GDPR-Module-Overview/cover-image.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 413 KiB

BIN
docs/en/Community-Articles/2023-08-12-ABP-Commercial-GDPR-Module-Overview/gdpr-personal-data-menu.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

BIN
docs/en/Community-Articles/2023-08-12-ABP-Commercial-GDPR-Module-Overview/gdpr-personal-data-page.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

BIN
docs/en/Community-Articles/2023-08-12-ABP-Commercial-GDPR-Module-Overview/personal-data-download.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

BIN
docs/en/Community-Articles/2023-08-12-ABP-Commercial-GDPR-Module-Overview/personal-data-files.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

94
docs/en/Migration-Guides/Abp-7_4.md

@ -0,0 +1,94 @@
# ABP Version 7.4 Migration Guide
This document is a guide for upgrading ABP v7.3 solutions to ABP v7.4. There are a few changes in this version that may affect your applications, please read it carefully and apply the necessary changes to your application.
## Renamed the `AddGlobalFilters<>` method as `FilterQueryable<>` in `IMongoDbRepositoryFilterer`
ABP Framework provides services to automatically filter data on querying from a database. Prior to this version, creating a new class that derives from the `MongoDbRepositoryFilterer` and overriding its `AddGlobalFilters` method was needed for implementing a data filter for [MongoDB](../MongoDB.md).
In this version, the `AddGlobalFilters<>` method is renamed as `FilterQueryable<>`. Therefore, you need to update the method name if you have used data filtering for MongoDB, in your application.
## Exposing Integration Services
[Integration Services](../Integration-Services.md) are now not being exposed by default. In a monolith application, integration services don't need to be exposed outside since the modules would probably be in-process communication with each other. Therefore, they don't need to be exposed for most of the time.
If you build a microservice solution or you need to access an integration service via a network call from any other application, you will probably need to expose the integration services so the other applications can consume them.
To expose integration services and controllers, you can configure the `AbpAspNetCoreMvcOptions` and set the `ExposeIntegrationServices` property as *true* in the `ConfigureServices` method of your [module class](../Module-Development-Basics.md):
```csharp
Configure<AbpAspNetCoreMvcOptions>(options =>
{
options.ExposeIntegrationServices = true;
});
```
## `LocalizationResource` property removed from the `TemplateDefinition` class
In this version, the `LocalizationResource` property was removed from the `TemplateDefinition` class and instead, the `LocalizationResourceName` property has been added.
```diff
- public Type LocalizationResource { get; set; }
+ public string LocalizationResourceName { get; set; }
```
## Changed the method signature for `ICorrelationIdProvider.Get()`
Prior to this version, the `ICorrelationIdProvider.Get()` method used to return a non nullable string that represented a *correlationId* (a unique key that is used in distributed applications to trace requests across multiple services/operations). In this version, this method may return `null` if it hasn't been generated by `AbpCorrelationIdMiddleware` before.
```diff
public interface ICorrelationIdProvider
{
- [NotNull] string Get();
+ string? Get();
//other methods
}
```
Therefore, if you've used this method in your application, you might want to make a null check and update the method signature where it's used.
> See [#16795](https://github.com/abpframework/abp/pull/16795) for more information.
## Dynamic Setting Store - Setting Management Module
In this version, ABP Framework introduces Dynamic Setting Store, which is an important feature that allows us to collect and get all setting definitions from a single point. This feature requires some actions that need to be taken care of as the following:
* You need to create a new migration and apply it to your database because a new database table has been added.
* `ISettingDefinitionManager`'s sync methods have been removed and instead, asynchronous versions of the existing methods have been added.
```diff
public interface ISettingDefinitionManager
{
- SettingDefinition Get([NotNull] string name);
+ Task<SettingDefinition> GetAsync([NotNull] string name);
- IReadOnlyList<SettingDefinition> GetAll();
+ Task<IReadOnlyList<SettingDefinition>> GetAllAsync();
- SettingDefinition? GetOrNull(string name);
+ Task<SettingDefinition?> GetOrNullAsync([NotNull] string name);
}
```
## `IdentityUserIntegrationService` - Identity Module
In this version, ABP Framework introduces the `IdentityUserIntegrationService`, which is designed to get the current user's information, such as his/her role names within a non-authorized integration service.
> For more information, see the related PR: [#16962](https://github.com/abpframework/abp/pull/16962)
This is a breaking change for microservice solutions because of the following two reasons and it should be considered:
* `IdentityUserIntegrationService` provides non-authorized services. This is not breaking the application, but should be taken care of. Since, everyone can use the service to retrieve some information for a certain user (for example, the role names of a user).
* Secondly, since integration services are not exposed by default anymore as explained in the *Exposing Integration Services* section above, you should explicitly enable exposing integration services. Otherwise, the operation will fail and you'll get a `404` error from the identity microservice.
To expose integration services and controllers, you can configure the `AbpAspNetCoreMvcOptions` and set the `ExposeIntegrationServices` property as *true* in the `ConfigureServices` method of your [module class](../Module-Development-Basics.md):
```csharp
Configure<AbpAspNetCoreMvcOptions>(options =>
{
options.ExposeIntegrationServices = true;
});
```

1
docs/en/Migration-Guides/Index.md

@ -2,6 +2,7 @@
The following documents explain how to migrate your existing ABP applications. We write migration documents only if you need to take an action while upgrading your solution. Otherwise, you can easily upgrade your solution using the [abp update command](../Upgrading.md). The following documents explain how to migrate your existing ABP applications. We write migration documents only if you need to take an action while upgrading your solution. Otherwise, you can easily upgrade your solution using the [abp update command](../Upgrading.md).
- [7.3 to 7.4](Abp-7_4.md)
- [7.2 to 7.3](Abp-7_3.md) - [7.2 to 7.3](Abp-7_3.md)
- [7.1 to 7.2](Abp-7_2.md) - [7.1 to 7.2](Abp-7_2.md)
- [7.0 to 7.1](Abp-7_1.md) - [7.0 to 7.1](Abp-7_1.md)

12
docs/en/Modules/Docs.md

@ -22,22 +22,16 @@ When you use GitHub to store your docs, Docs Module supports versioning. If you
## Installation ## Installation
### 1- Download This document covers `Entity Framework Core` provider but you can also select `MongoDB` as your database provider.
If you do not have an existing ABP project, this step shows you how to create a new project from [abp.io](https://abp.io) to add the Docs Module. If you already have an ABP project, you can skip this step. ### 1- Creating an application
It is recommended to use ABP CLI to create new projects. Use the following command: If you do not have an existing ABP project, you can either [generate a CLI command from the get started page of the abp.io website](https://abp.io/get-started) and runs it or run the command below:
```bash ```bash
abp new Acme.MyProject abp new Acme.MyProject
``` ```
You can also generate a CLI command from [get started page](https://abp.io/get-started). Enter your project name as `Acme.MyProject`, other use default options.
Note that this document covers `Entity Framework Core` provider but you can also select `MongoDB` as your database provider.
![Create new project](../images/docs-module_download-new-abp-project.png)
### 2- Running The Empty Application ### 2- Running The Empty Application
After you download the project, extract the ZIP file and open `Acme.MyProject.sln`. You will see that the solution consists of `Application`, `Application.Contracts`, `DbMigrator`, `Domain`, `Domain.Shared`, `EntityFrameworkCore`, `HttpApi`, `HttpApi.Client` and `Web` projects. Right click on `Acme.MyProject.Web` project and **Set as StartUp Project**. After you download the project, extract the ZIP file and open `Acme.MyProject.sln`. You will see that the solution consists of `Application`, `Application.Contracts`, `DbMigrator`, `Domain`, `Domain.Shared`, `EntityFrameworkCore`, `HttpApi`, `HttpApi.Client` and `Web` projects. Right click on `Acme.MyProject.Web` project and **Set as StartUp Project**.

6
docs/en/Modules/Index.md

@ -4,8 +4,8 @@ ABP is a **modular application framework** which consists of dozens of **NuGet &
There are **two types of modules.** They don't have any structural difference but are categorized by functionality and purpose: There are **two types of modules.** They don't have any structural difference but are categorized by functionality and purpose:
* [**Framework modules**](https://github.com/abpframework/abp/tree/master/framework/src): These are **core modules of the framework** like caching, emailing, theming, security, serialization, validation, EF Core integration, MongoDB integration... etc. They do not have application/business functionalities but makes your daily development easier by providing common infrastructure, integration and abstractions. * [**Framework modules**](https://github.com/abpframework/abp/tree/dev/framework/src): These are **core modules of the framework** like caching, emailing, theming, security, serialization, validation, EF Core integration, MongoDB integration... etc. They do not have application/business functionalities but makes your daily development easier by providing common infrastructure, integration and abstractions.
* [**Application modules**](https://github.com/abpframework/abp/tree/master/modules): These modules implement specific application/business functionalities like blogging, document management, identity management, tenant management... etc. They generally have their own entities, services, APIs and UI components. * [**Application modules**](https://github.com/abpframework/abp/tree/dev/modules): These modules implement specific application/business functionalities like blogging, document management, identity management, tenant management... etc. They generally have their own entities, services, APIs and UI components.
## Open Source Application Modules ## Open Source Application Modules
@ -29,4 +29,4 @@ See [the GitHub repository](https://github.com/abpframework/abp/tree/dev/modules
## Commercial Application 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. [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.

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

@ -177,7 +177,8 @@ public class BookStoreSettingPageContributor : ISettingPageContributor
new SettingPageGroup( new SettingPageGroup(
"Volo.Abp.MySettingGroup", "Volo.Abp.MySettingGroup",
"MySettingGroup", "MySettingGroup",
typeof(MySettingGroupViewComponent) typeof(MySettingGroupViewComponent),
order : 1
) )
); );
@ -240,7 +241,8 @@ public class BookStoreSettingComponentContributor : ISettingComponentContributor
new SettingComponentGroup( new SettingComponentGroup(
"Volo.Abp.MySettingGroup", "Volo.Abp.MySettingGroup",
"MySettingGroup", "MySettingGroup",
typeof(MySettingGroupComponent) typeof(MySettingGroupComponent),
order : 1
) )
); );

27
docs/en/Modules/Tenant-Management.md

@ -48,6 +48,33 @@ The Features action opens a modal to enable/disable/set [features](../Features.m
*Manage Host features* button is used to set features for the host side, if you use the features of your application also in the host side. *Manage Host features* button is used to set features for the host side, if you use the features of your application also in the host side.
## Distributed Events
This module defines the following ETOs (Event Transfer Objects) to allow you to subscribe to changes on the entities of the module;
- `TenantEto` is published on changes done on an `Tenant` entity.
**Example: Get notified when a new tenant has been created**
```
public class MyHandler :
IDistributedEventHandler<EntityCreatedEto<TenantEto>>,
ITransientDependency
{
public async Task HandleEventAsync(EntityCreatedEto<TenantEto> eventData)
{
TenantEto tenant = eventData.Entity;
// TODO: ...
}
}
```
`TenantEto` is configured to automatically publish the events. You should configure yourself for the others. See the [Distributed Event Bus document](https://github.com/abpframework/abp/blob/rel-7.3/docs/en/Distributed-Event-Bus.md) to learn details of the pre-defined events.
> Subscribing to the distributed events is especially useful for distributed scenarios (like microservice architecture). If you are building a monolithic application, or listening events in the same process that runs the Tenant Management Module, then subscribing to the [local events](https://github.com/abpframework/abp/blob/rel-7.3/docs/en/Local-Event-Bus.md) can be more efficient and easier.
## Internals ## Internals
This section can be used as a reference if you want to [customize](../Customizing-Application-Modules-Guide.md) this module without changing [its source code](https://github.com/abpframework/abp/tree/dev/modules/tenant-management). This section can be used as a reference if you want to [customize](../Customizing-Application-Modules-Guide.md) this module without changing [its source code](https://github.com/abpframework/abp/tree/dev/modules/tenant-management).

80
docs/en/UI/Angular/CapsLock.directive.md

@ -0,0 +1,80 @@
# Caps Lock Directive
In password inputs, You may want to show if Caps Lock is on. To make this even easier, you can use the `TrackCapsLockDirective` which has been exposed by the `@abp/ng.core` package.
## Getting Started
`TrackCapsLockDirective` is standalone. In order to use the `TrackCapsLockDirective` in an HTML template, import it to related module or your standalone component:
**Importing to NgModule**
```ts
import { TrackCapsLockDirective } from '@abp/ng.core';
@NgModule({
//...
declarations: [
...,
TestComponent
],
imports: [
...,
TrackCapsLockDirective
],
})
export class MyFeatureModule {}
```
## Usage
The `TrackCapsLockDirective` is very easy to use. The directive's selector is **`abpCapsLock`**. By adding the `abpCapsLock` event to an element, you can track the status of Caps Lock. You can use this to warn user.
See an example usage:
**NgModule Component usage**
```ts
@Component({
selector: 'test-component',
template: `
<div class="d-flex flex-column">
<label>Password</label>
<input (abpCapsLock)="capsLock = $event"/>
<i *ngIf="capsLock">icon</i>
</div>
`
})
export class TestComponent{
capsLock = false;
}
```
**Standalone Component usage**
```ts
import { TrackCapsLockDirective } from '@abp/ng.core'
@Component({
selector: 'standalone-component',
standalone: true,
template: `
<div class="d-flex flex-column">
<label>Password</label>
<input (abpCapsLock)="capsLock = $event"/>
<i *ngIf="capsLock">icon</i>
</div>
`,
imports: [TrackCapsLockDirective]
})
export class StandaloneComponent{
capsLock = false;
}
```
The `abpCapsLock` event has been added to the `<input>` element. Press Caps Lock to activate the `TrackCapsLockDirective`.
See the result:
![Show Password directive](./images/CapsLockDirective1.png)
To see Caps Lock icon press Caps Lock.
![Show Password directive](./images/CapsLockDirective2.png)

6
docs/en/UI/Angular/Entity-Action-Extensions.md

@ -312,6 +312,8 @@ type EntityActionOptions<R = any> = {
icon?: string, icon?: string,
permission?: string, permission?: string,
visible?: ActionPredicate<R>, visible?: ActionPredicate<R>,
btnClass?: string,
btnStyle?: string,
}; };
``` ```
@ -322,6 +324,8 @@ As you see, passing `action` and `text` is enough to create an entity action. He
- **icon** is the classes that define an icon to be placed before the text. (_default:_ `''`) - **icon** is the classes that define an icon to be placed before the text. (_default:_ `''`)
- **permission** is the permission context which will be used to decide if this type of grid action should be displayed to the user or not. (_default:_ `undefined`) - **permission** is the permission context which will be used to decide if this type of grid action should be displayed to the user or not. (_default:_ `undefined`)
- **visible** is a predicate that will be used to decide if the current record should have this grid action or not. (_default:_ `() => true`) - **visible** is a predicate that will be used to decide if the current record should have this grid action or not. (_default:_ `() => true`)
- **btnClass** is the classes that will be applied to the button. (_default:_ `'btn btn-primary text-center'`)
- **btnStyle** is the styles that will be applied to the button. (_default:_ `''`)
You may find a full example below. You may find a full example below.
@ -339,6 +343,8 @@ const options: EntityActionOptions<IdentityUserDto> = {
icon: 'fa fa-unlock', icon: 'fa fa-unlock',
permission: 'AbpIdentity.Users.Update', permission: 'AbpIdentity.Users.Update',
visible: data => data.record.isLockedOut, visible: data => data.record.isLockedOut,
btnClass:'btn btn-warning text-center',
btnStyle: '', //Adds inline style
}; };
const action = new EntityAction(options); const action = new EntityAction(options);

30
docs/en/UI/Angular/Internet-Connection-Service.md

@ -0,0 +1,30 @@
# Internet Connection Service
`InternetConnectionService` is a service which is exposed by the `@abp/ng.core` package. **You can use this service in order to check your internet connection**
## Getting Started
When you inject the InternetConnectionService you can get the current internet status, and it gets immediately updated if the status changes.
`InternetConnectionService` provides two choices to catch the network status:
1. Signal (readonly)
2. Observable
# How To Use
İt's easy, just inject the service and get the network status.
**You can get via signal**
```ts
class SomeComponent{
internetConnectionService = inject(InternetConnectionService);
isOnline = this.internetConnectionService.networkStatus
}
```
**or you can get the observable**
```ts
class SomeComponent{
internetConnectionService = inject(InternetConnectionService);
isOnline = this.internetConnectionService.networkStatus$
}
```
To see how we implement to the template, check the `InternetConnectionStatusComponent`

77
docs/en/UI/Angular/Show-Password-Directive.md

@ -0,0 +1,77 @@
# Show Password Directive
In password input, text can be shown easily via changing input type attribute to `text`. To make this even easier, you can use the `ShowPasswordDirective` which has been exposed by the `@abp/ng.core` package.
## Getting Started
`ShowPasswordDirective` is standalone. In order to use the `ShowPasswordDirective` in an HTML template, import it to related module or your standalone component:
**Importing to NgModule**
```ts
import { ShowPasswordDirective } from '@abp/ng.core';
@NgModule({
//...
declarations: [
...,
TestComponent
],
imports: [
...,
ShowPasswordDirective
],
})
export class MyFeatureModule {}
```
## Usage
The `ShowPasswordDirective` is very easy to use. The directive's selector is **`abpShowPassword`**. By adding the `abpShowPassword` attribute to an input element, you can activate the `ShowPasswordDirective` for the input element.
See an example usage:
**NgModule Component usage**
```ts
@Component({
selector: 'test-component',
template: `
<div class="d-flex flex-column">
<label>Password</label>
<input [abpShowPassword]="showPassword"/>
<i (click)="showPassword = !showPassword">icon</i>
</div>
`
})
export class TestComponent{
showPassword = false;
}
```
**Standalone Component usage**
```ts
import { ShowPasswordDirective } from '@abp/ng.core';
@Component({
selector: 'standalone-component',
standalone: true,
template: `
<div class="d-flex flex-column">
<label>Password</label>
<input [abpShowPassword]="showPassword"/>
<i (click)="showPassword = !showPassword">icon</i>
</div>
`,
imports: [ShowPasswordDirective]
})
export class StandaloneComponent{
showPassword = false;
}
```
The `abpShowPassword` attribute has been added to the `<input>` element. Click icon to activate the `ShowPasswordDirective`.
See the result:
![Show Password directive](./images/showPasswordDirective1.png)
To see password input click icon.
![Show Password directive](./images/showPasswordDirective2.png)

46
docs/en/UI/Angular/Sorting-Navigation-Elements.md

@ -0,0 +1,46 @@
# Sorting Navigation Elements
This documentation describes how the navigation elements are sorted and how to change this default behaviour.
When you want to add the `Navigation Element` you can use the `RoutesService`. For more details, see the [document](https://docs.abp.io/en/abp/latest/UI/Angular/Modifying-the-Menu#how-to-add-a-navigation-element).
However, in this documentation, we will talk more about how to sort the navigation elements with the `order` attribute from the `Routes Service`.
### Order Property
- This parameter is optional and is used for sorting purposes.
- If you define this property it will be sorted by the default sorting function.
- You can edit this function.
**Default Compare Function;**
``compare-func.token.ts``
```ts
export const SORT_COMPARE_FUNC = new InjectionToken<0 | 1 | -1>('SORT_COMPARE_FUNC');
export function compareFuncFactory() {
const localizationService = inject(LocalizationService);
const fn = (a,b) => {
const aName = localizationService.instant(a.name);
const bName = localizationService.instant(b.name);
const aNumber = a.order;
const bNumber = b.order;
if (!Number.isInteger(aNumber)) return 1;
if (!Number.isInteger(bNumber)) return -1;
if (aNumber > bNumber) return 1
if (aNumber < bNumber) return -1
if (aName > bName ) return 1;
if (aName < bName ) return -1;
return 0
}
return fn;
}
```
**What does this function do?**
- if the order property is defined, then it will be sorted by the order value.
- if both of the navigation elements have the same order value then it will be sorted by the name.
- If the order property is not defined, it will be the last element and the unordered navs will be sorted by name.
You can edit this sorting function behaviour as you wish.

BIN
docs/en/UI/Angular/images/CapsLockDirective1.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

BIN
docs/en/UI/Angular/images/CapsLockDirective2.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

BIN
docs/en/UI/Angular/images/showPasswordDirective1.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

BIN
docs/en/UI/Angular/images/showPasswordDirective2.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

8
docs/en/docs-nav.json

@ -1188,6 +1188,10 @@
"text": "Modifying the Menu", "text": "Modifying the Menu",
"path": "UI/Angular/Modifying-the-Menu.md" "path": "UI/Angular/Modifying-the-Menu.md"
}, },
{
"text": "Sorting Navigation Elements",
"path": "UI/Angular/Sorting-Navigation-Elements.md"
},
{ {
"text": "Component Replacement", "text": "Component Replacement",
"path": "UI/Angular/Component-Replacement.md" "path": "UI/Angular/Component-Replacement.md"
@ -1522,6 +1526,10 @@
} }
] ]
}, },
{
"text": "API Documentation",
"path": "{ApiDocumentationUrl}"
},
{ {
"text": "Contribution Guide", "text": "Contribution Guide",
"path": "Contribution/Index.md" "path": "Contribution/Index.md"

6
docs/zh-Hans/Modules/Setting-Management.md

@ -146,7 +146,8 @@ public class BookStoreSettingPageContributor : ISettingPageContributor
new SettingPageGroup( new SettingPageGroup(
"Volo.Abp.MySettingGroup", "Volo.Abp.MySettingGroup",
"MySettingGroup", "MySettingGroup",
typeof(MySettingGroupViewComponent) typeof(MySettingGroupViewComponent),
order : 1
) )
); );
@ -209,7 +210,8 @@ public class BookStoreSettingComponentContributor : ISettingComponentContributor
new SettingComponentGroup( new SettingComponentGroup(
"Volo.Abp.MySettingGroup", "Volo.Abp.MySettingGroup",
"MySettingGroup", "MySettingGroup",
typeof(MySettingGroupComponent) typeof(MySettingGroupComponent),
order : 1
) )
); );

2
framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/Layout/PageHeader.razor

@ -50,7 +50,7 @@
@foreach (var toolbarItemRender in ToolbarItemRenders) @foreach (var toolbarItemRender in ToolbarItemRenders)
{ {
<Column ColumnSize="ColumnSize.IsAuto" Class="px-1 pt-2"> <Column ColumnSize="ColumnSize.IsAuto" Class="px-1 py-2">
@toolbarItemRender @toolbarItemRender
</Column> </Column>
} }

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

@ -227,10 +227,9 @@ public class AbpInputTagHelperService : AbpTagHelperService<AbpInputTagHelper>
var attribute = TagHelper.AspFor.ModelExplorer.GetAttribute<Placeholder>(); var attribute = TagHelper.AspFor.ModelExplorer.GetAttribute<Placeholder>();
if (attribute != null) if (attribute != null || TagHelper.FloatingLabel)
{ {
var placeholderLocalized = _tagHelperLocalizer.GetLocalizedText(attribute.Value, TagHelper.AspFor.ModelExplorer); var placeholderLocalized = _tagHelperLocalizer.GetLocalizedText(attribute?.Value ?? TagHelper.AspFor.Name, TagHelper.AspFor.ModelExplorer);
inputTagHelperOutput.Attributes.Add("placeholder", placeholderLocalized); inputTagHelperOutput.Attributes.Add("placeholder", placeholderLocalized);
} }
} }

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

@ -1,15 +1,14 @@
using Microsoft.AspNetCore.Mvc.Diagnostics; using System;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Mvc.TagHelpers;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using Microsoft.AspNetCore.Razor.TagHelpers;
using Microsoft.Extensions.Localization;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using System.Linq; using System.Linq;
using System.Text.Encodings.Web; using System.Text.Encodings.Web;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Mvc.TagHelpers;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using Microsoft.AspNetCore.Razor.TagHelpers;
using Microsoft.Extensions.Localization;
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Microsoft.AspNetCore.Razor.TagHelpers; using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Microsoft.AspNetCore.Razor.TagHelpers;
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Extensions; using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Extensions;
using Volo.Abp.Localization; using Volo.Abp.Localization;
@ -38,7 +37,7 @@ public class AbpSelectTagHelperService : AbpTagHelperService<AbpSelectTagHelper>
_abpEnumLocalizer = abpEnumLocalizer; _abpEnumLocalizer = abpEnumLocalizer;
} }
public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output) public async override Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
{ {
var childContent = await output.GetChildContentAsync(); var childContent = await output.GetChildContentAsync();
@ -74,7 +73,8 @@ public class AbpSelectTagHelperService : AbpTagHelperService<AbpSelectTagHelper>
var validation = await GetValidationAsHtmlAsync(context, output, selectTag); var validation = await GetValidationAsHtmlAsync(context, output, selectTag);
var infoText = GetInfoAsHtml(context, output, selectTag); var infoText = GetInfoAsHtml(context, output, selectTag);
return label + Environment.NewLine + selectAsHtml + Environment.NewLine + infoText + Environment.NewLine + validation; return TagHelper.FloatingLabel ? selectAsHtml + Environment.NewLine + label + Environment.NewLine + infoText + Environment.NewLine + validation :
label + Environment.NewLine + selectAsHtml + Environment.NewLine + infoText + Environment.NewLine + validation;
} }
protected virtual string SurroundInnerHtmlAndGet(TagHelperContext context, TagHelperOutput output, string innerHtml) protected virtual string SurroundInnerHtmlAndGet(TagHelperContext context, TagHelperOutput output, string innerHtml)
@ -156,23 +156,15 @@ public class AbpSelectTagHelperService : AbpTagHelperService<AbpSelectTagHelper>
} }
var selectItemsAttribute = TagHelper.AspFor.ModelExplorer.GetAttribute<SelectItems>(); var selectItemsAttribute = TagHelper.AspFor.ModelExplorer.GetAttribute<SelectItems>();
if (selectItemsAttribute != null) return selectItemsAttribute != null
{ ? GetSelectItemsFromAttribute(selectItemsAttribute, TagHelper.AspFor.ModelExplorer)
return GetSelectItemsFromAttribute(selectItemsAttribute, TagHelper.AspFor.ModelExplorer); : throw new Exception("No items provided for select attribute.");
}
throw new Exception("No items provided for select attribute.");
} }
private bool IsEnum() private bool IsEnum()
{ {
var value = TagHelper.AspFor.Model; var value = TagHelper.AspFor.Model;
if (value != null && value.GetType().IsEnum) return (value != null && value.GetType().IsEnum) || TagHelper.AspFor.ModelExplorer.Metadata.IsEnum;
{
return true;
}
return TagHelper.AspFor.ModelExplorer.Metadata.IsEnum;
} }
protected virtual async Task<string> GetLabelAsHtmlAsync(TagHelperContext context, TagHelperOutput output, TagHelperOutput selectTag) protected virtual async Task<string> GetLabelAsHtmlAsync(TagHelperContext context, TagHelperOutput output, TagHelperOutput selectTag)
@ -296,12 +288,7 @@ public class AbpSelectTagHelperService : AbpTagHelperService<AbpSelectTagHelper>
{ {
var selectItems = selectItemsAttribute.GetItems(explorer)?.ToList(); var selectItems = selectItemsAttribute.GetItems(explorer)?.ToList();
if (selectItems == null) return selectItems ?? new List<SelectListItem>();
{
return new List<SelectListItem>();
}
return selectItems;
} }
protected virtual async Task<string> GetLabelAsHtmlUsingTagHelperAsync(TagHelperContext context, TagHelperOutput output) protected virtual async Task<string> GetLabelAsHtmlUsingTagHelperAsync(TagHelperContext context, TagHelperOutput output)
@ -337,17 +324,13 @@ public class AbpSelectTagHelperService : AbpTagHelperService<AbpSelectTagHelper>
TagHelper.Size = attribute.Size; TagHelper.Size = attribute.Size;
} }
switch (TagHelper.Size) return TagHelper.Size switch
{ {
case AbpFormControlSize.Small: AbpFormControlSize.Small => "form-select-sm",
return "form-select-sm"; AbpFormControlSize.Medium => "form-select-md",
case AbpFormControlSize.Medium: AbpFormControlSize.Large => "form-select-lg",
return "form-select-md"; _ => "",
case AbpFormControlSize.Large: };
return "form-select-lg";
}
return "";
} }
protected virtual TagHelperAttributeList GetInputAttributes(TagHelperContext context, TagHelperOutput output) protected virtual TagHelperAttributeList GetInputAttributes(TagHelperContext context, TagHelperOutput output)
@ -376,7 +359,7 @@ public class AbpSelectTagHelperService : AbpTagHelperService<AbpSelectTagHelper>
foreach (var tagHelperAttribute in tagHelperAttributes) foreach (var tagHelperAttribute in tagHelperAttributes)
{ {
var nameWithoutPrefix = tagHelperAttribute.Name.Substring(groupPrefix.Length); var nameWithoutPrefix = tagHelperAttribute.Name[groupPrefix.Length..];
var newAttritube = new TagHelperAttribute(nameWithoutPrefix, tagHelperAttribute.Value); var newAttritube = new TagHelperAttribute(nameWithoutPrefix, tagHelperAttribute.Value);
output.Attributes.Add(newAttritube); output.Attributes.Add(newAttritube);
} }

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

@ -83,7 +83,7 @@ public class AbpExceptionPageFilter : IAsyncPageFilter, ITransientDependency
remoteServiceErrorInfoBuilder.AppendLine($"---------- {nameof(RemoteServiceErrorInfo)} ----------"); remoteServiceErrorInfoBuilder.AppendLine($"---------- {nameof(RemoteServiceErrorInfo)} ----------");
remoteServiceErrorInfoBuilder.AppendLine(context.GetRequiredService<IJsonSerializer>().Serialize(remoteServiceErrorInfo, indented: true)); remoteServiceErrorInfoBuilder.AppendLine(context.GetRequiredService<IJsonSerializer>().Serialize(remoteServiceErrorInfo, indented: true));
var logger = context.GetService<ILogger<AbpExceptionFilter>>(NullLogger<AbpExceptionFilter>.Instance)!; var logger = context.GetService<ILogger<AbpExceptionPageFilter>>(NullLogger<AbpExceptionPageFilter>.Instance)!;
logger.LogWithLevel(logLevel, remoteServiceErrorInfoBuilder.ToString()); logger.LogWithLevel(logLevel, remoteServiceErrorInfoBuilder.ToString());
logger.LogException(context.Exception!, logLevel); logger.LogException(context.Exception!, logLevel);

2
framework/src/Volo.Abp.Auditing.Contracts/Volo/Abp/Auditing/IDeletionAuditedObject.cs

@ -22,5 +22,5 @@ public interface IDeletionAuditedObject<TUser> : IDeletionAuditedObject
/// <summary> /// <summary>
/// Reference to the deleter user. /// Reference to the deleter user.
/// </summary> /// </summary>
TUser Deleter { get; } TUser? Deleter { get; }
} }

3
framework/src/Volo.Abp.Auditing.Contracts/Volo/Abp/Auditing/IMayHaveCreator.cs

@ -8,8 +8,7 @@ public interface IMayHaveCreator<TCreator>
/// <summary> /// <summary>
/// Reference to the creator. /// Reference to the creator.
/// </summary> /// </summary>
[CanBeNull] TCreator? Creator { get; }
TCreator Creator { get; }
} }
/// <summary> /// <summary>

2
framework/src/Volo.Abp.Auditing.Contracts/Volo/Abp/Auditing/IModificationAuditedObject.cs

@ -22,5 +22,5 @@ public interface IModificationAuditedObject<TUser> : IModificationAuditedObject
/// <summary> /// <summary>
/// Reference to the last modifier user of this entity. /// Reference to the last modifier user of this entity.
/// </summary> /// </summary>
TUser LastModifier { get; } TUser? LastModifier { get; }
} }

2
framework/src/Volo.Abp.BlazoriseUI/Components/ObjectExtending/LookupExtensionProperty.razor

@ -9,7 +9,7 @@
<Autocomplete Data="@lookupItems" <Autocomplete Data="@lookupItems"
TItem="SelectItem<object>" TItem="SelectItem<object>"
TValue="object" TValue="object"
TextField="item => item?.Text" TextField="item => item?.Text!"
ValueField="item => item?.Value" ValueField="item => item?.Value"
SelectedValue="@SelectedValue" SelectedValue="@SelectedValue"
SelectedValueChanged="@SelectedValueChanged" SelectedValueChanged="@SelectedValueChanged"

20
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/VoloNugetPackagesVersionUpdater.cs

@ -229,12 +229,20 @@ public class VoloNugetPackagesVersionUpdater : ITransientDependency
{ {
if ((includeNightlyPreviews || (currentVersion.Contains("-preview") && !switchToStable)) && !includeReleaseCandidates) if ((includeNightlyPreviews || (currentVersion.Contains("-preview") && !switchToStable)) && !includeReleaseCandidates)
{ {
var latestVersion = latestMyGetVersion == null || isLeptonXPackage ? string latestVersion;
await GetLatestVersionFromMyGet(packageId) : latestMyGetVersion; if(isLeptonXPackage)
{
latestVersion = (await _packageVersionCheckerService.GetLatestVersionOrNullAsync(packageId, includeNightlyPreviews, includeReleaseCandidates))?.Version?.ToString();
}
else
{
latestVersion = latestMyGetVersion == null ? await GetLatestVersionFromMyGet(packageId) : latestMyGetVersion;
}
if(latestVersion == null && isLeptonXPackage) //leptonx-pro package if(latestVersion == null)
{ {
latestVersion = await GetLatestVersionFromMyGet("Volo.Abp.AspNetCore.Components.Server.LeptonXLiteTheme", isNightly: includeNightlyPreviews); Logger.LogWarning("Package: {0} could not be updated. Please manually update the package version yourself to prevent version mismatches.", packageId);
continue;
} }
if (currentVersion != latestVersion) if (currentVersion != latestVersion)
@ -288,10 +296,10 @@ public class VoloNugetPackagesVersionUpdater : ITransientDependency
return await Task.FromResult(content); return await Task.FromResult(content);
} }
private async Task<string> GetLatestVersionFromMyGet(string packageId, bool isNightly = false) private async Task<string> GetLatestVersionFromMyGet(string packageId)
{ {
var myGetPack = await _myGetPackageListFinder.GetPackagesAsync(); var myGetPack = await _myGetPackageListFinder.GetPackagesAsync();
return myGetPack.Packages.FirstOrDefault(p => p.Id == packageId)?.Versions.LastOrDefault(x => isNightly ? x.Contains("-preview") : true); return myGetPack.Packages.FirstOrDefault(p => p.Id == packageId)?.Versions.LastOrDefault();
} }
} }

20
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Version/PackageVersionCheckerService.cs

@ -80,21 +80,11 @@ public class PackageVersionCheckerService : ITransientDependency
return null; return null;
} }
List<SemanticVersion> versions; List<SemanticVersion> versions = versionList
.WhereIf(!includeNightly, v => !v.Contains("-preview"))
if (!includeNightly && includeReleaseCandidates) .WhereIf(!includeReleaseCandidates, v => !v.Contains("rc"))
{ .Select(SemanticVersion.Parse)
versions = versionList .OrderByDescending(v => v, new VersionComparer()).ToList();
.Where(v => !v.Contains("-preview"))
.Select(SemanticVersion.Parse)
.OrderByDescending(v => v, new VersionComparer()).ToList();
}
else
{
versions = versionList
.Select(SemanticVersion.Parse)
.OrderByDescending(v => v, new VersionComparer()).ToList();
}
return versions.Any() return versions.Any()
? new LatestVersionInfo(versions.Max()) ? new LatestVersionInfo(versions.Max())

2
framework/src/Volo.Abp.Core/Microsoft/Extensions/Hosting/AbpHostingHostBuilderExtensions.cs

@ -15,7 +15,7 @@ public static class AbpHostingHostBuilderExtensions
return hostBuilder.ConfigureAppConfiguration((_, builder) => return hostBuilder.ConfigureAppConfiguration((_, builder) =>
{ {
builder.AddJsonFile( builder.AddJsonFile(
path: AppSettingsSecretJsonPath, path: path,
optional: optional, optional: optional,
reloadOnChange: reloadOnChange reloadOnChange: reloadOnChange
); );

2
framework/src/Volo.Abp.Dapper/Volo.Abp.Dapper.csproj

@ -5,6 +5,8 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>net7.0</TargetFramework> <TargetFramework>net7.0</TargetFramework>
<Nullable>enable</Nullable>
<WarningsAsErrors>Nullable</WarningsAsErrors>
<AssemblyName>Volo.Abp.Dapper</AssemblyName> <AssemblyName>Volo.Abp.Dapper</AssemblyName>
<PackageId>Volo.Abp.Dapper</PackageId> <PackageId>Volo.Abp.Dapper</PackageId>
<AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback> <AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback>

6
framework/src/Volo.Abp.Dapper/Volo/Abp/Domain/Repositories/Dapper/DapperRepository.cs

@ -16,7 +16,7 @@ namespace Volo.Abp.Domain.Repositories.Dapper;
public class DapperRepository<TDbContext> : IDapperRepository, IUnitOfWorkEnabled public class DapperRepository<TDbContext> : IDapperRepository, IUnitOfWorkEnabled
where TDbContext : IEfCoreDbContext where TDbContext : IEfCoreDbContext
{ {
public IAbpLazyServiceProvider LazyServiceProvider { get; set; } public IAbpLazyServiceProvider LazyServiceProvider { get; set; } = default!;
public IDataFilter DataFilter => LazyServiceProvider.LazyGetRequiredService<IDataFilter>(); public IDataFilter DataFilter => LazyServiceProvider.LazyGetRequiredService<IDataFilter>();
@ -39,9 +39,9 @@ public class DapperRepository<TDbContext> : IDapperRepository, IUnitOfWorkEnable
public virtual async Task<IDbConnection> GetDbConnectionAsync() => (await _dbContextProvider.GetDbContextAsync()).Database.GetDbConnection(); public virtual async Task<IDbConnection> GetDbConnectionAsync() => (await _dbContextProvider.GetDbContextAsync()).Database.GetDbConnection();
[Obsolete("Use GetDbTransactionAsync method.")] [Obsolete("Use GetDbTransactionAsync method.")]
public IDbTransaction DbTransaction => _dbContextProvider.GetDbContext().Database.CurrentTransaction?.GetDbTransaction(); public IDbTransaction? DbTransaction => _dbContextProvider.GetDbContext().Database.CurrentTransaction?.GetDbTransaction();
public virtual async Task<IDbTransaction> GetDbTransactionAsync() => (await _dbContextProvider.GetDbContextAsync()).Database.CurrentTransaction?.GetDbTransaction(); public virtual async Task<IDbTransaction?> GetDbTransactionAsync() => (await _dbContextProvider.GetDbContextAsync()).Database.CurrentTransaction?.GetDbTransaction();
protected virtual CancellationToken GetCancellationToken(CancellationToken preferredValue = default) protected virtual CancellationToken GetCancellationToken(CancellationToken preferredValue = default)
{ {

4
framework/src/Volo.Abp.Dapper/Volo/Abp/Domain/Repositories/Dapper/IDapperRepository.cs

@ -12,7 +12,7 @@ public interface IDapperRepository
Task<IDbConnection> GetDbConnectionAsync(); Task<IDbConnection> GetDbConnectionAsync();
[Obsolete("Use GetDbTransactionAsync method.")] [Obsolete("Use GetDbTransactionAsync method.")]
IDbTransaction DbTransaction { get; } IDbTransaction? DbTransaction { get; }
Task<IDbTransaction> GetDbTransactionAsync(); Task<IDbTransaction?> GetDbTransactionAsync();
} }

2
framework/src/Volo.Abp.Dapr/Volo.Abp.Dapr.csproj

@ -5,6 +5,8 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>net7.0</TargetFramework> <TargetFramework>net7.0</TargetFramework>
<Nullable>enable</Nullable>
<WarningsAsErrors>Nullable</WarningsAsErrors>
<RootNamespace /> <RootNamespace />
</PropertyGroup> </PropertyGroup>

8
framework/src/Volo.Abp.Dapr/Volo/Abp/Dapr/AbpDaprClientFactory.cs

@ -24,7 +24,7 @@ public class AbpDaprClientFactory : IAbpDaprClientFactory, ISingletonDependency
JsonSerializerOptions = CreateJsonSerializerOptions(systemTextJsonSerializerOptions.Value); JsonSerializerOptions = CreateJsonSerializerOptions(systemTextJsonSerializerOptions.Value);
} }
public virtual DaprClient Create(Action<DaprClientBuilder> builderAction = null) public virtual DaprClient Create(Action<DaprClientBuilder>? builderAction = null)
{ {
var builder = new DaprClientBuilder() var builder = new DaprClientBuilder()
.UseJsonSerializationOptions(JsonSerializerOptions); .UseJsonSerializationOptions(JsonSerializerOptions);
@ -51,9 +51,9 @@ public class AbpDaprClientFactory : IAbpDaprClientFactory, ISingletonDependency
} }
public virtual HttpClient CreateHttpClient( public virtual HttpClient CreateHttpClient(
string appId = null, string? appId = null,
string daprEndpoint = null, string? daprEndpoint = null,
string daprApiToken = null) string? daprApiToken = null)
{ {
if(daprEndpoint.IsNullOrWhiteSpace() && if(daprEndpoint.IsNullOrWhiteSpace() &&
!DaprOptions.HttpEndpoint.IsNullOrWhiteSpace()) !DaprOptions.HttpEndpoint.IsNullOrWhiteSpace())

8
framework/src/Volo.Abp.Dapr/Volo/Abp/Dapr/AbpDaprModule.cs

@ -33,14 +33,14 @@ public class AbpDaprModule : AbpModule
var confEnv = configuration["DAPR_API_TOKEN"]; var confEnv = configuration["DAPR_API_TOKEN"];
if (!confEnv.IsNullOrWhiteSpace()) if (!confEnv.IsNullOrWhiteSpace())
{ {
options.DaprApiToken = confEnv; options.DaprApiToken = confEnv!;
} }
else else
{ {
var env = Environment.GetEnvironmentVariable("DAPR_API_TOKEN"); var env = Environment.GetEnvironmentVariable("DAPR_API_TOKEN");
if (!env.IsNullOrWhiteSpace()) if (!env.IsNullOrWhiteSpace())
{ {
options.DaprApiToken = env; options.DaprApiToken = env!;
} }
} }
} }
@ -50,14 +50,14 @@ public class AbpDaprModule : AbpModule
var confEnv = configuration["APP_API_TOKEN"]; var confEnv = configuration["APP_API_TOKEN"];
if (!confEnv.IsNullOrWhiteSpace()) if (!confEnv.IsNullOrWhiteSpace())
{ {
options.AppApiToken = confEnv; options.AppApiToken = confEnv!;
} }
else else
{ {
var env = Environment.GetEnvironmentVariable("APP_API_TOKEN"); var env = Environment.GetEnvironmentVariable("APP_API_TOKEN");
if (!env.IsNullOrWhiteSpace()) if (!env.IsNullOrWhiteSpace())
{ {
options.AppApiToken = env; options.AppApiToken = env!;
} }
} }
} }

8
framework/src/Volo.Abp.Dapr/Volo/Abp/Dapr/AbpDaprOptions.cs

@ -2,11 +2,11 @@
public class AbpDaprOptions public class AbpDaprOptions
{ {
public string HttpEndpoint { get; set; } public string? HttpEndpoint { get; set; }
public string GrpcEndpoint { get; set; } public string? GrpcEndpoint { get; set; }
public string DaprApiToken { get; set; } public string? DaprApiToken { get; set; }
public string AppApiToken { get; set; } public string? AppApiToken { get; set; }
} }

4
framework/src/Volo.Abp.Dapr/Volo/Abp/Dapr/DaprApiTokenProvider.cs

@ -12,12 +12,12 @@ public class DaprApiTokenProvider : IDaprApiTokenProvider, ISingletonDependency
Options = options.Value; Options = options.Value;
} }
public virtual string GetDaprApiToken() public virtual string? GetDaprApiToken()
{ {
return Options.DaprApiToken; return Options.DaprApiToken;
} }
public virtual string GetAppApiToken() public virtual string? GetAppApiToken()
{ {
return Options.AppApiToken; return Options.AppApiToken;
} }

8
framework/src/Volo.Abp.Dapr/Volo/Abp/Dapr/IAbpDaprClientFactory.cs

@ -6,11 +6,11 @@ namespace Volo.Abp.Dapr;
public interface IAbpDaprClientFactory public interface IAbpDaprClientFactory
{ {
DaprClient Create(Action<DaprClientBuilder> builderAction = null); DaprClient Create(Action<DaprClientBuilder>? builderAction = null);
HttpClient CreateHttpClient( HttpClient CreateHttpClient(
string appId = null, string? appId = null,
string daprEndpoint = null, string? daprEndpoint = null,
string daprApiToken = null string? daprApiToken = null
); );
} }

4
framework/src/Volo.Abp.Dapr/Volo/Abp/Dapr/IDaprApiTokenProvider.cs

@ -2,7 +2,7 @@ namespace Volo.Abp.Dapr;
public interface IDaprApiTokenProvider public interface IDaprApiTokenProvider
{ {
string GetDaprApiToken(); string? GetDaprApiToken();
string GetAppApiToken(); string? GetAppApiToken();
} }

2
framework/src/Volo.Abp.Ddd.Application.Contracts/Volo.Abp.Ddd.Application.Contracts.csproj

@ -5,6 +5,8 @@
<PropertyGroup> <PropertyGroup>
<TargetFrameworks>netstandard2.0;netstandard2.1;net7.0</TargetFrameworks> <TargetFrameworks>netstandard2.0;netstandard2.1;net7.0</TargetFrameworks>
<Nullable>enable</Nullable>
<WarningsAsErrors>Nullable</WarningsAsErrors>
<AssemblyName>Volo.Abp.Ddd.Application.Contracts</AssemblyName> <AssemblyName>Volo.Abp.Ddd.Application.Contracts</AssemblyName>
<PackageId>Volo.Abp.Ddd.Application.Contracts</PackageId> <PackageId>Volo.Abp.Ddd.Application.Contracts</PackageId>
<AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback> <AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback>

8
framework/src/Volo.Abp.Ddd.Application.Contracts/Volo/Abp/Application/Dtos/AuditedEntityWithUserDto.cs

@ -12,10 +12,10 @@ namespace Volo.Abp.Application.Dtos;
public abstract class AuditedEntityWithUserDto<TUserDto> : AuditedEntityDto, IAuditedObject<TUserDto> public abstract class AuditedEntityWithUserDto<TUserDto> : AuditedEntityDto, IAuditedObject<TUserDto>
{ {
/// <inheritdoc /> /// <inheritdoc />
public TUserDto Creator { get; set; } public TUserDto? Creator { get; set; }
/// <inheritdoc /> /// <inheritdoc />
public TUserDto LastModifier { get; set; } public TUserDto? LastModifier { get; set; }
} }
/// <summary> /// <summary>
@ -28,8 +28,8 @@ public abstract class AuditedEntityWithUserDto<TUserDto> : AuditedEntityDto, IAu
public abstract class AuditedEntityWithUserDto<TPrimaryKey, TUserDto> : AuditedEntityDto<TPrimaryKey>, IAuditedObject<TUserDto> public abstract class AuditedEntityWithUserDto<TPrimaryKey, TUserDto> : AuditedEntityDto<TPrimaryKey>, IAuditedObject<TUserDto>
{ {
/// <inheritdoc /> /// <inheritdoc />
public TUserDto Creator { get; set; } public TUserDto? Creator { get; set; }
/// <inheritdoc /> /// <inheritdoc />
public TUserDto LastModifier { get; set; } public TUserDto? LastModifier { get; set; }
} }

4
framework/src/Volo.Abp.Ddd.Application.Contracts/Volo/Abp/Application/Dtos/CreationAuditedEntityWithUserDto.cs

@ -11,7 +11,7 @@ namespace Volo.Abp.Application.Dtos;
[Serializable] [Serializable]
public abstract class CreationAuditedEntityWithUserDto<TUserDto> : CreationAuditedEntityDto, ICreationAuditedObject<TUserDto> public abstract class CreationAuditedEntityWithUserDto<TUserDto> : CreationAuditedEntityDto, ICreationAuditedObject<TUserDto>
{ {
public TUserDto Creator { get; set; } public TUserDto? Creator { get; set; }
} }
/// <summary> /// <summary>
@ -23,5 +23,5 @@ public abstract class CreationAuditedEntityWithUserDto<TUserDto> : CreationAudit
[Serializable] [Serializable]
public abstract class CreationAuditedEntityWithUserDto<TPrimaryKey, TUserDto> : CreationAuditedEntityDto<TPrimaryKey>, ICreationAuditedObject<TUserDto> public abstract class CreationAuditedEntityWithUserDto<TPrimaryKey, TUserDto> : CreationAuditedEntityDto<TPrimaryKey>, ICreationAuditedObject<TUserDto>
{ {
public TUserDto Creator { get; set; } public TUserDto? Creator { get; set; }
} }

2
framework/src/Volo.Abp.Ddd.Application.Contracts/Volo/Abp/Application/Dtos/EntityDto.cs

@ -17,7 +17,7 @@ public abstract class EntityDto<TKey> : EntityDto, IEntityDto<TKey>
/// <summary> /// <summary>
/// Id of the entity. /// Id of the entity.
/// </summary> /// </summary>
public TKey Id { get; set; } public TKey Id { get; set; } = default!;
public override string ToString() public override string ToString()
{ {

8
framework/src/Volo.Abp.Ddd.Application.Contracts/Volo/Abp/Application/Dtos/ExtensibleAuditedEntityWithUserDto.cs

@ -15,10 +15,10 @@ namespace Volo.Abp.Application.Dtos;
public abstract class ExtensibleAuditedEntityWithUserDto<TPrimaryKey, TUserDto> : ExtensibleAuditedEntityDto<TPrimaryKey>, IAuditedObject<TUserDto> public abstract class ExtensibleAuditedEntityWithUserDto<TPrimaryKey, TUserDto> : ExtensibleAuditedEntityDto<TPrimaryKey>, IAuditedObject<TUserDto>
{ {
/// <inheritdoc /> /// <inheritdoc />
public TUserDto Creator { get; set; } public TUserDto? Creator { get; set; }
/// <inheritdoc /> /// <inheritdoc />
public TUserDto LastModifier { get; set; } public TUserDto? LastModifier { get; set; }
protected ExtensibleAuditedEntityWithUserDto() protected ExtensibleAuditedEntityWithUserDto()
: this(true) : this(true)
@ -44,10 +44,10 @@ public abstract class ExtensibleAuditedEntityWithUserDto<TUserDto> : ExtensibleA
IAuditedObject<TUserDto> IAuditedObject<TUserDto>
{ {
/// <inheritdoc /> /// <inheritdoc />
public TUserDto Creator { get; set; } public TUserDto? Creator { get; set; }
/// <inheritdoc /> /// <inheritdoc />
public TUserDto LastModifier { get; set; } public TUserDto? LastModifier { get; set; }
protected ExtensibleAuditedEntityWithUserDto() protected ExtensibleAuditedEntityWithUserDto()
: this(true) : this(true)

4
framework/src/Volo.Abp.Ddd.Application.Contracts/Volo/Abp/Application/Dtos/ExtensibleCreationAuditedEntityWithUserDto.cs

@ -14,7 +14,7 @@ namespace Volo.Abp.Application.Dtos;
[Serializable] [Serializable]
public abstract class ExtensibleCreationAuditedEntityWithUserDto<TPrimaryKey, TUserDto> : ExtensibleCreationAuditedEntityDto<TPrimaryKey>, ICreationAuditedObject<TUserDto> public abstract class ExtensibleCreationAuditedEntityWithUserDto<TPrimaryKey, TUserDto> : ExtensibleCreationAuditedEntityDto<TPrimaryKey>, ICreationAuditedObject<TUserDto>
{ {
public TUserDto Creator { get; set; } public TUserDto? Creator { get; set; }
protected ExtensibleCreationAuditedEntityWithUserDto() protected ExtensibleCreationAuditedEntityWithUserDto()
: this(true) : this(true)
@ -39,7 +39,7 @@ public abstract class ExtensibleCreationAuditedEntityWithUserDto<TPrimaryKey, TU
public abstract class ExtensibleCreationAuditedEntityWithUserDto<TUserDto> : ExtensibleCreationAuditedEntityDto, public abstract class ExtensibleCreationAuditedEntityWithUserDto<TUserDto> : ExtensibleCreationAuditedEntityDto,
ICreationAuditedObject<TUserDto> ICreationAuditedObject<TUserDto>
{ {
public TUserDto Creator { get; set; } public TUserDto? Creator { get; set; }
protected ExtensibleCreationAuditedEntityWithUserDto() protected ExtensibleCreationAuditedEntityWithUserDto()
: this(true) : this(true)

2
framework/src/Volo.Abp.Ddd.Application.Contracts/Volo/Abp/Application/Dtos/ExtensibleEntityDto.cs

@ -9,7 +9,7 @@ public abstract class ExtensibleEntityDto<TKey> : ExtensibleObject, IEntityDto<T
/// <summary> /// <summary>
/// Id of the entity. /// Id of the entity.
/// </summary> /// </summary>
public TKey Id { get; set; } public TKey Id { get; set; } = default!;
protected ExtensibleEntityDto() protected ExtensibleEntityDto()
: this(true) : this(true)

12
framework/src/Volo.Abp.Ddd.Application.Contracts/Volo/Abp/Application/Dtos/ExtensibleFullAuditedEntityWithUserDto.cs

@ -15,13 +15,13 @@ namespace Volo.Abp.Application.Dtos;
public abstract class ExtensibleFullAuditedEntityWithUserDto<TPrimaryKey, TUserDto> : ExtensibleFullAuditedEntityDto<TPrimaryKey>, IFullAuditedObject<TUserDto> public abstract class ExtensibleFullAuditedEntityWithUserDto<TPrimaryKey, TUserDto> : ExtensibleFullAuditedEntityDto<TPrimaryKey>, IFullAuditedObject<TUserDto>
{ {
/// <inheritdoc /> /// <inheritdoc />
public TUserDto Creator { get; set; } public TUserDto? Creator { get; set; }
/// <inheritdoc /> /// <inheritdoc />
public TUserDto LastModifier { get; set; } public TUserDto? LastModifier { get; set; }
/// <inheritdoc /> /// <inheritdoc />
public TUserDto Deleter { get; set; } public TUserDto? Deleter { get; set; }
protected ExtensibleFullAuditedEntityWithUserDto() protected ExtensibleFullAuditedEntityWithUserDto()
: this(true) : this(true)
@ -47,13 +47,13 @@ public abstract class ExtensibleFullAuditedEntityWithUserDto<TUserDto> : Extensi
IFullAuditedObject<TUserDto> IFullAuditedObject<TUserDto>
{ {
/// <inheritdoc /> /// <inheritdoc />
public TUserDto Creator { get; set; } public TUserDto? Creator { get; set; }
/// <inheritdoc /> /// <inheritdoc />
public TUserDto LastModifier { get; set; } public TUserDto? LastModifier { get; set; }
/// <inheritdoc /> /// <inheritdoc />
public TUserDto Deleter { get; set; } public TUserDto? Deleter { get; set; }
protected ExtensibleFullAuditedEntityWithUserDto() protected ExtensibleFullAuditedEntityWithUserDto()
: this(true) : this(true)

12
framework/src/Volo.Abp.Ddd.Application.Contracts/Volo/Abp/Application/Dtos/FullAuditedEntityWithUserDto.cs

@ -12,13 +12,13 @@ namespace Volo.Abp.Application.Dtos;
public abstract class FullAuditedEntityWithUserDto<TUserDto> : FullAuditedEntityDto, IFullAuditedObject<TUserDto> public abstract class FullAuditedEntityWithUserDto<TUserDto> : FullAuditedEntityDto, IFullAuditedObject<TUserDto>
{ {
/// <inheritdoc /> /// <inheritdoc />
public TUserDto Creator { get; set; } public TUserDto? Creator { get; set; }
/// <inheritdoc /> /// <inheritdoc />
public TUserDto LastModifier { get; set; } public TUserDto? LastModifier { get; set; }
/// <inheritdoc /> /// <inheritdoc />
public TUserDto Deleter { get; set; } public TUserDto? Deleter { get; set; }
} }
/// <summary> /// <summary>
@ -31,11 +31,11 @@ public abstract class FullAuditedEntityWithUserDto<TUserDto> : FullAuditedEntity
public abstract class FullAuditedEntityWithUserDto<TPrimaryKey, TUserDto> : FullAuditedEntityDto<TPrimaryKey>, IFullAuditedObject<TUserDto> public abstract class FullAuditedEntityWithUserDto<TPrimaryKey, TUserDto> : FullAuditedEntityDto<TPrimaryKey>, IFullAuditedObject<TUserDto>
{ {
/// <inheritdoc /> /// <inheritdoc />
public TUserDto Creator { get; set; } public TUserDto? Creator { get; set; }
/// <inheritdoc /> /// <inheritdoc />
public TUserDto LastModifier { get; set; } public TUserDto? LastModifier { get; set; }
/// <inheritdoc /> /// <inheritdoc />
public TUserDto Deleter { get; set; } public TUserDto? Deleter { get; set; }
} }

2
framework/src/Volo.Abp.Ddd.Application.Contracts/Volo/Abp/Application/Dtos/ISortedResultRequest.cs

@ -16,5 +16,5 @@ public interface ISortedResultRequest
/// "Name DESC" /// "Name DESC"
/// "Name ASC, Age DESC" /// "Name ASC, Age DESC"
/// </example> /// </example>
string Sorting { get; set; } string? Sorting { get; set; }
} }

4
framework/src/Volo.Abp.Ddd.Application.Contracts/Volo/Abp/Application/Dtos/LimitedResultRequestDto.cs

@ -42,7 +42,7 @@ public class LimitedResultRequestDto : ILimitedResultRequest, IValidatableObject
"MaxResultCountExceededExceptionMessage", "MaxResultCountExceededExceptionMessage",
nameof(MaxResultCount), nameof(MaxResultCount),
MaxMaxResultCount, MaxMaxResultCount,
typeof(LimitedResultRequestDto).FullName, typeof(LimitedResultRequestDto).FullName!,
nameof(MaxMaxResultCount) nameof(MaxMaxResultCount)
], ],
new[] { nameof(MaxResultCount) }); new[] { nameof(MaxResultCount) });
@ -90,7 +90,7 @@ public class ExtensibleLimitedResultRequestDto : ExtensibleEntityDto, ILimitedRe
"MaxResultCountExceededExceptionMessage", "MaxResultCountExceededExceptionMessage",
nameof(MaxResultCount), nameof(MaxResultCount),
MaxMaxResultCount, MaxMaxResultCount,
typeof(ExtensibleLimitedResultRequestDto).FullName, typeof(ExtensibleLimitedResultRequestDto).FullName!,
nameof(MaxMaxResultCount) nameof(MaxMaxResultCount)
], ],
new[] { nameof(MaxResultCount) }); new[] { nameof(MaxResultCount) });

4
framework/src/Volo.Abp.Ddd.Application.Contracts/Volo/Abp/Application/Dtos/ListResultDto.cs

@ -13,7 +13,7 @@ public class ListResultDto<T> : IListResult<T>
get { return _items ?? (_items = new List<T>()); } get { return _items ?? (_items = new List<T>()); }
set { _items = value; } set { _items = value; }
} }
private IReadOnlyList<T> _items; private IReadOnlyList<T>? _items;
/// <summary> /// <summary>
/// Creates a new <see cref="ListResultDto{T}"/> object. /// Creates a new <see cref="ListResultDto{T}"/> object.
@ -42,7 +42,7 @@ public class ExtensibleListResultDto<T> : ExtensibleObject, IListResult<T>
get { return _items ?? (_items = new List<T>()); } get { return _items ?? (_items = new List<T>()); }
set { _items = value; } set { _items = value; }
} }
private IReadOnlyList<T> _items; private IReadOnlyList<T>? _items;
/// <summary> /// <summary>
/// Creates a new <see cref="ListResultDto{T}"/> object. /// Creates a new <see cref="ListResultDto{T}"/> object.

4
framework/src/Volo.Abp.Ddd.Application.Contracts/Volo/Abp/Application/Dtos/PagedAndSortedResultRequestDto.cs

@ -8,7 +8,7 @@ namespace Volo.Abp.Application.Dtos;
[Serializable] [Serializable]
public class PagedAndSortedResultRequestDto : PagedResultRequestDto, IPagedAndSortedResultRequest public class PagedAndSortedResultRequestDto : PagedResultRequestDto, IPagedAndSortedResultRequest
{ {
public virtual string Sorting { get; set; } public virtual string? Sorting { get; set; }
} }
/// <summary> /// <summary>
@ -17,5 +17,5 @@ public class PagedAndSortedResultRequestDto : PagedResultRequestDto, IPagedAndSo
[Serializable] [Serializable]
public class ExtensiblePagedAndSortedResultRequestDto : ExtensiblePagedResultRequestDto, IPagedAndSortedResultRequest public class ExtensiblePagedAndSortedResultRequestDto : ExtensiblePagedResultRequestDto, IPagedAndSortedResultRequest
{ {
public virtual string Sorting { get; set; } public virtual string? Sorting { get; set; }
} }

2
framework/src/Volo.Abp.Ddd.Application/Volo.Abp.Ddd.Application.csproj

@ -5,6 +5,8 @@
<PropertyGroup> <PropertyGroup>
<TargetFrameworks>netstandard2.0;netstandard2.1;net7.0</TargetFrameworks> <TargetFrameworks>netstandard2.0;netstandard2.1;net7.0</TargetFrameworks>
<Nullable>enable</Nullable>
<WarningsAsErrors>Nullable</WarningsAsErrors>
<AssemblyName>Volo.Abp.Ddd.Application</AssemblyName> <AssemblyName>Volo.Abp.Ddd.Application</AssemblyName>
<PackageId>Volo.Abp.Ddd.Application</PackageId> <PackageId>Volo.Abp.Ddd.Application</PackageId>
<AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback> <AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback>

6
framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/AbstractKeyCrudAppService.cs

@ -70,11 +70,11 @@ public abstract class AbstractKeyCrudAppService<TEntity, TGetOutputDto, TGetList
{ {
protected IRepository<TEntity> Repository { get; } protected IRepository<TEntity> Repository { get; }
protected virtual string CreatePolicyName { get; set; } protected virtual string? CreatePolicyName { get; set; }
protected virtual string UpdatePolicyName { get; set; } protected virtual string? UpdatePolicyName { get; set; }
protected virtual string DeletePolicyName { get; set; } protected virtual string? DeletePolicyName { get; set; }
protected AbstractKeyCrudAppService(IRepository<TEntity> repository) protected AbstractKeyCrudAppService(IRepository<TEntity> repository)
: base(repository) : base(repository)

6
framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/AbstractKeyReadOnlyAppService.cs

@ -40,9 +40,9 @@ public abstract class AbstractKeyReadOnlyAppService<TEntity, TGetOutputDto, TGet
{ {
protected IReadOnlyRepository<TEntity> ReadOnlyRepository { get; } protected IReadOnlyRepository<TEntity> ReadOnlyRepository { get; }
protected virtual string GetPolicyName { get; set; } protected virtual string? GetPolicyName { get; set; }
protected virtual string GetListPolicyName { get; set; } protected virtual string? GetListPolicyName { get; set; }
protected AbstractKeyReadOnlyAppService(IReadOnlyRepository<TEntity> repository) protected AbstractKeyReadOnlyAppService(IReadOnlyRepository<TEntity> repository)
{ {
@ -107,7 +107,7 @@ public abstract class AbstractKeyReadOnlyAppService<TEntity, TGetOutputDto, TGet
{ {
if (!sortInput.Sorting.IsNullOrWhiteSpace()) if (!sortInput.Sorting.IsNullOrWhiteSpace())
{ {
return query.OrderBy(sortInput.Sorting); return query.OrderBy(sortInput.Sorting!);
} }
} }

20
framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/ApplicationService.cs

@ -36,10 +36,10 @@ public abstract class ApplicationService :
IGlobalFeatureCheckingEnabled, IGlobalFeatureCheckingEnabled,
ITransientDependency ITransientDependency
{ {
public IAbpLazyServiceProvider LazyServiceProvider { get; set; } public IAbpLazyServiceProvider LazyServiceProvider { get; set; } = default!;
[Obsolete("Use LazyServiceProvider instead.")] [Obsolete("Use LazyServiceProvider instead.")]
public IServiceProvider ServiceProvider { get; set; } public IServiceProvider ServiceProvider { get; set; } = default!;
public static string[] CommonPostfixes { get; set; } = { "AppService", "ApplicationService", "IntService", "IntegrationService", "Service" }; public static string[] CommonPostfixes { get; set; } = { "AppService", "ApplicationService", "IntService", "IntegrationService", "Service" };
@ -49,7 +49,7 @@ public abstract class ApplicationService :
protected IAsyncQueryableExecuter AsyncExecuter => LazyServiceProvider.LazyGetRequiredService<IAsyncQueryableExecuter>(); protected IAsyncQueryableExecuter AsyncExecuter => LazyServiceProvider.LazyGetRequiredService<IAsyncQueryableExecuter>();
protected Type ObjectMapperContext { get; set; } protected Type? ObjectMapperContext { get; set; }
protected IObjectMapper ObjectMapper => LazyServiceProvider.LazyGetService<IObjectMapper>(provider => protected IObjectMapper ObjectMapper => LazyServiceProvider.LazyGetService<IObjectMapper>(provider =>
ObjectMapperContext == null ObjectMapperContext == null
? provider.GetRequiredService<IObjectMapper>() ? provider.GetRequiredService<IObjectMapper>()
@ -85,34 +85,34 @@ public abstract class ApplicationService :
return _localizer; return _localizer;
} }
} }
private IStringLocalizer _localizer; private IStringLocalizer? _localizer;
protected Type LocalizationResource { protected Type? LocalizationResource {
get => _localizationResource; get => _localizationResource;
set { set {
_localizationResource = value; _localizationResource = value;
_localizer = null; _localizer = null;
} }
} }
private Type _localizationResource = typeof(DefaultResource); private Type? _localizationResource = typeof(DefaultResource);
protected IUnitOfWork CurrentUnitOfWork => UnitOfWorkManager?.Current; protected IUnitOfWork? CurrentUnitOfWork => UnitOfWorkManager?.Current;
protected ILogger Logger => LazyServiceProvider.LazyGetService<ILogger>(provider => LoggerFactory?.CreateLogger(GetType().FullName) ?? NullLogger.Instance); protected ILogger Logger => LazyServiceProvider.LazyGetService<ILogger>(provider => LoggerFactory?.CreateLogger(GetType().FullName!) ?? NullLogger.Instance);
/// <summary> /// <summary>
/// Checks for given <paramref name="policyName"/>. /// Checks for given <paramref name="policyName"/>.
/// Throws <see cref="AbpAuthorizationException"/> if given policy has not been granted. /// Throws <see cref="AbpAuthorizationException"/> if given policy has not been granted.
/// </summary> /// </summary>
/// <param name="policyName">The policy name. This method does nothing if given <paramref name="policyName"/> is null or empty.</param> /// <param name="policyName">The policy name. This method does nothing if given <paramref name="policyName"/> is null or empty.</param>
protected virtual async Task CheckPolicyAsync([CanBeNull] string policyName) protected virtual async Task CheckPolicyAsync(string? policyName)
{ {
if (string.IsNullOrEmpty(policyName)) if (string.IsNullOrEmpty(policyName))
{ {
return; return;
} }
await AuthorizationService.CheckAsync(policyName); await AuthorizationService.CheckAsync(policyName!);
} }
protected virtual IStringLocalizer CreateLocalizer() protected virtual IStringLocalizer CreateLocalizer()

2
framework/src/Volo.Abp.Ddd.Domain.Shared/Volo.Abp.Ddd.Domain.Shared.csproj

@ -5,6 +5,8 @@
<PropertyGroup> <PropertyGroup>
<TargetFrameworks>netstandard2.0;netstandard2.1;net7.0</TargetFrameworks> <TargetFrameworks>netstandard2.0;netstandard2.1;net7.0</TargetFrameworks>
<Nullable>enable</Nullable>
<WarningsAsErrors>Nullable</WarningsAsErrors>
<AssemblyName>Volo.Abp.Ddd.Domain.Shared</AssemblyName> <AssemblyName>Volo.Abp.Ddd.Domain.Shared</AssemblyName>
<PackageId>Volo.Abp.Ddd.Domain.Shared</PackageId> <PackageId>Volo.Abp.Ddd.Domain.Shared</PackageId>
<AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback> <AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback>

6
framework/src/Volo.Abp.Ddd.Domain.Shared/Volo/Abp/Domain/Entities/Events/Distributed/EntityEto.cs

@ -5,9 +5,9 @@ namespace Volo.Abp.Domain.Entities.Events.Distributed;
[Serializable] [Serializable]
public class EntityEto : EtoBase public class EntityEto : EtoBase
{ {
public string EntityType { get; set; } public string EntityType { get; set; } = default!;
public string KeysAsString { get; set; } public string KeysAsString { get; set; } = default!;
public EntityEto() public EntityEto()
{ {
@ -23,5 +23,5 @@ public class EntityEto : EtoBase
public abstract class EntityEto<TKey> : IEntityEto<TKey> public abstract class EntityEto<TKey> : IEntityEto<TKey>
{ {
public TKey Id { get; set; } public TKey Id { get; set; } = default!;
} }

2
framework/src/Volo.Abp.Ddd.Domain.Shared/Volo/Abp/Domain/Entities/Events/Distributed/EtoMappingDictionary.cs

@ -5,7 +5,7 @@ namespace Volo.Abp.Domain.Entities.Events.Distributed;
public class EtoMappingDictionary : Dictionary<Type, EtoMappingDictionaryItem> public class EtoMappingDictionary : Dictionary<Type, EtoMappingDictionaryItem>
{ {
public void Add<TEntity, TEntityEto>(Type objectMappingContextType = null) public void Add<TEntity, TEntityEto>(Type? objectMappingContextType = null)
{ {
this[typeof(TEntity)] = new EtoMappingDictionaryItem(typeof(TEntityEto), objectMappingContextType); this[typeof(TEntity)] = new EtoMappingDictionaryItem(typeof(TEntityEto), objectMappingContextType);
} }

4
framework/src/Volo.Abp.Ddd.Domain.Shared/Volo/Abp/Domain/Entities/Events/Distributed/EtoMappingDictionaryItem.cs

@ -6,9 +6,9 @@ public class EtoMappingDictionaryItem
{ {
public Type EtoType { get; } public Type EtoType { get; }
public Type ObjectMappingContextType { get; } public Type? ObjectMappingContextType { get; }
public EtoMappingDictionaryItem(Type etoType, Type objectMappingContextType = null) public EtoMappingDictionaryItem(Type etoType, Type? objectMappingContextType = null)
{ {
EtoType = etoType; EtoType = etoType;
ObjectMappingContextType = objectMappingContextType; ObjectMappingContextType = objectMappingContextType;

3
framework/src/Volo.Abp.Ddd.Domain.Shared/Volo/Abp/Domain/Entities/Events/Distributed/IEntityToEtoMapper.cs

@ -4,6 +4,5 @@ namespace Volo.Abp.Domain.Entities.Events.Distributed;
public interface IEntityToEtoMapper public interface IEntityToEtoMapper
{ {
[CanBeNull] object? Map(object entityObj);
object Map(object entityObj);
} }

2
framework/src/Volo.Abp.Ddd.Domain/Volo.Abp.Ddd.Domain.csproj

@ -5,6 +5,8 @@
<PropertyGroup> <PropertyGroup>
<TargetFrameworks>netstandard2.0;netstandard2.1;net7.0</TargetFrameworks> <TargetFrameworks>netstandard2.0;netstandard2.1;net7.0</TargetFrameworks>
<Nullable>enable</Nullable>
<WarningsAsErrors>Nullable</WarningsAsErrors>
<AssemblyName>Volo.Abp.Ddd.Domain</AssemblyName> <AssemblyName>Volo.Abp.Ddd.Domain</AssemblyName>
<PackageId>Volo.Abp.Ddd.Domain</PackageId> <PackageId>Volo.Abp.Ddd.Domain</PackageId>
<AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback> <AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback>

10
framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/DependencyInjection/AbpCommonDbContextRegistrationOptions.cs

@ -16,13 +16,13 @@ public abstract class AbpCommonDbContextRegistrationOptions : IAbpCommonDbContex
public IServiceCollection Services { get; } public IServiceCollection Services { get; }
public Dictionary<MultiTenantDbContextType, Type> ReplacedDbContextTypes { get; } public Dictionary<MultiTenantDbContextType, Type?> ReplacedDbContextTypes { get; }
public Type DefaultRepositoryDbContextType { get; protected set; } public Type DefaultRepositoryDbContextType { get; protected set; }
public Type DefaultRepositoryImplementationType { get; private set; } public Type? DefaultRepositoryImplementationType { get; private set; }
public Type DefaultRepositoryImplementationTypeWithoutKey { get; private set; } public Type? DefaultRepositoryImplementationTypeWithoutKey { get; private set; }
public bool RegisterDefaultRepositories { get; private set; } public bool RegisterDefaultRepositories { get; private set; }
@ -40,7 +40,7 @@ public abstract class AbpCommonDbContextRegistrationOptions : IAbpCommonDbContex
Services = services; Services = services;
DefaultRepositoryDbContextType = originalDbContextType; DefaultRepositoryDbContextType = originalDbContextType;
CustomRepositories = new Dictionary<Type, Type>(); CustomRepositories = new Dictionary<Type, Type>();
ReplacedDbContextTypes = new Dictionary<MultiTenantDbContextType, Type>(); ReplacedDbContextTypes = new Dictionary<MultiTenantDbContextType, Type?>();
SpecifiedDefaultRepositories = new List<Type>(); SpecifiedDefaultRepositories = new List<Type>();
} }
@ -54,7 +54,7 @@ public abstract class AbpCommonDbContextRegistrationOptions : IAbpCommonDbContex
return ReplaceDbContext(typeof(TOtherDbContext), typeof(TTargetDbContext), multiTenancySides); return ReplaceDbContext(typeof(TOtherDbContext), typeof(TTargetDbContext), multiTenancySides);
} }
public IAbpCommonDbContextRegistrationOptionsBuilder ReplaceDbContext(Type otherDbContextType, Type targetDbContextType = null, MultiTenancySides multiTenancySides = MultiTenancySides.Both) public IAbpCommonDbContextRegistrationOptionsBuilder ReplaceDbContext(Type otherDbContextType, Type? targetDbContextType = null, MultiTenancySides multiTenancySides = MultiTenancySides.Both)
{ {
if (!otherDbContextType.IsAssignableFrom(OriginalDbContextType)) if (!otherDbContextType.IsAssignableFrom(OriginalDbContextType))
{ {

2
framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/DependencyInjection/IAbpCommonDbContextRegistrationOptionsBuilder.cs

@ -90,5 +90,5 @@ public interface IAbpCommonDbContextRegistrationOptionsBuilder
/// <param name="otherDbContextType">The DbContext type to be replaced</param> /// <param name="otherDbContextType">The DbContext type to be replaced</param>
/// <param name="targetDbContextType">The target DbContext type (optional, used this DbContext type if not provided)</param> /// <param name="targetDbContextType">The target DbContext type (optional, used this DbContext type if not provided)</param>
/// <param name="multiTenancySides">MultiTenancy side</param> /// <param name="multiTenancySides">MultiTenancy side</param>
IAbpCommonDbContextRegistrationOptionsBuilder ReplaceDbContext(Type otherDbContextType, Type targetDbContextType = null, MultiTenancySides multiTenancySides = MultiTenancySides.Both); IAbpCommonDbContextRegistrationOptionsBuilder ReplaceDbContext(Type otherDbContextType, Type? targetDbContextType = null, MultiTenancySides multiTenancySides = MultiTenancySides.Both);
} }

2
framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/DependencyInjection/MultiTenantDbContextType.cs

@ -15,7 +15,7 @@ public class MultiTenantDbContextType
MultiTenancySide = multiTenancySide; MultiTenancySide = multiTenancySide;
} }
public override bool Equals(object obj) public override bool Equals(object? obj)
{ {
var other = obj as MultiTenantDbContextType; var other = obj as MultiTenantDbContextType;

8
framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Auditing/AuditedAggregateRootWithUser.cs

@ -12,10 +12,10 @@ public abstract class AuditedAggregateRootWithUser<TUser> : AuditedAggregateRoot
where TUser : IEntity<Guid> where TUser : IEntity<Guid>
{ {
/// <inheritdoc /> /// <inheritdoc />
public virtual TUser Creator { get; protected set; } public virtual TUser? Creator { get; protected set; }
/// <inheritdoc /> /// <inheritdoc />
public virtual TUser LastModifier { get; set; } public virtual TUser? LastModifier { get; set; }
} }
/// <summary> /// <summary>
@ -28,10 +28,10 @@ public abstract class AuditedAggregateRootWithUser<TKey, TUser> : AuditedAggrega
where TUser : IEntity<Guid> where TUser : IEntity<Guid>
{ {
/// <inheritdoc /> /// <inheritdoc />
public virtual TUser Creator { get; protected set; } public virtual TUser? Creator { get; protected set; }
/// <inheritdoc /> /// <inheritdoc />
public virtual TUser LastModifier { get; set; } public virtual TUser? LastModifier { get; set; }
protected AuditedAggregateRootWithUser() protected AuditedAggregateRootWithUser()
{ {

8
framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Auditing/AuditedEntityWithUser.cs

@ -12,10 +12,10 @@ public abstract class AuditedEntityWithUser<TUser> : AuditedEntity, IAuditedObje
where TUser : IEntity<Guid> where TUser : IEntity<Guid>
{ {
/// <inheritdoc /> /// <inheritdoc />
public virtual TUser Creator { get; protected set; } public virtual TUser? Creator { get; protected set; }
/// <inheritdoc /> /// <inheritdoc />
public virtual TUser LastModifier { get; set; } public virtual TUser? LastModifier { get; set; }
} }
/// <summary> /// <summary>
@ -28,10 +28,10 @@ public abstract class AuditedEntityWithUser<TKey, TUser> : AuditedEntity<TKey>,
where TUser : IEntity<Guid> where TUser : IEntity<Guid>
{ {
/// <inheritdoc /> /// <inheritdoc />
public virtual TUser Creator { get; protected set; } public virtual TUser? Creator { get; protected set; }
/// <inheritdoc /> /// <inheritdoc />
public virtual TUser LastModifier { get; set; } public virtual TUser? LastModifier { get; set; }
protected AuditedEntityWithUser() protected AuditedEntityWithUser()
{ {

4
framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Auditing/CreationAuditedAggregateRootWithUser.cs

@ -11,7 +11,7 @@ namespace Volo.Abp.Domain.Entities.Auditing;
public abstract class CreationAuditedAggregateRootWithUser<TUser> : CreationAuditedAggregateRoot, ICreationAuditedObject<TUser> public abstract class CreationAuditedAggregateRootWithUser<TUser> : CreationAuditedAggregateRoot, ICreationAuditedObject<TUser>
{ {
/// <inheritdoc /> /// <inheritdoc />
public virtual TUser Creator { get; protected set; } public virtual TUser? Creator { get; protected set; }
} }
/// <summary> /// <summary>
@ -23,7 +23,7 @@ public abstract class CreationAuditedAggregateRootWithUser<TUser> : CreationAudi
public abstract class CreationAuditedAggregateRootWithUser<TKey, TUser> : CreationAuditedAggregateRoot<TKey>, ICreationAuditedObject<TUser> public abstract class CreationAuditedAggregateRootWithUser<TKey, TUser> : CreationAuditedAggregateRoot<TKey>, ICreationAuditedObject<TUser>
{ {
/// <inheritdoc /> /// <inheritdoc />
public virtual TUser Creator { get; protected set; } public virtual TUser? Creator { get; protected set; }
protected CreationAuditedAggregateRootWithUser() protected CreationAuditedAggregateRootWithUser()
{ {

4
framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Auditing/CreationAuditedEntityWithUser.cs

@ -11,7 +11,7 @@ namespace Volo.Abp.Domain.Entities.Auditing;
public abstract class CreationAuditedEntityWithUser<TUser> : CreationAuditedEntity, ICreationAuditedObject<TUser> public abstract class CreationAuditedEntityWithUser<TUser> : CreationAuditedEntity, ICreationAuditedObject<TUser>
{ {
/// <inheritdoc /> /// <inheritdoc />
public virtual TUser Creator { get; protected set; } public virtual TUser? Creator { get; protected set; }
} }
/// <summary> /// <summary>
@ -23,7 +23,7 @@ public abstract class CreationAuditedEntityWithUser<TUser> : CreationAuditedEnti
public abstract class CreationAuditedEntityWithUser<TKey, TUser> : CreationAuditedEntity<TKey>, ICreationAuditedObject<TUser> public abstract class CreationAuditedEntityWithUser<TKey, TUser> : CreationAuditedEntity<TKey>, ICreationAuditedObject<TUser>
{ {
/// <inheritdoc /> /// <inheritdoc />
public virtual TUser Creator { get; protected set; } public virtual TUser? Creator { get; protected set; }
protected CreationAuditedEntityWithUser() protected CreationAuditedEntityWithUser()
{ {

12
framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Auditing/FullAuditedAggregateRootWithUser.cs

@ -12,13 +12,13 @@ public abstract class FullAuditedAggregateRootWithUser<TUser> : FullAuditedAggre
where TUser : IEntity<Guid> where TUser : IEntity<Guid>
{ {
/// <inheritdoc /> /// <inheritdoc />
public virtual TUser Deleter { get; set; } public virtual TUser? Deleter { get; set; }
/// <inheritdoc /> /// <inheritdoc />
public virtual TUser Creator { get; protected set; } public virtual TUser? Creator { get; protected set; }
/// <inheritdoc /> /// <inheritdoc />
public virtual TUser LastModifier { get; set; } public virtual TUser? LastModifier { get; set; }
} }
/// <summary> /// <summary>
@ -31,13 +31,13 @@ public abstract class FullAuditedAggregateRootWithUser<TKey, TUser> : FullAudite
where TUser : IEntity<Guid> where TUser : IEntity<Guid>
{ {
/// <inheritdoc /> /// <inheritdoc />
public virtual TUser Deleter { get; set; } public virtual TUser? Deleter { get; set; }
/// <inheritdoc /> /// <inheritdoc />
public virtual TUser Creator { get; protected set; } public virtual TUser? Creator { get; protected set; }
/// <inheritdoc /> /// <inheritdoc />
public virtual TUser LastModifier { get; set; } public virtual TUser? LastModifier { get; set; }
protected FullAuditedAggregateRootWithUser() protected FullAuditedAggregateRootWithUser()
{ {

12
framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Auditing/FullAuditedEntityWithUser.cs

@ -12,13 +12,13 @@ public abstract class FullAuditedEntityWithUser<TUser> : FullAuditedEntity, IFul
where TUser : IEntity<Guid> where TUser : IEntity<Guid>
{ {
/// <inheritdoc /> /// <inheritdoc />
public virtual TUser Deleter { get; set; } public virtual TUser? Deleter { get; set; }
/// <inheritdoc /> /// <inheritdoc />
public virtual TUser Creator { get; protected set; } public virtual TUser? Creator { get; protected set; }
/// <inheritdoc /> /// <inheritdoc />
public virtual TUser LastModifier { get; set; } public virtual TUser? LastModifier { get; set; }
} }
/// <summary> /// <summary>
@ -31,13 +31,13 @@ public abstract class FullAuditedEntityWithUser<TKey, TUser> : FullAuditedEntity
where TUser : IEntity<Guid> where TUser : IEntity<Guid>
{ {
/// <inheritdoc /> /// <inheritdoc />
public virtual TUser Deleter { get; set; } public virtual TUser? Deleter { get; set; }
/// <inheritdoc /> /// <inheritdoc />
public virtual TUser Creator { get; protected set; } public virtual TUser? Creator { get; protected set; }
/// <inheritdoc /> /// <inheritdoc />
public virtual TUser LastModifier { get; set; } public virtual TUser? LastModifier { get; set; }
protected FullAuditedEntityWithUser() protected FullAuditedEntityWithUser()
{ {

12
framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Caching/EntityCacheBase.cs

@ -27,23 +27,23 @@ public abstract class EntityCacheBase<TEntity, TEntityCacheItem, TKey> :
UnitOfWorkManager = unitOfWorkManager; UnitOfWorkManager = unitOfWorkManager;
} }
public virtual async Task<TEntityCacheItem> FindAsync(TKey id) public virtual async Task<TEntityCacheItem?> FindAsync(TKey id)
{ {
return await Cache.GetOrAddAsync( return await Cache.GetOrAddAsync(
id, id,
async () => MapToCacheItem(await Repository.FindAsync(id)) async () => MapToCacheItem(await Repository.FindAsync(id))!
); );
} }
public virtual async Task<TEntityCacheItem> GetAsync(TKey id) public virtual async Task<TEntityCacheItem> GetAsync(TKey id)
{ {
return await Cache.GetOrAddAsync( return (await Cache.GetOrAddAsync(
id, id,
async () => MapToCacheItem(await Repository.GetAsync(id)) async () => MapToCacheItem(await Repository.GetAsync(id))!
); ))!;
} }
protected abstract TEntityCacheItem MapToCacheItem(TEntity entity); protected abstract TEntityCacheItem? MapToCacheItem(TEntity? entity);
public async Task HandleEventAsync(EntityChangedEventData<TEntity> eventData) public async Task HandleEventAsync(EntityChangedEventData<TEntity> eventData)
{ {

6
framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Caching/EntityCacheServiceCollectionExtensions.cs

@ -13,7 +13,7 @@ public static class EntityCacheServiceCollectionExtensions
{ {
public static IServiceCollection AddEntityCache<TEntity, TKey>( public static IServiceCollection AddEntityCache<TEntity, TKey>(
this IServiceCollection services, this IServiceCollection services,
[CanBeNull] DistributedCacheEntryOptions cacheOptions = null) DistributedCacheEntryOptions? cacheOptions = null)
where TEntity : Entity<TKey> where TEntity : Entity<TKey>
{ {
services services
@ -39,7 +39,7 @@ public static class EntityCacheServiceCollectionExtensions
public static IServiceCollection AddEntityCache<TEntity, TEntityCacheItem, TKey>( public static IServiceCollection AddEntityCache<TEntity, TEntityCacheItem, TKey>(
this IServiceCollection services, this IServiceCollection services,
[CanBeNull] DistributedCacheEntryOptions cacheOptions = null) DistributedCacheEntryOptions? cacheOptions = null)
where TEntity : Entity<TKey> where TEntity : Entity<TKey>
where TEntityCacheItem : class where TEntityCacheItem : class
{ {
@ -61,7 +61,7 @@ public static class EntityCacheServiceCollectionExtensions
public static IServiceCollection AddEntityCache<TObjectMapperContext, TEntity, TEntityCacheItem, TKey>( public static IServiceCollection AddEntityCache<TObjectMapperContext, TEntity, TEntityCacheItem, TKey>(
this IServiceCollection services, this IServiceCollection services,
[CanBeNull] DistributedCacheEntryOptions cacheOptions = null) DistributedCacheEntryOptions? cacheOptions = null)
where TEntity : Entity<TKey> where TEntity : Entity<TKey>
where TEntityCacheItem : class where TEntityCacheItem : class
{ {

2
framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Caching/EntityCacheWithObjectMapper.cs

@ -23,7 +23,7 @@ public class EntityCacheWithObjectMapper<TEntity, TEntityCacheItem, TKey> :
ObjectMapper = objectMapper; ObjectMapper = objectMapper;
} }
protected override TEntityCacheItem MapToCacheItem(TEntity entity) protected override TEntityCacheItem? MapToCacheItem(TEntity? entity)
{ {
if (entity == null) if (entity == null)
{ {

2
framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Caching/EntityCacheWithoutCacheItem.cs

@ -16,7 +16,7 @@ public class EntityCacheWithoutCacheItem<TEntity, TKey> :
{ {
} }
protected override TEntity MapToCacheItem(TEntity entity) protected override TEntity? MapToCacheItem(TEntity? entity)
{ {
return entity; return entity;
} }

3
framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Caching/IEntityCache.cs

@ -10,8 +10,7 @@ public interface IEntityCache<TEntityCacheItem, in TKey>
/// Gets the entity with given <paramref name="id"/>, /// Gets the entity with given <paramref name="id"/>,
/// or returns null if the entity was not found. /// or returns null if the entity was not found.
/// </summary> /// </summary>
[ItemCanBeNull] Task<TEntityCacheItem?> FindAsync(TKey id);
Task<TEntityCacheItem> FindAsync(TKey id);
/// <summary> /// <summary>
/// Gets the entity with given <paramref name="id"/>, /// Gets the entity with given <paramref name="id"/>,

8
framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Entity.cs

@ -18,7 +18,7 @@ public abstract class Entity : IEntity
return $"[ENTITY: {GetType().Name}] Keys = {GetKeys().JoinAsString(", ")}"; return $"[ENTITY: {GetType().Name}] Keys = {GetKeys().JoinAsString(", ")}";
} }
public abstract object[] GetKeys(); public abstract object?[] GetKeys();
public bool EntityEquals(IEntity other) public bool EntityEquals(IEntity other)
{ {
@ -31,7 +31,7 @@ public abstract class Entity : IEntity
public abstract class Entity<TKey> : Entity, IEntity<TKey> public abstract class Entity<TKey> : Entity, IEntity<TKey>
{ {
/// <inheritdoc/> /// <inheritdoc/>
public virtual TKey Id { get; protected set; } public virtual TKey Id { get; protected set; } = default!;
protected Entity() protected Entity()
{ {
@ -43,9 +43,9 @@ public abstract class Entity<TKey> : Entity, IEntity<TKey>
Id = id; Id = id;
} }
public override object[] GetKeys() public override object?[] GetKeys()
{ {
return new object[] { Id }; return new object?[] { Id };
} }
/// <inheritdoc/> /// <inheritdoc/>

16
framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/EntityHelper.cs

@ -25,7 +25,7 @@ public static class EntityHelper
return typeof(IMultiTenant).IsAssignableFrom(type); return typeof(IMultiTenant).IsAssignableFrom(type);
} }
public static bool EntityEquals(IEntity entity1, IEntity entity2) public static bool EntityEquals(IEntity? entity1, IEntity? entity2)
{ {
if (entity1 == null || entity2 == null) if (entity1 == null || entity2 == null)
{ {
@ -131,7 +131,7 @@ public static class EntityHelper
return IsValueObjectPredicate(type); return IsValueObjectPredicate(type);
} }
public static bool IsValueObject(object obj) public static bool IsValueObject(object? obj)
{ {
return obj != null && IsValueObject(obj.GetType()); return obj != null && IsValueObject(obj.GetType());
} }
@ -161,7 +161,7 @@ public static class EntityHelper
public static bool HasDefaultId<TKey>(IEntity<TKey> entity) public static bool HasDefaultId<TKey>(IEntity<TKey> entity)
{ {
if (EqualityComparer<TKey>.Default.Equals(entity.Id, default)) if (EqualityComparer<TKey>.Default.Equals(entity.Id, default!))
{ {
return true; return true;
} }
@ -180,7 +180,7 @@ public static class EntityHelper
return false; return false;
} }
private static bool IsDefaultKeyValue(object value) private static bool IsDefaultKeyValue(object? value)
{ {
if (value == null) if (value == null)
{ {
@ -222,8 +222,7 @@ public static class EntityHelper
/// Tries to find the primary key type of the given entity type. /// Tries to find the primary key type of the given entity type.
/// May return null if given type does not implement <see cref="IEntity{TKey}"/> /// May return null if given type does not implement <see cref="IEntity{TKey}"/>
/// </summary> /// </summary>
[CanBeNull] public static Type? FindPrimaryKeyType<TEntity>()
public static Type FindPrimaryKeyType<TEntity>()
where TEntity : IEntity where TEntity : IEntity
{ {
return FindPrimaryKeyType(typeof(TEntity)); return FindPrimaryKeyType(typeof(TEntity));
@ -233,8 +232,7 @@ public static class EntityHelper
/// Tries to find the primary key type of the given entity type. /// Tries to find the primary key type of the given entity type.
/// May return null if given type does not implement <see cref="IEntity{TKey}"/> /// May return null if given type does not implement <see cref="IEntity{TKey}"/>
/// </summary> /// </summary>
[CanBeNull] public static Type? FindPrimaryKeyType([NotNull] Type entityType)
public static Type FindPrimaryKeyType([NotNull] Type entityType)
{ {
if (!typeof(IEntity).IsAssignableFrom(entityType)) if (!typeof(IEntity).IsAssignableFrom(entityType))
{ {
@ -260,7 +258,7 @@ public static class EntityHelper
var lambdaParam = Expression.Parameter(typeof(TEntity)); var lambdaParam = Expression.Parameter(typeof(TEntity));
var leftExpression = Expression.PropertyOrField(lambdaParam, "Id"); var leftExpression = Expression.PropertyOrField(lambdaParam, "Id");
var idValue = Convert.ChangeType(id, typeof(TKey)); var idValue = Convert.ChangeType(id, typeof(TKey));
Expression<Func<object>> closure = () => idValue; Expression<Func<object?>> closure = () => idValue;
var rightExpression = Expression.Convert(closure.Body, leftExpression.Type); var rightExpression = Expression.Convert(closure.Body, leftExpression.Type);
var lambdaBody = Expression.Equal(leftExpression, rightExpression); var lambdaBody = Expression.Equal(leftExpression, rightExpression);
return Expression.Lambda<Func<TEntity, bool>>(lambdaBody, lambdaParam); return Expression.Lambda<Func<TEntity, bool>>(lambdaBody, lambdaParam);

7
framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Events/Distributed/EntitySynchronizer.cs

@ -22,7 +22,7 @@ public abstract class EntitySynchronizer<TEntity, TKey, TSourceEntityEto> :
Repository = repository; Repository = repository;
} }
protected override Task<TEntity> FindLocalEntityAsync(TSourceEntityEto eto) protected override Task<TEntity?> FindLocalEntityAsync(TSourceEntityEto eto)
{ {
return Repository.FindAsync(eto.Id); return Repository.FindAsync(eto.Id);
} }
@ -154,10 +154,9 @@ public abstract class EntitySynchronizer<TEntity, TSourceEntityEto> :
return true; return true;
} }
[ItemCanBeNull] protected abstract Task<TEntity?> FindLocalEntityAsync(TSourceEntityEto eto);
protected abstract Task<TEntity> FindLocalEntityAsync(TSourceEntityEto eto);
protected virtual Task<bool> IsEtoNewerAsync(TSourceEntityEto eto, [CanBeNull] TEntity localEntity) protected virtual Task<bool> IsEtoNewerAsync(TSourceEntityEto eto, TEntity? localEntity)
{ {
if (localEntity is IHasEntityVersion versionedLocalEntity && eto is IHasEntityVersion versionedEto) if (localEntity is IHasEntityVersion versionedLocalEntity && eto is IHasEntityVersion versionedEto)
{ {

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

Loading…
Cancel
Save