Browse Source

Merge branch 'dev' into bs5

pull/10355/head
maliming 5 years ago
parent
commit
9af48e7ffb
  1. 2
      .github/workflows/build-and-test.yml
  2. 12
      .github/workflows/cancel-workflow.yml
  3. 2
      Directory.Build.props
  4. 3
      abp_io/AbpIoLocalization/AbpIoLocalization/Account/Localization/Resources/en-GB.json
  5. 3
      abp_io/AbpIoLocalization/AbpIoLocalization/Account/Localization/Resources/en.json
  6. 3
      abp_io/AbpIoLocalization/AbpIoLocalization/Account/Localization/Resources/tr.json
  7. 9
      abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json
  8. 8
      abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/en.json
  9. 15
      abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json
  10. 4
      abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/zh-Hans.json
  11. 5
      common.props
  12. 29
      docs/en/Best-Practices/Entity-Framework-Core-Integration.md
  13. 26
      docs/en/Best-Practices/MongoDB-Integration.md
  14. 13
      docs/en/CLI.md
  15. 46
      docs/en/Community-Articles/2020-08-07-Passwordless-Authentication/POST.md
  16. 8
      docs/en/Dapper.md
  17. 9
      docs/en/Road-Map.md
  18. 67
      docs/en/UI/Angular/How-Replaceable-Components-Work-with-Extensions.md
  19. 276
      docs/en/UI/Angular/Permission-Management-Component-Replacement.md
  20. 2
      docs/en/UI/Angular/Settings.md
  21. 14
      framework/Volo.Abp.sln
  22. 2
      framework/src/Volo.Abp.AspNetCore.Authentication.JwtBearer/Volo.Abp.AspNetCore.Authentication.JwtBearer.csproj
  23. 27
      framework/src/Volo.Abp.AspNetCore.Authentication.OAuth/Properties/launchSettings.json
  24. 3
      framework/src/Volo.Abp.AspNetCore.Authentication.OAuth/Volo.Abp.AspNetCore.Authentication.OAuth.csproj
  25. 2
      framework/src/Volo.Abp.AspNetCore.Authentication.OpenIdConnect/Volo.Abp.AspNetCore.Authentication.OpenIdConnect.csproj
  26. 3
      framework/src/Volo.Abp.AspNetCore.Components.Server.Theming/Volo.Abp.AspNetCore.Components.Server.Theming.csproj
  27. 3
      framework/src/Volo.Abp.AspNetCore.Components.Server/Volo.Abp.AspNetCore.Components.Server.csproj
  28. 2
      framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/Volo.Abp.AspNetCore.Components.Web.Theming.csproj
  29. 2
      framework/src/Volo.Abp.AspNetCore.Components.Web/Volo.Abp.AspNetCore.Components.Web.csproj
  30. 2
      framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/Volo.Abp.AspNetCore.Components.WebAssembly.Theming.csproj
  31. 2
      framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo.Abp.AspNetCore.Components.WebAssembly.csproj
  32. 2
      framework/src/Volo.Abp.AspNetCore.Components/Volo.Abp.AspNetCore.Components.csproj
  33. 2
      framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo.Abp.AspNetCore.MultiTenancy.csproj
  34. 1
      framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/AbpMultiTenancyCookieHelper.cs
  35. 27
      framework/src/Volo.Abp.AspNetCore.Mvc.Client/Properties/launchSettings.json
  36. 3
      framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo.Abp.AspNetCore.Mvc.Client.csproj
  37. 1
      framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ApplicationConfigurationDto.cs
  38. 2
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.csproj
  39. 2
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling.Abstractions/Volo.Abp.AspNetCore.Mvc.UI.Bundling.Abstractions.csproj
  40. 2
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/Volo.Abp.AspNetCore.Mvc.UI.Bundling.csproj
  41. 4
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Pages/Abp/MultiTenancy/AbpTenantAppService.cs
  42. 4
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Pages/Abp/MultiTenancy/AbpTenantController.cs
  43. 4
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Pages/Abp/MultiTenancy/TenantSwitchModal.cshtml.cs
  44. 2
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy.csproj
  45. 2
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Packages/Volo.Abp.AspNetCore.Mvc.UI.Packages.csproj
  46. 6
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Packages/Volo/Abp/AspNetCore/Mvc/UI/Packages/SweetAlert2/Sweetalert2ScriptContributor.cs
  47. 2
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo.csproj
  48. 6
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/Bundling/SharedThemeGlobalScriptContributor.cs
  49. 2
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.csproj
  50. 24
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/sweetalert2/abp-sweetalert2.js
  51. 2
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Widgets/Volo.Abp.AspNetCore.Mvc.UI.Widgets.csproj
  52. 2
      framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo.Abp.AspNetCore.Mvc.UI.csproj
  53. 2
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo.Abp.AspNetCore.Mvc.csproj
  54. 25
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AspNetCoreApiDescriptionModelProvider.cs
  55. 10
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ContentFormatters/AbpRemoteStreamContentModelBinder.cs
  56. 9
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ContentFormatters/RemoteStreamContentOutputFormatter.cs
  57. 13
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Conventions/AbpServiceConvention.cs
  58. 24
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ExceptionHandling/AbpExceptionFilter.cs
  59. 24
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ExceptionHandling/AbpExceptionPageFilter.cs
  60. 7
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Response/AbpNoContentActionFilter.cs
  61. 27
      framework/src/Volo.Abp.AspNetCore.Serilog/Properties/launchSettings.json
  62. 3
      framework/src/Volo.Abp.AspNetCore.Serilog/Volo.Abp.AspNetCore.Serilog.csproj
  63. 27
      framework/src/Volo.Abp.AspNetCore.SignalR/Properties/launchSettings.json
  64. 3
      framework/src/Volo.Abp.AspNetCore.SignalR/Volo.Abp.AspNetCore.SignalR.csproj
  65. 27
      framework/src/Volo.Abp.AspNetCore.TestBase/Properties/launchSettings.json
  66. 3
      framework/src/Volo.Abp.AspNetCore.TestBase/Volo.Abp.AspNetCore.TestBase.csproj
  67. 6
      framework/src/Volo.Abp.AspNetCore.TestBase/Volo/Abp/AspNetCore/TestBase/DynamicProxying/AspNetCoreTestProxyHttpClientFactory.cs
  68. 17
      framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/Http/AbpHttpRequestExtensions.cs
  69. 1
      framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/RequestLocalization/AbpRequestCultureCookieHelper.cs
  70. 27
      framework/src/Volo.Abp.AspNetCore/Properties/launchSettings.json
  71. 3
      framework/src/Volo.Abp.AspNetCore/Volo.Abp.AspNetCore.csproj
  72. 7
      framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/ExceptionHandling/AbpAuthorizationExceptionHandlerOptions.cs
  73. 45
      framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/ExceptionHandling/AbpExceptionHandlingMiddleware.cs
  74. 67
      framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/ExceptionHandling/DefaultAbpAuthorizationExceptionHandler.cs
  75. 11
      framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/ExceptionHandling/IAbpAuthorizationExceptionHandler.cs
  76. 3
      framework/src/Volo.Abp.Auditing.Contracts/FodyWeavers.xml
  77. 30
      framework/src/Volo.Abp.Auditing.Contracts/FodyWeavers.xsd
  78. 21
      framework/src/Volo.Abp.Auditing.Contracts/Volo.Abp.Auditing.Contracts.csproj
  79. 9
      framework/src/Volo.Abp.Auditing.Contracts/Volo/Abp/Auditing/AbpAuditingContractsModule.cs
  80. 0
      framework/src/Volo.Abp.Auditing.Contracts/Volo/Abp/Auditing/AuditedAttribute.cs
  81. 0
      framework/src/Volo.Abp.Auditing.Contracts/Volo/Abp/Auditing/DisableAuditingAttribute.cs
  82. 0
      framework/src/Volo.Abp.Auditing.Contracts/Volo/Abp/Auditing/EntityChangeType.cs
  83. 0
      framework/src/Volo.Abp.Auditing.Contracts/Volo/Abp/Auditing/IAuditedObject.cs
  84. 0
      framework/src/Volo.Abp.Auditing.Contracts/Volo/Abp/Auditing/IAuditingEnabled.cs
  85. 0
      framework/src/Volo.Abp.Auditing.Contracts/Volo/Abp/Auditing/ICreationAuditedObject.cs
  86. 0
      framework/src/Volo.Abp.Auditing.Contracts/Volo/Abp/Auditing/IDeletionAuditedObject.cs
  87. 0
      framework/src/Volo.Abp.Auditing.Contracts/Volo/Abp/Auditing/IFullAuditedObject.cs
  88. 0
      framework/src/Volo.Abp.Auditing.Contracts/Volo/Abp/Auditing/IHasCreationTime.cs
  89. 0
      framework/src/Volo.Abp.Auditing.Contracts/Volo/Abp/Auditing/IHasDeletionTime.cs
  90. 0
      framework/src/Volo.Abp.Auditing.Contracts/Volo/Abp/Auditing/IHasModificationTime.cs
  91. 0
      framework/src/Volo.Abp.Auditing.Contracts/Volo/Abp/Auditing/IMayHaveCreator.cs
  92. 0
      framework/src/Volo.Abp.Auditing.Contracts/Volo/Abp/Auditing/IModificationAuditedObject.cs
  93. 0
      framework/src/Volo.Abp.Auditing.Contracts/Volo/Abp/Auditing/IMustHaveCreator.cs
  94. 1
      framework/src/Volo.Abp.Auditing/Volo.Abp.Auditing.csproj
  95. 3
      framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/AbpAuditingModule.cs
  96. 2
      framework/src/Volo.Abp.Autofac.WebAssembly/Volo.Abp.Autofac.WebAssembly.csproj
  97. 6
      framework/src/Volo.Abp.BackgroundJobs.RabbitMQ/Volo/Abp/BackgroundJobs/RabbitMQ/AbpRabbitMqBackgroundJobOptions.cs
  98. 22
      framework/src/Volo.Abp.BackgroundJobs.RabbitMQ/Volo/Abp/BackgroundJobs/RabbitMQ/JobQueue.cs
  99. 35
      framework/src/Volo.Abp.BackgroundJobs.RabbitMQ/Volo/Abp/BackgroundJobs/RabbitMQ/JobQueueConfiguration.cs
  100. 2
      framework/src/Volo.Abp.BlazoriseUI/Volo.Abp.BlazoriseUI.csproj

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

@ -21,7 +21,7 @@ jobs:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
- uses: actions/setup-dotnet@master - uses: actions/setup-dotnet@master
with: with:
dotnet-version: 5.0.201 dotnet-version: 6.0.100-rc.1.21458.32
- name: Build All - name: Build All
run: .\build-all.ps1 run: .\build-all.ps1

12
.github/workflows/cancel-workflow.yml

@ -0,0 +1,12 @@
name: cancel-workflow
on: [push]
jobs:
cancel:
name: 'Cancel Previous Runs'
runs-on: ubuntu-latest
timeout-minutes: 3
steps:
- uses: styfle/cancel-workflow-action@0.6.0
with:
workflow_id: 10629,1299107,2792859,8268314
access_token: ${{ github.token }}

2
Directory.Build.props

@ -2,7 +2,7 @@
<PropertyGroup> <PropertyGroup>
<!-- All Microsoft packages --> <!-- All Microsoft packages -->
<MicrosoftPackageVersion>5.0.*</MicrosoftPackageVersion> <MicrosoftPackageVersion>6.0.0-rc.*</MicrosoftPackageVersion>
<!-- Microsoft.NET.Test.Sdk https://www.nuget.org/packages/Microsoft.NET.Test.Sdk --> <!-- Microsoft.NET.Test.Sdk https://www.nuget.org/packages/Microsoft.NET.Test.Sdk -->
<MicrosoftNETTestSdkPackageVersion>16.9.1</MicrosoftNETTestSdkPackageVersion> <MicrosoftNETTestSdkPackageVersion>16.9.1</MicrosoftNETTestSdkPackageVersion>

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

@ -9,6 +9,7 @@
"OfficialBlog": "Official blog", "OfficialBlog": "Official blog",
"CommercialHomePage": "Commercial home page", "CommercialHomePage": "Commercial home page",
"CommercialSupportWebSite": "Commercial support web site", "CommercialSupportWebSite": "Commercial support web site",
"CommunityWebSite": "ABP community web site" "CommunityWebSite": "ABP community web site",
"ManageAccount": "My Account | ABP.IO"
} }
} }

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

@ -9,6 +9,7 @@
"OfficialBlog": "Official blog", "OfficialBlog": "Official blog",
"CommercialHomePage": "Commercial home page", "CommercialHomePage": "Commercial home page",
"CommercialSupportWebSite": "Commercial support web site", "CommercialSupportWebSite": "Commercial support web site",
"CommunityWebSite": "ABP community web site" "CommunityWebSite": "ABP community web site",
"ManageAccount": "My Account | ABP.IO"
} }
} }

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

@ -9,6 +9,7 @@
"OfficialBlog": "Resmi blog", "OfficialBlog": "Resmi blog",
"CommercialHomePage": "Kurumsal ana sayfa", "CommercialHomePage": "Kurumsal ana sayfa",
"CommercialSupportWebSite": "Kurumsal destek web sitesi", "CommercialSupportWebSite": "Kurumsal destek web sitesi",
"CommunityWebSite": "ABP topluluk web sitesi" "CommunityWebSite": "ABP topluluk web sitesi",
"ManageAccount": "Hesabım | ABP.IO"
} }
} }

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

@ -303,6 +303,13 @@
"ProductPrice": "Product Price", "ProductPrice": "Product Price",
"AdditionalDeveloper": "Additional developer", "AdditionalDeveloper": "Additional developer",
"ThisPaymentHasBeenAlreadyUsed": "This payment has been already used", "ThisPaymentHasBeenAlreadyUsed": "This payment has been already used",
"PaymentTimeCannotBeFutureTime": "Payment time cannot be future time" "PaymentTimeCannotBeFutureTime": "Payment time cannot be a future time!",
"SaveAndDownload": "Save and Download",
"BillingInfo": "Billing Info",
"GenerateInvoice": "Create Invoice",
"DeleteInvoice" : "Delete Invoice",
"SuccessfullyDeleted": "Successfully deleted!",
"PaymentStateSetTo" : "Payment state set to {0}",
"ChangeState": "Change State"
} }
} }

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

@ -35,6 +35,10 @@
"Support": "Support", "Support": "Support",
"FreeDDDBook": "Free DDD E-book", "FreeDDDBook": "Free DDD E-book",
"New": "New", "New": "New",
"Volo.AbpIo.Domain:020005": "License extend year can not be lower than {MinExtendLicenseYear} year and greater than {MaxExtendLicenseYear} years " "Volo.AbpIo.Domain:020005": "License extend year can not be lower than {MinExtendLicenseYear} year(s) and greater than {MaxExtendLicenseYear} year(s) ",
"TrialLicensePeriodHasExpired": "Your trial license period expired {0} days ago.",
"TrialLicensePeriodWillExpire": "Your trial license period will be expired in {0} days.",
"TrialLicensePeriodExpireToday": "Your trial license period will be expired today.",
"PurchaseNow": "Purchase Now!"
} }
} }

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

@ -377,6 +377,17 @@
"AddressValidationMessage": "Address is too long!", "AddressValidationMessage": "Address is too long!",
"TaxNoValidationMessage": "TAX/VAT No is too long!", "TaxNoValidationMessage": "TAX/VAT No is too long!",
"NotesValidationMessage": "Notes field is too long!", "NotesValidationMessage": "Notes field is too long!",
"CheckYourBillingInfo": "You can create your invoice only once! Check your billing info before creating your invoice." "CheckYourBillingInfo": "You can create your invoice only once! Check your billing information before creating your invoice.",
"Volo.AbpIo.Commercial:030000": "You already used your trial period.",
"Volo.AbpIo.Commercial:030001": "This organization name already exists.",
"StartYourFreeTrial": "Start your free trial",
"TrialLicenseModelInvalidErrorMessage": "One of the following fields are invalid: Country Name, Company Size, Industry or Purpose Of Usage.",
"Trial": "Trial",
"Purchased": "Purchased",
"PurchaseLicense": "Purchase License",
"PurchaseTrialLicenseMessage": "Your license expiration date is {0}. <br> If you want to continue using the projects you created during your free trial period, you need to change the license keys in your <code>appsettings.secrets.json</code> files. Here is your license key:",
"TrialLicenseExpireMessage": "You are using the trial license and your trial license will expire on {0}.",
"TryForFree": "Try For Free",
"TrialLicenseExpiredInfo": "Your trial license period has expired!"
} }
} }

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

@ -218,7 +218,7 @@
"LicenseURL": "许可URL", "LicenseURL": "许可URL",
"License": "许可", "License": "许可",
"ProjectCreationSuccessMessage": "你的项目创建成功", "ProjectCreationSuccessMessage": "你的项目创建成功",
"HowToRunSolution": "如何运行你的解决方案n?", "HowToRunSolution": "如何运行你的解决方案?",
"GettingStartedMessage": "查看入门文档了解如何配置和运行你的解决方案.", "GettingStartedMessage": "查看入门文档了解如何配置和运行你的解决方案.",
"WebAppDevTutorial": "Web App 开发教程", "WebAppDevTutorial": "Web App 开发教程",
"WebAppDevTutorialMessage": "查看web应用程序开发教程文档,一步一步的开发示例.", "WebAppDevTutorialMessage": "查看web应用程序开发教程文档,一步一步的开发示例.",
@ -231,4 +231,4 @@
"DatabaseProviderDocumentationMessage": "查看{0}文档来学习用数据库层开发.", "DatabaseProviderDocumentationMessage": "查看{0}文档来学习用数据库层开发.",
"ABPCommercialExplanationMessage": "ABP商业版为ABP框架提供了高级模块,主题,工具和支持." "ABPCommercialExplanationMessage": "ABP商业版为ABP框架提供了高级模块,主题,工具和支持."
} }
} }

5
common.props

@ -28,4 +28,9 @@
</None> </None>
</ItemGroup> </ItemGroup>
<ItemGroup Condition="$(AssemblyName.EndsWith('HttpApi.Client'))">
<EmbeddedResource Include="**\*generate-proxy.json" />
<Content Remove="**\*generate-proxy.json" />
</ItemGroup>
</Project> </Project>

29
docs/en/Best-Practices/Entity-Framework-Core-Integration.md

@ -66,12 +66,7 @@ public static string Schema { get; set; } = AbpIdentityConsts.DefaultDbSchema;
protected override void OnModelCreating(ModelBuilder builder) protected override void OnModelCreating(ModelBuilder builder)
{ {
base.OnModelCreating(builder); base.OnModelCreating(builder);
builder.ConfigureIdentity();
builder.ConfigureIdentity(options =>
{
options.TablePrefix = TablePrefix;
options.Schema = Schema;
});
} }
```` ````
@ -80,25 +75,20 @@ protected override void OnModelCreating(ModelBuilder builder)
````C# ````C#
public static class IdentityDbContextModelBuilderExtensions public static class IdentityDbContextModelBuilderExtensions
{ {
public static void ConfigureIdentity( public static void ConfigureIdentity([NotNull] this ModelBuilder builder)
[NotNull] this ModelBuilder builder,
Action<IdentityModelBuilderConfigurationOptions> optionsAction = null)
{ {
Check.NotNull(builder, nameof(builder)); Check.NotNull(builder, nameof(builder));
var options = new IdentityModelBuilderConfigurationOptions();
optionsAction?.Invoke(options);
builder.Entity<IdentityUser>(b => builder.Entity<IdentityUser>(b =>
{ {
b.ToTable(options.TablePrefix + "Users", options.Schema); b.ToTable(AbpIdentityDbProperties.DbTablePrefix + "Users", AbpIdentityDbProperties.DbSchema);
b.ConfigureByConvention(); b.ConfigureByConvention();
//code omitted for brevity //code omitted for brevity
}); });
builder.Entity<IdentityUserClaim>(b => builder.Entity<IdentityUserClaim>(b =>
{ {
b.ToTable(options.TablePrefix + "UserClaims", options.Schema); b.ToTable(AbpIdentityDbProperties.DbTablePrefix + "UserClaims", AbpIdentityDbProperties.DbSchema);
b.ConfigureByConvention(); b.ConfigureByConvention();
//code omitted for brevity //code omitted for brevity
}); });
@ -109,17 +99,6 @@ public static class IdentityDbContextModelBuilderExtensions
```` ````
* **Do** call `b.ConfigureByConvention();` for each entity mapping (as shown above). * **Do** call `b.ConfigureByConvention();` for each entity mapping (as shown above).
* **Do** create a **configuration options** class by inheriting from the `AbpModelBuilderConfigurationOptions`. Example:
````C#
public class IdentityModelBuilderConfigurationOptions : AbpModelBuilderConfigurationOptions
{
public IdentityModelBuilderConfigurationOptions()
: base(AbpIdentityConsts.DefaultDbTablePrefix, AbpIdentityConsts.DefaultDbSchema)
{
}
}
````
### Repository Implementation ### Repository Implementation

26
docs/en/Best-Practices/MongoDB-Integration.md

@ -55,10 +55,7 @@ protected override void CreateModel(IMongoModelBuilder modelBuilder)
{ {
base.CreateModel(modelBuilder); base.CreateModel(modelBuilder);
modelBuilder.ConfigureIdentity(options => modelBuilder.ConfigureIdentity();
{
options.CollectionPrefix = CollectionPrefix;
});
} }
``` ```
@ -73,36 +70,19 @@ public static class AbpIdentityMongoDbContextExtensions
{ {
Check.NotNull(builder, nameof(builder)); Check.NotNull(builder, nameof(builder));
var options = new IdentityMongoModelBuilderConfigurationOptions();
optionsAction?.Invoke(options);
builder.Entity<IdentityUser>(b => builder.Entity<IdentityUser>(b =>
{ {
b.CollectionName = options.CollectionPrefix + "Users"; b.CollectionName = AbpIdentityDbProperties.DbTablePrefix + "Users";
}); });
builder.Entity<IdentityRole>(b => builder.Entity<IdentityRole>(b =>
{ {
b.CollectionName = options.CollectionPrefix + "Roles"; b.CollectionName = AbpIdentityDbProperties.DbTablePrefix + "Roles";
}); });
} }
} }
``` ```
- **Do** create a **configuration options** class by inheriting from the `AbpMongoModelBuilderConfigurationOptions`. Example:
```c#
public class IdentityMongoModelBuilderConfigurationOptions
: AbpMongoModelBuilderConfigurationOptions
{
public IdentityMongoModelBuilderConfigurationOptions()
: base(AbpIdentityConsts.DefaultDbTablePrefix)
{
}
}
```
### Repository Implementation ### Repository Implementation
- **Do** **inherit** the repository from the `MongoDbRepository<TMongoDbContext, TEntity, TKey>` class and implement the corresponding repository interface. Example: - **Do** **inherit** the repository from the `MongoDbRepository<TMongoDbContext, TEntity, TKey>` class and implement the corresponding repository interface. Example:

13
docs/en/CLI.md

@ -161,7 +161,7 @@ abp add-package <package-name> [options]
Example: Example:
```` ````
abp add-package Volo.Abp.MongoDB abp add-package Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic
```` ````
* This example adds the Volo.Abp.MongoDB package to the project. * This example adds the Volo.Abp.MongoDB package to the project.
@ -170,7 +170,14 @@ abp add-package Volo.Abp.MongoDB
* `--project` or `-p`: Specifies the project (.csproj) file path. If not specified, CLI tries to find a .csproj file in the current directory. * `--project` or `-p`: Specifies the project (.csproj) file path. If not specified, CLI tries to find a .csproj file in the current directory.
* `--with-source-code`: Downloads the source code of the package to your solution folder and uses local project references instead of NuGet/NPM packages. * `--with-source-code`: Downloads the source code of the package to your solution folder and uses local project references instead of NuGet/NPM packages.
* `--add-to-solution-file`: Adds the downloaded package to your solution file, so you will also see the package when you open the solution on a IDE. (only available when `--with-source-code` is True.) * `--add-to-solution-file`: Adds the downloaded package to your solution file, so you will also see the package when you open the solution on a IDE. (only available when `--with-source-code` is True)
> Currently only the source code of the basic theme packages([MVC](https://docs.abp.io/en/abp/latest/UI/AspNetCore/Basic-Theme) and [Blazor](https://docs.abp.io/en/abp/latest/UI/Blazor/Basic-Theme)) can be downloaded.
> - Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic
> - Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme
> - Volo.Abp.AspNetCore.Components.Web.BasicTheme
> - Volo.Abp.AspNetCore.Components.Server.BasicTheme
### add-module ### add-module
@ -454,4 +461,4 @@ abp install-libs [options]
## See Also ## See Also
* [Examples for the new command](CLI-New-Command-Samples.md) * [Examples for the new command](CLI-New-Command-Samples.md)

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

@ -194,16 +194,11 @@ We implemented token generation infrastructure, now it's time validate the token
```csharp ```csharp
using System; using System;
using System.Collections.Generic;
using System.Security.Claims;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Volo.Abp.AspNetCore.Mvc; using Volo.Abp.AspNetCore.Mvc;
using Volo.Abp.Identity; using Volo.Abp.Identity;
using Volo.Abp.Security.Claims; using Volo.Abp.Identity.AspNetCore;
using Volo.Abp.Users;
namespace PasswordlessAuthentication.Web.Controllers namespace PasswordlessAuthentication.Web.Controllers
{ {
@ -211,9 +206,12 @@ namespace PasswordlessAuthentication.Web.Controllers
{ {
protected IdentityUserManager UserManager { get; } protected IdentityUserManager UserManager { get; }
public PasswordlessController(IdentityUserManager userManager) protected AbpSignInManager SignInManager { get; }
public PasswordlessController(IdentityUserManager userManager, AbpSignInManager signInManager)
{ {
UserManager = userManager; UserManager = userManager;
SignInManager = signInManager;
} }
public virtual async Task<IActionResult> Login(string token, string userId) public virtual async Task<IActionResult> Login(string token, string userId)
@ -228,45 +226,15 @@ namespace PasswordlessAuthentication.Web.Controllers
await UserManager.UpdateSecurityStampAsync(user); await UserManager.UpdateSecurityStampAsync(user);
var roles = await UserManager.GetRolesAsync(user); await SignInManager.SignInAsync(user, isPersistent: false);
var principal = new ClaimsPrincipal(
new ClaimsIdentity(CreateClaims(user, roles), IdentityConstants.ApplicationScheme)
);
await HttpContext.SignInAsync(IdentityConstants.ApplicationScheme, principal);
return Redirect("/"); return Redirect("/");
} }
private static IEnumerable<Claim> CreateClaims(IUser user, IEnumerable<string> roles)
{
var claims = new List<Claim>
{
new Claim("sub", user.Id.ToString()),
new Claim(AbpClaimTypes.UserId, user.Id.ToString()),
new Claim(AbpClaimTypes.Email, user.Email),
new Claim(AbpClaimTypes.UserName, user.UserName),
new Claim(AbpClaimTypes.EmailVerified, user.EmailConfirmed.ToString().ToLower()),
};
if (!string.IsNullOrWhiteSpace(user.PhoneNumber))
{
claims.Add(new Claim(AbpClaimTypes.PhoneNumber, user.PhoneNumber));
}
foreach (var role in roles)
{
claims.Add(new Claim(AbpClaimTypes.Role, role));
}
return claims;
}
} }
} }
``` ```
We created an endpoint for `/Passwordless/Login` that gets the token and the user Id. In this action, we find the user via repository and validate the token via `UserManager.VerifyUserTokenAsync()` method. If it's valid, we create claims of the user then call `HttpContext.SignInAsync` to be able to create an encrypted cookie and add it to the current response. Finally we redirect the page to the root URL. We created an endpoint for `/Passwordless/Login` that gets the token and the user Id. In this action, we find the user via repository and validate the token via `UserManager.VerifyUserTokenAsync()` method. If it's valid, we call `SignInManager.SignInAsync` to be able to create an encrypted cookie and add it to the current response. Finally we redirect the page to the root URL.
That's all! We created a passwordless login with 7 steps. That's all! We created a passwordless login with 7 steps.

8
docs/en/Dapper.md

@ -53,14 +53,16 @@ public class PersonDapperRepository : DapperRepository<MyAppDbContext>, ITransie
public virtual async Task<List<string>> GetAllPersonNames() public virtual async Task<List<string>> GetAllPersonNames()
{ {
return (await DbConnection.QueryAsync<string>("select Name from People", transaction: DbTransaction)) var dbConnection = await GetDbConnectionAsync();
return (await dbConnection.QueryAsync<string>("select Name from People", transaction: await GetDbTransactionAsync()))
.ToList(); .ToList();
} }
public virtual async Task<int> UpdatePersonNames(string name) public virtual async Task<int> UpdatePersonNames(string name)
{ {
return await DbConnection.ExecuteAsync("update People set Name = @NewName", new { NewName = name }, var dbConnection = await GetDbConnectionAsync();
DbTransaction); return await dbConnection.ExecuteAsync("update People set Name = @NewName", new { NewName = name },
await GetDbTransactionAsync());
} }
} }
``` ```

9
docs/en/Road-Map.md

@ -10,12 +10,9 @@ This version will focus on the following works:
* Upgrading to .NET 6.0 ([#9004](https://github.com/abpframework/abp/issues/9004)) * Upgrading to .NET 6.0 ([#9004](https://github.com/abpframework/abp/issues/9004))
* Upgrading to Bootstrap 5.x ([#8922](https://github.com/abpframework/abp/issues/8922)) * Upgrading to Bootstrap 5.x ([#8922](https://github.com/abpframework/abp/issues/8922))
* Alternative to IdentityServer4 ([#7221](https://github.com/abpframework/abp/issues/7221)) * C# and JavaScript Static Client Proxy Generation ([#9864](https://github.com/abpframework/abp/issues/9864))
* Revisit the microservice demo solution ([#8385](https://github.com/abpframework/abp/issues/8385)) * Revisit the microservice demo solution ([#8385](https://github.com/abpframework/abp/issues/8385))
* Dapr integration ([#2183](https://github.com/abpframework/abp/issues/2183))
* Publishing distributed events as transactional ([#6126](https://github.com/abpframework/abp/issues/6126)) * Publishing distributed events as transactional ([#6126](https://github.com/abpframework/abp/issues/6126))
* Resource based authorization system ([#236](https://github.com/abpframework/abp/issues/236))
* API Versioning system: finalize & document ([#497](https://github.com/abpframework/abp/issues/497))
* Performance optimizations; Enabling .NET Trimming, using source generators and reducing reflection, etc. * Performance optimizations; Enabling .NET Trimming, using source generators and reducing reflection, etc.
* Improving the abp.io platform and work more on contents and documents * Improving the abp.io platform and work more on contents and documents
@ -27,6 +24,10 @@ The *Next Versions* section above shows the main focus of the planned versions.
Here, a list of major items in the backlog we are considering to work on in the next versions. Here, a list of major items in the backlog we are considering to work on in the next versions.
* ([#497](https://github.com/abpframework/abp/issues/497)) API Versioning system: finalize & document
* ([#7221](https://github.com/abpframework/abp/issues/7221)) Alternative to IdentityServer4
* ([#2183](https://github.com/abpframework/abp/issues/2183)) Dapr integration
* ([#236](https://github.com/abpframework/abp/issues/236)) Resource based authorization system
* [#2882](https://github.com/abpframework/abp/issues/2882) / Providing a gRPC integration infrastructure (while it is [already possible](https://github.com/abpframework/abp-samples/tree/master/GrpcDemo) to create or consume gRPC endpoints for your application, we plan to create endpoints for the [standard application modules](https://docs.abp.io/en/abp/latest/Modules/Index)) * [#2882](https://github.com/abpframework/abp/issues/2882) / Providing a gRPC integration infrastructure (while it is [already possible](https://github.com/abpframework/abp-samples/tree/master/GrpcDemo) to create or consume gRPC endpoints for your application, we plan to create endpoints for the [standard application modules](https://docs.abp.io/en/abp/latest/Modules/Index))
* [#1754](https://github.com/abpframework/abp/issues/1754) / Multi-lingual entities * [#1754](https://github.com/abpframework/abp/issues/1754) / Multi-lingual entities
* [#57](https://github.com/abpframework/abp/issues/57) / Built-in CQRS infrastructure * [#57](https://github.com/abpframework/abp/issues/57) / Built-in CQRS infrastructure

67
docs/en/UI/Angular/How-Replaceable-Components-Work-with-Extensions.md

@ -17,30 +17,18 @@ yarn ng generate component my-roles/my-roles --flat --export
Open the generated `src/app/my-roles/my-roles.component.ts` file and replace its content with the following: Open the generated `src/app/my-roles/my-roles.component.ts` file and replace its content with the following:
```js ```js
import { ListService, PagedAndSortedResultRequestDto } from '@abp/ng.core'; import { ListService, PagedAndSortedResultRequestDto, PagedResultDto } from '@abp/ng.core';
import { import { eIdentityComponents, IdentityRoleDto, IdentityRoleService, RolesComponent } from '@abp/ng.identity';
CreateRole,
DeleteRole,
eIdentityComponents,
GetRoleById,
GetRoles,
IdentityRoleDto,
IdentityState,
RolesComponent,
UpdateRole,
} from '@abp/ng.identity';
import { ePermissionManagementComponents } from '@abp/ng.permission-management'; import { ePermissionManagementComponents } from '@abp/ng.permission-management';
import { Confirmation, ConfirmationService } from '@abp/ng.theme.shared'; import { Confirmation, ConfirmationService } from '@abp/ng.theme.shared';
import { import {
EXTENSIONS_IDENTIFIER, EXTENSIONS_IDENTIFIER,
FormPropData, FormPropData,
generateFormFromProps, generateFormFromProps
} from '@abp/ng.theme.shared/extensions'; } from '@abp/ng.theme.shared/extensions';
import { Component, Injector, OnInit } from '@angular/core'; import { Component, Injector, OnInit } from '@angular/core';
import { FormGroup } from '@angular/forms'; import { FormGroup } from '@angular/forms';
import { Select, Store } from '@ngxs/store'; import { finalize } from 'rxjs/operators';
import { Observable } from 'rxjs';
import { finalize, pluck } from 'rxjs/operators';
@Component({ @Component({
selector: 'app-my-roles', selector: 'app-my-roles',
@ -51,15 +39,14 @@ import { finalize, pluck } from 'rxjs/operators';
provide: EXTENSIONS_IDENTIFIER, provide: EXTENSIONS_IDENTIFIER,
useValue: eIdentityComponents.Roles, useValue: eIdentityComponents.Roles,
}, },
{ provide: RolesComponent, useExisting: MyRolesComponent }, {
provide: RolesComponent,
useExisting: MyRolesComponent
}
], ],
}) })
export class MyRolesComponent implements OnInit { export class MyRolesComponent implements OnInit {
@Select(IdentityState.getRoles) data: PagedResultDto<IdentityRoleDto> = { items: [], totalCount: 0 };
data$: Observable<IdentityRoleDto[]>;
@Select(IdentityState.getRolesTotalCount)
totalCount$: Observable<number>;
form: FormGroup; form: FormGroup;
@ -82,8 +69,8 @@ export class MyRolesComponent implements OnInit {
constructor( constructor(
public readonly list: ListService<PagedAndSortedResultRequestDto>, public readonly list: ListService<PagedAndSortedResultRequestDto>,
protected confirmationService: ConfirmationService, protected confirmationService: ConfirmationService,
protected store: Store, protected injector: Injector,
protected injector: Injector protected service: IdentityRoleService,
) {} ) {}
ngOnInit() { ngOnInit() {
@ -106,25 +93,21 @@ export class MyRolesComponent implements OnInit {
} }
edit(id: string) { edit(id: string) {
this.store this.service.get(id).subscribe(res => {
.dispatch(new GetRoleById(id)) this.selected = res;
.pipe(pluck('IdentityState', 'selectedRole')) this.openModal();
.subscribe(selectedRole => { });
this.selected = selectedRole;
this.openModal();
});
} }
save() { save() {
if (!this.form.valid) return; if (!this.form.valid) return;
this.modalBusy = true; this.modalBusy = true;
this.store const { id } = this.selected;
.dispatch( (id
this.selected.id ? this.service.update(id, { ...this.selected, ...this.form.value })
? new UpdateRole({ ...this.selected, ...this.form.value, id: this.selected.id }) : this.service.create(this.form.value)
: new CreateRole(this.form.value) )
)
.pipe(finalize(() => (this.modalBusy = false))) .pipe(finalize(() => (this.modalBusy = false)))
.subscribe(() => { .subscribe(() => {
this.isModalVisible = false; this.isModalVisible = false;
@ -139,13 +122,13 @@ export class MyRolesComponent implements OnInit {
}) })
.subscribe((status: Confirmation.Status) => { .subscribe((status: Confirmation.Status) => {
if (status === Confirmation.Status.confirm) { if (status === Confirmation.Status.confirm) {
this.store.dispatch(new DeleteRole(id)).subscribe(() => this.list.get()); this.service.delete(id).subscribe(() => this.list.get());
} }
}); });
} }
private hookToQuery() { private hookToQuery() {
this.list.hookToQuery(query => this.store.dispatch(new GetRoles(query))).subscribe(); this.list.hookToQuery(query => this.service.getList(query)).subscribe(res => (this.data = res));
} }
openPermissionsModal(providerKey: string) { openPermissionsModal(providerKey: string) {
@ -189,15 +172,15 @@ Open the generated `src/app/my-role/my-role.component.html` file and replace its
<h5 class="card-title">My Roles</h5> <h5 class="card-title">My Roles</h5>
</div> </div>
<div class="text-right col col-md-6"> <div class="text-right col col-md-6">
<abp-page-toolbar [record]="data$ | async"></abp-page-toolbar> <abp-page-toolbar [record]="data.items"></abp-page-toolbar>
</div> </div>
</div> </div>
</div> </div>
<div class="card-body"> <div class="card-body">
<abp-extensible-table <abp-extensible-table
[data]="data$ | async" [data]="data.items"
[recordsTotal]="totalCount$ | async" [recordsTotal]="data.totalCount"
[list]="list" [list]="list"
></abp-extensible-table> ></abp-extensible-table>
</div> </div>

276
docs/en/UI/Angular/Permission-Management-Component-Replacement.md

@ -5,37 +5,27 @@
Run the following command in `angular` folder to create a new component called `PermissionManagementComponent`. Run the following command in `angular` folder to create a new component called `PermissionManagementComponent`.
```bash ```bash
yarn ng generate component permission-management --entryComponent --inlineStyle yarn ng generate component permission-management --inlineStyle
# You don't need the --entryComponent option in Angular 9
``` ```
Open the generated `permission-management.component.ts` in `src/app/permission-management` folder and replace the content with the following: Open the generated `permission-management.component.ts` in `src/app/permission-management` folder and replace the content with the following:
```js ```js
import { ConfigStateService, CurrentUserDto, ReplaceableComponents } from '@abp/ng.core';
import {
GetPermissionListResultDto,
PermissionGrantInfoDto, PermissionGroupDto, PermissionManagement, PermissionsService, ProviderInfoDto, UpdatePermissionDto
} from '@abp/ng.permission-management';
import { LocaleDirection } from '@abp/ng.theme.shared';
import { import {
Component, Component,
EventEmitter, EventEmitter, Inject, Input, Optional, Output, TrackByFunction
Input,
Output,
Renderer2,
TrackByFunction,
Inject,
Optional,
} from '@angular/core'; } from '@angular/core';
import { ReplaceableComponents } from '@abp/ng.core'; import { of } from 'rxjs';
import { Select, Store } from '@ngxs/store'; import { finalize, switchMap, tap } from 'rxjs/operators';
import { Observable } from 'rxjs';
import { finalize, map, pluck, take, tap } from 'rxjs/operators';
import {
GetPermissions,
UpdatePermissions,
PermissionManagement,
PermissionManagementState,
} from '@abp/ng.permission-management';
type PermissionWithMargin = PermissionManagement.Permission & { type PermissionWithStyle = PermissionGrantInfoDto & {
margin: number; style: string;
}; };
@Component({ @Component({
@ -52,8 +42,8 @@ type PermissionWithMargin = PermissionManagement.Permission & {
}) })
export class PermissionManagementComponent export class PermissionManagementComponent
implements implements
PermissionManagement.PermissionManagementComponentInputs, PermissionManagement.PermissionManagementComponentInputs,
PermissionManagement.PermissionManagementComponentOutputs { PermissionManagement.PermissionManagementComponentOutputs {
protected _providerName: string; protected _providerName: string;
@Input() @Input()
get providerName(): string { get providerName(): string {
@ -115,15 +105,11 @@ export class PermissionManagementComponent
@Output() readonly visibleChange = new EventEmitter<boolean>(); @Output() readonly visibleChange = new EventEmitter<boolean>();
@Select(PermissionManagementState.getPermissionGroups) data: GetPermissionListResultDto = { groups: [], entityDisplayName: null };
groups$: Observable<PermissionManagement.Group[]>;
@Select(PermissionManagementState.getEntityDisplayName) selectedGroup: PermissionGroupDto;
entityName$: Observable<string>;
selectedGroup: PermissionManagement.Group; permissions: PermissionGrantInfoDto[] = [];
permissions: PermissionManagement.Permission[] = [];
selectThisTab = false; selectThisTab = false;
@ -131,25 +117,26 @@ export class PermissionManagementComponent
modalBusy = false; modalBusy = false;
trackByFn: TrackByFunction<PermissionManagement.Group> = (_, item) => item.name; trackByFn: TrackByFunction<PermissionGroupDto> = (_, item) => item.name;
get selectedGroupPermissions$(): Observable<PermissionWithMargin[]> { get selectedGroupPermissions(): PermissionWithStyle[] {
return this.groups$.pipe( if (!this.selectedGroup) return [];
map((groups) =>
this.selectedGroup const margin = `margin-${
? groups.find((group) => group.name === this.selectedGroup.name).permissions (document.body.dir as LocaleDirection) === 'rtl' ? 'right' : 'left'
: [] }.px`;
),
map<PermissionManagement.Permission[], PermissionWithMargin[]>((permissions) => const permissions = this.data.groups.find(
permissions.map( group => group.name === this.selectedGroup.name,
(permission) => ).permissions;
(({
...permission, return permissions.map(
margin: findMargin(permissions, permission), permission =>
isGranted: this.permissions.find((per) => per.name === permission.name).isGranted, ({
} as any) as PermissionWithMargin) ...permission,
) style: { [margin]: findMargin(permissions, permission) },
) isGranted: this.permissions.find(per => per.name === permission.name).isGranted,
} as unknown as PermissionWithStyle),
); );
} }
@ -166,21 +153,22 @@ export class PermissionManagementComponent
PermissionManagement.PermissionManagementComponentInputs, PermissionManagement.PermissionManagementComponentInputs,
PermissionManagement.PermissionManagementComponentOutputs PermissionManagement.PermissionManagementComponentOutputs
>, >,
private store: Store private service: PermissionsService,
private configState: ConfigStateService
) {} ) {}
getChecked(name: string) { getChecked(name: string) {
return (this.permissions.find((per) => per.name === name) || { isGranted: false }).isGranted; return (this.permissions.find(per => per.name === name) || { isGranted: false }).isGranted;
} }
isGrantedByOtherProviderName(grantedProviders: PermissionManagement.GrantedProvider[]): boolean { isGrantedByOtherProviderName(grantedProviders: ProviderInfoDto[]): boolean {
if (grantedProviders.length) { if (grantedProviders.length) {
return grantedProviders.findIndex((p) => p.providerName !== this.providerName) > -1; return grantedProviders.findIndex(p => p.providerName !== this.providerName) > -1;
} }
return false; return false;
} }
onClickCheckbox(clickedPermission: PermissionManagement.Permission, value) { onClickCheckbox(clickedPermission: PermissionGrantInfoDto, value) {
if ( if (
clickedPermission.isGranted && clickedPermission.isGranted &&
this.isGrantedByOtherProviderName(clickedPermission.grantedProviders) this.isGrantedByOtherProviderName(clickedPermission.grantedProviders)
@ -188,7 +176,7 @@ export class PermissionManagementComponent
return; return;
setTimeout(() => { setTimeout(() => {
this.permissions = this.permissions.map((per) => { this.permissions = this.permissions.map(per => {
if (clickedPermission.name === per.name) { if (clickedPermission.name === per.name) {
return { ...per, isGranted: !per.isGranted }; return { ...per, isGranted: !per.isGranted };
} else if (clickedPermission.name === per.parentName && clickedPermission.isGranted) { } else if (clickedPermission.name === per.parentName && clickedPermission.isGranted) {
@ -206,24 +194,22 @@ export class PermissionManagementComponent
} }
setTabCheckboxState() { setTabCheckboxState() {
this.selectedGroupPermissions$.pipe(take(1)).subscribe((permissions) => { const selectedPermissions = this.selectedGroupPermissions.filter(per => per.isGranted);
const selectedPermissions = permissions.filter((per) => per.isGranted); const element = document.querySelector('#select-all-in-this-tabs') as any;
const element = document.querySelector('#select-all-in-this-tabs') as any;
if (selectedPermissions.length === this.selectedGroupPermissions.length) {
if (selectedPermissions.length === permissions.length) { element.indeterminate = false;
element.indeterminate = false; this.selectThisTab = true;
this.selectThisTab = true; } else if (selectedPermissions.length === 0) {
} else if (selectedPermissions.length === 0) { element.indeterminate = false;
element.indeterminate = false; this.selectThisTab = false;
this.selectThisTab = false; } else {
} else { element.indeterminate = true;
element.indeterminate = true; }
}
});
} }
setGrantCheckboxState() { setGrantCheckboxState() {
const selectedAllPermissions = this.permissions.filter((per) => per.isGranted); const selectedAllPermissions = this.permissions.filter(per => per.isGranted);
const checkboxElement = document.querySelector('#select-all-in-all-tabs') as any; const checkboxElement = document.querySelector('#select-all-in-all-tabs') as any;
if (selectedAllPermissions.length === this.permissions.length) { if (selectedAllPermissions.length === this.permissions.length) {
@ -238,26 +224,24 @@ export class PermissionManagementComponent
} }
onClickSelectThisTab() { onClickSelectThisTab() {
this.selectedGroupPermissions$.pipe(take(1)).subscribe((permissions) => { this.selectedGroupPermissions.forEach(permission => {
permissions.forEach((permission) => { if (permission.isGranted && this.isGrantedByOtherProviderName(permission.grantedProviders))
if (permission.isGranted && this.isGrantedByOtherProviderName(permission.grantedProviders)) return;
return;
const index = this.permissions.findIndex(per => per.name === permission.name);
const index = this.permissions.findIndex((per) => per.name === permission.name);
this.permissions = [
this.permissions = [ ...this.permissions.slice(0, index),
...this.permissions.slice(0, index), { ...this.permissions[index], isGranted: !this.selectThisTab },
{ ...this.permissions[index], isGranted: !this.selectThisTab }, ...this.permissions.slice(index + 1),
...this.permissions.slice(index + 1), ];
];
});
}); });
this.setGrantCheckboxState(); this.setGrantCheckboxState();
} }
onClickSelectAll() { onClickSelectAll() {
this.permissions = this.permissions.map((permission) => ({ this.permissions = this.permissions.map(permission => ({
...permission, ...permission,
isGranted: isGranted:
this.isGrantedByOtherProviderName(permission.grantedProviders) || !this.selectAllTab, this.isGrantedByOtherProviderName(permission.grantedProviders) || !this.selectAllTab,
@ -266,43 +250,41 @@ export class PermissionManagementComponent
this.selectThisTab = !this.selectAllTab; this.selectThisTab = !this.selectAllTab;
} }
onChangeGroup(group: PermissionManagement.Group) { onChangeGroup(group: PermissionGroupDto) {
this.selectedGroup = group; this.selectedGroup = group;
this.setTabCheckboxState(); this.setTabCheckboxState();
} }
submit() { submit() {
this.modalBusy = true; const unchangedPermissions = getPermissions(this.data.groups);
const unchangedPermissions = getPermissions(
this.store.selectSnapshot(PermissionManagementState.getPermissionGroups)
);
const changedPermissions: PermissionManagement.MinimumPermission[] = this.permissions const changedPermissions: UpdatePermissionDto[] = this.permissions
.filter((per) => .filter(per =>
unchangedPermissions.find((unchanged) => unchanged.name === per.name).isGranted === unchangedPermissions.find(unchanged => unchanged.name === per.name).isGranted ===
per.isGranted per.isGranted
? false ? false
: true : true,
) )
.map(({ name, isGranted }) => ({ name, isGranted })); .map(({ name, isGranted }) => ({ name, isGranted }));
if (changedPermissions.length) { if (!changedPermissions.length) {
this.store
.dispatch(
new UpdatePermissions({
providerKey: this.providerKey,
providerName: this.providerName,
permissions: changedPermissions,
})
)
.pipe(finalize(() => (this.modalBusy = false)))
.subscribe(() => {
this.visible = false;
});
} else {
this.modalBusy = false;
this.visible = false; this.visible = false;
return;
} }
this.modalBusy = true;
this.service
.update(this.providerName, this.providerKey, { permissions: changedPermissions })
.pipe(
switchMap(() =>
this.shouldFetchAppConfig() ? this.configState.refreshAppState() : of(null),
),
finalize(() => (this.modalBusy = false)),
)
.subscribe(() => {
this.visible = false;
});
} }
openModal() { openModal() {
@ -310,20 +292,13 @@ export class PermissionManagementComponent
throw new Error('Provider Key and Provider Name are required.'); throw new Error('Provider Key and Provider Name are required.');
} }
return this.store return this.service.get(this.providerName, this.providerKey).pipe(
.dispatch( tap((permissionRes: GetPermissionListResultDto) => {
new GetPermissions({ this.data = permissionRes;
providerKey: this.providerKey, this.selectedGroup = permissionRes.groups[0];
providerName: this.providerName, this.permissions = getPermissions(permissionRes.groups);
}) }),
) );
.pipe(
pluck('PermissionManagementState', 'permissionRes'),
tap((permissionRes: PermissionManagement.Response) => {
this.selectedGroup = permissionRes.groups[0];
this.permissions = getPermissions(permissionRes.groups);
})
);
} }
initModal() { initModal() {
@ -331,6 +306,13 @@ export class PermissionManagementComponent
this.setGrantCheckboxState(); this.setGrantCheckboxState();
} }
getAssignedCount(groupName: string) {
return this.permissions.reduce(
(acc, val) => (val.name.split('.')[0] === groupName && val.isGranted ? acc + 1 : acc),
0,
);
}
onVisibleChange(visible: boolean) { onVisibleChange(visible: boolean) {
this.visible = visible; this.visible = visible;
@ -339,13 +321,20 @@ export class PermissionManagementComponent
this.replaceableData.outputs.visibleChange(visible); this.replaceableData.outputs.visibleChange(visible);
} }
} }
shouldFetchAppConfig() {
const currentUser = this.configState.getOne('currentUser') as CurrentUserDto;
if (this.providerName === 'R') return currentUser.roles.some(role => role === this.providerKey);
if (this.providerName === 'U') return currentUser.id === this.providerKey;
return false;
}
} }
function findMargin( function findMargin(permissions: PermissionGrantInfoDto[], permission: PermissionGrantInfoDto) {
permissions: PermissionManagement.Permission[], const parentPermission = permissions.find(per => per.name === permission.parentName);
permission: PermissionManagement.Permission
) {
const parentPermission = permissions.find((per) => per.name === permission.parentName);
if (parentPermission && parentPermission.parentName) { if (parentPermission && parentPermission.parentName) {
let margin = 20; let margin = 20;
@ -355,7 +344,7 @@ function findMargin(
return parentPermission ? 20 : 0; return parentPermission ? 20 : 0;
} }
function getPermissions(groups: PermissionManagement.Group[]): PermissionManagement.Permission[] { function getPermissions(groups: PermissionGroupDto[]): PermissionGrantInfoDto[] {
return groups.reduce((acc, val) => [...acc, ...val.permissions], []); return groups.reduce((acc, val) => [...acc, ...val.permissions], []);
} }
``` ```
@ -363,16 +352,12 @@ function getPermissions(groups: PermissionManagement.Group[]): PermissionManagem
Open the generated `permission-management.component.html` in `src/app/permission-management` folder and replace the content with the below: Open the generated `permission-management.component.html` in `src/app/permission-management` folder and replace the content with the below:
```html ```html
<abp-modal <abp-modal [visible]="isVisible" (visibleChange)="onVisibleChange($event)" [busy]="modalBusy">
[visible]="isVisible" <ng-container *ngIf="data.entityDisplayName">
(visibleChange)="onVisibleChange($event)"
(init)="initModal()"
[busy]="modalBusy"
>
<ng-container *ngIf="{ entityName: entityName$ | async } as data">
<ng-template #abpHeader> <ng-template #abpHeader>
<h4> <h4>
{%{{{ 'AbpPermissionManagement::Permissions' | abpLocalization }}}%} - {%{{{ data.entityName }}}%} {%{{{ 'AbpPermissionManagement::Permissions' | abpLocalization }}}%} -
{%{{{ data.entityDisplayName }}}%}
</h4> </h4>
</ng-template> </ng-template>
<ng-template #abpBody> <ng-template #abpBody>
@ -394,13 +379,18 @@ Open the generated `permission-management.component.html` in `src/app/permission
<div class="row"> <div class="row">
<div class="overflow-scroll col-md-4"> <div class="overflow-scroll col-md-4">
<ul class="nav nav-pills flex-column"> <ul class="nav nav-pills flex-column">
<li *ngFor="let group of groups$ | async; trackBy: trackByFn" class="nav-item"> <li *ngFor="let group of data.groups; trackBy: trackByFn" class="nav-item">
<a <a
*ngIf="{ assignedCount: getAssignedCount(group.name) } as count"
class="nav-link pointer" class="nav-link pointer"
[class.active]="selectedGroup?.name === group?.name" [class.active]="selectedGroup?.name === group?.name"
(click)="onChangeGroup(group)" (click)="onChangeGroup(group)"
>{%{{{ group?.displayName }}}%}</a
> >
<div [class.font-weight-bold]="count.assignedCount">
{%{{{ group?.displayName }}}%}
<span>({%{{{ count.assignedCount }}}%})</span>
</div>
</a>
</li> </li>
</ul> </ul>
</div> </div>
@ -423,12 +413,8 @@ Open the generated `permission-management.component.html` in `src/app/permission
</div> </div>
<hr class="mb-3" /> <hr class="mb-3" />
<div <div
*ngFor=" *ngFor="let permission of selectedGroupPermissions; let i = index; trackBy: trackByFn"
let permission of selectedGroupPermissions$ | async; [ngStyle]="permission.style"
let i = index;
trackBy: trackByFn
"
[style.margin-left]="permission.margin + 'px'"
class="custom-checkbox custom-control mb-2" class="custom-checkbox custom-control mb-2"
> >
<input <input

2
docs/en/UI/Angular/Settings.md

@ -2,7 +2,7 @@
You can get settings on the client-side using the [config state service](./Config-State.md) if they are allowed by their setting definition on the server-side. You can get settings on the client-side using the [config state service](./Config-State.md) if they are allowed by their setting definition on the server-side.
> This document only explains how settings work in the Angular UI projects. See the [settings document](../../../Settings.md) to understand the ABP setting system. > This document only explains how settings work in the Angular UI projects. See the [settings document](../../Settings.md) to understand the ABP setting system.
## Before Use ## Before Use

14
framework/Volo.Abp.sln

@ -383,8 +383,12 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.TextTemplating.Scr
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.MongoDB.Tests.SecondContext", "test\Volo.Abp.MongoDB.Tests.SecondContext\Volo.Abp.MongoDB.Tests.SecondContext.csproj", "{90B1866A-EF99-40B9-970E-B898E5AA523F}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.MongoDB.Tests.SecondContext", "test\Volo.Abp.MongoDB.Tests.SecondContext\Volo.Abp.MongoDB.Tests.SecondContext.csproj", "{90B1866A-EF99-40B9-970E-B898E5AA523F}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.IdentityModel.Tests", "test\Volo.Abp.IdentityModel.Tests\Volo.Abp.IdentityModel.Tests.csproj", "{40C6740E-BFCA-4D37-8344-3D84E2044BB2}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.Threading.Tests", "test\Volo.Abp.Threading.Tests\Volo.Abp.Threading.Tests.csproj", "{7B2FCAD6-86E6-49C8-ADBE-A61B4F4B101B}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.Threading.Tests", "test\Volo.Abp.Threading.Tests\Volo.Abp.Threading.Tests.csproj", "{7B2FCAD6-86E6-49C8-ADBE-A61B4F4B101B}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.Auditing.Contracts", "src\Volo.Abp.Auditing.Contracts\Volo.Abp.Auditing.Contracts.csproj", "{508B6355-AD28-4E60-8549-266D21DBF2CF}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
@ -1143,10 +1147,18 @@ Global
{90B1866A-EF99-40B9-970E-B898E5AA523F}.Debug|Any CPU.Build.0 = Debug|Any CPU {90B1866A-EF99-40B9-970E-B898E5AA523F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{90B1866A-EF99-40B9-970E-B898E5AA523F}.Release|Any CPU.ActiveCfg = Release|Any CPU {90B1866A-EF99-40B9-970E-B898E5AA523F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{90B1866A-EF99-40B9-970E-B898E5AA523F}.Release|Any CPU.Build.0 = Release|Any CPU {90B1866A-EF99-40B9-970E-B898E5AA523F}.Release|Any CPU.Build.0 = Release|Any CPU
{40C6740E-BFCA-4D37-8344-3D84E2044BB2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{40C6740E-BFCA-4D37-8344-3D84E2044BB2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{40C6740E-BFCA-4D37-8344-3D84E2044BB2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{40C6740E-BFCA-4D37-8344-3D84E2044BB2}.Release|Any CPU.Build.0 = Release|Any CPU
{7B2FCAD6-86E6-49C8-ADBE-A61B4F4B101B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {7B2FCAD6-86E6-49C8-ADBE-A61B4F4B101B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7B2FCAD6-86E6-49C8-ADBE-A61B4F4B101B}.Debug|Any CPU.Build.0 = Debug|Any CPU {7B2FCAD6-86E6-49C8-ADBE-A61B4F4B101B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7B2FCAD6-86E6-49C8-ADBE-A61B4F4B101B}.Release|Any CPU.ActiveCfg = Release|Any CPU {7B2FCAD6-86E6-49C8-ADBE-A61B4F4B101B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7B2FCAD6-86E6-49C8-ADBE-A61B4F4B101B}.Release|Any CPU.Build.0 = Release|Any CPU {7B2FCAD6-86E6-49C8-ADBE-A61B4F4B101B}.Release|Any CPU.Build.0 = Release|Any CPU
{508B6355-AD28-4E60-8549-266D21DBF2CF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{508B6355-AD28-4E60-8549-266D21DBF2CF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{508B6355-AD28-4E60-8549-266D21DBF2CF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{508B6355-AD28-4E60-8549-266D21DBF2CF}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
@ -1340,7 +1352,9 @@ Global
{C996F458-98FB-483D-9306-4701290E2FC1} = {447C8A77-E5F0-4538-8687-7383196D04EA} {C996F458-98FB-483D-9306-4701290E2FC1} = {447C8A77-E5F0-4538-8687-7383196D04EA}
{75D8DADB-3FA9-4C1D-B23A-DBFD08133B7C} = {447C8A77-E5F0-4538-8687-7383196D04EA} {75D8DADB-3FA9-4C1D-B23A-DBFD08133B7C} = {447C8A77-E5F0-4538-8687-7383196D04EA}
{90B1866A-EF99-40B9-970E-B898E5AA523F} = {447C8A77-E5F0-4538-8687-7383196D04EA} {90B1866A-EF99-40B9-970E-B898E5AA523F} = {447C8A77-E5F0-4538-8687-7383196D04EA}
{40C6740E-BFCA-4D37-8344-3D84E2044BB2} = {447C8A77-E5F0-4538-8687-7383196D04EA}
{7B2FCAD6-86E6-49C8-ADBE-A61B4F4B101B} = {447C8A77-E5F0-4538-8687-7383196D04EA} {7B2FCAD6-86E6-49C8-ADBE-A61B4F4B101B} = {447C8A77-E5F0-4538-8687-7383196D04EA}
{508B6355-AD28-4E60-8549-266D21DBF2CF} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}
EndGlobalSection EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {BB97ECF4-9A84-433F-A80B-2A3285BDD1D5} SolutionGuid = {BB97ECF4-9A84-433F-A80B-2A3285BDD1D5}

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

@ -4,7 +4,7 @@
<Import Project="..\..\..\common.props" /> <Import Project="..\..\..\common.props" />
<PropertyGroup> <PropertyGroup>
<TargetFramework>net5.0</TargetFramework> <TargetFramework>net6.0</TargetFramework>
<AssemblyName>Volo.Abp.AspNetCore.Authentication.JwtBearer</AssemblyName> <AssemblyName>Volo.Abp.AspNetCore.Authentication.JwtBearer</AssemblyName>
<PackageId>Volo.Abp.AspNetCore.Authentication.JwtBearer</PackageId> <PackageId>Volo.Abp.AspNetCore.Authentication.JwtBearer</PackageId>
<AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback> <AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback>

27
framework/src/Volo.Abp.AspNetCore.Authentication.OAuth/Properties/launchSettings.json

@ -1,27 +0,0 @@
{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:53601/",
"sslPort": 44330
}
},
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"Volo.Abp.AspNetCore.Authentication.OAuth": {
"commandName": "Project",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"applicationUrl": "https://localhost:5001;http://localhost:5000"
}
}
}

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

@ -4,7 +4,7 @@
<Import Project="..\..\..\common.props" /> <Import Project="..\..\..\common.props" />
<PropertyGroup> <PropertyGroup>
<TargetFramework>net5.0</TargetFramework> <TargetFramework>net6.0</TargetFramework>
<AssemblyName>Volo.Abp.AspNetCore.Authentication.OAuth</AssemblyName> <AssemblyName>Volo.Abp.AspNetCore.Authentication.OAuth</AssemblyName>
<PackageId>Volo.Abp.AspNetCore.Authentication.OAuth</PackageId> <PackageId>Volo.Abp.AspNetCore.Authentication.OAuth</PackageId>
<AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback> <AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback>
@ -13,6 +13,7 @@
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute> <GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<IsPackable>true</IsPackable> <IsPackable>true</IsPackable>
<OutputType>Library</OutputType> <OutputType>Library</OutputType>
<NoDefaultLaunchSettingsFile>true</NoDefaultLaunchSettingsFile>
<RootNamespace /> <RootNamespace />
</PropertyGroup> </PropertyGroup>

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

@ -4,7 +4,7 @@
<Import Project="..\..\..\common.props" /> <Import Project="..\..\..\common.props" />
<PropertyGroup> <PropertyGroup>
<TargetFramework>net5.0</TargetFramework> <TargetFramework>net6.0</TargetFramework>
<RootNamespace /> <RootNamespace />
</PropertyGroup> </PropertyGroup>

3
framework/src/Volo.Abp.AspNetCore.Components.Server.Theming/Volo.Abp.AspNetCore.Components.Server.Theming.csproj

@ -4,9 +4,10 @@
<Import Project="..\..\..\common.props" /> <Import Project="..\..\..\common.props" />
<PropertyGroup> <PropertyGroup>
<TargetFramework>net5.0</TargetFramework> <TargetFramework>net6.0</TargetFramework>
<IsPackable>true</IsPackable> <IsPackable>true</IsPackable>
<OutputType>Library</OutputType> <OutputType>Library</OutputType>
<NoDefaultLaunchSettingsFile>true</NoDefaultLaunchSettingsFile>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

3
framework/src/Volo.Abp.AspNetCore.Components.Server/Volo.Abp.AspNetCore.Components.Server.csproj

@ -4,9 +4,10 @@
<Import Project="..\..\..\common.props" /> <Import Project="..\..\..\common.props" />
<PropertyGroup> <PropertyGroup>
<TargetFramework>net5.0</TargetFramework> <TargetFramework>net6.0</TargetFramework>
<IsPackable>true</IsPackable> <IsPackable>true</IsPackable>
<OutputType>Library</OutputType> <OutputType>Library</OutputType>
<NoDefaultLaunchSettingsFile>true</NoDefaultLaunchSettingsFile>
<RootNamespace /> <RootNamespace />
</PropertyGroup> </PropertyGroup>

2
framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/Volo.Abp.AspNetCore.Components.Web.Theming.csproj

@ -4,7 +4,7 @@
<Import Project="..\..\..\common.props" /> <Import Project="..\..\..\common.props" />
<PropertyGroup> <PropertyGroup>
<TargetFramework>net5.0</TargetFramework> <TargetFramework>net6.0</TargetFramework>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

2
framework/src/Volo.Abp.AspNetCore.Components.Web/Volo.Abp.AspNetCore.Components.Web.csproj

@ -4,7 +4,7 @@
<Import Project="..\..\..\common.props" /> <Import Project="..\..\..\common.props" />
<PropertyGroup> <PropertyGroup>
<TargetFramework>net5.0</TargetFramework> <TargetFramework>net6.0</TargetFramework>
<RootNamespace /> <RootNamespace />
</PropertyGroup> </PropertyGroup>

2
framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/Volo.Abp.AspNetCore.Components.WebAssembly.Theming.csproj

@ -4,7 +4,7 @@
<Import Project="..\..\..\common.props" /> <Import Project="..\..\..\common.props" />
<PropertyGroup> <PropertyGroup>
<TargetFramework>net5.0</TargetFramework> <TargetFramework>net6.0</TargetFramework>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

2
framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo.Abp.AspNetCore.Components.WebAssembly.csproj

@ -4,7 +4,7 @@
<Import Project="..\..\..\common.props" /> <Import Project="..\..\..\common.props" />
<PropertyGroup> <PropertyGroup>
<TargetFramework>net5.0</TargetFramework> <TargetFramework>net6.0</TargetFramework>
<AssemblyName>Volo.Abp.AspNetCore.Components.WebAssembly</AssemblyName> <AssemblyName>Volo.Abp.AspNetCore.Components.WebAssembly</AssemblyName>
<PackageId>Volo.Abp.AspNetCore.Components.WebAssembly</PackageId> <PackageId>Volo.Abp.AspNetCore.Components.WebAssembly</PackageId>
<AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback> <AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback>

2
framework/src/Volo.Abp.AspNetCore.Components/Volo.Abp.AspNetCore.Components.csproj

@ -4,7 +4,7 @@
<Import Project="..\..\..\common.props" /> <Import Project="..\..\..\common.props" />
<PropertyGroup> <PropertyGroup>
<TargetFramework>net5.0</TargetFramework> <TargetFramework>net6.0</TargetFramework>
<AssemblyName>Volo.Abp.AspNetCore.Components</AssemblyName> <AssemblyName>Volo.Abp.AspNetCore.Components</AssemblyName>
<PackageId>Volo.Abp.AspNetCore.Components</PackageId> <PackageId>Volo.Abp.AspNetCore.Components</PackageId>
<AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback> <AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback>

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

@ -4,7 +4,7 @@
<Import Project="..\..\..\common.props" /> <Import Project="..\..\..\common.props" />
<PropertyGroup> <PropertyGroup>
<TargetFramework>net5.0</TargetFramework> <TargetFramework>net6.0</TargetFramework>
<AssemblyName>Volo.Abp.AspNetCore.MultiTenancy</AssemblyName> <AssemblyName>Volo.Abp.AspNetCore.MultiTenancy</AssemblyName>
<PackageId>Volo.Abp.AspNetCore.MultiTenancy</PackageId> <PackageId>Volo.Abp.AspNetCore.MultiTenancy</PackageId>
<AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback> <AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback>

1
framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/AbpMultiTenancyCookieHelper.cs

@ -19,6 +19,7 @@ namespace Volo.Abp.AspNetCore.MultiTenancy
{ {
Path = "/", Path = "/",
HttpOnly = false, HttpOnly = false,
IsEssential = true,
Expires = DateTimeOffset.Now.AddYears(10) Expires = DateTimeOffset.Now.AddYears(10)
} }
); );

27
framework/src/Volo.Abp.AspNetCore.Mvc.Client/Properties/launchSettings.json

@ -1,27 +0,0 @@
{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:53603/",
"sslPort": 44305
}
},
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"Volo.Abp.AspNetCore.Mvc.Client": {
"commandName": "Project",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"applicationUrl": "https://localhost:5001;http://localhost:5000"
}
}
}

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

@ -4,7 +4,7 @@
<Import Project="..\..\..\common.props" /> <Import Project="..\..\..\common.props" />
<PropertyGroup> <PropertyGroup>
<TargetFramework>net5.0</TargetFramework> <TargetFramework>net6.0</TargetFramework>
<AssemblyName>Volo.Abp.AspNetCore.Mvc.Client</AssemblyName> <AssemblyName>Volo.Abp.AspNetCore.Mvc.Client</AssemblyName>
<PackageId>Volo.Abp.AspNetCore.Mvc.Client</PackageId> <PackageId>Volo.Abp.AspNetCore.Mvc.Client</PackageId>
<AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback> <AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback>
@ -13,6 +13,7 @@
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute> <GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<IsPackable>true</IsPackable> <IsPackable>true</IsPackable>
<OutputType>Library</OutputType> <OutputType>Library</OutputType>
<NoDefaultLaunchSettingsFile>true</NoDefaultLaunchSettingsFile>
<RootNamespace /> <RootNamespace />
</PropertyGroup> </PropertyGroup>

1
framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ApplicationConfigurationDto.cs

@ -1,7 +1,6 @@
using System; using System;
using Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.ObjectExtending; using Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.ObjectExtending;
using Volo.Abp.AspNetCore.Mvc.MultiTenancy; using Volo.Abp.AspNetCore.Mvc.MultiTenancy;
using Volo.Abp.Timing;
namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations
{ {

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

@ -4,7 +4,7 @@
<Import Project="..\..\..\common.props" /> <Import Project="..\..\..\common.props" />
<PropertyGroup> <PropertyGroup>
<TargetFramework>net5.0</TargetFramework> <TargetFramework>net6.0</TargetFramework>
<AddRazorSupportForMvc>true</AddRazorSupportForMvc> <AddRazorSupportForMvc>true</AddRazorSupportForMvc>
<AssemblyName>Volo.Abp.AspNetCore.Mvc.UI.Bootstrap</AssemblyName> <AssemblyName>Volo.Abp.AspNetCore.Mvc.UI.Bootstrap</AssemblyName>
<PackageId>Volo.Abp.AspNetCore.Mvc.UI.Bootstrap</PackageId> <PackageId>Volo.Abp.AspNetCore.Mvc.UI.Bootstrap</PackageId>

2
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling.Abstractions/Volo.Abp.AspNetCore.Mvc.UI.Bundling.Abstractions.csproj

@ -4,7 +4,7 @@
<Import Project="..\..\..\common.props" /> <Import Project="..\..\..\common.props" />
<PropertyGroup> <PropertyGroup>
<TargetFramework>net5.0</TargetFramework> <TargetFramework>net6.0</TargetFramework>
<RootNamespace /> <RootNamespace />
</PropertyGroup> </PropertyGroup>

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

@ -4,7 +4,7 @@
<Import Project="..\..\..\common.props" /> <Import Project="..\..\..\common.props" />
<PropertyGroup> <PropertyGroup>
<TargetFramework>net5.0</TargetFramework> <TargetFramework>net6.0</TargetFramework>
<AddRazorSupportForMvc>true</AddRazorSupportForMvc> <AddRazorSupportForMvc>true</AddRazorSupportForMvc>
<AssemblyName>Volo.Abp.AspNetCore.Mvc.UI.Bundling</AssemblyName> <AssemblyName>Volo.Abp.AspNetCore.Mvc.UI.Bundling</AssemblyName>
<PackageId>Volo.Abp.AspNetCore.Mvc.UI.Bundling</PackageId> <PackageId>Volo.Abp.AspNetCore.Mvc.UI.Bundling</PackageId>

4
framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Pages/Abp/MultiTenancy/AbpTenantAppService.cs

@ -15,7 +15,7 @@ namespace Pages.Abp.MultiTenancy
TenantStore = tenantStore; TenantStore = tenantStore;
} }
public async Task<FindTenantResultDto> FindTenantByNameAsync(string name) public virtual async Task<FindTenantResultDto> FindTenantByNameAsync(string name)
{ {
var tenant = await TenantStore.FindAsync(name); var tenant = await TenantStore.FindAsync(name);
@ -33,7 +33,7 @@ namespace Pages.Abp.MultiTenancy
}; };
} }
public async Task<FindTenantResultDto> FindTenantByIdAsync(Guid id) public virtual async Task<FindTenantResultDto> FindTenantByIdAsync(Guid id)
{ {
var tenant = await TenantStore.FindAsync(id); var tenant = await TenantStore.FindAsync(id);

4
framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Pages/Abp/MultiTenancy/AbpTenantController.cs

@ -21,14 +21,14 @@ namespace Pages.Abp.MultiTenancy
[HttpGet] [HttpGet]
[Route("tenants/by-name/{name}")] [Route("tenants/by-name/{name}")]
public async Task<FindTenantResultDto> FindTenantByNameAsync(string name) public virtual async Task<FindTenantResultDto> FindTenantByNameAsync(string name)
{ {
return await _abpTenantAppService.FindTenantByNameAsync(name); return await _abpTenantAppService.FindTenantByNameAsync(name);
} }
[HttpGet] [HttpGet]
[Route("tenants/by-id/{id}")] [Route("tenants/by-id/{id}")]
public async Task<FindTenantResultDto> FindTenantByIdAsync(Guid id) public virtual async Task<FindTenantResultDto> FindTenantByIdAsync(Guid id)
{ {
return await _abpTenantAppService.FindTenantByIdAsync(id); return await _abpTenantAppService.FindTenantByIdAsync(id);
} }

4
framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Pages/Abp/MultiTenancy/TenantSwitchModal.cshtml.cs

@ -29,7 +29,7 @@ namespace Pages.Abp.MultiTenancy
LocalizationResourceType = typeof(AbpUiMultiTenancyResource); LocalizationResourceType = typeof(AbpUiMultiTenancyResource);
} }
public async Task OnGetAsync() public virtual async Task OnGetAsync()
{ {
Input = new TenantInfoModel(); Input = new TenantInfoModel();
@ -40,7 +40,7 @@ namespace Pages.Abp.MultiTenancy
} }
} }
public async Task OnPostAsync() public virtual async Task OnPostAsync()
{ {
Guid? tenantId = null; Guid? tenantId = null;
if (!Input.Name.IsNullOrEmpty()) if (!Input.Name.IsNullOrEmpty())

2
framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy.csproj

@ -4,7 +4,7 @@
<Import Project="..\..\..\common.props" /> <Import Project="..\..\..\common.props" />
<PropertyGroup> <PropertyGroup>
<TargetFramework>net5.0</TargetFramework> <TargetFramework>net6.0</TargetFramework>
<AddRazorSupportForMvc>true</AddRazorSupportForMvc> <AddRazorSupportForMvc>true</AddRazorSupportForMvc>
<AssemblyName>Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy</AssemblyName> <AssemblyName>Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy</AssemblyName>
<PackageId>Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy</PackageId> <PackageId>Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy</PackageId>

2
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Packages/Volo.Abp.AspNetCore.Mvc.UI.Packages.csproj

@ -4,7 +4,7 @@
<Import Project="..\..\..\common.props" /> <Import Project="..\..\..\common.props" />
<PropertyGroup> <PropertyGroup>
<TargetFramework>net5.0</TargetFramework> <TargetFramework>net6.0</TargetFramework>
<AddRazorSupportForMvc>true</AddRazorSupportForMvc> <AddRazorSupportForMvc>true</AddRazorSupportForMvc>
<AssemblyName>Volo.Abp.AspNetCore.Mvc.UI.Packages</AssemblyName> <AssemblyName>Volo.Abp.AspNetCore.Mvc.UI.Packages</AssemblyName>
<PackageId>Volo.Abp.AspNetCore.Mvc.UI.Packages</PackageId> <PackageId>Volo.Abp.AspNetCore.Mvc.UI.Packages</PackageId>

6
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Packages/Volo/Abp/AspNetCore/Mvc/UI/Packages/SweetAlert/SweetalertScriptContributor.cs → framework/src/Volo.Abp.AspNetCore.Mvc.UI.Packages/Volo/Abp/AspNetCore/Mvc/UI/Packages/SweetAlert2/Sweetalert2ScriptContributor.cs

@ -3,14 +3,14 @@ using Volo.Abp.AspNetCore.Mvc.UI.Bundling;
using Volo.Abp.AspNetCore.Mvc.UI.Packages.Core; using Volo.Abp.AspNetCore.Mvc.UI.Packages.Core;
using Volo.Abp.Modularity; using Volo.Abp.Modularity;
namespace Volo.Abp.AspNetCore.Mvc.UI.Packages.SweetAlert namespace Volo.Abp.AspNetCore.Mvc.UI.Packages.SweetAlert2
{ {
[DependsOn(typeof(CoreScriptContributor))] [DependsOn(typeof(CoreScriptContributor))]
public class SweetalertScriptContributor : BundleContributor public class Sweetalert2ScriptContributor : BundleContributor
{ {
public override void ConfigureBundle(BundleConfigurationContext context) public override void ConfigureBundle(BundleConfigurationContext context)
{ {
context.Files.AddIfNotContains("/libs/sweetalert/sweetalert.min.js"); context.Files.AddIfNotContains("/libs/sweetalert2/sweetalert2.all.min.js");
} }
} }
} }

2
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo.csproj

@ -4,7 +4,7 @@
<Import Project="..\..\..\common.props" /> <Import Project="..\..\..\common.props" />
<PropertyGroup> <PropertyGroup>
<TargetFramework>net5.0</TargetFramework> <TargetFramework>net6.0</TargetFramework>
<AddRazorSupportForMvc>true</AddRazorSupportForMvc> <AddRazorSupportForMvc>true</AddRazorSupportForMvc>
<AssemblyName>Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo</AssemblyName> <AssemblyName>Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo</AssemblyName>
<PackageId>Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo</PackageId> <PackageId>Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo</PackageId>

6
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/Bundling/SharedThemeGlobalScriptContributor.cs

@ -9,7 +9,7 @@ using Volo.Abp.AspNetCore.Mvc.UI.Packages.Lodash;
using Volo.Abp.AspNetCore.Mvc.UI.Packages.Luxon; using Volo.Abp.AspNetCore.Mvc.UI.Packages.Luxon;
using Volo.Abp.AspNetCore.Mvc.UI.Packages.MalihuCustomScrollbar; using Volo.Abp.AspNetCore.Mvc.UI.Packages.MalihuCustomScrollbar;
using Volo.Abp.AspNetCore.Mvc.UI.Packages.Select2; using Volo.Abp.AspNetCore.Mvc.UI.Packages.Select2;
using Volo.Abp.AspNetCore.Mvc.UI.Packages.SweetAlert; using Volo.Abp.AspNetCore.Mvc.UI.Packages.SweetAlert2;
using Volo.Abp.AspNetCore.Mvc.UI.Packages.Timeago; using Volo.Abp.AspNetCore.Mvc.UI.Packages.Timeago;
using Volo.Abp.AspNetCore.Mvc.UI.Packages.Toastr; using Volo.Abp.AspNetCore.Mvc.UI.Packages.Toastr;
using Volo.Abp.Modularity; using Volo.Abp.Modularity;
@ -24,7 +24,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Bundling
typeof(JQueryFormScriptContributor), typeof(JQueryFormScriptContributor),
typeof(Select2ScriptContributor), typeof(Select2ScriptContributor),
typeof(DatatablesNetBs5ScriptContributor), typeof(DatatablesNetBs5ScriptContributor),
typeof(SweetalertScriptContributor), typeof(Sweetalert2ScriptContributor),
typeof(ToastrScriptBundleContributor), typeof(ToastrScriptBundleContributor),
typeof(MalihuCustomScrollbarPluginScriptBundleContributor), typeof(MalihuCustomScrollbarPluginScriptBundleContributor),
typeof(LuxonScriptContributor), typeof(LuxonScriptContributor),
@ -44,7 +44,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Bundling
"/libs/abp/aspnetcore-mvc-ui-theme-shared/bootstrap/dom-event-handlers.js", "/libs/abp/aspnetcore-mvc-ui-theme-shared/bootstrap/dom-event-handlers.js",
"/libs/abp/aspnetcore-mvc-ui-theme-shared/bootstrap/modal-manager.js", "/libs/abp/aspnetcore-mvc-ui-theme-shared/bootstrap/modal-manager.js",
"/libs/abp/aspnetcore-mvc-ui-theme-shared/datatables/datatables-extensions.js", "/libs/abp/aspnetcore-mvc-ui-theme-shared/datatables/datatables-extensions.js",
"/libs/abp/aspnetcore-mvc-ui-theme-shared/sweetalert/abp-sweetalert.js", "/libs/abp/aspnetcore-mvc-ui-theme-shared/sweetalert2/abp-sweetalert2.js",
"/libs/abp/aspnetcore-mvc-ui-theme-shared/toastr/abp-toastr.js" "/libs/abp/aspnetcore-mvc-ui-theme-shared/toastr/abp-toastr.js"
}); });
} }

2
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.csproj

@ -4,7 +4,7 @@
<Import Project="..\..\..\common.props" /> <Import Project="..\..\..\common.props" />
<PropertyGroup> <PropertyGroup>
<TargetFramework>net5.0</TargetFramework> <TargetFramework>net6.0</TargetFramework>
<AddRazorSupportForMvc>true</AddRazorSupportForMvc> <AddRazorSupportForMvc>true</AddRazorSupportForMvc>
<AssemblyName>Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared</AssemblyName> <AssemblyName>Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared</AssemblyName>
<PackageId>Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared</PackageId> <PackageId>Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared</PackageId>

24
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/sweetalert/abp-sweetalert.js → framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/sweetalert2/abp-sweetalert2.js

@ -1,6 +1,6 @@
var abp = abp || {}; var abp = abp || {};
(function ($) { (function ($) {
if (!sweetAlert || !$) { if (!Swal || !$) {
return; return;
} }
@ -27,7 +27,8 @@
confirm: { confirm: {
icon: 'warning', icon: 'warning',
title: 'Are you sure?', title: 'Are you sure?',
buttons: ['Cancel', 'Yes'] showCancelButton: true,
reverseButtons: true
} }
} }
}; };
@ -51,7 +52,7 @@
); );
return $.Deferred(function ($dfd) { return $.Deferred(function ($dfd) {
sweetAlert(opts).then(function () { Swal.fire(opts).then(function () {
$dfd.resolve(); $dfd.resolve();
}); });
}); });
@ -73,7 +74,7 @@
return showMessage('error', message, title); return showMessage('error', message, title);
}; };
abp.message.confirm = function (message, titleOrCallback, callback, closeOnEsc) { abp.message.confirm = function (message, titleOrCallback, callback) {
var userOpts = { var userOpts = {
text: message text: message
@ -86,8 +87,6 @@
userOpts.title = titleOrCallback; userOpts.title = titleOrCallback;
}; };
userOpts.closeOnEsc = closeOnEsc;
var opts = $.extend( var opts = $.extend(
{}, {},
abp.libs.sweetAlert.config['default'], abp.libs.sweetAlert.config['default'],
@ -96,10 +95,10 @@
); );
return $.Deferred(function ($dfd) { return $.Deferred(function ($dfd) {
sweetAlert(opts).then(function (isConfirmed) { Swal.fire(opts).then(result => {
callback && callback(isConfirmed); callback && callback(result.value);
$dfd.resolve(isConfirmed); $dfd.resolve(result.value);
}); })
}); });
}; };
@ -107,7 +106,8 @@
var l = abp.localization.getResource('AbpUi'); var l = abp.localization.getResource('AbpUi');
abp.libs.sweetAlert.config.confirm.title = l('AreYouSure'); abp.libs.sweetAlert.config.confirm.title = l('AreYouSure');
abp.libs.sweetAlert.config.confirm.buttons = [l('Cancel'), l('Yes')]; abp.libs.sweetAlert.config.confirm.showCancelButton = true;
abp.libs.sweetAlert.config.confirm.reverseButtons = true;
}); });
})(jQuery); })(jQuery);

2
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Widgets/Volo.Abp.AspNetCore.Mvc.UI.Widgets.csproj

@ -4,7 +4,7 @@
<Import Project="..\..\..\common.props" /> <Import Project="..\..\..\common.props" />
<PropertyGroup> <PropertyGroup>
<TargetFramework>net5.0</TargetFramework> <TargetFramework>net6.0</TargetFramework>
<AddRazorSupportForMvc>true</AddRazorSupportForMvc> <AddRazorSupportForMvc>true</AddRazorSupportForMvc>
<AssemblyName>Volo.Abp.AspNetCore.Mvc.UI.Widgets</AssemblyName> <AssemblyName>Volo.Abp.AspNetCore.Mvc.UI.Widgets</AssemblyName>
<PackageId>Volo.Abp.AspNetCore.Mvc.UI.Widgets</PackageId> <PackageId>Volo.Abp.AspNetCore.Mvc.UI.Widgets</PackageId>

2
framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo.Abp.AspNetCore.Mvc.UI.csproj

@ -4,7 +4,7 @@
<Import Project="..\..\..\common.props" /> <Import Project="..\..\..\common.props" />
<PropertyGroup> <PropertyGroup>
<TargetFramework>net5.0</TargetFramework> <TargetFramework>net6.0</TargetFramework>
<AddRazorSupportForMvc>true</AddRazorSupportForMvc> <AddRazorSupportForMvc>true</AddRazorSupportForMvc>
<AssemblyName>Volo.Abp.AspNetCore.Mvc.UI</AssemblyName> <AssemblyName>Volo.Abp.AspNetCore.Mvc.UI</AssemblyName>
<PackageId>Volo.Abp.AspNetCore.Mvc.UI</PackageId> <PackageId>Volo.Abp.AspNetCore.Mvc.UI</PackageId>

2
framework/src/Volo.Abp.AspNetCore.Mvc/Volo.Abp.AspNetCore.Mvc.csproj

@ -4,7 +4,7 @@
<Import Project="..\..\..\common.props" /> <Import Project="..\..\..\common.props" />
<PropertyGroup> <PropertyGroup>
<TargetFramework>net5.0</TargetFramework> <TargetFramework>net6.0</TargetFramework>
<AddRazorSupportForMvc>true</AddRazorSupportForMvc> <AddRazorSupportForMvc>true</AddRazorSupportForMvc>
<AssemblyName>Volo.Abp.AspNetCore.Mvc</AssemblyName> <AssemblyName>Volo.Abp.AspNetCore.Mvc</AssemblyName>
<PackageId>Volo.Abp.AspNetCore.Mvc</PackageId> <PackageId>Volo.Abp.AspNetCore.Mvc</PackageId>

25
framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AspNetCoreApiDescriptionModelProvider.cs

@ -86,6 +86,7 @@ namespace Volo.Abp.AspNetCore.Mvc
var controllerModel = moduleModel.GetOrAddController( var controllerModel = moduleModel.GetOrAddController(
_options.ControllerNameGenerator(controllerType, setting), _options.ControllerNameGenerator(controllerType, setting),
FindGroupName(controllerType) ?? apiDescription.GroupName,
controllerType, controllerType,
_modelOptions.IgnoredInterfaces _modelOptions.IgnoredInterfaces
); );
@ -113,6 +114,14 @@ namespace Volo.Abp.AspNetCore.Mvc
allowAnonymous = false; allowAnonymous = false;
} }
var implementFrom = controllerType.FullName;
var interfaceType = controllerType.GetInterfaces().FirstOrDefault(i => i.GetMethods().Any(x => x.ToString() == method.ToString()));
if (interfaceType != null)
{
implementFrom = TypeHelper.GetFullNameHandlingNullableAndGenerics(interfaceType);
}
var actionModel = controllerModel.AddAction( var actionModel = controllerModel.AddAction(
uniqueMethodName, uniqueMethodName,
ActionApiDescriptionModel.Create( ActionApiDescriptionModel.Create(
@ -121,7 +130,8 @@ namespace Volo.Abp.AspNetCore.Mvc
apiDescription.RelativePath, apiDescription.RelativePath,
apiDescription.HttpMethod, apiDescription.HttpMethod,
GetSupportedVersions(controllerType, method, setting), GetSupportedVersions(controllerType, method, setting),
allowAnonymous allowAnonymous,
implementFrom
) )
); );
@ -351,6 +361,19 @@ namespace Volo.Abp.AspNetCore.Mvc
return ModuleApiDescriptionModel.DefaultRemoteServiceName; return ModuleApiDescriptionModel.DefaultRemoteServiceName;
} }
private string FindGroupName(Type controllerType)
{
var controllerNameAttribute =
controllerType.GetCustomAttributes().OfType<ControllerNameAttribute>().FirstOrDefault();
if (controllerNameAttribute?.Name != null)
{
return controllerNameAttribute.Name;
}
return null;
}
[CanBeNull] [CanBeNull]
private ConventionalControllerSetting FindSetting(Type controllerType) private ConventionalControllerSetting FindSetting(Type controllerType)
{ {

10
framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ContentFormatters/AbpRemoteStreamContentModelBinder.cs

@ -108,14 +108,14 @@ namespace Volo.Abp.AspNetCore.Mvc.ContentFormatters
if (file.Name.Equals(modelName, StringComparison.OrdinalIgnoreCase)) if (file.Name.Equals(modelName, StringComparison.OrdinalIgnoreCase))
{ {
postedFiles.Add(new RemoteStreamContent(file.OpenReadStream()) postedFiles.Add(new RemoteStreamContent(file.OpenReadStream(), file.FileName, file.ContentType, file.Length));
{
ContentType = file.ContentType,
FileName = file.FileName
});
} }
} }
} }
else if (bindingContext.IsTopLevelObject)
{
postedFiles.Add(new RemoteStreamContent(request.Body, null, request.ContentType, request.ContentLength));
}
} }
} }
} }

9
framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ContentFormatters/RemoteStreamContentOutputFormatter.cs

@ -33,14 +33,9 @@ namespace Volo.Abp.AspNetCore.Mvc.ContentFormatters
context.HttpContext.Response.Headers[HeaderNames.ContentDisposition] = contentDisposition.ToString(); context.HttpContext.Response.Headers[HeaderNames.ContentDisposition] = contentDisposition.ToString();
} }
using (var stream = remoteStream.GetStream()) using (remoteStream)
{ {
if (stream.CanSeek) await remoteStream.GetStream().CopyToAsync(context.HttpContext.Response.Body);
{
stream.Position = 0;
}
await stream.CopyToAsync(context.HttpContext.Response.Body);
} }
} }
} }

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

@ -45,7 +45,7 @@ namespace Volo.Abp.AspNetCore.Mvc.Conventions
{ {
RemoveDuplicateControllers(application); RemoveDuplicateControllers(application);
foreach (var controller in application.Controllers) foreach (var controller in GetControllers(application))
{ {
var controllerType = controller.ControllerType.AsType(); var controllerType = controller.ControllerType.AsType();
@ -71,11 +71,16 @@ namespace Volo.Abp.AspNetCore.Mvc.Conventions
} }
} }
protected virtual IList<ControllerModel> GetControllers(ApplicationModel application)
{
return application.Controllers;
}
protected virtual void RemoveDuplicateControllers(ApplicationModel application) protected virtual void RemoveDuplicateControllers(ApplicationModel application)
{ {
var controllerModelsToRemove = new List<ControllerModel>(); var controllerModelsToRemove = new List<ControllerModel>();
foreach (var controllerModel in application.Controllers) foreach (var controllerModel in GetControllers(application))
{ {
if (!controllerModel.ControllerType.IsDefined(typeof(ExposeServicesAttribute), false)) if (!controllerModel.ControllerType.IsDefined(typeof(ExposeServicesAttribute), false))
{ {
@ -90,7 +95,7 @@ namespace Volo.Abp.AspNetCore.Mvc.Conventions
var exposeServicesAttr = ReflectionHelper.GetSingleAttributeOrDefault<ExposeServicesAttribute>(controllerModel.ControllerType); var exposeServicesAttr = ReflectionHelper.GetSingleAttributeOrDefault<ExposeServicesAttribute>(controllerModel.ControllerType);
if (exposeServicesAttr.IncludeSelf) if (exposeServicesAttr.IncludeSelf)
{ {
var exposedControllerModels = application.Controllers var exposedControllerModels = GetControllers(application)
.Where(cm => exposeServicesAttr.ServiceTypes.Contains(cm.ControllerType)) .Where(cm => exposeServicesAttr.ServiceTypes.Contains(cm.ControllerType))
.ToArray(); .ToArray();
@ -109,7 +114,7 @@ namespace Volo.Abp.AspNetCore.Mvc.Conventions
continue; continue;
} }
var baseControllerModels = application.Controllers var baseControllerModels = GetControllers(application)
.Where(cm => baseControllerTypes.Contains(cm.ControllerType)) .Where(cm => baseControllerTypes.Contains(cm.ControllerType))
.ToArray(); .ToArray();

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

@ -5,10 +5,12 @@ using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Abstractions; using Microsoft.AspNetCore.Mvc.Abstractions;
using Microsoft.AspNetCore.Mvc.Filters; using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions; using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using Volo.Abp.AspNetCore.ExceptionHandling; using Volo.Abp.AspNetCore.ExceptionHandling;
using Volo.Abp.Authorization;
using Volo.Abp.DependencyInjection; using Volo.Abp.DependencyInjection;
using Volo.Abp.ExceptionHandling; using Volo.Abp.ExceptionHandling;
using Volo.Abp.Http; using Volo.Abp.Http;
@ -55,17 +57,10 @@ namespace Volo.Abp.AspNetCore.Mvc.ExceptionHandling
{ {
//TODO: Trigger an AbpExceptionHandled event or something like that. //TODO: Trigger an AbpExceptionHandled event or something like that.
context.HttpContext.Response.Headers.Add(AbpHttpConsts.AbpErrorFormat, "true");
context.HttpContext.Response.StatusCode = (int) context
.GetRequiredService<IHttpExceptionStatusCodeFinder>()
.GetStatusCode(context.HttpContext, context.Exception);
var exceptionHandlingOptions = context.GetRequiredService<IOptions<AbpExceptionHandlingOptions>>().Value; var exceptionHandlingOptions = context.GetRequiredService<IOptions<AbpExceptionHandlingOptions>>().Value;
var exceptionToErrorInfoConverter = context.GetRequiredService<IExceptionToErrorInfoConverter>(); var exceptionToErrorInfoConverter = context.GetRequiredService<IExceptionToErrorInfoConverter>();
var remoteServiceErrorInfo = exceptionToErrorInfoConverter.Convert(context.Exception, exceptionHandlingOptions.SendExceptionsDetailsToClients); var remoteServiceErrorInfo = exceptionToErrorInfoConverter.Convert(context.Exception, exceptionHandlingOptions.SendExceptionsDetailsToClients);
context.Result = new ObjectResult(new RemoteServiceErrorResponse(remoteServiceErrorInfo));
var logLevel = context.Exception.GetLogLevel(); var logLevel = context.Exception.GetLogLevel();
var remoteServiceErrorInfoBuilder = new StringBuilder(); var remoteServiceErrorInfoBuilder = new StringBuilder();
@ -80,6 +75,21 @@ namespace Volo.Abp.AspNetCore.Mvc.ExceptionHandling
await context.GetRequiredService<IExceptionNotifier>().NotifyAsync(new ExceptionNotificationContext(context.Exception)); await context.GetRequiredService<IExceptionNotifier>().NotifyAsync(new ExceptionNotificationContext(context.Exception));
if (context.Exception is AbpAuthorizationException)
{
await context.HttpContext.RequestServices.GetRequiredService<IAbpAuthorizationExceptionHandler>()
.HandleAsync(context.Exception.As<AbpAuthorizationException>(), context.HttpContext);
}
else
{
context.HttpContext.Response.Headers.Add(AbpHttpConsts.AbpErrorFormat, "true");
context.HttpContext.Response.StatusCode = (int) context
.GetRequiredService<IHttpExceptionStatusCodeFinder>()
.GetStatusCode(context.HttpContext, context.Exception);
context.Result = new ObjectResult(new RemoteServiceErrorResponse(remoteServiceErrorInfo));
}
context.Exception = null; //Handled! context.Exception = null; //Handled!
} }
} }

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

@ -5,10 +5,12 @@ using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Abstractions; using Microsoft.AspNetCore.Mvc.Abstractions;
using Microsoft.AspNetCore.Mvc.Filters; using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions; using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using Volo.Abp.AspNetCore.ExceptionHandling; using Volo.Abp.AspNetCore.ExceptionHandling;
using Volo.Abp.Authorization;
using Volo.Abp.DependencyInjection; using Volo.Abp.DependencyInjection;
using Volo.Abp.ExceptionHandling; using Volo.Abp.ExceptionHandling;
using Volo.Abp.Http; using Volo.Abp.Http;
@ -67,17 +69,10 @@ namespace Volo.Abp.AspNetCore.Mvc.ExceptionHandling
{ {
//TODO: Trigger an AbpExceptionHandled event or something like that. //TODO: Trigger an AbpExceptionHandled event or something like that.
context.HttpContext.Response.Headers.Add(AbpHttpConsts.AbpErrorFormat, "true");
context.HttpContext.Response.StatusCode = (int) context
.GetRequiredService<IHttpExceptionStatusCodeFinder>()
.GetStatusCode(context.HttpContext, context.Exception);
var exceptionHandlingOptions = context.GetRequiredService<IOptions<AbpExceptionHandlingOptions>>().Value; var exceptionHandlingOptions = context.GetRequiredService<IOptions<AbpExceptionHandlingOptions>>().Value;
var exceptionToErrorInfoConverter = context.GetRequiredService<IExceptionToErrorInfoConverter>(); var exceptionToErrorInfoConverter = context.GetRequiredService<IExceptionToErrorInfoConverter>();
var remoteServiceErrorInfo = exceptionToErrorInfoConverter.Convert(context.Exception, exceptionHandlingOptions.SendExceptionsDetailsToClients); var remoteServiceErrorInfo = exceptionToErrorInfoConverter.Convert(context.Exception, exceptionHandlingOptions.SendExceptionsDetailsToClients);
context.Result = new ObjectResult(new RemoteServiceErrorResponse(remoteServiceErrorInfo));
var logLevel = context.Exception.GetLogLevel(); var logLevel = context.Exception.GetLogLevel();
var remoteServiceErrorInfoBuilder = new StringBuilder(); var remoteServiceErrorInfoBuilder = new StringBuilder();
@ -91,6 +86,21 @@ namespace Volo.Abp.AspNetCore.Mvc.ExceptionHandling
await context.GetRequiredService<IExceptionNotifier>().NotifyAsync(new ExceptionNotificationContext(context.Exception)); await context.GetRequiredService<IExceptionNotifier>().NotifyAsync(new ExceptionNotificationContext(context.Exception));
if (context.Exception is AbpAuthorizationException)
{
await context.HttpContext.RequestServices.GetRequiredService<IAbpAuthorizationExceptionHandler>()
.HandleAsync(context.Exception.As<AbpAuthorizationException>(), context.HttpContext);
}
else
{
context.HttpContext.Response.Headers.Add(AbpHttpConsts.AbpErrorFormat, "true");
context.HttpContext.Response.StatusCode = (int) context
.GetRequiredService<IHttpExceptionStatusCodeFinder>()
.GetStatusCode(context.HttpContext, context.Exception);
context.Result = new ObjectResult(new RemoteServiceErrorResponse(remoteServiceErrorInfo));
}
context.Exception = null; //Handled! context.Exception = null; //Handled!
} }
} }

7
framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Response/AbpNoContentActionFilter.cs

@ -18,8 +18,9 @@ namespace Volo.Abp.AspNetCore.Mvc.Response
await next(); await next();
if (context.HttpContext.Response.StatusCode == (int)HttpStatusCode.OK if (!context.HttpContext.Response.HasStarted &&
&& context.Result == null) context.HttpContext.Response.StatusCode == (int)HttpStatusCode.OK &&
context.Result == null)
{ {
var returnType = context.ActionDescriptor.GetReturnType(); var returnType = context.ActionDescriptor.GetReturnType();
if (returnType == typeof(Task) || returnType == typeof(void)) if (returnType == typeof(Task) || returnType == typeof(void))
@ -29,4 +30,4 @@ namespace Volo.Abp.AspNetCore.Mvc.Response
} }
} }
} }
} }

27
framework/src/Volo.Abp.AspNetCore.Serilog/Properties/launchSettings.json

@ -1,27 +0,0 @@
{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:53606/",
"sslPort": 44319
}
},
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"Volo.Abp.AspNetCore.Serilog": {
"commandName": "Project",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"applicationUrl": "https://localhost:5001;http://localhost:5000"
}
}
}

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

@ -4,7 +4,7 @@
<Import Project="..\..\..\common.props" /> <Import Project="..\..\..\common.props" />
<PropertyGroup> <PropertyGroup>
<TargetFramework>net5.0</TargetFramework> <TargetFramework>net6.0</TargetFramework>
<AssemblyName>Volo.Abp.AspNetCore.Serilog</AssemblyName> <AssemblyName>Volo.Abp.AspNetCore.Serilog</AssemblyName>
<PackageId>Volo.Abp.AspNetCore.Serilog</PackageId> <PackageId>Volo.Abp.AspNetCore.Serilog</PackageId>
<AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback> <AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback>
@ -13,6 +13,7 @@
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute> <GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<IsPackable>true</IsPackable> <IsPackable>true</IsPackable>
<OutputType>Library</OutputType> <OutputType>Library</OutputType>
<NoDefaultLaunchSettingsFile>true</NoDefaultLaunchSettingsFile>
<RootNamespace /> <RootNamespace />
</PropertyGroup> </PropertyGroup>

27
framework/src/Volo.Abp.AspNetCore.SignalR/Properties/launchSettings.json

@ -1,27 +0,0 @@
{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:53611/",
"sslPort": 44331
}
},
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"Volo.Abp.AspNetCore.SignalR": {
"commandName": "Project",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"applicationUrl": "https://localhost:5001;http://localhost:5000"
}
}
}

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

@ -4,7 +4,7 @@
<Import Project="..\..\..\common.props" /> <Import Project="..\..\..\common.props" />
<PropertyGroup> <PropertyGroup>
<TargetFramework>net5.0</TargetFramework> <TargetFramework>net6.0</TargetFramework>
<AssemblyName>Volo.Abp.AspNetCore.SignalR</AssemblyName> <AssemblyName>Volo.Abp.AspNetCore.SignalR</AssemblyName>
<PackageId>Volo.Abp.AspNetCore.SignalR</PackageId> <PackageId>Volo.Abp.AspNetCore.SignalR</PackageId>
<AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback> <AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback>
@ -13,6 +13,7 @@
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute> <GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<IsPackable>true</IsPackable> <IsPackable>true</IsPackable>
<OutputType>Library</OutputType> <OutputType>Library</OutputType>
<NoDefaultLaunchSettingsFile>true</NoDefaultLaunchSettingsFile>
<RootNamespace /> <RootNamespace />
</PropertyGroup> </PropertyGroup>

27
framework/src/Volo.Abp.AspNetCore.TestBase/Properties/launchSettings.json

@ -1,27 +0,0 @@
{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:53599/",
"sslPort": 44358
}
},
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"Volo.Abp.AspNetCore.TestBase": {
"commandName": "Project",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"applicationUrl": "https://localhost:5001;http://localhost:5000"
}
}
}

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

@ -4,7 +4,7 @@
<Import Project="..\..\..\common.props" /> <Import Project="..\..\..\common.props" />
<PropertyGroup> <PropertyGroup>
<TargetFramework>net5.0</TargetFramework> <TargetFramework>net6.0</TargetFramework>
<AssemblyName>Volo.Abp.AspNetCore.TestBase</AssemblyName> <AssemblyName>Volo.Abp.AspNetCore.TestBase</AssemblyName>
<PackageId>Volo.Abp.AspNetCore.TestBase</PackageId> <PackageId>Volo.Abp.AspNetCore.TestBase</PackageId>
<AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback> <AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback>
@ -13,6 +13,7 @@
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute> <GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<IsPackable>true</IsPackable> <IsPackable>true</IsPackable>
<OutputType>Library</OutputType> <OutputType>Library</OutputType>
<NoDefaultLaunchSettingsFile>true</NoDefaultLaunchSettingsFile>
<RootNamespace /> <RootNamespace />
</PropertyGroup> </PropertyGroup>

6
framework/src/Volo.Abp.AspNetCore.TestBase/Volo/Abp/AspNetCore/TestBase/DynamicProxying/AspNetCoreTestDynamicProxyHttpClientFactory.cs → framework/src/Volo.Abp.AspNetCore.TestBase/Volo/Abp/AspNetCore/TestBase/DynamicProxying/AspNetCoreTestProxyHttpClientFactory.cs

@ -1,15 +1,17 @@
using System.Net.Http; using System.Net.Http;
using Volo.Abp.DependencyInjection; using Volo.Abp.DependencyInjection;
using Volo.Abp.Http.Client;
using Volo.Abp.Http.Client.DynamicProxying; using Volo.Abp.Http.Client.DynamicProxying;
using Volo.Abp.Http.Client.Proxying;
namespace Volo.Abp.AspNetCore.TestBase.DynamicProxying namespace Volo.Abp.AspNetCore.TestBase.DynamicProxying
{ {
[Dependency(ReplaceServices = true)] [Dependency(ReplaceServices = true)]
public class AspNetCoreTestDynamicProxyHttpClientFactory : IDynamicProxyHttpClientFactory, ITransientDependency public class AspNetCoreTestProxyHttpClientFactory : IProxyHttpClientFactory, ITransientDependency
{ {
private readonly ITestServerAccessor _testServerAccessor; private readonly ITestServerAccessor _testServerAccessor;
public AspNetCoreTestDynamicProxyHttpClientFactory( public AspNetCoreTestProxyHttpClientFactory(
ITestServerAccessor testServerAccessor) ITestServerAccessor testServerAccessor)
{ {
_testServerAccessor = testServerAccessor; _testServerAccessor = testServerAccessor;

17
framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/Http/AbpHttpRequestExtensions.cs

@ -1,23 +1,18 @@
using JetBrains.Annotations; using System;
using JetBrains.Annotations;
using Microsoft.Net.Http.Headers;
using Volo.Abp; using Volo.Abp;
namespace Microsoft.AspNetCore.Http namespace Microsoft.AspNetCore.Http
{ {
public static class AbpHttpRequestExtensions public static class AbpHttpRequestExtensions
{ {
private const string RequestedWithHeader = "X-Requested-With";
private const string XmlHttpRequest = "XMLHttpRequest";
public static bool IsAjax([NotNull]this HttpRequest request) public static bool IsAjax([NotNull]this HttpRequest request)
{ {
Check.NotNull(request, nameof(request)); Check.NotNull(request, nameof(request));
if (request.Headers == null) return string.Equals(request.Query[HeaderNames.XRequestedWith], "XMLHttpRequest", StringComparison.Ordinal) ||
{ string.Equals(request.Headers[HeaderNames.XRequestedWith], "XMLHttpRequest", StringComparison.Ordinal);
return false;
}
return request.Headers[RequestedWithHeader] == XmlHttpRequest;
} }
public static bool CanAccept([NotNull]this HttpRequest request, [NotNull] string contentType) public static bool CanAccept([NotNull]this HttpRequest request, [NotNull] string contentType)
@ -25,7 +20,7 @@ namespace Microsoft.AspNetCore.Http
Check.NotNull(request, nameof(request)); Check.NotNull(request, nameof(request));
Check.NotNull(contentType, nameof(contentType)); Check.NotNull(contentType, nameof(contentType));
return request.Headers["Accept"].ToString().Contains(contentType); return request.Headers[HeaderNames.Accept].ToString().Contains(contentType, StringComparison.OrdinalIgnoreCase);
} }
} }
} }

1
framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/RequestLocalization/AbpRequestCultureCookieHelper.cs

@ -15,6 +15,7 @@ namespace Microsoft.AspNetCore.RequestLocalization
CookieRequestCultureProvider.MakeCookieValue(requestCulture), CookieRequestCultureProvider.MakeCookieValue(requestCulture),
new CookieOptions new CookieOptions
{ {
IsEssential = true,
Expires = DateTime.Now.AddYears(2) Expires = DateTime.Now.AddYears(2)
} }
); );

27
framework/src/Volo.Abp.AspNetCore/Properties/launchSettings.json

@ -1,27 +0,0 @@
{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:53596/",
"sslPort": 44300
}
},
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"Volo.Abp.AspNetCore": {
"commandName": "Project",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"applicationUrl": "https://localhost:5001;http://localhost:5000"
}
}
}

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

@ -4,7 +4,7 @@
<Import Project="..\..\..\common.props" /> <Import Project="..\..\..\common.props" />
<PropertyGroup> <PropertyGroup>
<TargetFramework>net5.0</TargetFramework> <TargetFramework>net6.0</TargetFramework>
<AssemblyName>Volo.Abp.AspNetCore</AssemblyName> <AssemblyName>Volo.Abp.AspNetCore</AssemblyName>
<PackageId>Volo.Abp.AspNetCore</PackageId> <PackageId>Volo.Abp.AspNetCore</PackageId>
<AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback> <AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback>
@ -13,6 +13,7 @@
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute> <GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<IsPackable>true</IsPackable> <IsPackable>true</IsPackable>
<OutputType>Library</OutputType> <OutputType>Library</OutputType>
<NoDefaultLaunchSettingsFile>true</NoDefaultLaunchSettingsFile>
<RootNamespace /> <RootNamespace />
</PropertyGroup> </PropertyGroup>

7
framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/ExceptionHandling/AbpAuthorizationExceptionHandlerOptions.cs

@ -0,0 +1,7 @@
namespace Volo.Abp.AspNetCore.ExceptionHandling
{
public class AbpAuthorizationExceptionHandlerOptions
{
public string AuthenticationScheme { get; set; }
}
}

45
framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/ExceptionHandling/AbpExceptionHandlingMiddleware.cs

@ -6,6 +6,7 @@ using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using Microsoft.Net.Http.Headers; using Microsoft.Net.Http.Headers;
using Volo.Abp.AspNetCore.Mvc; using Volo.Abp.AspNetCore.Mvc;
using Volo.Abp.Authorization;
using Volo.Abp.DependencyInjection; using Volo.Abp.DependencyInjection;
using Volo.Abp.ExceptionHandling; using Volo.Abp.ExceptionHandling;
using Volo.Abp.Http; using Volo.Abp.Http;
@ -58,30 +59,38 @@ namespace Volo.Abp.AspNetCore.ExceptionHandling
{ {
_logger.LogException(exception); _logger.LogException(exception);
var errorInfoConverter = httpContext.RequestServices.GetRequiredService<IExceptionToErrorInfoConverter>();
var statusCodeFinder = httpContext.RequestServices.GetRequiredService<IHttpExceptionStatusCodeFinder>();
var jsonSerializer = httpContext.RequestServices.GetRequiredService<IJsonSerializer>();
var options = httpContext.RequestServices.GetRequiredService<IOptions<AbpExceptionHandlingOptions>>().Value;
httpContext.Response.Clear();
httpContext.Response.StatusCode = (int)statusCodeFinder.GetStatusCode(httpContext, exception);
httpContext.Response.OnStarting(_clearCacheHeadersDelegate, httpContext.Response);
httpContext.Response.Headers.Add(AbpHttpConsts.AbpErrorFormat, "true");
await httpContext.Response.WriteAsync(
jsonSerializer.Serialize(
new RemoteServiceErrorResponse(
errorInfoConverter.Convert(exception, options.SendExceptionsDetailsToClients)
)
)
);
await httpContext await httpContext
.RequestServices .RequestServices
.GetRequiredService<IExceptionNotifier>() .GetRequiredService<IExceptionNotifier>()
.NotifyAsync( .NotifyAsync(
new ExceptionNotificationContext(exception) new ExceptionNotificationContext(exception)
); );
if (exception is AbpAuthorizationException)
{
await httpContext.RequestServices.GetRequiredService<IAbpAuthorizationExceptionHandler>()
.HandleAsync(exception.As<AbpAuthorizationException>(), httpContext);
}
else
{
var errorInfoConverter = httpContext.RequestServices.GetRequiredService<IExceptionToErrorInfoConverter>();
var statusCodeFinder = httpContext.RequestServices.GetRequiredService<IHttpExceptionStatusCodeFinder>();
var jsonSerializer = httpContext.RequestServices.GetRequiredService<IJsonSerializer>();
var options = httpContext.RequestServices.GetRequiredService<IOptions<AbpExceptionHandlingOptions>>().Value;
httpContext.Response.Clear();
httpContext.Response.StatusCode = (int)statusCodeFinder.GetStatusCode(httpContext, exception);
httpContext.Response.OnStarting(_clearCacheHeadersDelegate, httpContext.Response);
httpContext.Response.Headers.Add(AbpHttpConsts.AbpErrorFormat, "true");
await httpContext.Response.WriteAsync(
jsonSerializer.Serialize(
new RemoteServiceErrorResponse(
errorInfoConverter.Convert(exception, options.SendExceptionsDetailsToClients)
)
)
);
}
} }
private Task ClearCacheHeaders(object state) private Task ClearCacheHeaders(object state)

67
framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/ExceptionHandling/DefaultAbpAuthorizationExceptionHandler.cs

@ -0,0 +1,67 @@
using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using Volo.Abp.Authorization;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.AspNetCore.ExceptionHandling
{
public class DefaultAbpAuthorizationExceptionHandler : IAbpAuthorizationExceptionHandler, ITransientDependency
{
public virtual async Task HandleAsync(AbpAuthorizationException exception, HttpContext httpContext)
{
var handlerOptions = httpContext.RequestServices.GetRequiredService<IOptions<AbpAuthorizationExceptionHandlerOptions>>().Value;
var isAuthenticated = httpContext.User.Identity?.IsAuthenticated ?? false;
var authenticationSchemeProvider = httpContext.RequestServices.GetRequiredService<IAuthenticationSchemeProvider>();
AuthenticationScheme scheme = null;
if (!handlerOptions.AuthenticationScheme.IsNullOrWhiteSpace())
{
scheme = await authenticationSchemeProvider.GetSchemeAsync(handlerOptions.AuthenticationScheme);
if (scheme == null)
{
throw new AbpException($"No authentication scheme named {handlerOptions.AuthenticationScheme} was found.");
}
}
else
{
if (isAuthenticated)
{
scheme = await authenticationSchemeProvider.GetDefaultForbidSchemeAsync();
if (scheme == null)
{
throw new AbpException($"There was no DefaultForbidScheme found.");
}
}
else
{
scheme = await authenticationSchemeProvider.GetDefaultChallengeSchemeAsync();
if (scheme == null)
{
throw new AbpException($"There was no DefaultChallengeScheme found.");
}
}
}
var handlers = httpContext.RequestServices.GetRequiredService<IAuthenticationHandlerProvider>();
var handler = await handlers.GetHandlerAsync(httpContext, scheme.Name);
if (handler == null)
{
throw new AbpException($"No handler of {scheme.Name} was found.");
}
if (isAuthenticated)
{
await handler.ForbidAsync(null);
}
else
{
await handler.ChallengeAsync(null);
}
}
}
}

11
framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/ExceptionHandling/IAbpAuthorizationExceptionHandler.cs

@ -0,0 +1,11 @@
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Volo.Abp.Authorization;
namespace Volo.Abp.AspNetCore.ExceptionHandling
{
public interface IAbpAuthorizationExceptionHandler
{
Task HandleAsync(AbpAuthorizationException exception, HttpContext httpContext);
}
}

3
framework/src/Volo.Abp.Auditing.Contracts/FodyWeavers.xml

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

30
framework/src/Volo.Abp.Auditing.Contracts/FodyWeavers.xsd

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

21
framework/src/Volo.Abp.Auditing.Contracts/Volo.Abp.Auditing.Contracts.csproj

@ -0,0 +1,21 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\configureawait.props" />
<Import Project="..\..\..\common.props" />
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<AssemblyName>Volo.Abp.Auditing.Contracts</AssemblyName>
<PackageId>Volo.Abp.Auditing.Contracts</PackageId>
<AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Volo.Abp.Core\Volo.Abp.Core.csproj" />
</ItemGroup>
</Project>

9
framework/src/Volo.Abp.Auditing.Contracts/Volo/Abp/Auditing/AbpAuditingContractsModule.cs

@ -0,0 +1,9 @@
using Volo.Abp.Modularity;
namespace Volo.Abp.Auditing
{
public class AbpAuditingContractsModule : AbpModule
{
}
}

0
framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/AuditedAttribute.cs → framework/src/Volo.Abp.Auditing.Contracts/Volo/Abp/Auditing/AuditedAttribute.cs

0
framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/DisableAuditingAttribute.cs → framework/src/Volo.Abp.Auditing.Contracts/Volo/Abp/Auditing/DisableAuditingAttribute.cs

0
framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/EntityChangeType.cs → framework/src/Volo.Abp.Auditing.Contracts/Volo/Abp/Auditing/EntityChangeType.cs

0
framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/IAuditedObject.cs → framework/src/Volo.Abp.Auditing.Contracts/Volo/Abp/Auditing/IAuditedObject.cs

0
framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/IAuditingEnabled.cs → framework/src/Volo.Abp.Auditing.Contracts/Volo/Abp/Auditing/IAuditingEnabled.cs

0
framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/ICreationAuditedObject.cs → framework/src/Volo.Abp.Auditing.Contracts/Volo/Abp/Auditing/ICreationAuditedObject.cs

0
framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/IDeletionAuditedObject.cs → framework/src/Volo.Abp.Auditing.Contracts/Volo/Abp/Auditing/IDeletionAuditedObject.cs

0
framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/IFullAuditedObject.cs → framework/src/Volo.Abp.Auditing.Contracts/Volo/Abp/Auditing/IFullAuditedObject.cs

0
framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/IHasCreationTime.cs → framework/src/Volo.Abp.Auditing.Contracts/Volo/Abp/Auditing/IHasCreationTime.cs

0
framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/IHasDeletionTime.cs → framework/src/Volo.Abp.Auditing.Contracts/Volo/Abp/Auditing/IHasDeletionTime.cs

0
framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/IHasModificationTime.cs → framework/src/Volo.Abp.Auditing.Contracts/Volo/Abp/Auditing/IHasModificationTime.cs

0
framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/IMayHaveCreator.cs → framework/src/Volo.Abp.Auditing.Contracts/Volo/Abp/Auditing/IMayHaveCreator.cs

0
framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/IModificationAuditedObject.cs → framework/src/Volo.Abp.Auditing.Contracts/Volo/Abp/Auditing/IModificationAuditedObject.cs

0
framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/IMustHaveCreator.cs → framework/src/Volo.Abp.Auditing.Contracts/Volo/Abp/Auditing/IMustHaveCreator.cs

1
framework/src/Volo.Abp.Auditing/Volo.Abp.Auditing.csproj

@ -15,6 +15,7 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Volo.Abp.Auditing.Contracts\Volo.Abp.Auditing.Contracts.csproj" />
<ProjectReference Include="..\Volo.Abp.Data\Volo.Abp.Data.csproj" /> <ProjectReference Include="..\Volo.Abp.Data\Volo.Abp.Data.csproj" />
<ProjectReference Include="..\Volo.Abp.Json\Volo.Abp.Json.csproj" /> <ProjectReference Include="..\Volo.Abp.Json\Volo.Abp.Json.csproj" />
<ProjectReference Include="..\Volo.Abp.MultiTenancy\Volo.Abp.MultiTenancy.csproj" /> <ProjectReference Include="..\Volo.Abp.MultiTenancy\Volo.Abp.MultiTenancy.csproj" />

3
framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/AbpAuditingModule.cs

@ -15,7 +15,8 @@ namespace Volo.Abp.Auditing
typeof(AbpTimingModule), typeof(AbpTimingModule),
typeof(AbpSecurityModule), typeof(AbpSecurityModule),
typeof(AbpThreadingModule), typeof(AbpThreadingModule),
typeof(AbpMultiTenancyModule) typeof(AbpMultiTenancyModule),
typeof(AbpAuditingContractsModule)
)] )]
public class AbpAuditingModule : AbpModule public class AbpAuditingModule : AbpModule
{ {

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

@ -4,7 +4,7 @@
<Import Project="..\..\..\common.props" /> <Import Project="..\..\..\common.props" />
<PropertyGroup> <PropertyGroup>
<TargetFramework>net5.0</TargetFramework> <TargetFramework>net6.0</TargetFramework>
<RootNamespace /> <RootNamespace />
</PropertyGroup> </PropertyGroup>

6
framework/src/Volo.Abp.BackgroundJobs.RabbitMQ/Volo/Abp/BackgroundJobs/RabbitMQ/AbpRabbitMqBackgroundJobOptions.cs

@ -15,10 +15,16 @@ namespace Volo.Abp.BackgroundJobs.RabbitMQ
/// </summary> /// </summary>
public string DefaultQueueNamePrefix { get; set; } public string DefaultQueueNamePrefix { get; set; }
/// <summary>
/// Default value: "AbpBackgroundJobsDelayed."
/// </summary>
public string DefaultDelayedQueueNamePrefix { get; set;}
public AbpRabbitMqBackgroundJobOptions() public AbpRabbitMqBackgroundJobOptions()
{ {
JobQueues = new Dictionary<Type, JobQueueConfiguration>(); JobQueues = new Dictionary<Type, JobQueueConfiguration>();
DefaultQueueNamePrefix = "AbpBackgroundJobs."; DefaultQueueNamePrefix = "AbpBackgroundJobs.";
DefaultDelayedQueueNamePrefix = "AbpBackgroundJobsDelayed.";
} }
} }
} }

22
framework/src/Volo.Abp.BackgroundJobs.RabbitMQ/Volo/Abp/BackgroundJobs/RabbitMQ/JobQueue.cs

@ -1,5 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Globalization;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
@ -64,7 +65,8 @@ namespace Volo.Abp.BackgroundJobs.RabbitMQ
return AbpRabbitMqBackgroundJobOptions.JobQueues.GetOrDefault(typeof(TArgs)) ?? return AbpRabbitMqBackgroundJobOptions.JobQueues.GetOrDefault(typeof(TArgs)) ??
new JobQueueConfiguration( new JobQueueConfiguration(
typeof(TArgs), typeof(TArgs),
AbpRabbitMqBackgroundJobOptions.DefaultQueueNamePrefix + JobConfiguration.JobName AbpRabbitMqBackgroundJobOptions.DefaultQueueNamePrefix + JobConfiguration.JobName,
AbpRabbitMqBackgroundJobOptions.DefaultDelayedQueueNamePrefix + JobConfiguration.JobName
); );
} }
@ -133,6 +135,9 @@ namespace Volo.Abp.BackgroundJobs.RabbitMQ
var result = QueueConfiguration.Declare(ChannelAccessor.Channel); var result = QueueConfiguration.Declare(ChannelAccessor.Channel);
Logger.LogDebug($"RabbitMQ Queue '{QueueConfiguration.QueueName}' has {result.MessageCount} messages and {result.ConsumerCount} consumers."); Logger.LogDebug($"RabbitMQ Queue '{QueueConfiguration.QueueName}' has {result.MessageCount} messages and {result.ConsumerCount} consumers.");
// Declare delayed queue
QueueConfiguration.DeclareDelayed(ChannelAccessor.Channel);
if (AbpBackgroundJobOptions.IsJobExecutionEnabled) if (AbpBackgroundJobOptions.IsJobExecutionEnabled)
{ {
Consumer = new AsyncEventingBasicConsumer(ChannelAccessor.Channel); Consumer = new AsyncEventingBasicConsumer(ChannelAccessor.Channel);
@ -154,12 +159,21 @@ namespace Volo.Abp.BackgroundJobs.RabbitMQ
BackgroundJobPriority priority = BackgroundJobPriority.Normal, BackgroundJobPriority priority = BackgroundJobPriority.Normal,
TimeSpan? delay = null) TimeSpan? delay = null)
{ {
//TODO: How to handle priority & delay? //TODO: How to handle priority
var routingKey = QueueConfiguration.QueueName;
var basicProperties = CreateBasicPropertiesToPublish();
if (delay.HasValue)
{
routingKey = QueueConfiguration.DelayedQueueName;
basicProperties.Expiration = delay.Value.TotalMilliseconds.ToString();
}
ChannelAccessor.Channel.BasicPublish( ChannelAccessor.Channel.BasicPublish(
exchange: "", exchange: "",
routingKey: QueueConfiguration.QueueName, routingKey: routingKey,
basicProperties: CreateBasicPropertiesToPublish(), basicProperties: basicProperties,
body: Serializer.Serialize(args) body: Serializer.Serialize(args)
); );

35
framework/src/Volo.Abp.BackgroundJobs.RabbitMQ/Volo/Abp/BackgroundJobs/RabbitMQ/JobQueueConfiguration.cs

@ -1,4 +1,6 @@
using System; using System;
using System.Collections.Generic;
using RabbitMQ.Client;
using Volo.Abp.RabbitMQ; using Volo.Abp.RabbitMQ;
namespace Volo.Abp.BackgroundJobs.RabbitMQ namespace Volo.Abp.BackgroundJobs.RabbitMQ
@ -9,21 +11,42 @@ namespace Volo.Abp.BackgroundJobs.RabbitMQ
public string ConnectionName { get; set; } public string ConnectionName { get; set; }
public string DelayedQueueName { get; set; }
public JobQueueConfiguration( public JobQueueConfiguration(
Type jobArgsType, Type jobArgsType,
string queueName, string queueName,
string delayedQueueName,
string connectionName = null, string connectionName = null,
bool durable = true, bool durable = true,
bool exclusive = false, bool exclusive = false,
bool autoDelete = false) bool autoDelete = false)
: base( : base(
queueName, queueName,
durable, durable,
exclusive, exclusive,
autoDelete) autoDelete)
{ {
JobArgsType = jobArgsType; JobArgsType = jobArgsType;
ConnectionName = connectionName; ConnectionName = connectionName;
DelayedQueueName = delayedQueueName;
}
public virtual QueueDeclareOk DeclareDelayed(IModel channel)
{
var delayedArguments = new Dictionary<string, object>(Arguments)
{
["x-dead-letter-routing-key"] = QueueName,
["x-dead-letter-exchange"] = string.Empty
};
return channel.QueueDeclare(
queue: DelayedQueueName,
durable: Durable,
exclusive: Exclusive,
autoDelete: AutoDelete,
arguments: delayedArguments
);
} }
} }
} }

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

@ -4,7 +4,7 @@
<Import Project="..\..\..\common.props" /> <Import Project="..\..\..\common.props" />
<PropertyGroup> <PropertyGroup>
<TargetFramework>net5.0</TargetFramework> <TargetFramework>net6.0</TargetFramework>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

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

Loading…
Cancel
Save