Browse Source

Merge branch 'dev' into auto-merge/rel-7-3/2059

pull/17066/head
Engincan VESKE 3 years ago
parent
commit
eb7e1fd2e9
  1. 3
      .github/scripts/update_versions.py
  2. 3
      Directory.Build.props
  3. 3
      abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json
  4. 1
      abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/ar.json
  5. 8
      abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/en.json
  6. 1
      abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/fi.json
  7. 1
      abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/hu.json
  8. 1
      abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/tr.json
  9. 1
      abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/zh-Hans.json
  10. 2
      abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/ar.json
  11. 57
      abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json
  12. 2
      abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/fi.json
  13. 2
      abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/hu.json
  14. 10
      abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/tr.json
  15. 13
      abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/zh-Hans.json
  16. 2
      common.props
  17. 267
      docs/en/Blog-Posts/2023-06-05 v7_3_Preview/POST.md
  18. BIN
      docs/en/Blog-Posts/2023-06-05 v7_3_Preview/abp-conf.png
  19. BIN
      docs/en/Blog-Posts/2023-06-05 v7_3_Preview/community-talks-2023-4.png
  20. BIN
      docs/en/Blog-Posts/2023-06-05 v7_3_Preview/cover-image.png
  21. BIN
      docs/en/Blog-Posts/2023-06-05 v7_3_Preview/devnot-conference.png
  22. BIN
      docs/en/Blog-Posts/2023-06-05 v7_3_Preview/devnot-talk.png
  23. BIN
      docs/en/Blog-Posts/2023-06-05 v7_3_Preview/leptonx-account-layout.png
  24. BIN
      docs/en/Blog-Posts/2023-06-05 v7_3_Preview/reset-authenticator.png
  25. BIN
      docs/en/Blog-Posts/2023-06-05 v7_3_Preview/two-factor-auth-1.png
  26. BIN
      docs/en/Blog-Posts/2023-06-05 v7_3_Preview/two-factor-auth-2.png
  27. BIN
      docs/en/Blog-Posts/2023-06-05 v7_3_Preview/two-factor-auth-3.png
  28. 4
      docs/en/Community-Articles/2023-06-05-Kubernetes-Integration-Abp-Studio/POST.md
  29. 293
      docs/en/Community-Articles/2023-07-03-Image-Compression-And-Resize/POST.md
  30. BIN
      docs/en/Community-Articles/2023-07-03-Image-Compression-And-Resize/image-manipulation.gif
  31. BIN
      docs/en/Community-Articles/2023-07-03-Image-Compression-And-Resize/image-upload-ui.png
  32. 40
      docs/en/Integration-Services.md
  33. 8
      docs/en/Migration-Guides/docs/en/Migration-Guides/Abp-7_4.md
  34. 23
      docs/en/Module-Development-Basics.md
  35. 14
      docs/en/Module-Entity-Extensions.md
  36. 2
      framework/src/Volo.Abp.ApiVersioning.Abstractions/Volo.Abp.ApiVersioning.Abstractions.csproj
  37. 2
      framework/src/Volo.Abp.ApiVersioning.Abstractions/Volo/Abp/ApiVersioning/IRequestedApiVersion.cs
  38. 2
      framework/src/Volo.Abp.ApiVersioning.Abstractions/Volo/Abp/ApiVersioning/NullRequestedApiVersion.cs
  39. 2
      framework/src/Volo.Abp.AspNetCore.Authentication.JwtBearer/Volo.Abp.AspNetCore.Authentication.JwtBearer.csproj
  40. 2
      framework/src/Volo.Abp.AspNetCore.Authentication.OAuth/Volo.Abp.AspNetCore.Authentication.OAuth.csproj
  41. 4
      framework/src/Volo.Abp.AspNetCore.Authentication.OAuth/Volo/Abp/AspNetCore/Authentication/OAuth/Claims/MultipleClaimAction.cs
  42. 15
      framework/src/Volo.Abp.AspNetCore.Authentication.OpenIdConnect/Microsoft/Extensions/DependencyInjection/AbpOpenIdConnectExtensions.cs
  43. 2
      framework/src/Volo.Abp.AspNetCore.Authentication.OpenIdConnect/Volo.Abp.AspNetCore.Authentication.OpenIdConnect.csproj
  44. 5
      framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/AbpComponentBase.cs
  45. 29
      framework/src/Volo.Abp.AspNetCore.Mvc.Dapr.EventBus/Volo/Abp/AspNetCore/Mvc/Dapr/EventBus/Controllers/AbpAspNetCoreMvcDaprEventsController.cs
  46. 19
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcModule.cs
  47. 2
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcOptions.cs
  48. 4
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ApplicationPartSorter.cs
  49. 15
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Conventions/AbpServiceConvention.cs
  50. 18
      framework/src/Volo.Abp.AspNetCore.TestBase/Volo/Abp/AspNetCore/TestBase/AbpAspNetCoreIntegratedTestBase.cs
  51. 18
      framework/src/Volo.Abp.AspNetCore.TestBase/Volo/Abp/AspNetCore/TestBase/TestStartup.cs
  52. 17
      framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/Builder/AbpAspNetCoreApplicationBuilderExtensions.cs
  53. 28
      framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Tracing/AbpCorrelationIdMiddleware.cs
  54. 51
      framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Tracing/AspNetCoreCorrelationIdProvider.cs
  55. 2
      framework/src/Volo.Abp.Autofac.WebAssembly/Microsoft/AspNetCore/Components/WebAssembly/Hosting/AbpWebAssemblyApplicationCreationOptionsAutofacExtensions.cs
  56. 2
      framework/src/Volo.Abp.Autofac.WebAssembly/Volo.Abp.Autofac.WebAssembly.csproj
  57. 2
      framework/src/Volo.Abp.Autofac/Autofac/Builder/AbpRegistrationBuilderExtensions.cs
  58. 8
      framework/src/Volo.Abp.Autofac/Autofac/Extensions/DependencyInjection/AutofacRegistration.cs
  59. 2
      framework/src/Volo.Abp.Autofac/Microsoft/Extensions/DependencyInjection/AbpAutofacServiceCollectionExtensions.cs
  60. 2
      framework/src/Volo.Abp.Autofac/Volo.Abp.Autofac.csproj
  61. 2
      framework/src/Volo.Abp.Autofac/Volo/Abp/Autofac/AbpAutofacServiceProviderFactory.cs
  62. 35
      framework/src/Volo.Abp.BlazoriseUI/AbpCrudPageBase.cs
  63. 2
      framework/src/Volo.Abp.BlazoriseUI/Components/ObjectExtending/CheckExtensionProperty.razor
  64. 1
      framework/src/Volo.Abp.BlazoriseUI/Components/ObjectExtending/DateTimeExtensionProperty.razor
  65. 1
      framework/src/Volo.Abp.BlazoriseUI/Components/ObjectExtending/ExtensionProperties.razor
  66. 4
      framework/src/Volo.Abp.BlazoriseUI/Components/ObjectExtending/ExtensionProperties.razor.cs
  67. 7
      framework/src/Volo.Abp.BlazoriseUI/Components/ObjectExtending/ExtensionPropertyComponentBase.cs
  68. 7
      framework/src/Volo.Abp.BlazoriseUI/Components/ObjectExtending/ExtensionPropertyModalType.cs
  69. 3
      framework/src/Volo.Abp.BlazoriseUI/Components/ObjectExtending/LookupExtensionProperty.razor
  70. 2
      framework/src/Volo.Abp.BlazoriseUI/Components/ObjectExtending/SelectExtensionProperty.razor
  71. 2
      framework/src/Volo.Abp.BlazoriseUI/Components/ObjectExtending/TextExtensionProperty.razor
  72. 2
      framework/src/Volo.Abp.BlazoriseUI/Components/ObjectExtending/TimeExtensionProperty.razor
  73. 2
      framework/src/Volo.Abp.Castle.Core/Volo.Abp.Castle.Core.csproj
  74. 4
      framework/src/Volo.Abp.Castle.Core/Volo/Abp/Castle/DynamicProxy/CastleAbpMethodInvocationAdapterBase.cs
  75. 2
      framework/src/Volo.Abp.Castle.Core/Volo/Abp/Castle/DynamicProxy/CastleAbpMethodInvocationAdapterWithReturnValue.cs
  76. 8
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/LoginCommand.cs
  77. 28
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/Services/SuiteAppSettingsService.cs
  78. 21
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/ConnectionStringRenameStep.cs
  79. 5
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/App/AppTemplateBase.cs
  80. 8
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/Microservice/MicroserviceServiceTemplateBase.cs
  81. 7
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/Module/ModuleTemplateBase.cs
  82. 2
      framework/src/Volo.Abp.Core/Volo.Abp.Core.csproj
  83. 20
      framework/src/Volo.Abp.Core/Volo/Abp/AbpApplicationBase.cs
  84. 4
      framework/src/Volo.Abp.Core/Volo/Abp/AbpException.cs
  85. 4
      framework/src/Volo.Abp.Core/Volo/Abp/Modularity/AbpModuleDescriptor.cs
  86. 15
      framework/src/Volo.Abp.Core/Volo/Abp/Modularity/AbpModuleDescriptorExtensions.cs
  87. 21
      framework/src/Volo.Abp.Core/Volo/Abp/Modularity/AbpModuleHelper.cs
  88. 24
      framework/src/Volo.Abp.Core/Volo/Abp/Modularity/AdditionalAssemblyAttribute.cs
  89. 4
      framework/src/Volo.Abp.Core/Volo/Abp/Modularity/DependsOnAttribute.cs
  90. 25
      framework/src/Volo.Abp.Core/Volo/Abp/Modularity/IAbpModuleDescriptor.cs
  91. 8
      framework/src/Volo.Abp.Core/Volo/Abp/Modularity/IAdditionalModuleAssemblyProvider.cs
  92. 2
      framework/src/Volo.Abp.Core/Volo/Abp/Reflection/AssemblyFinder.cs
  93. 18
      framework/src/Volo.Abp.Core/Volo/Abp/Tracing/DefaultCorrelationIdProvider.cs
  94. 7
      framework/src/Volo.Abp.Core/Volo/Abp/Tracing/ICorrelationIdProvider.cs
  95. 2
      framework/src/Volo.Abp.Dapr/Volo/Abp/Dapr/IDaprSerializer.cs
  96. 5
      framework/src/Volo.Abp.Dapr/Volo/Abp/Dapr/Utf8JsonDaprSerializer.cs
  97. 2
      framework/src/Volo.Abp.Data/Volo.Abp.Data.csproj
  98. 2
      framework/src/Volo.Abp.Data/Volo/Abp/Data/AbpCommonDbProperties.cs
  99. 8
      framework/src/Volo.Abp.Data/Volo/Abp/Data/AbpDataMigrationEnvironmentExtensions.cs
  100. 12
      framework/src/Volo.Abp.Data/Volo/Abp/Data/AbpDatabaseInfo.cs

3
.github/scripts/update_versions.py

@ -51,5 +51,4 @@ def create_pr():
if __name__ == "__main__":
should_create_pr = update_latest_versions()
if should_create_pr:
create_pr()
create_pr()

3
Directory.Build.props

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

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

@ -463,6 +463,7 @@
"DiscountAmount": "Discount Amount",
"FullChangeHistory": "Full Change History",
"Permission:RefreshReleaseLogs": "Refresh Release Logs",
"ReleaseLogs": "Release Logs"
"ReleaseLogs": "Release Logs",
"AuthorUserName": "Author User Name"
}
}

1
abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/ar.json

@ -137,6 +137,7 @@
"Address": "العنوان",
"Homepage": "الصفحة الرئيسية",
"Year": "السنة",
"Year_Plural": "سنوات",
"Copyright": "حقوق النشر © <a href=\"{0}\" target=\"_blank\">{1}</a>",
"DomainDrivenDesign": "التصميم المُقاد بالنطاق DDD",
"CrossCuttingConcerns": "اهتمامات مشتركة",

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

@ -141,6 +141,7 @@
"Address": "Address",
"Homepage": "Homepage",
"Year": "Year",
"Year_Plural": "Years",
"Copyright": "Copyright © <a href=\"{0}\" target=\"_blank\">{1}</a>",
"DomainDrivenDesign": "Domain Driven Design",
"CrossCuttingConcerns": "Cross Cutting Concerns",
@ -211,6 +212,11 @@
"RecentActivities": "Recent Activities",
"SpringCampaign": "Welcome <br>Spring Sale!",
"SpringCampaign2": "<span>Limited <br> Time Offer!</span>",
"AboutUs": "About Us"
"AboutUs": "About Us",
"HowItWorks": "How it works?",
"ReleaseNotes": "Release Notes",
"DetailedChangeNotes" : "Detailed Change Notes",
"SeeTrainings": "See Trainings",
"NoContent": "No content"
}
}

1
abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/fi.json

@ -140,6 +140,7 @@
"Address": "Osoite",
"Homepage": "Kotisivu",
"Year": "vuosi",
"Year_Plural": "vuotta",
"Copyright": "Tekijänoikeus © <a href=\"{0}\" target=\"_blank\">{1}</a>",
"DomainDrivenDesign": "Domain Driven Design",
"CrossCuttingConcerns": "Cross Cutting Concerns",

1
abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/hu.json

@ -138,6 +138,7 @@
"Address": "Cím",
"Homepage": "Kezdőlap",
"Year": "Év",
"Year_Plural": "Év",
"Copyright": "Copyright © <a href=\"{0}\" target=\"_blank\">{1}</a>",
"DomainDrivenDesign": "Domainvezérelt tervezés",
"CrossCuttingConcerns": "Cross Cutting Concerns",

1
abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/tr.json

@ -132,6 +132,7 @@
"Address": "Adres",
"Homepage": "Anasayfa",
"Year": "Yıl",
"Year_Plural": "Yıl",
"Copyright": "Telif hakkı © <a href=\"{0}\" target=\"_blank\">{1}</a>",
"DomainDrivenDesign": "Alan Odaklı Tasarım",
"CrossCuttingConcerns": "Cross Cutting Concerns",

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

@ -140,6 +140,7 @@
"Address": "地址",
"Homepage": "主页",
"Year": "年份",
"Year_Plural": "年份",
"Copyright": "版权所有 © <a href=\"{0}\" target=\"_blank\">{1}</a>",
"DomainDrivenDesign": "领域驱动设计",
"CrossCuttingConcerns": "横切关注点",

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

@ -454,7 +454,7 @@
"MultipleUIOptionsExplanation": "نحن نحب طرقًا مختلفة لإنشاء واجهة المستخدم. يوفر حل بدء التشغيل هذا ثلاثة خيارات مختلفة لإطار عمل واجهة المستخدم لتطبيق عملك.",
"MultipleDatabaseOptions": "خيارات قاعدة بيانات متعددة",
"MultipleDatabaseOptionsExplanation": "لديك خياران لموفر قاعدة البيانات (بالإضافة إلى استخدام كليهما في تطبيق واحد). استخدم Entity Framework Core للعمل مع أي قاعدة بيانات علائقية واستخدم Dapper اختياريًا عندما تحتاج إلى كتابة استعلامات منخفضة المستوى للحصول على أداء أفضل. يعد MongoDB خيارًا آخر إذا كنت بحاجة إلى استخدام قاعدة بيانات NoSQL قائمة على المستندات. في حين أن هؤلاء الموفرين مدمجون جيدًا وملخصون ومهيئون مسبقًا ، يمكنك في الواقع التفاعل مع أي نظام قاعدة بيانات يمكنك استخدامه مع .NET.",
"ModularArchitectureExplanation2": "النمطية هي مواطن من الدرجة الأولى في منصة ABP.IO. يتم تقسيم جميع وظائف التطبيق إلى وحدات اختيارية معزولة جيدًا. يأتي حل بدء التشغيل بالفعل مع وحدات <a href=\"@Url.Page(\"/Modules\")\" class=\"text-primary\">ABP Commercial الأساسية </a> المثبتة مسبقًا. يمكنك أيضًا إنشاء الوحدات النمطية الخاصة بك لبناء نظام معياري لتطبيقك الخاص.",
"ModularArchitectureExplanation2": "النمطية هي مواطن من الدرجة الأولى في منصة ABP.IO. يتم تقسيم جميع وظائف التطبيق إلى وحدات اختيارية معزولة جيدًا. يأتي حل بدء التشغيل بالفعل مع وحدات <a href=\"/modules\" class=\"text-primary\">ABP Commercial الأساسية </a> المثبتة مسبقًا. يمكنك أيضًا إنشاء الوحدات النمطية الخاصة بك لبناء نظام معياري لتطبيقك الخاص.",
"MultiTenancyForSaasBusiness": "متعدد الإيجارات لأعمال SaaS الخاصة بك",
"MultiTenancyForSaasBusinessExplanation": "توفر ABP Commercial نظامًا كاملاً ومتعدد الإيجارات لإنشاء أنظمة SaaS (البرمجيات كخدمة). يسمح للمستأجرين بمشاركة قواعد البيانات الخاصة بهم أو الحصول عليها من خلال إنشاء قاعدة بيانات سريعة ونظام الهجرة.",
"MicroserviceStartupSolution": "حل بدء تشغيل الخدمات المصغرة",

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

@ -476,7 +476,7 @@
"MultipleUIOptionsExplanation": "We love different ways to create the User Interface. This startup solution provides three different UI framework options for your business application.",
"MultipleDatabaseOptions": "Multiple Database Options",
"MultipleDatabaseOptionsExplanation": "You have two database provider options (in addition to use both in a single application). Use Entity Framework Core to work with any relational database and optionally use Dapper when you need to write low-level queries for a better performance. MongoDB is another option if you need to use a document based NoSQL database. While these providers are well-integrated, abstracted and pre-configured, you can actually interact to any database system that you can use with .NET.",
"ModularArchitectureExplanation2": "Modularity is a first-class citizen in the ABP.IO platform. All the application functionalities are split into well-isolated optional modules. The startup solution already comes with the fundamental <a href=\"@Url.Page(\"/Modules\")\" class=\"text-primary\">ABP Commercial modules</a> pre-installed. You can also create your own modules to build a modular system for your own application.",
"ModularArchitectureExplanation2": "Modularity is a first-class citizen in the ABP.IO platform. All the application functionalities are split into well-isolated optional modules. The startup solution already comes with the fundamental <a href=\"/modules\" class=\"text-primary\">ABP Commercial modules</a> pre-installed. You can also create your own modules to build a modular system for your own application.",
"MultiTenancyForSaasBusiness": "Multi-Tenancy for your SaaS Business",
"MultiTenancyForSaasBusinessExplanation": "ABP Commercial provides a complete, end-to-end multi-tenancy system to create your SaaS (Software-as-a-Service) systems. It allows the tenants to share or have their own databases with on-the-fly database creation and migration system.",
"MicroserviceStartupSolution": "Microservice Startup Solution",
@ -844,7 +844,7 @@
"BlazoriseSupportExplanation5": "You can post your questions on the support website and generate a product token for your application.",
"AbpLiveTrainingPackages": "ABP Live Training Packages",
"Releases": "Releases",
"ReleasesDescription": "ABP Commercial releases and their changelogs.",
"ReleasesDescription": "Release logs of ABP Commercial.",
"ReleaseDate": "Release Date",
"Labels": "Labels",
"PreRelease": "Pre-release",
@ -852,7 +852,56 @@
"Enhancement": "Enhancement",
"Bug": "Bug",
"Feature": "Feature",
"AllUIs": "All UI's",
"MVC": "MVC"
"AllUIs": "All UIs",
"MVC": "MVC",
"BlazorServer": "Blazor Server",
"MAUI": "MAUI",
"HowItWorks_Page_Title": "How it works?",
"HowItWorks_Page_Description": "ABP Framework extends the .NET platform. So, anything you can do with a plain .NET solution is already possible with the ABP Framework. That makes it easy to get started with a low learning curve.",
"HowItWorks_Description1": "ABP Framework extends the .NET platform. So, anything you can do with a plain .NET solution is already possible with the ABP Framework. That makes it easy to get started with a low learning curve.",
"HowItWorks_Description2": "Once you start learning and using the ABP Framework features, developing your software will be much more enjoyable than ever.",
"HowItWorks_Description3": "This page basically explains how you use the ABP.IO Platform as a .NET developer.",
"CreateANewSolution": "Create a New .NET Solution",
"CreateANewSolution_Description1": "Everything starts by creating a new ABP integrated .NET solution.",
"StartWithStartupTemplates": "Start one of the pre-built <a href=\"/startup-templates\">startup solution templates</a>",
"SimpleMonolithApplicationTemplate": "Simple monolith application template",
"LayeredApplicationTemplate": "Layered application template",
"MicroserviceSolutionTemplate": "Microservice solution template",
"CreateEmptySolutionAndUseAbp": "Or create a new empty .NET solution and install ABP NuGet & NPM <a href=\"https://abp.io/packages\" target=\"_blank\">packages</a> yourself.",
"CreatingSolutionWithMultipleOptions": "There are multiple User Interface and Database options while creating a new solution.",
"UIFrameworkOptions": "UI Framework Options",
"DotnetSolutionWithoutDependency": "Now, you have a regular .NET solution in your local computer that has no dependency to a cloud platform or external service.",
"CheckTheDocumentForDetails": "You can check the <a href=\"{0}\" target=\"_blank\">{1}</a> document for details.",
"UIAndDatabaseIndependent": "ABP can work with any UI and any database provider supported by .NET. \n However, these UI and database providers are pre-integrated and well documented.",
"InstallAbpModules": "Install ABP Modules",
"DevelopYourSolution": "Develop Your Solution",
"DeployAnywhere": "Deploy Anywhere",
"InstallAbpModule_Description1": "ABP is a modular application development framework. Startup solution templates already come with the essential modules installed. \n But there are more application modules you may want to use in your solution.",
"InstallAbpModule_Description2": "Every module consists of a few NuGet and NPM packages and has an installation document. <a href=\"/tools/suite\">ABP Suite</a> does most of the work automatically, then you manually configure or fine tune the module based on its documentation.",
"DevelopYourSolution_Description1": "ABP’s infrastructure makes you <b class=\"text-white\">focus on your own business code</b> by automating the repetitive work and providing pre-built infrastructure and application <a href=\"https://abp.io/features\" target=\"_blank\">features</a>.",
"DevelopYourSolution_Description2": "In the following code block, you can see how the ABP Framework seamlessly integrates into your code and automates the repetitive tasks for you.",
"DevelopYourSolution_Description3": "Even in this short code block, ABP does a lot of things for you.",
"DevelopYourSolution_Description4": "It provides base classes to apply conventions, like \n <a href=\"https://docs.abp.io/en/abp/latest/Dependency-Injection\" target=\"_blank\">dependency injection</a>. Generic \n <a href=\"https://docs.abp.io/en/abp/latest/Repositories\" target=\"_blank\">repository</a> services provide a convenient \n way to interact with the database. Declarative \n <a href=\"https://docs.abp.io/en/abp/latest/Authorization\" target=\"_blank\">authorization</a> works with a fine-tuned permission system.",
"DevelopYourSolution_Description5": "ABP completely automates \n <a href=\"https://docs.abp.io/en/abp/latest/Unit-Of-Work\" target=\"_blank\">unit of work</a> (for database connection and transaction management), \n <a href=\"https://docs.abp.io/en/abp/latest/Exception-Handling\" target=\"_blank\">exception handling</a>, \n <a href=\"https://docs.abp.io/en/abp/latest/Validation\" target=\"_blank\">validation</a>\n and <a href=\"https://docs.abp.io/en/abp/latest/Audit-Logging\" target=\"_blank\">audit logging</a>. It provides many more building blocks to simplify your daily development tasks and focus on your own code while creating production ready \n applications.",
"DevelopYourSolution_Description6": "You can imagine how much that code block can be long and complicated if you would do it all manually.",
"SuiteCrudGenerationInFewSeconds": "In addition to hand coding your solution, you can create fully working advanced CRUD pages in a few minutes using the ABP Suite tooling. It generates the code into your solution, so you can fine tune it based on your custom requirements.",
"DeployAnywhere_Description1": "At the end of the day, you have a pure .NET solution. You can deploy your solution to your own server, to a cloud platform, kubernetes or anywhere you want. You can deploy to as many servers as you want. ABP is a deployment environment agnostic tool.",
"ExpertiseAbpFramework": "Expertise the ABP Framework",
"ExpertiseAbpFramework_Description1": "Want to go beyond basics and get expertise with the ABP.IO Platform?",
"FreeDownload": "Free Download",
"Read": "Read",
"HavingTrouble": "Having Trouble?",
"HavingTrouble_Description1": "Do you have problems with developing your solution? We are here! Use the ABP Support platform \n or send an email to get help directly from the Core ABP Framework team members.",
"WeAreHereToHelp_Description1": "You can browse our help topics or search in the frequently asked questions, \n or you can ask us a question by using the contact form.",
"OtherModules": "Other Modules",
"OtherModules_Description1": "Account, Audit Logging, Chat , CMS Kit,File Management , Forms, GDPR, Identity, Language Management, Payment , Saas and more...",
"HowItWorks_DatabaseProviderOptions": "Database provider options",
"SeeFAQ" : "See FAQ",
"ReleaseLogs": "Release Logs",
"ReleaseLogs_Tag": "{0} Release Logs",
"ReleaseLogs_Pr": "Pull Request #{0} - {1}",
"NoLabels": "No labels",
"DoesTheSubscriptionRenewAutomatically": "Does the subscription renew automatically?",
"DoesTheSubscriptionRenewAutomaticallyExplanation": "The ABP Commercial does not have an auto-renewal billing model. Therefore <strong>your subscription will not be automatically renewed</strong> at the end of your license period. If you want to continue to have the benefits of ABP Commercial, you can manually renew it at the <a href=\"/my-organizations\">organization management page</a>. If you have multiple organizations, click the \"Manage\" button at your expiring organization and then click the \"Extend Now\" button to renew your license. You may also want to take a look at the <a href=\"/faq#what-happens-when-license-ends\">What Happens When My License Ends?</a> section."
}
}

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

@ -476,7 +476,7 @@
"MultipleUIOptionsExplanation": "Rakastamme erilaisia tapoja luoda käyttöliittymä. Tämä käynnistysratkaisu tarjoaa kolme erilaista käyttöliittymäkehysvaihtoehtoa yrityssovelluksellesi.",
"MultipleDatabaseOptions": "Useita tietokantavaihtoehtoja",
"MultipleDatabaseOptionsExplanation": "Sinulla on kaksi tietokannan tarjoajavaihtoehtoa (sen lisäksi, että voit käyttää molempia yhdessä sovelluksessa). Käytä Entity Framework Corea työskennelläksesi minkä tahansa relaatiotietokannan kanssa ja käytä valinnaisesti Dapperia, kun sinun on kirjoitettava matalan tason kyselyitä parantaaksesi suorituskykyä. MongoDB on toinen vaihtoehto, jos haluat käyttää dokumenttipohjaista NoSQL-tietokantaa. Vaikka nämä palveluntarjoajat ovat hyvin integroituja, abstrakteja ja esikonfiguroituja, voit itse asiassa olla vuorovaikutuksessa minkä tahansa tietokantajärjestelmän kanssa, jota voit käyttää .NET:n kanssa.",
"ModularArchitectureExplanation2": "Modulaarisuus on ensiluokkainen kansalainen ABP.IO-alustalla. Kaikki sovelluksen toiminnot on jaettu hyvin eristettyihin valinnaisiin moduuleihin. Käynnistysratkaisussa on valmiiksi asennettuna perus <a href=\"@Url.Page(\"/Modules\")\" class=\"text-primary\">ABP Commercial -moduulit</a>. Voit myös luoda omia moduuleita rakentaaksesi modulaarisen järjestelmän omalle sovelluksellesi.",
"ModularArchitectureExplanation2": "Modulaarisuus on ensiluokkainen kansalainen ABP.IO-alustalla. Kaikki sovelluksen toiminnot on jaettu hyvin eristettyihin valinnaisiin moduuleihin. Käynnistysratkaisussa on valmiiksi asennettuna perus <a href=\"/modules\" class=\"text-primary\">ABP Commercial -moduulit</a>. Voit myös luoda omia moduuleita rakentaaksesi modulaarisen järjestelmän omalle sovelluksellesi.",
"MultiTenancyForSaasBusiness": "Monivuokraus SaaS-yrityksellesi",
"MultiTenancyForSaasBusinessExplanation": "ABP Commercial tarjoaa täydellisen, päästä-päähän usean vuokrausjärjestelmän SaaS-järjestelmien (Software-as-a-Service) luomiseen. Sen avulla vuokralaiset voivat jakaa tai käyttää omia tietokantojaan tietokantojen luonti- ja siirtojärjestelmässä.",
"MicroserviceStartupSolution": "Mikropalvelun käynnistysratkaisu",

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

@ -477,7 +477,7 @@
"MultipleUIOptionsExplanation": "Szeretjük a felhasználói felület létrehozásának különböző módjait. Ez az indítási megoldás három különböző felhasználói felületi keretrendszert biztosít az üzleti alkalmazás számára.",
"MultipleDatabaseOptions": "Több adatbázis-beállítás",
"MultipleDatabaseOptionsExplanation": "Két adatbázis-szolgáltató lehetősége van (amellett, hogy mindkettőt egyetlen alkalmazásban használhatja). Az Entity Framework Core segítségével bármilyen relációs adatbázissal dolgozhat, és opcionálisan használja a Dappert, ha alacsony szintű lekérdezéseket kell írnia a jobb teljesítmény érdekében. A MongoDB egy másik lehetőség, ha dokumentum alapú NoSQL adatbázist kell használnia. Noha ezek a szolgáltatók jól integráltak, absztraktáltak és előre konfiguráltak, valójában bármilyen adatbázis-rendszerrel kapcsolatba léphet, amelyet a .NET-tel használhat.",
"ModularArchitectureExplanation2": "A a legfőbb szempont az ABP.IO platformon. Az alkalmazás összes funkciója jól elkülönített opcionális modulokra van felosztva. Az indítási megoldás már előre telepítve tartalmazza az alapvető <a href=\"@Url.Page(\"/Modules\")\" class=\"text-primary\">ABP Commercial modulokat</a> . Saját modulokat is létrehozhat, hogy moduláris rendszert építsen fel saját alkalmazásához.",
"ModularArchitectureExplanation2": "A a legfőbb szempont az ABP.IO platformon. Az alkalmazás összes funkciója jól elkülönített opcionális modulokra van felosztva. Az indítási megoldás már előre telepítve tartalmazza az alapvető <a href=\"/modules\" class=\"text-primary\">ABP Commercial modulokat</a> . Saját modulokat is létrehozhat, hogy moduláris rendszert építsen fel saját alkalmazásához.",
"MultiTenancyForSaasBusiness": "Többérlős felépítés az Ön SaaS-üzleteihez",
"MultiTenancyForSaasBusinessExplanation": "Az ABP Commercial teljes körű, többbérlős rendszert biztosít SaaS (Software-as-a-Service) rendszereinek létrehozásához. Lehetővé teszi a bérlők számára, hogy megosszák vagy rendelkezzenek saját adatbázisokkal az on-the-fly adatbázis-létrehozó és migrációs rendszerrel.",
"MicroserviceStartupSolution": "Mikroszolgáltatás indítási megoldás",

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

@ -21,7 +21,7 @@
"SetDefault": "Varsayılan olarak ayarla",
"DefaultOrganization": "Varsayılan",
"StartDate": "Başlangıç tarihi",
"EndDate": "bitiş tarihi",
"EndDate": "Bitiş tarihi",
"Modules": "Modüller",
"LicenseExtendMessage": "Lisans bitiş tarihiniz {0} tarihine kadar uzatıldı",
"LicenseUpgradeMessage": "Lisansınız {0} lisansa yükseltildi",
@ -129,8 +129,8 @@
"TellUsWhatYouNeed": "Bize neye ihtiyacın olduğunu söyle.",
"YourMessage": "Mesajın",
"YourFullName": "Tam adınız",
"EmailField": "E",
"YourEmailAddress": "E",
"EmailField": "E-posta Adresi",
"YourEmailAddress": "E-posta adresiniz",
"HowMayWeHelpYou": "Size nasıl yardımcı olabiliriz?",
"SendMessage": "Mesaj gönder",
"Success": "Başarı",
@ -486,7 +486,7 @@
"MultipleUIOptionsExplanation": "Kullanıcı Arayüzü oluşturmanın farklı yollarını seviyoruz. Bu başlangıç çözümü, iş uygulamanız için üç farklı UI çerçeve seçeneği sunuyor.",
"MultipleDatabaseOptions": "Çoklu Veritabanı Seçenekleri",
"MultipleDatabaseOptionsExplanation": "İki veritabanı sağlayıcısı seçeneğiniz var (her ikisini de tek bir uygulamada kullanmanın yanı sıra). Herhangi bir ilişkisel veritabanıyla çalışmak için Entity Framework Core'u kullanın ve daha iyi bir performans için düşük seviyeli sorgular yazmanız gerektiğinde isteğe bağlı olarak Dapper'ı kullanın. Belge tabanlı bir NoSQL veritabanı kullanmanız gerekiyorsa MongoDB başka bir seçenektir. Bu sağlayıcılar iyi entegre edilmiş, soyutlanmış ve önceden yapılandırılmış olsa da, .NET ile kullanabileceğiniz herhangi bir veritabanı sistemiyle etkileşime girebilirsiniz. ",
"ModularArchitectureExplanation2": "Modülerlik, ABP.IO platformunda birinci sınıf bir vatandaştır. Uygulamalardaki tüm işlevler iyi izole edilmiş opsiyonel modüllere ayrılmıştır. Başlangıç çözümü zaten temel <a href=\"@Url.Page(\"/Modules\")\" class=\"text-primary\">ABP Ticari modülleri</a> önceden yüklenmiş olarak gelir. Kendi uygulamanız için modüler bir sistem oluşturmak üzere kendi modüllerinizi de oluşturabilirsiniz.",
"ModularArchitectureExplanation2": "Modülerlik, ABP.IO platformunda birinci sınıf bir vatandaştır. Uygulamalardaki tüm işlevler iyi izole edilmiş opsiyonel modüllere ayrılmıştır. Başlangıç çözümü zaten temel <a href=\"/modules\" class=\"text-primary\">ABP Ticari modülleri</a> önceden yüklenmiş olarak gelir. Kendi uygulamanız için modüler bir sistem oluşturmak üzere kendi modüllerinizi de oluşturabilirsiniz.",
"MultiTenancyForSaasBusiness": "Saas İşletmeleri için Çoklu Kiralama",
"MultiTenancyForSaasBusinessExplanation": "ABP Commercial, SaaS (Hizmet Olarak Yazılım) sistemlerinizi oluşturmak için eksiksiz, uçtan uca çoklu kiracılık sistemi sağlar. Anında veritabanı oluşturma ve taşıma sistemi ile kiracıların kendi veritabanlarını paylaşmalarına veya sahip olmalarına olanak tanır.",
"MicroserviceStartupSolution": "Mikro Hizmet Başlangıç Çözümü",
@ -808,4 +808,4 @@
"BlazoriseLicense": "Blazorise lisansı satın almamız gerekiyor mu?",
"BlazoriseLicenseExplanation": "Volosoft ve Megabit arasında bir anlaşmamız var, bu anlaşma ile Blazorise lisansı ABP Ticari ürünleri ile birlikte geliyor, bu nedenle müşterilerimizin ekstra bir Blazorise lisansı satın almasına gerek kalmıyor."
}
}
}

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

@ -476,7 +476,7 @@
"MultipleUIOptionsExplanation": "我们喜欢不同的方式来创建用户界面。 此启动解决方案为您的业务应用程序提供了三种不同的 UI 框架选项。",
"MultipleDatabaseOptions": "多个数据库选项",
"MultipleDatabaseOptionsExplanation": "您有两个数据库提供程序选项(除了在单个应用程序中使用两者)。 使用 Entity Framework Core 处理任何关系数据库,当您需要编写低级查询以获得更好的性能时,可以选择使用 Dapper。 如果您需要使用基于文档的 NoSQL 数据库,MongoDB 是另一种选择。 虽然这些提供程序是良好集成、抽象和预配置的,但您实际上可以与任何可与 .NET 一起使用的数据库系统进行交互。",
"ModularArchitectureExplanation2": "模块化是 ABP.IO 平台的一等公民。 所有应用程序功能都被拆分为隔离良好的可选模块。 启动解决方案已经预装了基本的 <a href=\"@Url.Page(\"/Modules\")\" class=\"text-primary\">ABP 商业模块</a>。 您还可以创建自己的模块来为自己的应用程序构建模块化系统。",
"ModularArchitectureExplanation2": "模块化是 ABP.IO 平台的一等公民。 所有应用程序功能都被拆分为隔离良好的可选模块。 启动解决方案已经预装了基本的 <a href=\"/modules\" class=\"text-primary\">ABP 商业模块</a>。 您还可以创建自己的模块来为自己的应用程序构建模块化系统。",
"MultiTenancyForSaasBusiness": "SaaS 业务的多租户",
"MultiTenancyForSaasBusinessExplanation": "ABP 商业版 提供完整的端到端多租户系统来创建您的 SaaS(软件即服务)系统。 它允许租户通过动态数据库创建和迁移系统共享或拥有自己的数据库。",
"MicroserviceStartupSolution": "微服务启动解决方案",
@ -827,6 +827,15 @@
"PrivacyPolicyPageTitle": "隐私政策 - Cookies政策",
"TermsConditionsPageTitle": "条款和条件",
"TrainingsPageTitle": "ABP培训套餐",
"ModulesPageTitle": "ABP内置的应用模块"
"ModulesPageTitle": "ABP内置的应用模块",
"DoesTheSubscriptionRenewAutomatically": "订阅会自动续订吗?",
"DoesTheSubscriptionRenewAutomaticallyExplanation": "ABP 商业版没有自动续订计费模式。因此,在您的许可期结束时,<strong>您的订阅将不会自动续订</strong>。如果您希望继续享受 ABP 商业版的好处,您可以在<a href=\"/my-organizations\">组织管理</a>页面手动续订。如果您有多个组织,请点击即将到期的组织上的“管理”按钮,然后点击“立即续订”按钮来续订您的许可证。您还可以查看<a href=\"/faq#what-happens-when-license-ends\">许可证到期后会发生什么?</a>部分。",
"BlazoriseSupport": "如何获取Blazorise许可密钥并获得Blazorise团队的支持?",
"BlazoriseSupportExplanation": "请按照以下步骤获取Blazorise团队的支持并获得您的Blazorise许可密钥:",
"BlazoriseSupportExplanation1": "使用与您的abp.io账户相同的电子邮件地址在<a href=\"https://blazorise.com/support/register\" rel=\"nofollow\">blazorise.com/support/register</a>上注册一个新账户。请将“许可密钥”一栏留空,<strong>并确保该电子邮件地址与您在abp.io上的电子邮件账户相同</strong>。",
"BlazoriseSupportExplanation2": "通过查看您的电子邮件信箱来验证您的电子邮件地址。如果在收件箱中没有看到电子邮件,请检查您的垃圾邮件箱!",
"BlazoriseSupportExplanation3": "在<a href=\"https://blazorise.com/support/login\" rel=\"nofollow\">blazorise.com/support/login</a>上登录Blazorise支持网站。",
"BlazoriseSupportExplanation4": "如果您有有效的ABP商业版许可证,您还将拥有Blazorise PRO许可证。您可以在<a href=\"https://blazorise.com/support/user/manage/license\" rel=\"nofollow\">blazorise.com/support/user/manage/license</a>获取您的Blazorise许可密钥。",
"BlazoriseSupportExplanation5": "您可以在support网站上发布您的问题,并为您的应用程序生成一个产品令牌。"
}
}

2
common.props

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

267
docs/en/Blog-Posts/2023-06-05 v7_3_Preview/POST.md

@ -0,0 +1,267 @@
# ABP.IO Platform 7.3 RC Has Been Released
Today, we are happy to release the [ABP Framework](https://abp.io/) and [ABP Commercial](https://commercial.abp.io/) version **7.3 RC** (Release Candidate). This blog post introduces the new features and important changes in this new version.
Try this version and provide feedback for a more stable version of ABP v7.3! Thanks to all of you.
## Get Started with the 7.3 RC
Follow the steps below to try version 7.3.0 RC today:
1) **Upgrade** the ABP CLI to version `7.3.0-rc.1` using a command line terminal:
````bash
dotnet tool update Volo.Abp.Cli -g --version 7.3.0-rc.1
````
**or install** it if you haven't before:
````bash
dotnet tool install Volo.Abp.Cli -g --version 7.3.0-rc.1
````
2) Create a **new application** with the `--preview` option:
````bash
abp new BookStore --preview
````
See the [ABP CLI documentation](https://docs.abp.io/en/abp/latest/CLI) for all the available options.
> You can also use the [Get Started](https://abp.io/get-started) page to generate a CLI command to create a new application.
You can use any IDE that supports .NET 7.x, like [Visual Studio 2022](https://visualstudio.microsoft.com/downloads/).
## Migration Guides
There are a few breaking changes in this version that may affect your application.
Please see the following migration documents, if you are upgrading from v7.2:
* [ABP Framework 7.2 to 7.3 Migration Guide](https://docs.abp.io/en/abp/7.3/Migration-Guides/Abp-7_3)
> If you are using the CMS Kit or CMS Kit Pro module, please don't forget to create a new migration and apply it to your database.
## What's New with ABP Framework 7.3?
In this section, I will introduce some major features released in this version. Here is a brief list of the titles that will be explained in the next sections:
* Introducing the Volo.Abp.Imaging packages
* ABP CLI: switch-to-local command
* Monitoring Distributed Events
* Ordering of the Local Event Handlers
* Nonce attribute support for Content Security Policy (CSP)
* Other News
### Introducing the Volo.Abp.Imaging packages
ABP Framework provides some packages to compress and resize images. Currently, there are four official packages:
* `Volo.Abp.Imaging.Abstractions`: Provides common services for compression and resizing purposes.
* `Volo.Abp.Imaging.AspNetCore`: Provides some attributes for controller actions that can automatically compress and/or resize uploaded files.
* `Volo.Abp.Imaging.ImageSharp`: Implements the image compression & resize operations using the [ImageSharp](https://github.com/SixLabors/ImageSharp) library.
* `Volo.Abp.Imaging.MagickNet`: Implements the image compression & resize operations using the [Magick.NET](https://github.com/dlemstra/Magick.NET) library.
You can use one of these official providers (`ImageSharp` or `Magick.NET`) or implement your own image resizer/compressor contributor and use it in your application.
> See the [Image Manipulation](https://docs.abp.io/en/abp/7.3/Image-Manipulation) documentation to learn more and see the required configurations.
### ABP CLI: switch-to-local command
In this version, ABP CLI introduces a new CLI command: **"switch-to-local"**. The `switch-to-local` command changes all NuGet package references on a solution to local project references for all the `.csproj` files in the specified folder (and all its subfolders with any depth).
**Usage:**
```bash
abp switch-to-local --paths "C:\Github\abp"
```
### Monitoring Distributed Events
ABP Framework allows you to stay informed when your application **receives** or **sends** a distributed event. This enables you to track the event flow within your application and take appropriate actions based on the received or sent distributed events.
You just need to subscribe to one of the `DistributedEventReceived` or `DistributedEventSent` events and take additional actions according to your cases.
**Example: Get informed when your application sends an event to the distributed event bus**
```csharp
public class DistributedEventSentHandler : ILocalEventHandler<DistributedEventSent>, ITransientDependency
{
public async Task HandleEventAsync(DistributedEventSent eventData)
{
// TODO: IMPLEMENT YOUR LOGIC...
}
}
```
> See the documentation to learn more: [https://docs.abp.io/en/abp/7.3/Distributed-Event-Bus](https://docs.abp.io/en/abp/7.3/Distributed-Event-Bus)
### Ordering of the Local Event Handlers
In this version, ABP Framework introduces the `LocalEventHandlerOrder` attribute, which can be used to set the execution order for the event handlers. This can be helpful if you want to handle your local event handlers in a specific order.
**Example:**
```csharp
[LocalEventHandlerOrder(-1)]
public class MyHandler
: ILocalEventHandler<StockCountChangedEvent>,
ITransientDependency
{
public async Task HandleEventAsync(StockCountChangedEvent eventData)
{
//TODO: your implementation
}
}
```
By default, all event handlers have an order value of 0. Thus, if you want to take certain event handlers to be executed before other event handlers, you can set the order value as a negative value.
> See the documentation to learn more: [https://docs.abp.io/en/abp/7.3/Local-Event-Bus](https://docs.abp.io/en/abp/7.3/Local-Event-Bus)
### Nonce attribute support for Content Security Policy (CSP)
ABP Framework supports adding unique value to nonce attribute for script tags which can be used by Content Security Policy to determine whether or not a given fetch will be allowed to proceed for a given element. In other words, it provides a mechanism to execute only correct script tags with the correct nonce value.
This feature is disabled by default. You can enable it by setting the *UseContentSecurityPolicyScriptNonce* property of the `AbpSecurityHeadersOptions` class to **true**:
```csharp
Configure<AbpSecurityHeadersOptions>(options =>
{
//adding script-src nonce
options.UseContentSecurityPolicyScriptNonce = true; //false by default
});
```
> See the [Security Headers](https://docs.abp.io/en/abp/7.3/UI/AspNetCore/Security-Headers) documentation for more information.
### Other News
* Upgraded the [Blazorise](https://blazorise.com/) library to v1.2.3 for Blazor UI. After the upgrade, ensure that all Blazorise-related packages are using v1.2.3 in your application.
* Module Entity Extension support has been added for the CMS Kit module. See [#16572](https://github.com/abpframework/abp/issues/16572) for more information.
If you want to see more details, you can check [the release on GitHub](https://github.com/abpframework/abp/releases/tag/5.3.0-rc.1), which contains a list of all the issues and pull requests were closed with this version.
## What's New with ABP Commercial 7.3?
We've also worked on [ABP Commercial](https://commercial.abp.io/) to align the features and changes made in the ABP Framework. The following sections introduce a few new features coming with ABP Commercial 7.3.
### Account Module - Using Authenticator App for Two-Factor Authentication
In this version, ABP Commercial provides a new **Two-Factor Authentication (2FA) provider** that allows you to log in to an application by scanning a QR Code with an Authenticator App, such as Microsoft Authenticator or Google Authenticator.
You need to apply the following actions to configure an Authenticator and then you are free to log in by using the Authenticator App:
**Step 1 - Enable Two Factor Authentication and Scan the QR Code:**
![](./two-factor-auth-1.png)
**Step 2 - Verify the QR Code with an authenticator app:**
![](./two-factor-auth-2.png)
**Step 3 - Save the recovery codes for later use in case of not being able to login by verifying the QR code:**
![](./two-factor-auth-3.png)
You can disable the two-factor authentication and reset the Authenticator App anytime you want, just by disabling the two-factor authentication or resetting the authenticator:
![](./reset-authenticator.png)
### Upgrade Blazorise to v1.2.3
Upgraded the [Blazorise](https://blazorise.com/) library to v1.2.3 for Blazor UI. If you are upgrading your project to v7.3.0, please ensure that all the Blazorise-related packages are using v1.2.3 in your application. Otherwise, you might get errors due to incompatible versions.
### CMS Kit: Module Entity Extensions
Module entity extension system is a high-level extension system that allows you to define new properties for existing entities of the dependent modules. ABP Framework and ABP Commercial use this system to allow developers to extend entities in different modules.
In this version, Module Entity Extension support has been added for the CMS Kit Pro module.
You can open the `YourProjectNameModuleExtensionConfigurator` class inside the `Domain.Shared` project of your solution and change the `ConfigureExtraProperties` method as shown below to add a new property to the `Poll` entity of the [CMS Kit Pro module](https://docs.abp.io/en/commercial/latest/modules/cms-kit/index):
```csharp
public static void ConfigureExtraProperties()
{
OneTimeRunner.Run(() =>
{
ObjectExtensionManager.Instance.Modules()
.ConfigureCmsKitPro(cmsKitPro =>
{
cmsKitPro.ConfigurePoll(poll =>
{
poll.AddOrUpdateProperty<string>(
"<property-name>",
property =>
{
//configuration for this property
}
)
});
});
});
}
```
> See the [Module Entity Extensions documentation](https://docs.abp.io/en/abp/latest/Module-Entity-Extensions) to learn more.
### LeptonX Account Layout
In this version, Account Layout has been re-designed for LeptonX Theme. You can see the new account layout in the following figure:
![](leptonx-account-layout.png)
> To use this new account layout, ensure that your LeptonX Theme package versions are v2.3+.
## Community News
### ABP Community Talks 2023.4: Angular 16 and ABP v7.3
![](./community-talks-2023-4.png)
In this episode, the core ABP team talked about what's new with ABP v7.3 and Angular 16. You can watch the event from [here](https://www.youtube.com/watch?v=lq6u4vQURcI).
### ABP .NET Conference 2023
![](./abp-conf.png)
We organized ABP .NET Conference 2023 on May 2023 and we are happy to share the success of the conference, which captivated overwhelmingly interested live viewers from all over the world. 13 great line up of speakers which includes .NET experts and Microsoft MVPs delivered captivating talks that resonated with the audiences. Each of the talks attracted a great amount of interest and a lot of questions, sparking curiosity in the attendees.
Thanks to all speakers and attendees for joining our event.
> We shared our takeaways in a blog post, which you can read at [https://blog.abp.io/abp/ABP-.NET-Conference-2023-Wrap-Up](https://blog.abp.io/abp/ABP-.NET-Conference-2023-Wrap-Up).
### Volosoft Attendeed & Sponsored Devnot .NET Conference 2023
![](devnot-conference.png)
We are thrilled to announce that the Volosoft Company proudly attended as one of the Gold Sponsors at the Devnot .NET Conference 2023! We are happy to join and be a sponsor of events and contribute to the software society, empowering developers and driving innovation with the .NET community.
![](devnot-talk.png)
Co-Founder of [Volosoft](https://volosoft.com/) and Lead Developer of the ABP Framework, [Halil Ibrahim Kalkan](https://twitter.com/hibrahimkalkan) gave a word about "Dealing with Concurrency and Multi Threading in .NET" at this event.
> You can check [this blog post](https://volosoft.com/blog/Reflecting-on-Devnot-Dotnet-Conference-2023) if you want to learn more about the Devnot .NET Conference 2023.
### New ABP Community Posts
There are exciting articles contributed by the ABP community as always. I will highlight some of them here:
* [Authority Delegation in ABP Commercial](https://community.abp.io/posts/authority-delegation-in-abp-commercial-3wtljpp0) by [Liang Shiwei](https://github.com/realLiangshiwei)
* [What's new in Angular 16? New Features and Updates](https://community.abp.io/posts/whats-new-in-angular-16-new-features-and-updates-s1izi9br) by [Masum Ulu](https://twitter.com/masumulu)
* [Kubernetes Integrated Microservice Development with ABP Studio](https://community.abp.io/videos/kubernetes-integrated-microservice-development-with-abp-studio-oix9zkp8) by [Halil Ibrahim Kalkan](https://twitter.com/hibrahimkalkan)
Thanks to the ABP Community for all the content they have published. You can also [post your ABP-related (text or video) content](https://community.abp.io/articles/submit) to the ABP Community.
### New ABP Blog Posts
There are also some exciting blog posts written by the ABP team. You can see the following list for some of those articles:
* [ABP .NET Conference 2023 Wrap Up](https://blog.abp.io/abp/ABP-.NET-Conference-2023-Wrap-Up) by [Bige Beşikçi](https://twitter.com/bigedediki)
* [Meet Volosoft at the Devnot .NET Conference 2023!](https://volosoft.com/blog/Meet-Volosoft-at-the-Devnot-.NET-Conference-2023) by [Roo Xu](https://github.com/Roo1227)
## Conclusion
This version comes with some new features and a lot of enhancements to the existing features. You can see the [Road Map](https://docs.abp.io/en/abp/7.3/Road-Map) documentation to learn about the release schedule and planned features for the next releases. Please try ABP v7.3 RC and provide feedback to help us release a more stable version.
Thanks for being a part of this community!

BIN
docs/en/Blog-Posts/2023-06-05 v7_3_Preview/abp-conf.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 742 KiB

BIN
docs/en/Blog-Posts/2023-06-05 v7_3_Preview/community-talks-2023-4.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

BIN
docs/en/Blog-Posts/2023-06-05 v7_3_Preview/cover-image.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 234 KiB

BIN
docs/en/Blog-Posts/2023-06-05 v7_3_Preview/devnot-conference.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 MiB

BIN
docs/en/Blog-Posts/2023-06-05 v7_3_Preview/devnot-talk.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

BIN
docs/en/Blog-Posts/2023-06-05 v7_3_Preview/leptonx-account-layout.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 691 KiB

BIN
docs/en/Blog-Posts/2023-06-05 v7_3_Preview/reset-authenticator.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

BIN
docs/en/Blog-Posts/2023-06-05 v7_3_Preview/two-factor-auth-1.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 69 KiB

BIN
docs/en/Blog-Posts/2023-06-05 v7_3_Preview/two-factor-auth-2.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

BIN
docs/en/Blog-Posts/2023-06-05 v7_3_Preview/two-factor-auth-3.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

4
docs/en/Community-Articles/2023-06-05-Kubernetes-Integration-Abp-Studio/POST.md

@ -163,12 +163,10 @@ The solution runner is a great way of running multiple services locally. However
### How ABP Studio Kubernetes Tunnel works
I am sure that you want to see it in action, but before that, let me explain how the solution works. No problem if you can not understand it completely. It is enough to see the big picture:
I am sure that you want to see it in action, but before that, let me explain how the solution works.
![abp-studio-kubernetes-tunnel-how-it-works](06-abp-studio-kubernetes-tunnel-how-it-works.png)
Let's explain how it works:
* **Kubernetes cluster** is shown on the right side and your **local development machine** is shown on the left side.
* As you know, when a **user requests a web page** from your web application, the request is accepted by an **Ingress Controller** inside your Kubernetes cluster.
* The Ingress controller forwards the request to your **web application**, which then uses an **API gateway** to consume your microservices.

293
docs/en/Community-Articles/2023-07-03-Image-Compression-And-Resize/POST.md

@ -0,0 +1,293 @@
# Image Compression and Resize with ABP Framework
## Introduction
In this article, I will show how to compress and resize images easily with the ABP Framework's new [Image Manipulation System](https://docs.abp.io/en/abp/7.3/Image-Manipulation), which is introduced in v7.3.0.
ABP Framework provides services to compress and resize images and implements these services with popular [ImageSharp](https://sixlabors.com/products/imagesharp/) and [Magick.NET](https://github.com/dlemstra/Magick.NET) libraries. Currently, only these two providers are officially supported by the ABP Framework but thanks to the system being designed extensible, you can implement your own image resizer/compressor and use it in your application.
> Refer to the documentation for more info: [Image Manipulation](https://docs.abp.io/en/abp/7.3/Image-Manipulation)
### Source Code
You can find the source code of the application at [https://github.com/abpframework/abp-samples/tree/master/ImageManipulation](https://github.com/abpframework/abp-samples/tree/master/ImageManipulation). Don't hesitate to check the source code, if you are stuck on any point.
## Demo: Image Compression and Resize
The best way to see what ABP's Image Manipulation System is capable of is to see it in action. Thus, we can create a simple application that basically allows us to upload, search and display images.
### Creating a New ABP Solution
> I have created an ABP solution and you can find the [full source code of the demo application here](https://github.com/abpframework/abp-samples/tree/master/ImageManipulation). If you want to create the same solution from scratch, you can apply the following steps:
Install the ABP CLI, if you haven't installed it before:
```bash
dotnet tool install -g Volo.Abp.Cli
```
Create a new solution with the ABP Framework's Application Startup Template with MVC UI and EF Core database (default options):
```bash
abp new ImageManipulationDemo -t app --version 7.3.0-rc.2
```
> As I have mentioned above, ABP introduced the Image Manipulation System in v7.3.0. So, ensure your application is v7.3.0 or higher.
After creating the application, let's create the database and seed the initial data by running the `*.DbMigrator` project. Also, you can run the application to see if it's working as expected.
### Configuring the BLOB Storing System
Since we are creating an image upload application, we need to store our images somewhere and read these image contents when it's needed. [BLOB Storing System](https://docs.abp.io/en/abp/latest/Blob-Storing) is a great solution to achieve this. Let's install & configure the BLOB Storing System into our application.
First, run the following command under the directory of your `*.HttpApi` project:
```bash
abp add-package Volo.Abp.BlobStoring
```
Then, we need to select and configure a storage provider to tell the BLOB Storing System where to store the file contents. There are [multiple providers](https://docs.abp.io/en/abp/latest/Blob-Storing#blob-storage-providers) that we can choose. For the simplicity of the demo, let's continue with the **database provider** and run the following command under the directory of your solution (`*.sln`):
```bash
abp add-module Volo.Abp.BlobStoring.Database
```
* This command adds all the NuGet packages to the corresponding layers of your solution.
* Also, it makes the necessary configurations, adds a new database migration, and updates the database.
* Since we are not configuring the connection string, the BLOB Storing system will use the default connection string in our application.
That's it. We have installed and configured the BLOB Storing System in our application.
### Configuring the Image Manipulation System
After, configuring the BLOB Storing System, now we can install and configure the Image Manipulation System to be able to compress and resize images.
ABP Framework provides two image resizer/compressor implementations out of the box: [ImageSharp](https://docs.abp.io/en/abp/7.3/Image-Manipulation#imagesharp-provider) and [Magick.NET](https://docs.abp.io/en/abp/7.3/Image-Manipulation#magick-net-provider).
We can use the `Volo.Abp.Imaging.ImageSharp` as the provider for our application. To install the package, run the following command under the `*.HttpApi` project:
```bash
abp add-package Volo.Abp.Imaging.ImageSharp
```
* This package will provide the required services to compress and resize images.
* You can [configure the `ImageSharpCompressOptions`](https://docs.abp.io/en/abp/7.3/Image-Manipulation#configuration-1) to define *DefaultQuality* and encoders.
After installing the provider, now we can use the services to compress and resize our images, such as `IImageCompression` and `IImageResizer`. But there is an easier way. The `Volo.Abp.Imaging.AspNetCore` NuGet package defines some attributes for controller actions that can automatically compress and/or resize the uploaded files.
To be able to use these attributes, we need to install the `Volo.Abp.Imaging.AspNetCore` package. Type the following command under the `*.HttpApi` project:
```bash
abp add-package Volo.Abp.Imaging.AspNetCore
```
This package provides two attributes: `[CompressImage]` and `[ResizeImage]`. Whenever we use these attributes, the Image Manipulation System will automatically compress and/or resize uploaded files.
### Image Upload (with Compress & Resize)
After all the required package installations and configurations are done, now we can start implementing the API and UI for the Image Upload.
Let's start with creating the API. Create a controller in the `*.HttpApi` project named `ImageController` and perform the image upload and image display operations:
```csharp
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using System.Threading.Tasks;
using Volo.Abp.BlobStoring;
using Volo.Abp.Imaging;
namespace ImageManipulationDemo.Controllers
{
[Controller]
[Route("api/image")]
public class ImageController : ImageManipulationDemoController
{
private readonly IBlobContainer<ImageManipulationContainer> _blobContainer;
public ImageController(IBlobContainer<ImageManipulationContainer> blobContainer)
{
_blobContainer = blobContainer;
}
[HttpPost("upload")]
[CompressImage]
[ResizeImage(width: 200, height: 200)]
public async Task<IActionResult> UploadAsync(IFormFile file)
{
var fileBytes = await file.GetAllBytesAsync();
var blobName = file.FileName;
await _blobContainer.SaveAsync(blobName, fileBytes, overrideExisting: true);
return Ok();
}
[HttpGet("")]
public async Task<byte[]> GetImageAsync(string fileName)
{
return await _blobContainer.GetAllBytesAsync(fileName);
}
}
}
```
* Here, we have used both `CompressImage` and `ResizeImage` attributes to automatically compress & resize the uploaded file.
* As you can see, we used the `IBlobContainer<TContainer>` service to save our file content.
* Since we are using the *database provider* as BLOB storing provider, the file contents will be added to our database and then we will be able to fetch them whenever it's needed like we have done in the `GetImageAsync` method above.
* We simply used the required attributes (and they do the rest on behalf of us and call the related image resize and compress services) to resize & compress images and save the new resized/compressed image into the database.
Before implementing the UI side, as you may notice, we've injected the `IBlobContainer` as a typed service (`IBlobContainer<ImageManipulationContainer>`). A typed BLOB container system is a way of creating and managing multiple containers in an application. We haven't created the `ImageManipulationContainer` class yet.
Let's create this class as below:
```csharp
using Volo.Abp.BlobStoring;
namespace ImageManipulationDemo
{
[BlobContainerName("image-manipulation-demo")]
public class ImageManipulationContainer
{
}
}
```
* We have used the `BlobContainerName` attribute to define the name of the container.
* If we haven't used the `BlobContainerName` attribute, ABP Framework uses the full name of the class with its namespace.
We have implemented the endpoints and now can start implementing the UI side. You can see the following figure to see what we are going to design for the image upload page:
![](image-upload-ui.png)
Let's start designing this page. Open the `Index.cshtml` file (*/Pages/Index.cshtml*) under the `*.Web` project and replace it with the following content:
```html
@page
@using Microsoft.AspNetCore.Mvc.Localization
@using ImageManipulationDemo.Localization
@using Volo.Abp.Users
@model ImageManipulationDemo.Web.Pages.IndexModel
@inject IHtmlLocalizer<ImageManipulationDemoResource> L
@inject ICurrentUser CurrentUser
@section styles {
<abp-style src="/Pages/Index.css" />
}
@section scripts {
<abp-script src="/Pages/Index.js" />
}
<div class="container">
<div class="row">
<div class="col">
<div class="card">
<div class="card-body">
<form method="post" id="upload-image" enctype="multipart/form-data">
<div class="mb-3">
<label for="formFile" class="form-label">Upload an image</label>
<input class="form-control" type="file" id="formFile" required/>
</div>
<div class="mb-3">
<button type="submit" class="btn btn-primary d-block w-100">Submit</button>
</div>
</form>
</div>
</div>
</div>
<div class="col">
<div class="card">
<div class="card-title">
</div>
<div class="card-body">
<h5 class="card-title my-2">Search & Display Images</h5>
<form method="get" id="search-image">
<div class="input-group mb-3">
<input id="img-search-input" type="text" class="form-control" placeholder="Search with image name... E.g. image.png" aria-label="Search with image name" aria-describedby="button-search" required>
<button class="btn btn-outline-secondary" type="submit" id="button-search">Search</button>
</div>
</form>
<div class="d-none" id="image-result">
</div>
</div>
</div>
</div>
</div>
</div>
```
Then, open the `index.js` file and replace it with the following content:
```js
$(function () {
$("#upload-image").submit(function (e) {
e.preventDefault();
var file = document.getElementById("formFile").files[0];
var formData = new FormData();
formData.append("file", file);
$.ajax(
{
url: "/api/image/upload",
data: formData,
processData: false,
contentType: false,
type: "POST",
success: function (data) {
abp.message.success("Image saved successfully!");
},
error: function (err) {
abp.message.error("An error occured while saving the image.");
}
}
);
});
$("#search-image").submit(function (e) {
e.preventDefault();
var imgResult = $("#image-result");
imgResult.removeClass("d-none");
imgResult.html("<p>Loading...</p>");
var fileName = $("#img-search-input").val();
imageManipulationDemo.controllers.image.getImage(fileName)
.then(function (imageFile) {
var src = "data:image/png;base64," + imageFile;
var img = "<img src='" + src + "' />";
imgResult.html(img);
})
.catch(function (err) {
imgResult.html("<p>Could not find the image...</p>");
});
});
});
```
Now, we can run the application and see the Image Manipulation System in action:
![](image-manipulation.gif)
The results are impressive for the example above:
* The original image was 12 KB and now the compressed & resized image has been reduced to 8 KB.
* The original image was 225x225 and now resized as 200x200.
## Conclusion
In this article, I have shown you how to compress and/or resize images with ABP Framework's Image Manipulation System by just defining some attributes to the top of the controller actions.
Also, I have shown that you can use the BLOB Storing System to store file contents and compress/resize images before saving them into BLOB Storages thanks to the image resizers/compressors provided by ABP Framework.
## See Also
* [BLOB Storing](https://docs.abp.io/en/abp/latest/Blob-Storing)
* [Image Manipulation](https://docs.abp.io/en/abp/7.3/Image-Manipulation#iimageresizer)

BIN
docs/en/Community-Articles/2023-07-03-Image-Compression-And-Resize/image-manipulation.gif

Binary file not shown.

After

Width:  |  Height:  |  Size: 625 KiB

BIN
docs/en/Community-Articles/2023-07-03-Image-Compression-And-Resize/image-upload-ui.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

40
docs/en/Integration-Services.md

@ -34,11 +34,47 @@ public interface IProductAppService : IApplicationService
That's all. From now, ABP will handle your application service as integration service and implement the followings by convention:
* If you are using the [Auto API Controllers](API/Auto-API-Controllers.md) feature in your application, the URL prefix will be `/integration-api` instead of `/api` for your integration services. Thus, you can distinguish internal and external service communications and take additional actions, such as preventing REST API calls for integration services out of API Gateway.
* Audit logging is disabled by default for the integration services. See the next section if you want to enable it.
* That service is **not exposed** by default, unless you explicitly set `ExposeIntegrationServices` options (see the *Exposing Integration Services* section).
* If you are using the [Auto API Controllers](API/Auto-API-Controllers.md) feature in your application, the **URL prefix** will be `/integration-api` instead of `/api` for your integration services. Thus, you can distinguish internal and external service communications and take additional actions, such as preventing REST API calls for integration services out of API Gateway.
* **Audit logging** is disabled by default for the integration services. See the next section if you want to enable it.
## Marking an MVC Controller as Integration Service
In addition to application services, you can mark a regular MVC Controller as integration service, using the same `IntegrationService` attribute, or inheriting an interface that has the `IntegrationService` attribute.
**Example:**
````csharp
[IntegrationService] // Mark as integration service
[Route("integration-api/products")]
public class ProductController : AbpControllerBase
{
//...
}
````
When you use the `IntegrationService` attribute, ABP will handle your controller as integration service and implement the followings by convention:
* That controller is **not exposed** to clients by default, unless you explicitly set `ExposeIntegrationServices` options (see the *Exposing Integration Services* section).
* **Audit logging** is disabled by default for controller. See the next section if you want to enable it.
## Configuration
### Exposing Integration Services
Integration services and controllers are not exposed by default for security reasons. They typically don't require authorization, so you should **carefully and explicitly** allow them to be visible and usable to client applications.
To expose integration services and controllers, set `AbpAspNetCoreMvcOptions.ExposeIntegrationServices` to `true` in the `ConfigureServices` method of your [module class](Module-Development-Basics.md):
````csharp
Configure<AbpAspNetCoreMvcOptions>(options =>
{
options.ExposeIntegrationServices = true;
});
````
> Hiding integration services is useful when you are building reusable application modules, where they may be used in a monolith application or in a microservice system. In a monolith application, integration services don't need to be exposed outside since the modules may in-process communicate with each other. On the other hand, if you build a microservice solution and use that module as a service, it will be proper to expose the integration services, so other microservices can consume them remotely inside your private network (or Kubernetes cluster). In that case, be careful to not accidently expose the integration services out of your private network. Configuring your API Gateway so that it blocks requests to `integration-api` prefixed URLs from outside of your network will be a good option.
### Enabling/Disabling the Audit Logging
Audit Logging is disabled by default for integration services but it can be enabled by configuring the `AbpAuditingOptions` [options class](Options.md) in the `ConfigureServices` method of your [module class](Module-Development-Basics.md):

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

@ -0,0 +1,8 @@
# 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.
## TemplateDefinition
The `LocalizationResource(Type)` of `TemplateDefinition` class is changed to `LocalizationResourceName(string)`.

23
docs/en/Module-Development-Basics.md

@ -147,7 +147,7 @@ Lastly, you can override ``OnApplicationShutdown`` method if you want to execute
## Module Dependencies
In a modular application, it's not unusual for one module to depend upon another module(s). An Abp module must declare ``[DependsOn]`` attribute if it does have a dependency upon another module, as shown below:
In a modular application, it's not unusual for one module to depend upon another module(s). An ABP module must declare a ``[DependsOn]`` attribute if it does have a dependency upon another module, as shown below:
````C#
[DependsOn(typeof(AbpAspNetCoreMvcModule))]
@ -162,6 +162,27 @@ You can use multiple ``DependsOn`` attribute or pass multiple module types to a
A depended module may depend on another module, but you only need to define your direct dependencies. ABP investigates the dependency graph for the application at startup and initializes/shutdowns modules in the correct order.
## Additional Module Assemblies
ABP automatically registers all the services of your module to the [dependency injection](Dependency-Injection.md) system. It finds the service types by scanning types in the assembly that defines your module class. That assembly is considered as the main assembly of your module.
Typically, every assembly contains a separate module class definition. Then modules depend on each other using the `DependsOn` attribute as explained in the previous section. However, in some rare cases, your module may consist of multiple assemblies, and only one of them defines a module class, and you want to make the other assemblies parts of your module. In that case, you can use the `AdditionalAssembly` attribute as shown below:
````csharp
[DependsOn(...)] // Your module dependencies as you normally do
[AdditionalAssembly(typeof(BlogService))] // A type in the target assembly
public class BlogModule
{
//...
}
````
In this example, we assume that the `BlogService` class is inside one assembly (`csproj`) and the `BlogModule` class is inside another assembly (`csproj`). With the `AdditionalAssembly` definition, ABP will load the assembly containing the `BlogService` class as a part of the blog module.
Notice that `BlogService` is only an arbitrary selected type in the target assembly. It is just used to indicate the related assembly. You could use any type in the assembly.
> WARNING: If you need to use the `AdditionalAssembly`, be sure that you don't design your system in a wrong way. With this example above, the `BlogService` class' assembly should normally have its own module class and the `BlogModule` should depend on it using the `DependsOn` attribute. Do not use the `AdditionalAssembly` attribute when you can already use the `DependsOn` attribute.
## Framework Modules vs Application Modules
There are **two types of modules.** They don't have any structural difference but categorized by functionality and purpose:

14
docs/en/Module-Entity-Extensions.md

@ -255,6 +255,20 @@ property =>
Use `property.UI.OnCreateForm` and `property.UI.OnEditForm` to control forms too. If a property is required, but not added to the create form, you definitely get a validation exception, so use this option carefully. But a required property may not be in the edit form if that's your requirement.
### UI Order
When you define a property, it appears on the data table, create and edit forms on the related UI page. However, you can control its order. Example:
````csharp
property =>
{
property.UI.Order = 1;
//...other configurations
}
````
Use `property.UI.OnCreateForm` and `property.UI.OnEditForm` to control forms too. If a property is required, but not added to the create form, you definitely get a validation exception, so use this option carefully. But a required property may not be in the edit form if that's your requirement.
### HTTP API Availability
Even if you disable a property on UI, it can be still available through the HTTP API. By default, a property is available on all APIs.

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

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

2
framework/src/Volo.Abp.ApiVersioning.Abstractions/Volo/Abp/ApiVersioning/IRequestedApiVersion.cs

@ -2,5 +2,5 @@
public interface IRequestedApiVersion
{
string Current { get; }
string? Current { get; }
}

2
framework/src/Volo.Abp.ApiVersioning.Abstractions/Volo/Abp/ApiVersioning/NullRequestedApiVersion.cs

@ -4,7 +4,7 @@ public class NullRequestedApiVersion : IRequestedApiVersion
{
public static NullRequestedApiVersion Instance = new NullRequestedApiVersion();
public string Current => null;
public string? Current => null;
private NullRequestedApiVersion()
{

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

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

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

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

4
framework/src/Volo.Abp.AspNetCore.Authentication.OAuth/Volo/Abp/AspNetCore/Authentication/OAuth/Claims/MultipleClaimAction.cs

@ -29,7 +29,7 @@ public class MultipleClaimAction : ClaimAction
switch (prop.ValueKind)
{
case JsonValueKind.String:
claim = new Claim(ClaimType, prop.GetString(), ValueType, issuer);
claim = new Claim(ClaimType, prop.GetString()!, ValueType, issuer);
if (!identity.Claims.Any(c => c.Type == claim.Type && c.Value == claim.Value))
{
identity.AddClaim(claim);
@ -38,7 +38,7 @@ public class MultipleClaimAction : ClaimAction
case JsonValueKind.Array:
foreach (var arramItem in prop.EnumerateArray())
{
claim = new Claim(ClaimType, arramItem.GetString(), ValueType, issuer);
claim = new Claim(ClaimType, arramItem.GetString()!, ValueType, issuer);
if (!identity.Claims.Any(c => c.Type == claim.Type && c.Value == claim.Value))
{
identity.AddClaim(claim);

15
framework/src/Volo.Abp.AspNetCore.Authentication.OpenIdConnect/Microsoft/Extensions/DependencyInjection/AbpOpenIdConnectExtensions.cs

@ -28,8 +28,6 @@ public static class AbpOpenIdConnectExtensions
{
options.ClaimActions.MapAbpClaimTypes();
configureOptions?.Invoke(options);
options.Events ??= new OpenIdConnectEvents();
var authorizationCodeReceived = options.Events.OnAuthorizationCodeReceived ?? (_ => Task.CompletedTask);
@ -39,16 +37,7 @@ public static class AbpOpenIdConnectExtensions
return authorizationCodeReceived.Invoke(receivedContext);
};
options.Events.OnRemoteFailure = remoteFailureContext =>
{
if (remoteFailureContext.Failure is OpenIdConnectProtocolException &&
remoteFailureContext.Failure.Message.Contains("access_denied"))
{
remoteFailureContext.HandleResponse();
remoteFailureContext.Response.Redirect($"{remoteFailureContext.Request.PathBase}/");
}
return Task.CompletedTask;
};
options.AccessDeniedPath = "/";
options.Events.OnTokenValidated = async (context) =>
{
@ -63,6 +52,8 @@ public static class AbpOpenIdConnectExtensions
logger?.LogException(ex);
}
};
configureOptions?.Invoke(options);
});
}

2
framework/src/Volo.Abp.AspNetCore.Authentication.OpenIdConnect/Volo.Abp.AspNetCore.Authentication.OpenIdConnect.csproj

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

5
framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/AbpComponentBase.cs

@ -168,6 +168,11 @@ public abstract class AbpComponentBase : OwningComponentBase
protected virtual async Task HandleErrorAsync(Exception exception)
{
if (IsDisposed)
{
return;
}
Logger.LogException(exception);
await InvokeAsync(async () =>
{

29
framework/src/Volo.Abp.AspNetCore.Mvc.Dapr.EventBus/Volo/Abp/AspNetCore/Mvc/Dapr/EventBus/Controllers/AbpAspNetCoreMvcDaprEventsController.cs

@ -1,4 +1,5 @@
using System;
using System.Linq;
using System.Text.Json;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
@ -21,7 +22,6 @@ public class AbpAspNetCoreMvcDaprEventsController : AbpController
var daprSerializer = HttpContext.RequestServices.GetRequiredService<IDaprSerializer>();
var body = (await JsonDocument.ParseAsync(HttpContext.Request.Body));
var id = body.RootElement.GetProperty("id").GetString();
var pubSubName = body.RootElement.GetProperty("pubsubname").GetString();
var topic = body.RootElement.GetProperty("topic").GetString();
var data = body.RootElement.GetProperty("data").GetRawText();
@ -32,8 +32,31 @@ public class AbpAspNetCoreMvcDaprEventsController : AbpController
}
var distributedEventBus = HttpContext.RequestServices.GetRequiredService<DaprDistributedEventBus>();
var eventData = daprSerializer.Deserialize(data, distributedEventBus.GetEventType(topic));
await distributedEventBus.TriggerHandlersAsync(id, distributedEventBus.GetEventType(topic), eventData);
if (IsAbpDaprEventData(data))
{
var daprEventData = daprSerializer.Deserialize(data, typeof(AbpDaprEventData)).As<AbpDaprEventData>();
var eventData = daprSerializer.Deserialize(daprEventData.JsonData, distributedEventBus.GetEventType(daprEventData.Topic));
await distributedEventBus.TriggerHandlersAsync(distributedEventBus.GetEventType(daprEventData.Topic), eventData, daprEventData.MessageId, daprEventData.CorrelationId);
}
else
{
var eventData = daprSerializer.Deserialize(data, distributedEventBus.GetEventType(topic));
await distributedEventBus.TriggerHandlersAsync(distributedEventBus.GetEventType(topic), eventData);
}
return Ok();
}
protected virtual bool IsAbpDaprEventData(string data)
{
var document = JsonDocument.Parse(data);
var objects = document.RootElement.EnumerateObject().ToList();
return objects.Count == 5 &&
objects.Any(x => x.Name.Equals("PubSubName", StringComparison.CurrentCultureIgnoreCase)) &&
objects.Any(x => x.Name.Equals("Topic", StringComparison.CurrentCultureIgnoreCase)) &&
objects.Any(x => x.Name.Equals("MessageId", StringComparison.CurrentCultureIgnoreCase)) &&
objects.Any(x => x.Name.Equals("JsonData", StringComparison.CurrentCultureIgnoreCase)) &&
objects.Any(x => x.Name.Equals("CorrelationId", StringComparison.CurrentCultureIgnoreCase));
}
}

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

@ -227,18 +227,16 @@ public class AbpAspNetCoreMvcModule : AbpModule
return;
}
//Plugin modules
var moduleAssemblies = context
.ServiceProvider
.GetRequiredService<IModuleContainer>()
var moduleContainer = context.ServiceProvider.GetRequiredService<IModuleContainer>();
var plugInModuleAssemblies = moduleContainer
.Modules
.Where(m => m.IsLoadedAsPlugIn)
.Select(m => m.Type.Assembly)
.SelectMany(m => m.AllAssemblies)
.Distinct();
AddToApplicationParts(partManager, moduleAssemblies);
AddToApplicationParts(partManager, plugInModuleAssemblies);
//Controllers for application services
var controllerAssemblies = context
.ServiceProvider
.GetRequiredService<IOptions<AbpAspNetCoreMvcOptions>>()
@ -249,6 +247,13 @@ public class AbpAspNetCoreMvcModule : AbpModule
.Distinct();
AddToApplicationParts(partManager, controllerAssemblies);
var additionalAssemblies = moduleContainer
.Modules
.SelectMany(m => m.GetAdditionalAssemblies())
.Distinct();
AddToApplicationParts(partManager, additionalAssemblies);
}
private static void AddToApplicationParts(ApplicationPartManager partManager, IEnumerable<Assembly> moduleAssemblies)

2
framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcOptions.cs

@ -14,6 +14,8 @@ public class AbpAspNetCoreMvcOptions
public HashSet<Type> ControllersToRemove { get; }
public bool ExposeIntegrationServices { get; set; } = false;
public bool AutoModelValidation { get; set; }
public bool EnableRazorRuntimeCompilationOnDevelopment { get; set; }

4
framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ApplicationPartSorter.cs

@ -125,7 +125,7 @@ public static class ApplicationPartSorter
var moduleDependedAssemblies = moduleDescriptor
.Dependencies
.Select(d => d.Assembly)
.SelectMany(d => d.AllAssemblies)
.ToArray();
return partManager.ApplicationParts
@ -161,6 +161,6 @@ public static class ApplicationPartSorter
{
return moduleContainer
.Modules
.FirstOrDefault(m => m.Assembly == assembly);
.FirstOrDefault(m => m.AllAssemblies.Contains(assembly));
}
}

15
framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Conventions/AbpServiceConvention.cs

@ -45,6 +45,7 @@ public class AbpServiceConvention : IAbpServiceConvention, ITransientDependency
protected virtual void ApplyForControllers(ApplicationModel application)
{
RemoveDuplicateControllers(application);
RemoveIntegrationControllersIfNotExposed(application);
foreach (var controller in GetControllers(application))
{
@ -72,6 +73,20 @@ public class AbpServiceConvention : IAbpServiceConvention, ITransientDependency
}
}
protected virtual void RemoveIntegrationControllersIfNotExposed(ApplicationModel application)
{
if (Options.ExposeIntegrationServices)
{
return;
}
var integrationControllers = GetControllers(application)
.Where(c => IntegrationServiceAttribute.IsDefinedOrInherited(c.ControllerType))
.ToArray();
application.Controllers.RemoveAll(integrationControllers);
}
protected virtual IList<ControllerModel> GetControllers(ApplicationModel application)
{
return application.Controllers;

18
framework/src/Volo.Abp.AspNetCore.TestBase/Volo/Abp/AspNetCore/TestBase/AbpAspNetCoreIntegratedTestBase.cs

@ -7,11 +7,15 @@ using Microsoft.AspNetCore.Routing;
using Microsoft.AspNetCore.TestHost;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Volo.Abp.Modularity;
namespace Volo.Abp.AspNetCore.TestBase;
public abstract class AbpAspNetCoreIntegratedTestBase<TStartup> : AbpTestBaseWithServiceProvider, IDisposable
where TStartup : class
/// <typeparam name="TStartupModule">
/// Can be a module type or old-style ASP.NET Core Startup class.
/// </typeparam>
public abstract class AbpAspNetCoreIntegratedTestBase<TStartupModule> : AbpTestBaseWithServiceProvider, IDisposable
where TStartupModule : class
{
protected TestServer Server { get; }
@ -39,7 +43,15 @@ public abstract class AbpAspNetCoreIntegratedTestBase<TStartup> : AbpTestBaseWit
return Host.CreateDefaultBuilder()
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<TStartup>();
if (typeof(TStartupModule).IsAssignableTo<IAbpModule>())
{
webBuilder.UseStartup<TestStartup<TStartupModule>>();
}
else
{
webBuilder.UseStartup<TStartupModule>();
}
webBuilder.UseAbpTestServer();
})
.UseAutofac()

18
framework/src/Volo.Abp.AspNetCore.TestBase/Volo/Abp/AspNetCore/TestBase/TestStartup.cs

@ -0,0 +1,18 @@
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Threading;
namespace Volo.Abp.AspNetCore.TestBase;
internal class TestStartup<TStartupModule>
{
public void ConfigureServices(IServiceCollection services)
{
AsyncHelper.RunSync(() => services.AddApplicationAsync(typeof(TStartupModule)));
}
public void Configure(IApplicationBuilder app)
{
AsyncHelper.RunSync(app.InitializeApplicationAsync);
}
}

17
framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/Builder/AbpAspNetCoreApplicationBuilderExtensions.cs

@ -23,7 +23,7 @@ public static class AbpAspNetCoreApplicationBuilderExtensions
.GetRequiredService<IOptions<AbpEndpointRouterOptions>>()
.Value;
if (!options.EndpointConfigureActions.Any())
if (!options.EndpointConfigureActions.Any() && additionalConfigurationAction == null)
{
return app;
}
@ -32,15 +32,18 @@ public static class AbpAspNetCoreApplicationBuilderExtensions
{
using (var scope = app.ApplicationServices.CreateScope())
{
var context = new EndpointRouteBuilderContext(endpoints, scope.ServiceProvider);
foreach (var configureAction in options.EndpointConfigureActions)
if (options.EndpointConfigureActions.Any())
{
configureAction(context);
}
var context = new EndpointRouteBuilderContext(endpoints, scope.ServiceProvider);
additionalConfigurationAction?.Invoke(endpoints);
foreach (var configureAction in options.EndpointConfigureActions)
{
configureAction(context);
}
}
}
additionalConfigurationAction?.Invoke(endpoints);
});
}
}

28
framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Tracing/AbpCorrelationIdMiddleware.cs

@ -1,4 +1,5 @@
using Microsoft.AspNetCore.Http;
using System;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Options;
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
@ -20,16 +21,31 @@ public class AbpCorrelationIdMiddleware : IMiddleware, ITransientDependency
public async Task InvokeAsync(HttpContext context, RequestDelegate next)
{
var correlationId = _correlationIdProvider.Get();
var correlationId = GetCorrelationIdFromRequest(context);
try
using (_correlationIdProvider.Change(correlationId))
{
await next(context);
try
{
await next(context);
}
finally
{
CheckAndSetCorrelationIdOnResponse(context, _options, correlationId);
}
}
finally
}
protected virtual string GetCorrelationIdFromRequest(HttpContext context)
{
string correlationId = context.Request.Headers[_options.HttpHeaderName];
if (correlationId.IsNullOrEmpty())
{
CheckAndSetCorrelationIdOnResponse(context, _options, correlationId);
correlationId = Guid.NewGuid().ToString("N");
context.Request.Headers[_options.HttpHeaderName] = correlationId;
}
return correlationId;
}
protected virtual void CheckAndSetCorrelationIdOnResponse(

51
framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Tracing/AspNetCoreCorrelationIdProvider.cs

@ -1,51 +0,0 @@
using System;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Options;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Tracing;
namespace Volo.Abp.AspNetCore.Tracing;
[Dependency(ReplaceServices = true)]
public class AspNetCoreCorrelationIdProvider : ICorrelationIdProvider, ITransientDependency
{
protected IHttpContextAccessor HttpContextAccessor { get; }
protected AbpCorrelationIdOptions Options { get; }
public AspNetCoreCorrelationIdProvider(
IHttpContextAccessor httpContextAccessor,
IOptions<AbpCorrelationIdOptions> options)
{
HttpContextAccessor = httpContextAccessor;
Options = options.Value;
}
public virtual string Get()
{
if (HttpContextAccessor.HttpContext?.Request?.Headers == null)
{
return CreateNewCorrelationId();
}
string correlationId = HttpContextAccessor.HttpContext.Request.Headers[Options.HttpHeaderName];
if (correlationId.IsNullOrEmpty())
{
lock (HttpContextAccessor.HttpContext.Request.Headers)
{
if (correlationId.IsNullOrEmpty())
{
correlationId = CreateNewCorrelationId();
HttpContextAccessor.HttpContext.Request.Headers[Options.HttpHeaderName] = correlationId;
}
}
}
return correlationId;
}
protected virtual string CreateNewCorrelationId()
{
return Guid.NewGuid().ToString("N");
}
}

2
framework/src/Volo.Abp.Autofac.WebAssembly/Microsoft/AspNetCore/Components/WebAssembly/Hosting/AbpWebAssemblyApplicationCreationOptionsAutofacExtensions.cs

@ -11,7 +11,7 @@ public static class AbpWebAssemblyApplicationCreationOptionsAutofacExtensions
{
public static void UseAutofac(
[NotNull] this AbpWebAssemblyApplicationCreationOptions options,
[CanBeNull] Action<ContainerBuilder> configure = null)
Action<ContainerBuilder>? configure = null)
{
options.HostBuilder.Services.AddAutofacServiceProviderFactory();
options.HostBuilder.ConfigureContainer(

2
framework/src/Volo.Abp.Autofac.WebAssembly/Volo.Abp.Autofac.WebAssembly.csproj

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

2
framework/src/Volo.Abp.Autofac/Autofac/Builder/AbpRegistrationBuilderExtensions.cs

@ -69,7 +69,7 @@ public static class AbpRegistrationBuilderExtensions
where TActivatorData : ReflectionActivatorData
{
// Enable Property Injection only for types in an assembly containing an AbpModule and without a DisablePropertyInjection attribute on class or properties.
if (moduleContainer.Modules.Any(m => m.Assembly == implementationType.Assembly) &&
if (moduleContainer.Modules.Any(m => m.AllAssemblies.Contains(implementationType.Assembly)) &&
implementationType.GetCustomAttributes(typeof(DisablePropertyInjectionAttribute), true).IsNullOrEmpty())
{
registrationBuilder = registrationBuilder.PropertiesAutowired(new AbpPropertySelector(false));

8
framework/src/Volo.Abp.Autofac/Autofac/Extensions/DependencyInjection/AutofacRegistration.cs

@ -87,7 +87,7 @@ public static class AutofacRegistration
public static void Populate(
this ContainerBuilder builder,
IServiceCollection services,
object lifetimeScopeTagForSingletons)
object? lifetimeScopeTagForSingletons)
{
if (services == null)
{
@ -134,7 +134,7 @@ public static class AutofacRegistration
private static IRegistrationBuilder<object, TActivatorData, TRegistrationStyle> ConfigureLifecycle<TActivatorData, TRegistrationStyle>(
this IRegistrationBuilder<object, TActivatorData, TRegistrationStyle> registrationBuilder,
ServiceLifetime lifecycleKind,
object lifetimeScopeTagForSingleton)
object? lifetimeScopeTagForSingleton)
{
switch (lifecycleKind)
{
@ -179,7 +179,7 @@ public static class AutofacRegistration
private static void Register(
ContainerBuilder builder,
IServiceCollection services,
object lifetimeScopeTagForSingletons)
object? lifetimeScopeTagForSingletons)
{
var moduleContainer = services.GetSingletonInstance<IModuleContainer>();
var registrationActionList = services.GetRegistrationActionList();
@ -223,7 +223,7 @@ public static class AutofacRegistration
else
{
builder
.RegisterInstance(descriptor.ImplementationInstance)
.RegisterInstance(descriptor.ImplementationInstance!)
.As(descriptor.ServiceType)
.ConfigureLifecycle(descriptor.Lifetime, null);
}

2
framework/src/Volo.Abp.Autofac/Microsoft/Extensions/DependencyInjection/AbpAutofacServiceCollectionExtensions.cs

@ -21,7 +21,7 @@ public static class AbpAutofacServiceCollectionExtensions
return builder;
}
public static IServiceProvider BuildAutofacServiceProvider([NotNull] this IServiceCollection services, Action<ContainerBuilder> builderAction = null)
public static IServiceProvider BuildAutofacServiceProvider([NotNull] this IServiceCollection services, Action<ContainerBuilder>? builderAction = null)
{
return services.BuildServiceProviderFromFactory(builderAction);
}

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

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

2
framework/src/Volo.Abp.Autofac/Volo/Abp/Autofac/AbpAutofacServiceProviderFactory.cs

@ -11,7 +11,7 @@ namespace Volo.Abp.Autofac;
public class AbpAutofacServiceProviderFactory : IServiceProviderFactory<ContainerBuilder>
{
private readonly ContainerBuilder _builder;
private IServiceCollection _services;
private IServiceCollection _services = default!;
public AbpAutofacServiceProviderFactory(ContainerBuilder builder)
{

35
framework/src/Volo.Abp.BlazoriseUI/AbpCrudPageBase.cs

@ -215,9 +215,9 @@ public abstract class AbpCrudPageBase<
protected async override Task OnInitializedAsync()
{
await SetPermissionsAsync();
await SetEntityActionsAsync();
await SetTableColumnsAsync();
await TrySetPermissionsAsync();
await TrySetEntityActionsAsync();
await TrySetTableColumnsAsync();
await InvokeAsync(StateHasChanged);
}
@ -231,7 +231,15 @@ public abstract class AbpCrudPageBase<
await base.OnAfterRenderAsync(firstRender);
}
private async Task TrySetPermissionsAsync()
{
if (IsDisposed)
{
return;
}
await SetPermissionsAsync();
}
protected virtual async Task SetPermissionsAsync()
{
@ -579,13 +587,34 @@ public abstract class AbpCrudPageBase<
return ValueTask.CompletedTask;
}
private async ValueTask TrySetEntityActionsAsync()
{
if (IsDisposed)
{
return;
}
await SetEntityActionsAsync();
}
protected virtual ValueTask SetEntityActionsAsync()
{
return ValueTask.CompletedTask;
}
private async ValueTask TrySetTableColumnsAsync()
{
if (IsDisposed)
{
return;
}
await SetTableColumnsAsync();
}
protected virtual ValueTask SetTableColumnsAsync()
{
return ValueTask.CompletedTask;
}

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

@ -8,7 +8,7 @@
{
<Validation Validator="@Validate" MessageLocalizer="@LH.Localize">
<Field>
<Check TValue="bool" @bind-Checked="@Value">
<Check TValue="bool" @bind-Checked="@Value" Disabled="IsReadonlyField">
<ChildContent>
@PropertyInfo.GetLocalizedDisplayName(StringLocalizerFactory)
</ChildContent>

1
framework/src/Volo.Abp.BlazoriseUI/Components/ObjectExtending/DateTimeExtensionProperty.razor

@ -13,6 +13,7 @@
<DateEdit TValue="DateTime?"
InputMode="@(PropertyInfo.IsDate() ? DateInputMode.Date : DateInputMode.DateTime)"
Pattern="@PropertyInfo.GetDateEditInputFormatOrNull()"
Disabled="IsReadonlyField"
@bind-Date="@Value">
<Feedback>
<ValidationError/>

1
framework/src/Volo.Abp.BlazoriseUI/Components/ObjectExtending/ExtensionProperties.razor

@ -25,6 +25,7 @@
__builder.AddAttribute(1, "PropertyInfo", propertyInfo);
__builder.AddAttribute(2, "Entity", Entity);
__builder.AddAttribute(3, "LH", LH);
__builder.AddAttribute(4, "ModalType", ModalType);
__builder.CloseComponent();
}
}

4
framework/src/Volo.Abp.BlazoriseUI/Components/ObjectExtending/ExtensionProperties.razor.cs

@ -2,6 +2,7 @@
using Microsoft.Extensions.Localization;
using Volo.Abp.AspNetCore.Components.Web;
using Volo.Abp.Data;
using Volo.Abp.ObjectExtending;
namespace Volo.Abp.BlazoriseUI.Components.ObjectExtending;
@ -16,4 +17,7 @@ public partial class ExtensionProperties<TEntityType, TResourceType> : Component
[Parameter]
public TEntityType Entity { get; set; }
[Parameter]
public ExtensionPropertyModalType? ModalType { get; set; }
}

7
framework/src/Volo.Abp.BlazoriseUI/Components/ObjectExtending/ExtensionPropertyComponentBase.cs

@ -33,6 +33,9 @@ public abstract class ExtensionPropertyComponentBase<TEntity, TResourceType> : O
[Parameter]
public AbpBlazorMessageLocalizerHelper<TResourceType> LH { get; set; }
[Parameter]
public ExtensionPropertyModalType? ModalType { get; set; }
protected virtual void Validate(ValidatorEventArgs e)
{
e.Status = ValidationStatus.Success;
@ -65,12 +68,14 @@ public abstract class ExtensionPropertyComponentBase<TEntity, TResourceType> : O
}
e.MemberNames = result.MemberNames;
e.Status = ValidationStatus.Error;
e.Status = ValidationStatus.Error;
e.ErrorText = errorMessage;
break;
}
}
protected bool IsReadonlyField => ModalType is ExtensionPropertyModalType.EditModal && PropertyInfo.UI.EditModal.IsReadOnly;
private static string GetDefaultErrorMessage(ValidationAttribute validationAttribute)
{
if (validationAttribute is StringLengthAttribute stringLengthAttribute && stringLengthAttribute.MinimumLength != 0)

7
framework/src/Volo.Abp.BlazoriseUI/Components/ObjectExtending/ExtensionPropertyModalType.cs

@ -0,0 +1,7 @@
namespace Volo.Abp.BlazoriseUI.Components.ObjectExtending;
public enum ExtensionPropertyModalType : byte
{
CreateModal = 0,
EditModal = 1
}

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

@ -15,6 +15,7 @@
SelectedValueChanged="@SelectedValueChanged"
SearchChanged="@SearchFilterChangedAsync"
Validator="@Validate"
MinLength="0">
MinLength="0"
Disabled="IsReadonlyField">
</Autocomplete>
</Field>

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

@ -10,7 +10,7 @@
<ChildContent>
@foreach (var item in SelectItems)
{
<SelectItem Value="@item.Value">@item.Text</SelectItem>
<SelectItem Value="@item.Value" Disabled="IsReadonlyField">@item.Text</SelectItem>
}
</ChildContent>
<Feedback>

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

@ -9,7 +9,7 @@
<Validation Validator="@Validate" MessageLocalizer="@LH.Localize">
<Field>
<FieldLabel>@PropertyInfo.GetLocalizedDisplayName(StringLocalizerFactory)</FieldLabel>
<TextEdit @bind-Text="@Value" Role="@PropertyInfo.GetTextRole()" InputMode="@PropertyInfo.GetTextInputMode()">
<TextEdit @bind-Text="@Value" Role="@PropertyInfo.GetTextRole()" InputMode="@PropertyInfo.GetTextInputMode()" Disabled="IsReadonlyField">
<Feedback>
<ValidationError/>
</Feedback>

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

@ -9,7 +9,7 @@
<Validation Validator="@Validate" MessageLocalizer="@LH.Localize">
<Field>
<FieldLabel>@PropertyInfo.GetLocalizedDisplayName(StringLocalizerFactory)</FieldLabel>-->
<TimeEdit TValue="TimeSpan?" @bind-Time="@Value">
<TimeEdit TValue="TimeSpan?" @bind-Time="@Value" Disabled="IsReadonlyField">
<Feedback>
<ValidationError/>
</Feedback>

2
framework/src/Volo.Abp.Castle.Core/Volo.Abp.Castle.Core.csproj

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

4
framework/src/Volo.Abp.Castle.Core/Volo/Abp/Castle/DynamicProxy/CastleAbpMethodInvocationAdapterBase.cs

@ -20,7 +20,7 @@ public abstract class CastleAbpMethodInvocationAdapterBase : IAbpMethodInvocatio
public MethodInfo Method => Invocation.MethodInvocationTarget ?? Invocation.Method;
public object ReturnValue { get; set; }
public object ReturnValue { get; set; } = default!;
protected IInvocation Invocation { get; }
@ -39,7 +39,7 @@ public abstract class CastleAbpMethodInvocationAdapterBase : IAbpMethodInvocatio
var methodParameters = Method.GetParameters();
for (int i = 0; i < methodParameters.Length; i++)
{
dict[methodParameters[i].Name] = Invocation.Arguments[i];
dict[methodParameters[i].Name!] = Invocation.Arguments[i];
}
return dict;

2
framework/src/Volo.Abp.Castle.Core/Volo/Abp/Castle/DynamicProxy/CastleAbpMethodInvocationAdapterWithReturnValue.cs

@ -21,6 +21,6 @@ public class CastleAbpMethodInvocationAdapterWithReturnValue<TResult> : CastleAb
public override async Task ProceedAsync()
{
ReturnValue = await Proceed(Invocation, ProceedInfo);
ReturnValue = (await Proceed(Invocation, ProceedInfo))!;
}
}

8
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/LoginCommand.cs

@ -17,7 +17,7 @@ namespace Volo.Abp.Cli.Commands;
public class LoginCommand : IConsoleCommand, ITransientDependency
{
public const string Name = "login";
public ILogger<LoginCommand> Logger { get; set; }
protected AuthService AuthService { get; }
@ -122,6 +122,12 @@ public class LoginCommand : IConsoleCommand, ITransientDependency
return;
}
if (ex.Message.Contains("RequiresTwoFactor"))
{
Logger.LogError("Two factor authentication is enabled for your account. Please use `abp login --device` command to login.");
return;
}
if (TryGetErrorMessageFromHtmlPage(ex.Message, out var errorMsg))
{
Logger.LogError(errorMsg);

28
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/Services/SuiteAppSettingsService.cs

@ -46,6 +46,34 @@ public class SuiteAppSettingsService : ITransientDependency
return Convert.ToInt32(url.Split(":").Last());
}
public int GetSuitePort()
{
return GetSuitePort(GetCurrentSuiteVersion());
}
public int GetSuitePort(string version)
{
var filePath = GetFilePathOrNull(version);
if (filePath == null)
{
return DefaultPort;
}
var content = File.ReadAllText(filePath);
var contentAsJson = JObject.Parse(content);
var url = contentAsJson["AbpSuite"]?["ApplicationUrl"]?.ToString();
if (url == null)
{
return DefaultPort;
}
return Convert.ToInt32(url.Split(":").Last());
}
private string GetFilePathOrNull(string version)
{

21
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/ConnectionStringRenameStep.cs

@ -0,0 +1,21 @@
using System;
using System.Linq;
using Volo.Abp.Cli.ProjectBuilding.Files;
namespace Volo.Abp.Cli.ProjectBuilding.Building;
public class ConnectionStringRenameStep : ProjectBuildPipelineStep
{
public override void Execute(ProjectBuildContext context)
{
foreach (var fileEntry in context.Files.Where(file => file.Name.EndsWith(CliConsts.AppSettingsJsonFileName, StringComparison.OrdinalIgnoreCase)))
{
RenameDatabaseName(fileEntry);
}
}
private void RenameDatabaseName(FileEntry fileEntry)
{
fileEntry.SetContent(fileEntry.Content.Replace("MyProjectNamePro", "MyProjectName"));
}
}

5
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/App/AppTemplateBase.cs

@ -645,6 +645,11 @@ public abstract class AppTemplateBase : TemplateInfo
{
steps.Add(new ConnectionStringChangeStep());
}
if (IsPro())
{
steps.Add(new ConnectionStringRenameStep());
}
}
protected void CleanupFolderHierarchy(ProjectBuildContext context, List<ProjectBuildPipelineStep> steps)

8
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/Microservice/MicroserviceServiceTemplateBase.cs

@ -39,7 +39,8 @@ public abstract class MicroserviceServiceTemplateBase : TemplateInfo
SetRandomPortForHostProject(context, steps);
RandomizeStringEncryption(context, steps);
RandomizeAuthServerPassPhrase(context, steps);
ChangeConnectionString(context, steps);
return steps;
}
@ -75,4 +76,9 @@ public abstract class MicroserviceServiceTemplateBase : TemplateInfo
{
steps.Add(new RandomizeAuthServerPassPhraseStep());
}
private static void ChangeConnectionString(ProjectBuildContext context, List<ProjectBuildPipelineStep> steps)
{
steps.Add(new ConnectionStringRenameStep());
}
}

7
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/Module/ModuleTemplateBase.cs

@ -102,12 +102,17 @@ public abstract class ModuleTemplateBase : TemplateInfo
steps.Add(new UpdateNuGetConfigStep("/NuGet.Config"));
}
private static void ChangeConnectionString(ProjectBuildContext context, List<ProjectBuildPipelineStep> steps)
private void ChangeConnectionString(ProjectBuildContext context, List<ProjectBuildPipelineStep> steps)
{
if (context.BuildArgs.ConnectionString != null)
{
steps.Add(new ConnectionStringChangeStep());
}
if (IsPro())
{
steps.Add(new ConnectionStringRenameStep());
}
}
private void CleanupFolderHierarchy(ProjectBuildContext context, List<ProjectBuildPipelineStep> steps)

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

@ -28,7 +28,7 @@
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="$(MicrosoftPackageVersion)" />
<PackageReference Include="System.Text.Encodings.Web" Version="$(MicrosoftPackageVersion)" />
<PackageReference Include="System.Runtime.Loader" Version="4.3.0" />
<PackageReference Include="System.Linq.Dynamic.Core" Version="1.2.18" />
<PackageReference Include="System.Linq.Dynamic.Core" Version="1.3.3" />
<PackageReference Include="System.Linq.Queryable" Version="4.3.0" />
<PackageReference Include="JetBrains.Annotations" Version="2022.1.0" />
<PackageReference Include="Nito.AsyncEx.Coordination" Version="5.1.2" />

20
framework/src/Volo.Abp.Core/Volo/Abp/AbpApplicationBase.cs

@ -188,11 +188,13 @@ public abstract class AbpApplicationBase : IAbpApplication
{
if (!abpModule.SkipAutoServiceRegistration)
{
var assembly = module.Type.Assembly;
if (!assemblies.Contains(assembly))
foreach (var assembly in module.AllAssemblies)
{
Services.AddAssembly(assembly);
assemblies.Add(assembly);
if (!assemblies.Contains(assembly))
{
Services.AddAssembly(assembly);
assemblies.Add(assembly);
}
}
}
}
@ -279,11 +281,13 @@ public abstract class AbpApplicationBase : IAbpApplication
{
if (!abpModule.SkipAutoServiceRegistration)
{
var assembly = module.Type.Assembly;
if (!assemblies.Contains(assembly))
foreach (var assembly in module.AllAssemblies)
{
Services.AddAssembly(assembly);
assemblies.Add(assembly);
if (!assemblies.Contains(assembly))
{
Services.AddAssembly(assembly);
assemblies.Add(assembly);
}
}
}
}

4
framework/src/Volo.Abp.Core/Volo/Abp/AbpException.cs

@ -13,13 +13,13 @@ public class AbpException : Exception
}
public AbpException(string message)
public AbpException(string? message)
: base(message)
{
}
public AbpException(string message, Exception innerException)
public AbpException(string? message, Exception? innerException)
: base(message, innerException)
{

4
framework/src/Volo.Abp.Core/Volo/Abp/Modularity/AbpModuleDescriptor.cs

@ -11,6 +11,8 @@ public class AbpModuleDescriptor : IAbpModuleDescriptor
public Type Type { get; }
public Assembly Assembly { get; }
public Assembly[] AllAssemblies { get; }
public IAbpModule Instance { get; }
@ -26,6 +28,7 @@ public class AbpModuleDescriptor : IAbpModuleDescriptor
{
Check.NotNull(type, nameof(type));
Check.NotNull(instance, nameof(instance));
AbpModule.CheckAbpModuleType(type);
if (!type.GetTypeInfo().IsAssignableFrom(instance.GetType()))
{
@ -34,6 +37,7 @@ public class AbpModuleDescriptor : IAbpModuleDescriptor
Type = type;
Assembly = type.Assembly;
AllAssemblies = AbpModuleHelper.GetAllAssemblies(type);
Instance = instance;
IsLoadedAsPlugIn = isLoadedAsPlugIn;

15
framework/src/Volo.Abp.Core/Volo/Abp/Modularity/AbpModuleDescriptorExtensions.cs

@ -0,0 +1,15 @@
using System;
using System.Linq;
using System.Reflection;
namespace Volo.Abp.Modularity;
public static class AbpModuleDescriptorExtensions
{
public static Assembly[] GetAdditionalAssemblies(this IAbpModuleDescriptor module)
{
return module.AllAssemblies.Length <= 1
? Array.Empty<Assembly>()
: module.AllAssemblies.Where(x => x != module.Assembly).ToArray();
}
}

21
framework/src/Volo.Abp.Core/Volo/Abp/Modularity/AbpModuleHelper.cs

@ -36,6 +36,27 @@ internal static class AbpModuleHelper
return dependencies;
}
public static Assembly[] GetAllAssemblies(Type moduleType)
{
var assemblies = new List<Assembly>();
var additionalAssemblyDescriptors = moduleType
.GetCustomAttributes()
.OfType<IAdditionalModuleAssemblyProvider>();
foreach (var descriptor in additionalAssemblyDescriptors)
{
foreach (var assembly in descriptor.GetAssemblies())
{
assemblies.AddIfNotContains(assembly);
}
}
assemblies.Add(moduleType.Assembly);
return assemblies.ToArray();
}
private static void AddModuleAndDependenciesRecursively(
List<Type> moduleTypes,

24
framework/src/Volo.Abp.Core/Volo/Abp/Modularity/AdditionalAssemblyAttribute.cs

@ -0,0 +1,24 @@
using System;
using System.Linq;
using System.Reflection;
namespace Volo.Abp.Modularity;
/// <summary>
/// Used to define additional assemblies for a module.
/// </summary>
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
public class AdditionalAssemblyAttribute : Attribute, IAdditionalModuleAssemblyProvider
{
public Type[] TypesInAssemblies { get; }
public AdditionalAssemblyAttribute(params Type[]? typesInAssemblies)
{
TypesInAssemblies = typesInAssemblies ?? Type.EmptyTypes;
}
public virtual Assembly[] GetAssemblies()
{
return TypesInAssemblies.Select(t => t.Assembly).Distinct().ToArray();
}
}

4
framework/src/Volo.Abp.Core/Volo/Abp/Modularity/DependsOnAttribute.cs

@ -1,5 +1,4 @@
using System;
using JetBrains.Annotations;
namespace Volo.Abp.Modularity;
@ -9,12 +8,11 @@ namespace Volo.Abp.Modularity;
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
public class DependsOnAttribute : Attribute, IDependedTypesProvider
{
[NotNull]
public Type[] DependedTypes { get; }
public DependsOnAttribute(params Type[]? dependedTypes)
{
DependedTypes = dependedTypes ?? new Type[0];
DependedTypes = dependedTypes ?? Type.EmptyTypes;
}
public virtual Type[] GetDependedTypes()

25
framework/src/Volo.Abp.Core/Volo/Abp/Modularity/IAbpModuleDescriptor.cs

@ -6,13 +6,36 @@ namespace Volo.Abp.Modularity;
public interface IAbpModuleDescriptor
{
/// <summary>
/// Type of the module class.
/// </summary>
Type Type { get; }
/// <summary>
/// Main assembly that defines the module <see cref="Type"/>.
/// </summary>
Assembly Assembly { get; }
/// <summary>
/// All the assemblies of the module.
/// Includes the main <see cref="Assembly"/> and other assemblies defined
/// on the module <see cref="Type"/> using the <see cref="AdditionalAssemblyAttribute"/> attribute.
/// </summary>
Assembly[] AllAssemblies { get; }
/// <summary>
/// The instance of the module class (singleton).
/// </summary>
IAbpModule Instance { get; }
/// <summary>
/// Is this module loaded as a plug-in?
/// </summary>
bool IsLoadedAsPlugIn { get; }
/// <summary>
/// Modules on which this module depends on.
/// A module can depend on another module using the <see cref="DependsOnAttribute"/> attribute.
/// </summary>
IReadOnlyList<IAbpModuleDescriptor> Dependencies { get; }
}
}

8
framework/src/Volo.Abp.Core/Volo/Abp/Modularity/IAdditionalModuleAssemblyProvider.cs

@ -0,0 +1,8 @@
using System.Reflection;
namespace Volo.Abp.Modularity;
public interface IAdditionalModuleAssemblyProvider
{
Assembly[] GetAssemblies();
}

2
framework/src/Volo.Abp.Core/Volo/Abp/Reflection/AssemblyFinder.cs

@ -29,7 +29,7 @@ public class AssemblyFinder : IAssemblyFinder
foreach (var module in _moduleContainer.Modules)
{
assemblies.Add(module.Type.Assembly);
assemblies.AddRange(module.AllAssemblies);
}
return assemblies.Distinct().ToImmutableList();

18
framework/src/Volo.Abp.Core/Volo/Abp/Tracing/DefaultCorrelationIdProvider.cs

@ -1,17 +1,27 @@
using System;
using System.Threading;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.Tracing;
public class DefaultCorrelationIdProvider : ICorrelationIdProvider, ISingletonDependency
{
public string Get()
private readonly AsyncLocal<string?> _currentCorrelationId = new AsyncLocal<string?>();
private string? CorrelationId => _currentCorrelationId.Value;
public virtual string? Get()
{
return CreateNewCorrelationId();
return CorrelationId;
}
protected virtual string CreateNewCorrelationId()
public virtual IDisposable Change(string? correlationId)
{
return Guid.NewGuid().ToString("N");
var parent = CorrelationId;
_currentCorrelationId.Value = correlationId;
return new DisposeAction(() =>
{
_currentCorrelationId.Value = parent;
});
}
}

7
framework/src/Volo.Abp.Core/Volo/Abp/Tracing/ICorrelationIdProvider.cs

@ -1,9 +1,10 @@
using JetBrains.Annotations;
using System;
namespace Volo.Abp.Tracing;
public interface ICorrelationIdProvider
{
[NotNull]
string Get();
string? Get();
IDisposable Change(string? correlationId);
}

2
framework/src/Volo.Abp.Dapr/Volo/Abp/Dapr/IDaprSerializer.cs

@ -6,6 +6,8 @@ public interface IDaprSerializer
{
byte[] Serialize(object obj);
string SerializeToString(object obj);
object Deserialize(byte[] value, Type type);
object Deserialize(string value, Type type);

5
framework/src/Volo.Abp.Dapr/Volo/Abp/Dapr/Utf8JsonDaprSerializer.cs

@ -19,6 +19,11 @@ public class Utf8JsonDaprSerializer : IDaprSerializer, ITransientDependency
return Encoding.UTF8.GetBytes(_jsonSerializer.Serialize(obj));
}
public string SerializeToString(object obj)
{
return _jsonSerializer.Serialize(obj);
}
public object Deserialize(byte[] value, Type type)
{
return _jsonSerializer.Deserialize(type, Encoding.UTF8.GetString(value));

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

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

2
framework/src/Volo.Abp.Data/Volo/Abp/Data/AbpCommonDbProperties.cs

@ -13,5 +13,5 @@ public static class AbpCommonDbProperties
/// <summary>
/// Default value: null.
/// </summary>
public static string DbSchema { get; set; } = null;
public static string? DbSchema { get; set; } = null;
}

8
framework/src/Volo.Abp.Data/Volo/Abp/Data/AbpDataMigrationEnvironmentExtensions.cs

@ -6,17 +6,17 @@ namespace Volo.Abp.Data;
public static class AbpDataMigrationEnvironmentExtensions
{
public static void AddDataMigrationEnvironment(this AbpApplicationCreationOptions options, AbpDataMigrationEnvironment environment = null)
public static void AddDataMigrationEnvironment(this AbpApplicationCreationOptions options, AbpDataMigrationEnvironment? environment = null)
{
options.Services.AddDataMigrationEnvironment(environment ?? new AbpDataMigrationEnvironment());
}
public static void AddDataMigrationEnvironment(this IServiceCollection services, AbpDataMigrationEnvironment environment = null)
public static void AddDataMigrationEnvironment(this IServiceCollection services, AbpDataMigrationEnvironment? environment = null)
{
services.AddObjectAccessor<AbpDataMigrationEnvironment>(environment ?? new AbpDataMigrationEnvironment());
}
public static AbpDataMigrationEnvironment GetDataMigrationEnvironment(this IServiceCollection services)
public static AbpDataMigrationEnvironment? GetDataMigrationEnvironment(this IServiceCollection services)
{
return services.GetObjectOrNull<AbpDataMigrationEnvironment>();
}
@ -26,7 +26,7 @@ public static class AbpDataMigrationEnvironmentExtensions
return services.GetDataMigrationEnvironment() != null;
}
public static AbpDataMigrationEnvironment GetDataMigrationEnvironment(this IServiceProvider serviceProvider)
public static AbpDataMigrationEnvironment? GetDataMigrationEnvironment(this IServiceProvider serviceProvider)
{
return serviceProvider.GetService<IObjectAccessor<AbpDataMigrationEnvironment>>()?.Value;
}

12
framework/src/Volo.Abp.Data/Volo/Abp/Data/AbpDatabaseInfo.cs

@ -24,4 +24,16 @@ public class AbpDatabaseInfo
DatabaseName = databaseName;
MappedConnections = new HashSet<string>();
}
/// <summary>
/// Shortcut method to add one or multiple connections to the <see cref="MappedConnections"/> collection.
/// </summary>
/// <param name="connectionNames"></param>
public void MapConnection(params string[] connectionNames)
{
foreach (var connectionName in connectionNames)
{
MappedConnections.AddIfNotContains(connectionName);
}
}
}

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

Loading…
Cancel
Save