From 35c1d810c4e4dc4b9aef2db5baf23bf474181f7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mehmet=20Tu=CC=88ken?= Date: Wed, 18 Dec 2019 02:22:08 +0300 Subject: [PATCH 01/88] [framework] fix mongo.exe dispose --- .../Volo/Abp/MongoDB/AbpMongoDbTestModule.cs | 7 ++---- .../Abp/MongoDB/Auditing/Auditing_Tests.cs | 2 ++ .../MultiTenant_Creation_Tests.cs | 2 ++ .../DataFiltering/MultiTenant_Filter_Tests.cs | 2 ++ .../DataFiltering/SoftDelete_Filter_Tests.cs | 2 ++ .../MongoDB/DataFiltering/SoftDelete_Tests.cs | 2 ++ .../MongoDB/Domain/ConcurrencyStamp_Tests.cs | 2 ++ .../MongoDB/Domain/ExtraProperties_Tests.cs | 2 ++ .../DomainEvents/DomainEvents_Tests.cs | 2 ++ .../DomainEvents/EntityChangeEvents_Tests.cs | 2 ++ .../Volo/Abp/MongoDB/MongoDbFixture.cs | 25 +++++++++++++++++++ .../Volo/Abp/MongoDB/MongoTestCollection.cs | 10 ++++++++ .../Repositories/Repository_Basic_Tests.cs | 1 + .../Repository_Basic_Tests_With_Int_Pk.cs | 1 + .../Repository_Queryable_Tests.cs | 2 ++ .../Repository_Specifications_Tests.cs | 2 ++ .../Abp/MongoDB/Uow/Uow_Completed_Tests.cs | 3 ++- 17 files changed, 63 insertions(+), 6 deletions(-) create mode 100644 framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/MongoDbFixture.cs create mode 100644 framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/MongoTestCollection.cs diff --git a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/AbpMongoDbTestModule.cs b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/AbpMongoDbTestModule.cs index 86620366b3..112ecaf34d 100644 --- a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/AbpMongoDbTestModule.cs +++ b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/AbpMongoDbTestModule.cs @@ -1,6 +1,5 @@ using System; using Microsoft.Extensions.DependencyInjection; -using Mongo2Go; using Volo.Abp.Data; using Volo.Abp.Modularity; using Volo.Abp.TestApp; @@ -15,13 +14,11 @@ namespace Volo.Abp.MongoDB )] public class AbpMongoDbTestModule : AbpModule { - private static readonly MongoDbRunner MongoDbRunner = MongoDbRunner.Start(); - public override void ConfigureServices(ServiceConfigurationContext context) { - var connectionString = MongoDbRunner.ConnectionString.EnsureEndsWith('/') + + var connectionString = MongoDbFixture.GetConnectionString().EnsureEndsWith('/') + "Db_" + - Guid.NewGuid().ToString("N"); + Guid.NewGuid().ToString("N"); Configure(options => { diff --git a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/Auditing/Auditing_Tests.cs b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/Auditing/Auditing_Tests.cs index c5d7b87752..e20cceaf0e 100644 --- a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/Auditing/Auditing_Tests.cs +++ b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/Auditing/Auditing_Tests.cs @@ -1,7 +1,9 @@ using Volo.Abp.TestApp.Testing; +using Xunit; namespace Volo.Abp.MongoDB.Auditing { + [Collection("MongoDB Collection")] public class Auditing_Tests : Auditing_Tests { diff --git a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/DataFiltering/MultiTenant_Creation_Tests.cs b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/DataFiltering/MultiTenant_Creation_Tests.cs index a1ee94a943..3e4e532f5a 100644 --- a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/DataFiltering/MultiTenant_Creation_Tests.cs +++ b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/DataFiltering/MultiTenant_Creation_Tests.cs @@ -1,7 +1,9 @@ using Volo.Abp.TestApp.Testing; +using Xunit; namespace Volo.Abp.MongoDB.DataFiltering { + [Collection("MongoDB Collection")] public class MultiTenant_Creation_Tests : MultiTenant_Creation_Tests { diff --git a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/DataFiltering/MultiTenant_Filter_Tests.cs b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/DataFiltering/MultiTenant_Filter_Tests.cs index c23761a05c..c4ace6f1fe 100644 --- a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/DataFiltering/MultiTenant_Filter_Tests.cs +++ b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/DataFiltering/MultiTenant_Filter_Tests.cs @@ -1,7 +1,9 @@ using Volo.Abp.TestApp.Testing; +using Xunit; namespace Volo.Abp.MongoDB.DataFiltering { + [Collection("MongoDB Collection")] public class MultiTenant_Filter_Tests : MultiTenant_Filter_Tests { diff --git a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/DataFiltering/SoftDelete_Filter_Tests.cs b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/DataFiltering/SoftDelete_Filter_Tests.cs index 3636b998bb..6a6167133b 100644 --- a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/DataFiltering/SoftDelete_Filter_Tests.cs +++ b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/DataFiltering/SoftDelete_Filter_Tests.cs @@ -1,7 +1,9 @@ using Volo.Abp.TestApp.Testing; +using Xunit; namespace Volo.Abp.MongoDB.DataFiltering { + [Collection("MongoDB Collection")] public class SoftDelete_Filter_Tests : SoftDelete_Filter_Tests { diff --git a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/DataFiltering/SoftDelete_Tests.cs b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/DataFiltering/SoftDelete_Tests.cs index fdd8ec1a5e..f3d9d75c9e 100644 --- a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/DataFiltering/SoftDelete_Tests.cs +++ b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/DataFiltering/SoftDelete_Tests.cs @@ -1,7 +1,9 @@ using Volo.Abp.TestApp.Testing; +using Xunit; namespace Volo.Abp.MongoDB.DataFiltering { + [Collection("MongoDB Collection")] public class SoftDelete_Tests : SoftDelete_Tests { diff --git a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/Domain/ConcurrencyStamp_Tests.cs b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/Domain/ConcurrencyStamp_Tests.cs index 117cd5dde1..4882e43c13 100644 --- a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/Domain/ConcurrencyStamp_Tests.cs +++ b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/Domain/ConcurrencyStamp_Tests.cs @@ -1,7 +1,9 @@ using Volo.Abp.TestApp.Testing; +using Xunit; namespace Volo.Abp.MongoDB.Domain { + [Collection("MongoDB Collection")] public class ConcurrencyStamp_Tests : ConcurrencyStamp_Tests { diff --git a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/Domain/ExtraProperties_Tests.cs b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/Domain/ExtraProperties_Tests.cs index b389ad61b9..9a4675e24f 100644 --- a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/Domain/ExtraProperties_Tests.cs +++ b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/Domain/ExtraProperties_Tests.cs @@ -1,7 +1,9 @@ using Volo.Abp.TestApp.Testing; +using Xunit; namespace Volo.Abp.MongoDB.Domain { + [Collection("MongoDB Collection")] public class ExtraProperties_Tests : ExtraProperties_Tests { diff --git a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/DomainEvents/DomainEvents_Tests.cs b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/DomainEvents/DomainEvents_Tests.cs index b01cb690f6..a9f232b989 100644 --- a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/DomainEvents/DomainEvents_Tests.cs +++ b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/DomainEvents/DomainEvents_Tests.cs @@ -1,7 +1,9 @@ using Volo.Abp.TestApp.Testing; +using Xunit; namespace Volo.Abp.MongoDB.DomainEvents { + [Collection("MongoDB Collection")] public class DomainEvents_Tests : DomainEvents_Tests { } diff --git a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/DomainEvents/EntityChangeEvents_Tests.cs b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/DomainEvents/EntityChangeEvents_Tests.cs index 0df187f34e..3f4882b524 100644 --- a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/DomainEvents/EntityChangeEvents_Tests.cs +++ b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/DomainEvents/EntityChangeEvents_Tests.cs @@ -1,7 +1,9 @@ using Volo.Abp.TestApp.Testing; +using Xunit; namespace Volo.Abp.MongoDB.DomainEvents { + [Collection("MongoDB Collection")] public class EntityChangeEvents_Tests : EntityChangeEvents_Tests { diff --git a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/MongoDbFixture.cs b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/MongoDbFixture.cs new file mode 100644 index 0000000000..0e483febab --- /dev/null +++ b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/MongoDbFixture.cs @@ -0,0 +1,25 @@ +using System; +using Mongo2Go; + +namespace Volo.Abp.MongoDB +{ + public class MongoDbFixture : IDisposable + { + public static MongoDbRunner MongoDbRunner; + + public MongoDbFixture() + { + MongoDbRunner = MongoDbRunner.Start(); + } + + public static string GetConnectionString() + { + return MongoDbRunner.ConnectionString; + } + + public void Dispose() + { + MongoDbRunner?.Dispose(); + } + } +} \ No newline at end of file diff --git a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/MongoTestCollection.cs b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/MongoTestCollection.cs new file mode 100644 index 0000000000..2d57ed24fa --- /dev/null +++ b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/MongoTestCollection.cs @@ -0,0 +1,10 @@ +using Xunit; + +namespace Volo.Abp.MongoDB +{ + [CollectionDefinition("MongoDB Collection")] + public class MongoTestCollection : ICollectionFixture + { + + } +} \ No newline at end of file diff --git a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/Repositories/Repository_Basic_Tests.cs b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/Repositories/Repository_Basic_Tests.cs index 72774be545..112044d22d 100644 --- a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/Repositories/Repository_Basic_Tests.cs +++ b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/Repositories/Repository_Basic_Tests.cs @@ -9,6 +9,7 @@ using Xunit; namespace Volo.Abp.MongoDB.Repositories { + [Collection("MongoDB Collection")] public class Repository_Basic_Tests : Repository_Basic_Tests { [Fact] diff --git a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/Repositories/Repository_Basic_Tests_With_Int_Pk.cs b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/Repositories/Repository_Basic_Tests_With_Int_Pk.cs index 58914e8e50..a3ae87cf58 100644 --- a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/Repositories/Repository_Basic_Tests_With_Int_Pk.cs +++ b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/Repositories/Repository_Basic_Tests_With_Int_Pk.cs @@ -3,6 +3,7 @@ using Xunit; namespace Volo.Abp.MongoDB.Repositories { + [Collection("MongoDB Collection")] public class Repository_Basic_Tests_With_Int_Pk : Repository_Basic_Tests_With_Int_Pk { [Fact(Skip = "Int PKs are not working for MongoDb")] diff --git a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/Repositories/Repository_Queryable_Tests.cs b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/Repositories/Repository_Queryable_Tests.cs index d396471bed..f75a5b4a34 100644 --- a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/Repositories/Repository_Queryable_Tests.cs +++ b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/Repositories/Repository_Queryable_Tests.cs @@ -1,7 +1,9 @@ using Volo.Abp.TestApp.Testing; +using Xunit; namespace Volo.Abp.MongoDB.Repositories { + [Collection("MongoDB Collection")] public class Repository_Queryable_Tests : Repository_Queryable_Tests { diff --git a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/Repositories/Repository_Specifications_Tests.cs b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/Repositories/Repository_Specifications_Tests.cs index 6529b4c5a9..c0a4439f09 100644 --- a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/Repositories/Repository_Specifications_Tests.cs +++ b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/Repositories/Repository_Specifications_Tests.cs @@ -1,7 +1,9 @@ using Volo.Abp.TestApp.Testing; +using Xunit; namespace Volo.Abp.MongoDB.Repositories { + [Collection("MongoDB Collection")] public class Repository_Specifications_Tests : Repository_Specifications_Tests { } diff --git a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/Uow/Uow_Completed_Tests.cs b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/Uow/Uow_Completed_Tests.cs index 4773644885..00bae8dc12 100644 --- a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/Uow/Uow_Completed_Tests.cs +++ b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/Uow/Uow_Completed_Tests.cs @@ -1,9 +1,10 @@ using Volo.Abp.TestApp.Testing; +using Xunit; namespace Volo.Abp.MongoDB.Uow { + [Collection("MongoDB Collection")] public class Uow_Completed_Tests : Uow_Completed_Tests { - } } \ No newline at end of file From ca57cf3ea70fa551026d8de09bb115da26e63d3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mehmet=20Tu=CC=88ken?= Date: Wed, 18 Dec 2019 02:39:10 +0300 Subject: [PATCH 02/88] refactor --- .../Volo/Abp/MongoDB/AbpMongoDbTestModule.cs | 2 +- .../Volo/Abp/MongoDB/Auditing/Auditing_Tests.cs | 2 +- .../DataFiltering/MultiTenant_Creation_Tests.cs | 2 +- .../DataFiltering/MultiTenant_Filter_Tests.cs | 2 +- .../DataFiltering/SoftDelete_Filter_Tests.cs | 2 +- .../Abp/MongoDB/DataFiltering/SoftDelete_Tests.cs | 2 +- .../Abp/MongoDB/Domain/ConcurrencyStamp_Tests.cs | 2 +- .../Abp/MongoDB/Domain/ExtraProperties_Tests.cs | 2 +- .../Abp/MongoDB/DomainEvents/DomainEvents_Tests.cs | 2 +- .../DomainEvents/EntityChangeEvents_Tests.cs | 2 +- .../Volo/Abp/MongoDB/MongoDbFixture.cs | 13 ++----------- .../Volo/Abp/MongoDB/MongoTestCollection.cs | 4 ++-- .../MongoDB/Repositories/Repository_Basic_Tests.cs | 2 +- .../Repository_Basic_Tests_With_Int_Pk.cs | 2 +- .../Repositories/Repository_Queryable_Tests.cs | 2 +- .../Repositories/Repository_Specifications_Tests.cs | 2 +- .../Volo/Abp/MongoDB/Uow/Uow_Completed_Tests.cs | 2 +- .../Volo/Abp/AuditLogging/MongoDB/MongoDbFixture.cs | 7 +++++++ .../Abp/AuditLogging/MongoDB/MongoTestCollection.cs | 7 +++++++ 19 files changed, 33 insertions(+), 28 deletions(-) create mode 100644 modules/audit-logging/test/Volo.Abp.AuditLogging.MongoDB.Tests/Volo/Abp/AuditLogging/MongoDB/MongoDbFixture.cs create mode 100644 modules/audit-logging/test/Volo.Abp.AuditLogging.MongoDB.Tests/Volo/Abp/AuditLogging/MongoDB/MongoTestCollection.cs diff --git a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/AbpMongoDbTestModule.cs b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/AbpMongoDbTestModule.cs index 112ecaf34d..cfa7b033b7 100644 --- a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/AbpMongoDbTestModule.cs +++ b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/AbpMongoDbTestModule.cs @@ -16,7 +16,7 @@ namespace Volo.Abp.MongoDB { public override void ConfigureServices(ServiceConfigurationContext context) { - var connectionString = MongoDbFixture.GetConnectionString().EnsureEndsWith('/') + + var connectionString = MongoDbFixture.ConnectionString.EnsureEndsWith('/') + "Db_" + Guid.NewGuid().ToString("N"); diff --git a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/Auditing/Auditing_Tests.cs b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/Auditing/Auditing_Tests.cs index e20cceaf0e..b08c2120a4 100644 --- a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/Auditing/Auditing_Tests.cs +++ b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/Auditing/Auditing_Tests.cs @@ -3,7 +3,7 @@ using Xunit; namespace Volo.Abp.MongoDB.Auditing { - [Collection("MongoDB Collection")] + [Collection(MongoTestCollection.Name)] public class Auditing_Tests : Auditing_Tests { diff --git a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/DataFiltering/MultiTenant_Creation_Tests.cs b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/DataFiltering/MultiTenant_Creation_Tests.cs index 3e4e532f5a..0ab365a568 100644 --- a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/DataFiltering/MultiTenant_Creation_Tests.cs +++ b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/DataFiltering/MultiTenant_Creation_Tests.cs @@ -3,7 +3,7 @@ using Xunit; namespace Volo.Abp.MongoDB.DataFiltering { - [Collection("MongoDB Collection")] + [Collection(MongoTestCollection.Name)] public class MultiTenant_Creation_Tests : MultiTenant_Creation_Tests { diff --git a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/DataFiltering/MultiTenant_Filter_Tests.cs b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/DataFiltering/MultiTenant_Filter_Tests.cs index c4ace6f1fe..c32b640e03 100644 --- a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/DataFiltering/MultiTenant_Filter_Tests.cs +++ b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/DataFiltering/MultiTenant_Filter_Tests.cs @@ -3,7 +3,7 @@ using Xunit; namespace Volo.Abp.MongoDB.DataFiltering { - [Collection("MongoDB Collection")] + [Collection(MongoTestCollection.Name)] public class MultiTenant_Filter_Tests : MultiTenant_Filter_Tests { diff --git a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/DataFiltering/SoftDelete_Filter_Tests.cs b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/DataFiltering/SoftDelete_Filter_Tests.cs index 6a6167133b..5de6caf661 100644 --- a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/DataFiltering/SoftDelete_Filter_Tests.cs +++ b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/DataFiltering/SoftDelete_Filter_Tests.cs @@ -3,7 +3,7 @@ using Xunit; namespace Volo.Abp.MongoDB.DataFiltering { - [Collection("MongoDB Collection")] + [Collection(MongoTestCollection.Name)] public class SoftDelete_Filter_Tests : SoftDelete_Filter_Tests { diff --git a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/DataFiltering/SoftDelete_Tests.cs b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/DataFiltering/SoftDelete_Tests.cs index f3d9d75c9e..bffb38f858 100644 --- a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/DataFiltering/SoftDelete_Tests.cs +++ b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/DataFiltering/SoftDelete_Tests.cs @@ -3,7 +3,7 @@ using Xunit; namespace Volo.Abp.MongoDB.DataFiltering { - [Collection("MongoDB Collection")] + [Collection(MongoTestCollection.Name)] public class SoftDelete_Tests : SoftDelete_Tests { diff --git a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/Domain/ConcurrencyStamp_Tests.cs b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/Domain/ConcurrencyStamp_Tests.cs index 4882e43c13..88bf889b7c 100644 --- a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/Domain/ConcurrencyStamp_Tests.cs +++ b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/Domain/ConcurrencyStamp_Tests.cs @@ -3,7 +3,7 @@ using Xunit; namespace Volo.Abp.MongoDB.Domain { - [Collection("MongoDB Collection")] + [Collection(MongoTestCollection.Name)] public class ConcurrencyStamp_Tests : ConcurrencyStamp_Tests { diff --git a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/Domain/ExtraProperties_Tests.cs b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/Domain/ExtraProperties_Tests.cs index 9a4675e24f..5f8f8784c3 100644 --- a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/Domain/ExtraProperties_Tests.cs +++ b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/Domain/ExtraProperties_Tests.cs @@ -3,7 +3,7 @@ using Xunit; namespace Volo.Abp.MongoDB.Domain { - [Collection("MongoDB Collection")] + [Collection(MongoTestCollection.Name)] public class ExtraProperties_Tests : ExtraProperties_Tests { diff --git a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/DomainEvents/DomainEvents_Tests.cs b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/DomainEvents/DomainEvents_Tests.cs index a9f232b989..ed480a229e 100644 --- a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/DomainEvents/DomainEvents_Tests.cs +++ b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/DomainEvents/DomainEvents_Tests.cs @@ -3,7 +3,7 @@ using Xunit; namespace Volo.Abp.MongoDB.DomainEvents { - [Collection("MongoDB Collection")] + [Collection(MongoTestCollection.Name)] public class DomainEvents_Tests : DomainEvents_Tests { } diff --git a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/DomainEvents/EntityChangeEvents_Tests.cs b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/DomainEvents/EntityChangeEvents_Tests.cs index 3f4882b524..184142d77c 100644 --- a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/DomainEvents/EntityChangeEvents_Tests.cs +++ b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/DomainEvents/EntityChangeEvents_Tests.cs @@ -3,7 +3,7 @@ using Xunit; namespace Volo.Abp.MongoDB.DomainEvents { - [Collection("MongoDB Collection")] + [Collection(MongoTestCollection.Name)] public class EntityChangeEvents_Tests : EntityChangeEvents_Tests { diff --git a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/MongoDbFixture.cs b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/MongoDbFixture.cs index 0e483febab..f401d0d6d4 100644 --- a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/MongoDbFixture.cs +++ b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/MongoDbFixture.cs @@ -5,18 +5,9 @@ namespace Volo.Abp.MongoDB { public class MongoDbFixture : IDisposable { - public static MongoDbRunner MongoDbRunner; + private static readonly MongoDbRunner MongoDbRunner = MongoDbRunner.Start(); + public static readonly string ConnectionString = MongoDbRunner.ConnectionString; - public MongoDbFixture() - { - MongoDbRunner = MongoDbRunner.Start(); - } - - public static string GetConnectionString() - { - return MongoDbRunner.ConnectionString; - } - public void Dispose() { MongoDbRunner?.Dispose(); diff --git a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/MongoTestCollection.cs b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/MongoTestCollection.cs index 2d57ed24fa..ae23dc9450 100644 --- a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/MongoTestCollection.cs +++ b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/MongoTestCollection.cs @@ -2,9 +2,9 @@ using Xunit; namespace Volo.Abp.MongoDB { - [CollectionDefinition("MongoDB Collection")] + [CollectionDefinition(Name)] public class MongoTestCollection : ICollectionFixture { - + public const string Name = "MongoDB Collection"; } } \ No newline at end of file diff --git a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/Repositories/Repository_Basic_Tests.cs b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/Repositories/Repository_Basic_Tests.cs index 112044d22d..64af3aa855 100644 --- a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/Repositories/Repository_Basic_Tests.cs +++ b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/Repositories/Repository_Basic_Tests.cs @@ -9,7 +9,7 @@ using Xunit; namespace Volo.Abp.MongoDB.Repositories { - [Collection("MongoDB Collection")] + [Collection(MongoTestCollection.Name)] public class Repository_Basic_Tests : Repository_Basic_Tests { [Fact] diff --git a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/Repositories/Repository_Basic_Tests_With_Int_Pk.cs b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/Repositories/Repository_Basic_Tests_With_Int_Pk.cs index a3ae87cf58..2b8be02617 100644 --- a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/Repositories/Repository_Basic_Tests_With_Int_Pk.cs +++ b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/Repositories/Repository_Basic_Tests_With_Int_Pk.cs @@ -3,7 +3,7 @@ using Xunit; namespace Volo.Abp.MongoDB.Repositories { - [Collection("MongoDB Collection")] + [Collection(MongoTestCollection.Name)] public class Repository_Basic_Tests_With_Int_Pk : Repository_Basic_Tests_With_Int_Pk { [Fact(Skip = "Int PKs are not working for MongoDb")] diff --git a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/Repositories/Repository_Queryable_Tests.cs b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/Repositories/Repository_Queryable_Tests.cs index f75a5b4a34..05ffb6ae27 100644 --- a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/Repositories/Repository_Queryable_Tests.cs +++ b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/Repositories/Repository_Queryable_Tests.cs @@ -3,7 +3,7 @@ using Xunit; namespace Volo.Abp.MongoDB.Repositories { - [Collection("MongoDB Collection")] + [Collection(MongoTestCollection.Name)] public class Repository_Queryable_Tests : Repository_Queryable_Tests { diff --git a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/Repositories/Repository_Specifications_Tests.cs b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/Repositories/Repository_Specifications_Tests.cs index c0a4439f09..4670ac5d00 100644 --- a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/Repositories/Repository_Specifications_Tests.cs +++ b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/Repositories/Repository_Specifications_Tests.cs @@ -3,7 +3,7 @@ using Xunit; namespace Volo.Abp.MongoDB.Repositories { - [Collection("MongoDB Collection")] + [Collection(MongoTestCollection.Name)] public class Repository_Specifications_Tests : Repository_Specifications_Tests { } diff --git a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/Uow/Uow_Completed_Tests.cs b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/Uow/Uow_Completed_Tests.cs index 00bae8dc12..cef724b9bd 100644 --- a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/Uow/Uow_Completed_Tests.cs +++ b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/Uow/Uow_Completed_Tests.cs @@ -3,7 +3,7 @@ using Xunit; namespace Volo.Abp.MongoDB.Uow { - [Collection("MongoDB Collection")] + [Collection(MongoTestCollection.Name)] public class Uow_Completed_Tests : Uow_Completed_Tests { } diff --git a/modules/audit-logging/test/Volo.Abp.AuditLogging.MongoDB.Tests/Volo/Abp/AuditLogging/MongoDB/MongoDbFixture.cs b/modules/audit-logging/test/Volo.Abp.AuditLogging.MongoDB.Tests/Volo/Abp/AuditLogging/MongoDB/MongoDbFixture.cs new file mode 100644 index 0000000000..cc2f90e01d --- /dev/null +++ b/modules/audit-logging/test/Volo.Abp.AuditLogging.MongoDB.Tests/Volo/Abp/AuditLogging/MongoDB/MongoDbFixture.cs @@ -0,0 +1,7 @@ +namespace Volo.Abp.AuditLogging.MongoDB +{ + public class MongoDbFixture + { + + } +} \ No newline at end of file diff --git a/modules/audit-logging/test/Volo.Abp.AuditLogging.MongoDB.Tests/Volo/Abp/AuditLogging/MongoDB/MongoTestCollection.cs b/modules/audit-logging/test/Volo.Abp.AuditLogging.MongoDB.Tests/Volo/Abp/AuditLogging/MongoDB/MongoTestCollection.cs new file mode 100644 index 0000000000..4ed185cb9c --- /dev/null +++ b/modules/audit-logging/test/Volo.Abp.AuditLogging.MongoDB.Tests/Volo/Abp/AuditLogging/MongoDB/MongoTestCollection.cs @@ -0,0 +1,7 @@ +namespace Volo.Abp.AuditLogging.MongoDB +{ + public class MongoTestCollection + { + + } +} \ No newline at end of file From 1645483bd0b2cce12eb53934c2728184d49e2f3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mehmet=20Tu=CC=88ken?= Date: Wed, 18 Dec 2019 02:40:06 +0300 Subject: [PATCH 03/88] [modules/auditlogging] fix mongo.exe dispose --- .../MongoDB/AbpAuditLoggingMongoDbTestModule.cs | 4 +--- .../AuditLogging/MongoDB/AuditLogRepository_Tests.cs | 2 ++ .../AuditLogging/MongoDB/AuditStore_Basic_Tests.cs | 5 ++++- .../Volo/Abp/AuditLogging/MongoDB/MongoDbFixture.cs | 11 ++++++++++- .../Abp/AuditLogging/MongoDB/MongoTestCollection.cs | 7 +++++-- 5 files changed, 22 insertions(+), 7 deletions(-) diff --git a/modules/audit-logging/test/Volo.Abp.AuditLogging.MongoDB.Tests/Volo/Abp/AuditLogging/MongoDB/AbpAuditLoggingMongoDbTestModule.cs b/modules/audit-logging/test/Volo.Abp.AuditLogging.MongoDB.Tests/Volo/Abp/AuditLogging/MongoDB/AbpAuditLoggingMongoDbTestModule.cs index 7c70d720ec..b57c204818 100644 --- a/modules/audit-logging/test/Volo.Abp.AuditLogging.MongoDB.Tests/Volo/Abp/AuditLogging/MongoDB/AbpAuditLoggingMongoDbTestModule.cs +++ b/modules/audit-logging/test/Volo.Abp.AuditLogging.MongoDB.Tests/Volo/Abp/AuditLogging/MongoDB/AbpAuditLoggingMongoDbTestModule.cs @@ -12,11 +12,9 @@ namespace Volo.Abp.AuditLogging.MongoDB )] public class AbpAuditLoggingMongoDbTestModule : AbpModule { - private static readonly MongoDbRunner MongoDbRunner = MongoDbRunner.Start(); - public override void ConfigureServices(ServiceConfigurationContext context) { - var connectionString = MongoDbRunner.ConnectionString.EnsureEndsWith('/') + + var connectionString = MongoDbFixture.ConnectionString.EnsureEndsWith('/') + "Db_" + Guid.NewGuid().ToString("N"); diff --git a/modules/audit-logging/test/Volo.Abp.AuditLogging.MongoDB.Tests/Volo/Abp/AuditLogging/MongoDB/AuditLogRepository_Tests.cs b/modules/audit-logging/test/Volo.Abp.AuditLogging.MongoDB.Tests/Volo/Abp/AuditLogging/MongoDB/AuditLogRepository_Tests.cs index ffcc2094ab..a0edd58a45 100644 --- a/modules/audit-logging/test/Volo.Abp.AuditLogging.MongoDB.Tests/Volo/Abp/AuditLogging/MongoDB/AuditLogRepository_Tests.cs +++ b/modules/audit-logging/test/Volo.Abp.AuditLogging.MongoDB.Tests/Volo/Abp/AuditLogging/MongoDB/AuditLogRepository_Tests.cs @@ -1,9 +1,11 @@ using System; using System.Collections.Generic; using System.Text; +using Xunit; namespace Volo.Abp.AuditLogging.MongoDB { + [Collection(MongoTestCollection.Name)] public class AuditLogRepository_Tests : AuditLogRepository_Tests { diff --git a/modules/audit-logging/test/Volo.Abp.AuditLogging.MongoDB.Tests/Volo/Abp/AuditLogging/MongoDB/AuditStore_Basic_Tests.cs b/modules/audit-logging/test/Volo.Abp.AuditLogging.MongoDB.Tests/Volo/Abp/AuditLogging/MongoDB/AuditStore_Basic_Tests.cs index fa7a41ecfd..ad590c61e1 100644 --- a/modules/audit-logging/test/Volo.Abp.AuditLogging.MongoDB.Tests/Volo/Abp/AuditLogging/MongoDB/AuditStore_Basic_Tests.cs +++ b/modules/audit-logging/test/Volo.Abp.AuditLogging.MongoDB.Tests/Volo/Abp/AuditLogging/MongoDB/AuditStore_Basic_Tests.cs @@ -1,5 +1,8 @@ -namespace Volo.Abp.AuditLogging.MongoDB +using Xunit; + +namespace Volo.Abp.AuditLogging.MongoDB { + [Collection(MongoTestCollection.Name)] public class AuditStore_Basic_Tests : AuditStore_Basic_Tests { diff --git a/modules/audit-logging/test/Volo.Abp.AuditLogging.MongoDB.Tests/Volo/Abp/AuditLogging/MongoDB/MongoDbFixture.cs b/modules/audit-logging/test/Volo.Abp.AuditLogging.MongoDB.Tests/Volo/Abp/AuditLogging/MongoDB/MongoDbFixture.cs index cc2f90e01d..33803c1af4 100644 --- a/modules/audit-logging/test/Volo.Abp.AuditLogging.MongoDB.Tests/Volo/Abp/AuditLogging/MongoDB/MongoDbFixture.cs +++ b/modules/audit-logging/test/Volo.Abp.AuditLogging.MongoDB.Tests/Volo/Abp/AuditLogging/MongoDB/MongoDbFixture.cs @@ -1,7 +1,16 @@ +using System; +using Mongo2Go; + namespace Volo.Abp.AuditLogging.MongoDB { - public class MongoDbFixture + public class MongoDbFixture : IDisposable { + private static readonly MongoDbRunner MongoDbRunner = MongoDbRunner.Start(); + public static readonly string ConnectionString = MongoDbRunner.ConnectionString; + public void Dispose() + { + MongoDbRunner?.Dispose(); + } } } \ No newline at end of file diff --git a/modules/audit-logging/test/Volo.Abp.AuditLogging.MongoDB.Tests/Volo/Abp/AuditLogging/MongoDB/MongoTestCollection.cs b/modules/audit-logging/test/Volo.Abp.AuditLogging.MongoDB.Tests/Volo/Abp/AuditLogging/MongoDB/MongoTestCollection.cs index 4ed185cb9c..1d89caa8b0 100644 --- a/modules/audit-logging/test/Volo.Abp.AuditLogging.MongoDB.Tests/Volo/Abp/AuditLogging/MongoDB/MongoTestCollection.cs +++ b/modules/audit-logging/test/Volo.Abp.AuditLogging.MongoDB.Tests/Volo/Abp/AuditLogging/MongoDB/MongoTestCollection.cs @@ -1,7 +1,10 @@ +using Xunit; + namespace Volo.Abp.AuditLogging.MongoDB { - public class MongoTestCollection + [CollectionDefinition(Name)] + public class MongoTestCollection : ICollectionFixture { - + public const string Name = "MongoDB Collection"; } } \ No newline at end of file From 734059d9ff727aec681fe5693be6beddbab1ef9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mehmet=20Tu=CC=88ken?= Date: Wed, 18 Dec 2019 02:46:26 +0300 Subject: [PATCH 04/88] [modules/backgroundjobs] fix mongo.exe dispose --- .../AbpBackgroundJobsMongoDbTestModule.cs | 6 +----- .../MongoDB/BackgroundJobRepositoryTests.cs | 5 ++++- .../Abp/BackgroundJobs/MongoDB/MongoDbFixture.cs | 16 ++++++++++++++++ .../MongoDB/MongoTestCollection.cs | 10 ++++++++++ 4 files changed, 31 insertions(+), 6 deletions(-) create mode 100644 modules/background-jobs/test/Volo.Abp.BackgroundJobs.MongoDB.Tests/Volo/Abp/BackgroundJobs/MongoDB/MongoDbFixture.cs create mode 100644 modules/background-jobs/test/Volo.Abp.BackgroundJobs.MongoDB.Tests/Volo/Abp/BackgroundJobs/MongoDB/MongoTestCollection.cs diff --git a/modules/background-jobs/test/Volo.Abp.BackgroundJobs.MongoDB.Tests/Volo/Abp/BackgroundJobs/MongoDB/AbpBackgroundJobsMongoDbTestModule.cs b/modules/background-jobs/test/Volo.Abp.BackgroundJobs.MongoDB.Tests/Volo/Abp/BackgroundJobs/MongoDB/AbpBackgroundJobsMongoDbTestModule.cs index 4147917829..07be76b792 100644 --- a/modules/background-jobs/test/Volo.Abp.BackgroundJobs.MongoDB.Tests/Volo/Abp/BackgroundJobs/MongoDB/AbpBackgroundJobsMongoDbTestModule.cs +++ b/modules/background-jobs/test/Volo.Abp.BackgroundJobs.MongoDB.Tests/Volo/Abp/BackgroundJobs/MongoDB/AbpBackgroundJobsMongoDbTestModule.cs @@ -1,6 +1,4 @@ using System; -using Microsoft.Extensions.DependencyInjection; -using Mongo2Go; using Volo.Abp.Data; using Volo.Abp.Modularity; @@ -12,11 +10,9 @@ namespace Volo.Abp.BackgroundJobs.MongoDB )] public class AbpBackgroundJobsMongoDbTestModule : AbpModule { - private static readonly MongoDbRunner MongoDbRunner = MongoDbRunner.Start(); - public override void ConfigureServices(ServiceConfigurationContext context) { - var connectionString = MongoDbRunner.ConnectionString.EnsureEndsWith('/') + + var connectionString = MongoDbFixture.ConnectionString.EnsureEndsWith('/') + "Db_" + Guid.NewGuid().ToString("N"); diff --git a/modules/background-jobs/test/Volo.Abp.BackgroundJobs.MongoDB.Tests/Volo/Abp/BackgroundJobs/MongoDB/BackgroundJobRepositoryTests.cs b/modules/background-jobs/test/Volo.Abp.BackgroundJobs.MongoDB.Tests/Volo/Abp/BackgroundJobs/MongoDB/BackgroundJobRepositoryTests.cs index 429cf4821f..f3827c50e2 100644 --- a/modules/background-jobs/test/Volo.Abp.BackgroundJobs.MongoDB.Tests/Volo/Abp/BackgroundJobs/MongoDB/BackgroundJobRepositoryTests.cs +++ b/modules/background-jobs/test/Volo.Abp.BackgroundJobs.MongoDB.Tests/Volo/Abp/BackgroundJobs/MongoDB/BackgroundJobRepositoryTests.cs @@ -1,5 +1,8 @@ -namespace Volo.Abp.BackgroundJobs.MongoDB +using Xunit; + +namespace Volo.Abp.BackgroundJobs.MongoDB { + [Collection((MongoTestCollection.Name))] public class BackgroundJobRepositoryTests : BackgroundJobRepository_Tests { diff --git a/modules/background-jobs/test/Volo.Abp.BackgroundJobs.MongoDB.Tests/Volo/Abp/BackgroundJobs/MongoDB/MongoDbFixture.cs b/modules/background-jobs/test/Volo.Abp.BackgroundJobs.MongoDB.Tests/Volo/Abp/BackgroundJobs/MongoDB/MongoDbFixture.cs new file mode 100644 index 0000000000..3ae1d8fc10 --- /dev/null +++ b/modules/background-jobs/test/Volo.Abp.BackgroundJobs.MongoDB.Tests/Volo/Abp/BackgroundJobs/MongoDB/MongoDbFixture.cs @@ -0,0 +1,16 @@ +using System; +using Mongo2Go; + +namespace Volo.Abp.BackgroundJobs.MongoDB +{ + public class MongoDbFixture : IDisposable + { + private static readonly MongoDbRunner MongoDbRunner = MongoDbRunner.Start(); + public static readonly string ConnectionString = MongoDbRunner.ConnectionString; + + public void Dispose() + { + MongoDbRunner?.Dispose(); + } + } +} \ No newline at end of file diff --git a/modules/background-jobs/test/Volo.Abp.BackgroundJobs.MongoDB.Tests/Volo/Abp/BackgroundJobs/MongoDB/MongoTestCollection.cs b/modules/background-jobs/test/Volo.Abp.BackgroundJobs.MongoDB.Tests/Volo/Abp/BackgroundJobs/MongoDB/MongoTestCollection.cs new file mode 100644 index 0000000000..0096ae6f10 --- /dev/null +++ b/modules/background-jobs/test/Volo.Abp.BackgroundJobs.MongoDB.Tests/Volo/Abp/BackgroundJobs/MongoDB/MongoTestCollection.cs @@ -0,0 +1,10 @@ +using Xunit; + +namespace Volo.Abp.BackgroundJobs.MongoDB +{ + [CollectionDefinition(Name)] + public class MongoTestCollection : ICollectionFixture + { + public const string Name = "MongoDB Collection"; + } +} \ No newline at end of file From db4a558f064113306872643fa967fd73410b987d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mehmet=20Tu=CC=88ken?= Date: Wed, 18 Dec 2019 02:48:07 +0300 Subject: [PATCH 05/88] remove unused usings --- .../AuditLogging/MongoDB/AbpAuditLoggingMongoDbTestModule.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/modules/audit-logging/test/Volo.Abp.AuditLogging.MongoDB.Tests/Volo/Abp/AuditLogging/MongoDB/AbpAuditLoggingMongoDbTestModule.cs b/modules/audit-logging/test/Volo.Abp.AuditLogging.MongoDB.Tests/Volo/Abp/AuditLogging/MongoDB/AbpAuditLoggingMongoDbTestModule.cs index b57c204818..5cac32faae 100644 --- a/modules/audit-logging/test/Volo.Abp.AuditLogging.MongoDB.Tests/Volo/Abp/AuditLogging/MongoDB/AbpAuditLoggingMongoDbTestModule.cs +++ b/modules/audit-logging/test/Volo.Abp.AuditLogging.MongoDB.Tests/Volo/Abp/AuditLogging/MongoDB/AbpAuditLoggingMongoDbTestModule.cs @@ -1,6 +1,4 @@ using System; -using Microsoft.Extensions.DependencyInjection; -using Mongo2Go; using Volo.Abp.Data; using Volo.Abp.Modularity; From 4adaf68123aa4d86db728b4755575db64a7e22dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mehmet=20Tu=CC=88ken?= Date: Wed, 18 Dec 2019 02:55:26 +0300 Subject: [PATCH 06/88] [modules/blogging] fix mongo.exe dispose --- .../Volo/Blogging/Blogs/BlogRepository_Tests.cs | 2 ++ .../Blogging/Comments/CommentRepository_Tests.cs | 2 ++ .../MongoDB/BloggingMongoDBTestModule.cs | 6 +----- .../Volo/Blogging/MongoDB/MongoDbFixture.cs | 16 ++++++++++++++++ .../Volo/Blogging/MongoDB/MongoTestCollection.cs | 10 ++++++++++ .../Volo/Blogging/Posts/PostRepository_Tests.cs | 2 ++ .../Volo/Blogging/Tagging/TagRepository_Tests.cs | 2 ++ 7 files changed, 35 insertions(+), 5 deletions(-) create mode 100644 modules/blogging/test/Volo.Blogging.MongoDB.Tests/Volo/Blogging/MongoDB/MongoDbFixture.cs create mode 100644 modules/blogging/test/Volo.Blogging.MongoDB.Tests/Volo/Blogging/MongoDB/MongoTestCollection.cs diff --git a/modules/blogging/test/Volo.Blogging.MongoDB.Tests/Volo/Blogging/Blogs/BlogRepository_Tests.cs b/modules/blogging/test/Volo.Blogging.MongoDB.Tests/Volo/Blogging/Blogs/BlogRepository_Tests.cs index 76044f257c..060d3b86fc 100644 --- a/modules/blogging/test/Volo.Blogging.MongoDB.Tests/Volo/Blogging/Blogs/BlogRepository_Tests.cs +++ b/modules/blogging/test/Volo.Blogging.MongoDB.Tests/Volo/Blogging/Blogs/BlogRepository_Tests.cs @@ -1,8 +1,10 @@ using Volo.Blogging.Blogs; using Volo.Blogging.MongoDB; +using Xunit; namespace Volo.Blogging { + [Collection(MongoTestCollection.Name)] public class BlogRepository_Tests : BlogRepository_Tests { } diff --git a/modules/blogging/test/Volo.Blogging.MongoDB.Tests/Volo/Blogging/Comments/CommentRepository_Tests.cs b/modules/blogging/test/Volo.Blogging.MongoDB.Tests/Volo/Blogging/Comments/CommentRepository_Tests.cs index a001f9b0d9..d956cf1b15 100644 --- a/modules/blogging/test/Volo.Blogging.MongoDB.Tests/Volo/Blogging/Comments/CommentRepository_Tests.cs +++ b/modules/blogging/test/Volo.Blogging.MongoDB.Tests/Volo/Blogging/Comments/CommentRepository_Tests.cs @@ -1,8 +1,10 @@ using Volo.Blogging.Comments; using Volo.Blogging.MongoDB; +using Xunit; namespace Volo.Blogging { + [Collection(MongoTestCollection.Name)] public class CommentRepository_Tests : CommentRepository_Tests { } diff --git a/modules/blogging/test/Volo.Blogging.MongoDB.Tests/Volo/Blogging/MongoDB/BloggingMongoDBTestModule.cs b/modules/blogging/test/Volo.Blogging.MongoDB.Tests/Volo/Blogging/MongoDB/BloggingMongoDBTestModule.cs index 4c4b34ef54..1e68cebf21 100644 --- a/modules/blogging/test/Volo.Blogging.MongoDB.Tests/Volo/Blogging/MongoDB/BloggingMongoDBTestModule.cs +++ b/modules/blogging/test/Volo.Blogging.MongoDB.Tests/Volo/Blogging/MongoDB/BloggingMongoDBTestModule.cs @@ -1,6 +1,4 @@ using System; -using Mongo2Go; -using Volo.Abp; using Volo.Abp.Data; using Volo.Abp.Modularity; @@ -12,11 +10,9 @@ namespace Volo.Blogging.MongoDB )] public class BloggingMongoDbTestModule : AbpModule { - private static readonly MongoDbRunner MongoDbRunner = MongoDbRunner.Start(); - public override void ConfigureServices(ServiceConfigurationContext context) { - var connectionString = MongoDbRunner.ConnectionString.EnsureEndsWith('/') + + var connectionString = MongoDbFixture.ConnectionString.EnsureEndsWith('/') + "Db_" + Guid.NewGuid().ToString("N"); diff --git a/modules/blogging/test/Volo.Blogging.MongoDB.Tests/Volo/Blogging/MongoDB/MongoDbFixture.cs b/modules/blogging/test/Volo.Blogging.MongoDB.Tests/Volo/Blogging/MongoDB/MongoDbFixture.cs new file mode 100644 index 0000000000..d5fbfb4451 --- /dev/null +++ b/modules/blogging/test/Volo.Blogging.MongoDB.Tests/Volo/Blogging/MongoDB/MongoDbFixture.cs @@ -0,0 +1,16 @@ +using System; +using Mongo2Go; + +namespace Volo.Blogging.MongoDB +{ + public class MongoDbFixture : IDisposable + { + private static readonly MongoDbRunner MongoDbRunner = MongoDbRunner.Start(); + public static readonly string ConnectionString = MongoDbRunner.ConnectionString; + + public void Dispose() + { + MongoDbRunner?.Dispose(); + } + } +} \ No newline at end of file diff --git a/modules/blogging/test/Volo.Blogging.MongoDB.Tests/Volo/Blogging/MongoDB/MongoTestCollection.cs b/modules/blogging/test/Volo.Blogging.MongoDB.Tests/Volo/Blogging/MongoDB/MongoTestCollection.cs new file mode 100644 index 0000000000..f075e5dd07 --- /dev/null +++ b/modules/blogging/test/Volo.Blogging.MongoDB.Tests/Volo/Blogging/MongoDB/MongoTestCollection.cs @@ -0,0 +1,10 @@ +using Xunit; + +namespace Volo.Blogging.MongoDB +{ + [CollectionDefinition(Name)] + public class MongoTestCollection : ICollectionFixture + { + public const string Name = "MongoDB Collection"; + } +} \ No newline at end of file diff --git a/modules/blogging/test/Volo.Blogging.MongoDB.Tests/Volo/Blogging/Posts/PostRepository_Tests.cs b/modules/blogging/test/Volo.Blogging.MongoDB.Tests/Volo/Blogging/Posts/PostRepository_Tests.cs index d0e13ba403..814f0d206e 100644 --- a/modules/blogging/test/Volo.Blogging.MongoDB.Tests/Volo/Blogging/Posts/PostRepository_Tests.cs +++ b/modules/blogging/test/Volo.Blogging.MongoDB.Tests/Volo/Blogging/Posts/PostRepository_Tests.cs @@ -1,8 +1,10 @@ using Volo.Blogging.Posts; using Volo.Blogging.MongoDB; +using Xunit; namespace Volo.Blogging { + [Collection(MongoTestCollection.Name)] public class PostRepository_Tests : PostRepository_Tests { } diff --git a/modules/blogging/test/Volo.Blogging.MongoDB.Tests/Volo/Blogging/Tagging/TagRepository_Tests.cs b/modules/blogging/test/Volo.Blogging.MongoDB.Tests/Volo/Blogging/Tagging/TagRepository_Tests.cs index 8f13c6c6b0..66cb0d52c5 100644 --- a/modules/blogging/test/Volo.Blogging.MongoDB.Tests/Volo/Blogging/Tagging/TagRepository_Tests.cs +++ b/modules/blogging/test/Volo.Blogging.MongoDB.Tests/Volo/Blogging/Tagging/TagRepository_Tests.cs @@ -1,8 +1,10 @@ using Volo.Blogging.Tagging; using Volo.Blogging.MongoDB; +using Xunit; namespace Volo.Blogging { + [Collection(MongoTestCollection.Name)] public class TagRepository_Tests : TagRepository_Tests { } From 8bf5a24fbc40e01ebc8fd56bc7d17557cfd1168e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mehmet=20Tu=CC=88ken?= Date: Wed, 18 Dec 2019 03:14:34 +0300 Subject: [PATCH 07/88] [modules/docs] fix mongo.exe dispose --- .../Volo/Docs/MongoDB/DocsMongoDBTestModule.cs | 6 +----- .../Volo/Docs/MongoDB/MongoDbFixture.cs | 16 ++++++++++++++++ .../Volo/Docs/MongoDB/MongoTestCollection.cs | 10 ++++++++++ .../Volo/Docs/Project/ProjectRepository_Tests.cs | 2 ++ 4 files changed, 29 insertions(+), 5 deletions(-) create mode 100644 modules/docs/test/Volo.Docs.MongoDB.Tests/Volo/Docs/MongoDB/MongoDbFixture.cs create mode 100644 modules/docs/test/Volo.Docs.MongoDB.Tests/Volo/Docs/MongoDB/MongoTestCollection.cs diff --git a/modules/docs/test/Volo.Docs.MongoDB.Tests/Volo/Docs/MongoDB/DocsMongoDBTestModule.cs b/modules/docs/test/Volo.Docs.MongoDB.Tests/Volo/Docs/MongoDB/DocsMongoDBTestModule.cs index c5fef83ddb..b31f9b5acd 100644 --- a/modules/docs/test/Volo.Docs.MongoDB.Tests/Volo/Docs/MongoDB/DocsMongoDBTestModule.cs +++ b/modules/docs/test/Volo.Docs.MongoDB.Tests/Volo/Docs/MongoDB/DocsMongoDBTestModule.cs @@ -1,6 +1,4 @@ using System; -using Mongo2Go; -using Volo.Abp; using Volo.Abp.Data; using Volo.Abp.Modularity; @@ -12,11 +10,9 @@ namespace Volo.Docs.MongoDB )] public class DocsMongoDBTestModule : AbpModule { - private static readonly MongoDbRunner MongoDbRunner = MongoDbRunner.Start(); - public override void ConfigureServices(ServiceConfigurationContext context) { - var connectionString = MongoDbRunner.ConnectionString.EnsureEndsWith('/') + + var connectionString = MongoDbFixture.ConnectionString.EnsureEndsWith('/') + "Db_" + Guid.NewGuid().ToString("N"); diff --git a/modules/docs/test/Volo.Docs.MongoDB.Tests/Volo/Docs/MongoDB/MongoDbFixture.cs b/modules/docs/test/Volo.Docs.MongoDB.Tests/Volo/Docs/MongoDB/MongoDbFixture.cs new file mode 100644 index 0000000000..fc920813ab --- /dev/null +++ b/modules/docs/test/Volo.Docs.MongoDB.Tests/Volo/Docs/MongoDB/MongoDbFixture.cs @@ -0,0 +1,16 @@ +using System; +using Mongo2Go; + +namespace Volo.Docs.MongoDB +{ + public class MongoDbFixture : IDisposable + { + private static readonly MongoDbRunner MongoDbRunner = MongoDbRunner.Start(); + public static readonly string ConnectionString = MongoDbRunner.ConnectionString; + + public void Dispose() + { + MongoDbRunner?.Dispose(); + } + } +} \ No newline at end of file diff --git a/modules/docs/test/Volo.Docs.MongoDB.Tests/Volo/Docs/MongoDB/MongoTestCollection.cs b/modules/docs/test/Volo.Docs.MongoDB.Tests/Volo/Docs/MongoDB/MongoTestCollection.cs new file mode 100644 index 0000000000..86505c5a73 --- /dev/null +++ b/modules/docs/test/Volo.Docs.MongoDB.Tests/Volo/Docs/MongoDB/MongoTestCollection.cs @@ -0,0 +1,10 @@ +using Xunit; + +namespace Volo.Docs.MongoDB +{ + [CollectionDefinition(Name)] + public class MongoTestCollection : ICollectionFixture + { + public const string Name = "MongoDB Collection"; + } +} \ No newline at end of file diff --git a/modules/docs/test/Volo.Docs.MongoDB.Tests/Volo/Docs/Project/ProjectRepository_Tests.cs b/modules/docs/test/Volo.Docs.MongoDB.Tests/Volo/Docs/Project/ProjectRepository_Tests.cs index 6f2df01a11..696dd31185 100644 --- a/modules/docs/test/Volo.Docs.MongoDB.Tests/Volo/Docs/Project/ProjectRepository_Tests.cs +++ b/modules/docs/test/Volo.Docs.MongoDB.Tests/Volo/Docs/Project/ProjectRepository_Tests.cs @@ -1,7 +1,9 @@ using Volo.Docs.MongoDB; +using Xunit; namespace Volo.Docs.Project { + [Collection(MongoTestCollection.Name)] public class ProjectRepository_Tests : ProjectRepository_Tests { } From 993d5c5a09320c92a9c4fa8bbf7bd0c22e385943 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mehmet=20Tu=CC=88ken?= Date: Wed, 18 Dec 2019 03:24:53 +0300 Subject: [PATCH 08/88] [modules/featuremanagement] fix mongo.exe dispose --- .../AbpFeatureManagementMongoDbTestModule.cs | 5 +---- .../MongoDB/FeatureManagementStore_Tests.cs | 5 ++--- .../MongoDB/FeatureValueRepositoryTests.cs | 5 ++++- .../FeatureManagement/MongoDB/MongoDbFixture.cs | 16 ++++++++++++++++ .../MongoDB/MongoTestCollection.cs | 10 ++++++++++ 5 files changed, 33 insertions(+), 8 deletions(-) create mode 100644 modules/feature-management/test/Volo.Abp.FeatureManagement.MongoDB.Tests/Volo/Abp/FeatureManagement/MongoDB/MongoDbFixture.cs create mode 100644 modules/feature-management/test/Volo.Abp.FeatureManagement.MongoDB.Tests/Volo/Abp/FeatureManagement/MongoDB/MongoTestCollection.cs diff --git a/modules/feature-management/test/Volo.Abp.FeatureManagement.MongoDB.Tests/Volo/Abp/FeatureManagement/MongoDB/AbpFeatureManagementMongoDbTestModule.cs b/modules/feature-management/test/Volo.Abp.FeatureManagement.MongoDB.Tests/Volo/Abp/FeatureManagement/MongoDB/AbpFeatureManagementMongoDbTestModule.cs index 00b5b22871..04d4ac916f 100644 --- a/modules/feature-management/test/Volo.Abp.FeatureManagement.MongoDB.Tests/Volo/Abp/FeatureManagement/MongoDB/AbpFeatureManagementMongoDbTestModule.cs +++ b/modules/feature-management/test/Volo.Abp.FeatureManagement.MongoDB.Tests/Volo/Abp/FeatureManagement/MongoDB/AbpFeatureManagementMongoDbTestModule.cs @@ -1,5 +1,4 @@ using System; -using Mongo2Go; using Volo.Abp.Data; using Volo.Abp.Modularity; @@ -11,11 +10,9 @@ namespace Volo.Abp.FeatureManagement.MongoDB )] public class AbpFeatureManagementMongoDbTestModule : AbpModule { - private static readonly MongoDbRunner MongoDbRunner = MongoDbRunner.Start(); - public override void ConfigureServices(ServiceConfigurationContext context) { - var connectionString = MongoDbRunner.ConnectionString.EnsureEndsWith('/') + + var connectionString = MongoDbFixture.ConnectionString.EnsureEndsWith('/') + "Db_" + Guid.NewGuid().ToString("N"); diff --git a/modules/feature-management/test/Volo.Abp.FeatureManagement.MongoDB.Tests/Volo/Abp/FeatureManagement/MongoDB/FeatureManagementStore_Tests.cs b/modules/feature-management/test/Volo.Abp.FeatureManagement.MongoDB.Tests/Volo/Abp/FeatureManagement/MongoDB/FeatureManagementStore_Tests.cs index 7df6e3516b..0337bc8822 100644 --- a/modules/feature-management/test/Volo.Abp.FeatureManagement.MongoDB.Tests/Volo/Abp/FeatureManagement/MongoDB/FeatureManagementStore_Tests.cs +++ b/modules/feature-management/test/Volo.Abp.FeatureManagement.MongoDB.Tests/Volo/Abp/FeatureManagement/MongoDB/FeatureManagementStore_Tests.cs @@ -1,9 +1,8 @@ -using System; -using System.Collections.Generic; -using System.Text; +using Xunit; namespace Volo.Abp.FeatureManagement.MongoDB { + [Collection(MongoTestCollection.Name)] public class FeatureManagementStore_Tests : FeatureManagementStore_Tests { diff --git a/modules/feature-management/test/Volo.Abp.FeatureManagement.MongoDB.Tests/Volo/Abp/FeatureManagement/MongoDB/FeatureValueRepositoryTests.cs b/modules/feature-management/test/Volo.Abp.FeatureManagement.MongoDB.Tests/Volo/Abp/FeatureManagement/MongoDB/FeatureValueRepositoryTests.cs index 6184e4c90f..9654d8ab27 100644 --- a/modules/feature-management/test/Volo.Abp.FeatureManagement.MongoDB.Tests/Volo/Abp/FeatureManagement/MongoDB/FeatureValueRepositoryTests.cs +++ b/modules/feature-management/test/Volo.Abp.FeatureManagement.MongoDB.Tests/Volo/Abp/FeatureManagement/MongoDB/FeatureValueRepositoryTests.cs @@ -1,5 +1,8 @@ -namespace Volo.Abp.FeatureManagement.MongoDB +using Xunit; + +namespace Volo.Abp.FeatureManagement.MongoDB { + [Collection(MongoTestCollection.Name)] public class FeatureValueRepositoryTests : FeatureValueRepository_Tests { diff --git a/modules/feature-management/test/Volo.Abp.FeatureManagement.MongoDB.Tests/Volo/Abp/FeatureManagement/MongoDB/MongoDbFixture.cs b/modules/feature-management/test/Volo.Abp.FeatureManagement.MongoDB.Tests/Volo/Abp/FeatureManagement/MongoDB/MongoDbFixture.cs new file mode 100644 index 0000000000..bfd7fa9c04 --- /dev/null +++ b/modules/feature-management/test/Volo.Abp.FeatureManagement.MongoDB.Tests/Volo/Abp/FeatureManagement/MongoDB/MongoDbFixture.cs @@ -0,0 +1,16 @@ +using System; +using Mongo2Go; + +namespace Volo.Abp.FeatureManagement.MongoDB +{ + public class MongoDbFixture : IDisposable + { + private static readonly MongoDbRunner MongoDbRunner = MongoDbRunner.Start(); + public static readonly string ConnectionString = MongoDbRunner.ConnectionString; + + public void Dispose() + { + MongoDbRunner?.Dispose(); + } + } +} \ No newline at end of file diff --git a/modules/feature-management/test/Volo.Abp.FeatureManagement.MongoDB.Tests/Volo/Abp/FeatureManagement/MongoDB/MongoTestCollection.cs b/modules/feature-management/test/Volo.Abp.FeatureManagement.MongoDB.Tests/Volo/Abp/FeatureManagement/MongoDB/MongoTestCollection.cs new file mode 100644 index 0000000000..c8a6e1c58c --- /dev/null +++ b/modules/feature-management/test/Volo.Abp.FeatureManagement.MongoDB.Tests/Volo/Abp/FeatureManagement/MongoDB/MongoTestCollection.cs @@ -0,0 +1,10 @@ +using Xunit; + +namespace Volo.Abp.FeatureManagement.MongoDB +{ + [CollectionDefinition(Name)] + public class MongoTestCollection : ICollectionFixture + { + public const string Name = "MongoDB Collection"; + } +} \ No newline at end of file From 96f7b57ab73611c1eec297329d1042808a21d7a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mehmet=20Tu=CC=88ken?= Date: Wed, 18 Dec 2019 03:28:49 +0300 Subject: [PATCH 09/88] [modules/identity] fix mongo.exe dispose --- .../MongoDB/AbpIdentityMongoDbTestModule.cs | 6 +----- .../MongoDB/IdentityClaimTypeRepository_Tests.cs | 5 ++++- .../Identity/MongoDB/IdentityDataSeeder_Tests.cs | 5 ++++- .../MongoDB/IdentityRoleRepository_Tests.cs | 5 ++++- .../MongoDB/IdentityUserRepository_Tests.cs | 5 ++++- .../MongoDB/Identity_Repository_Resolve_Tests.cs | 5 ++++- .../Volo/Abp/Identity/MongoDB/MongoDbFixture.cs | 16 ++++++++++++++++ .../Abp/Identity/MongoDB/MongoTestCollection.cs | 10 ++++++++++ 8 files changed, 47 insertions(+), 10 deletions(-) create mode 100644 modules/identity/test/Volo.Abp.Identity.MongoDB.Tests/Volo/Abp/Identity/MongoDB/MongoDbFixture.cs create mode 100644 modules/identity/test/Volo.Abp.Identity.MongoDB.Tests/Volo/Abp/Identity/MongoDB/MongoTestCollection.cs diff --git a/modules/identity/test/Volo.Abp.Identity.MongoDB.Tests/Volo/Abp/Identity/MongoDB/AbpIdentityMongoDbTestModule.cs b/modules/identity/test/Volo.Abp.Identity.MongoDB.Tests/Volo/Abp/Identity/MongoDB/AbpIdentityMongoDbTestModule.cs index 6e9f3806a2..f730e5f445 100644 --- a/modules/identity/test/Volo.Abp.Identity.MongoDB.Tests/Volo/Abp/Identity/MongoDB/AbpIdentityMongoDbTestModule.cs +++ b/modules/identity/test/Volo.Abp.Identity.MongoDB.Tests/Volo/Abp/Identity/MongoDB/AbpIdentityMongoDbTestModule.cs @@ -1,6 +1,4 @@ using System; -using Microsoft.Extensions.DependencyInjection; -using Mongo2Go; using Volo.Abp.Data; using Volo.Abp.Modularity; using Volo.Abp.PermissionManagement.MongoDB; @@ -14,11 +12,9 @@ namespace Volo.Abp.Identity.MongoDB )] public class AbpIdentityMongoDbTestModule : AbpModule { - private static readonly MongoDbRunner MongoDbRunner = MongoDbRunner.Start(); - public override void ConfigureServices(ServiceConfigurationContext context) { - var connectionString = MongoDbRunner.ConnectionString.EnsureEndsWith('/') + + var connectionString = MongoDbFixture.ConnectionString.EnsureEndsWith('/') + "Db_" + Guid.NewGuid().ToString("N"); diff --git a/modules/identity/test/Volo.Abp.Identity.MongoDB.Tests/Volo/Abp/Identity/MongoDB/IdentityClaimTypeRepository_Tests.cs b/modules/identity/test/Volo.Abp.Identity.MongoDB.Tests/Volo/Abp/Identity/MongoDB/IdentityClaimTypeRepository_Tests.cs index b7926aae00..cc66856c06 100644 --- a/modules/identity/test/Volo.Abp.Identity.MongoDB.Tests/Volo/Abp/Identity/MongoDB/IdentityClaimTypeRepository_Tests.cs +++ b/modules/identity/test/Volo.Abp.Identity.MongoDB.Tests/Volo/Abp/Identity/MongoDB/IdentityClaimTypeRepository_Tests.cs @@ -1,5 +1,8 @@ -namespace Volo.Abp.Identity.MongoDB +using Xunit; + +namespace Volo.Abp.Identity.MongoDB { + [Collection(MongoTestCollection.Name)] public class IdentityClaimTypeRepository_Tests : IdentityClaimTypeRepository_Tests { diff --git a/modules/identity/test/Volo.Abp.Identity.MongoDB.Tests/Volo/Abp/Identity/MongoDB/IdentityDataSeeder_Tests.cs b/modules/identity/test/Volo.Abp.Identity.MongoDB.Tests/Volo/Abp/Identity/MongoDB/IdentityDataSeeder_Tests.cs index e97269c7e2..d614807395 100644 --- a/modules/identity/test/Volo.Abp.Identity.MongoDB.Tests/Volo/Abp/Identity/MongoDB/IdentityDataSeeder_Tests.cs +++ b/modules/identity/test/Volo.Abp.Identity.MongoDB.Tests/Volo/Abp/Identity/MongoDB/IdentityDataSeeder_Tests.cs @@ -1,5 +1,8 @@ -namespace Volo.Abp.Identity.MongoDB +using Xunit; + +namespace Volo.Abp.Identity.MongoDB { + [Collection(MongoTestCollection.Name)] public class IdentityDataSeeder_Tests : IdentityDataSeeder_Tests { diff --git a/modules/identity/test/Volo.Abp.Identity.MongoDB.Tests/Volo/Abp/Identity/MongoDB/IdentityRoleRepository_Tests.cs b/modules/identity/test/Volo.Abp.Identity.MongoDB.Tests/Volo/Abp/Identity/MongoDB/IdentityRoleRepository_Tests.cs index 4873aa7298..8fde9dbb2c 100644 --- a/modules/identity/test/Volo.Abp.Identity.MongoDB.Tests/Volo/Abp/Identity/MongoDB/IdentityRoleRepository_Tests.cs +++ b/modules/identity/test/Volo.Abp.Identity.MongoDB.Tests/Volo/Abp/Identity/MongoDB/IdentityRoleRepository_Tests.cs @@ -1,5 +1,8 @@ -namespace Volo.Abp.Identity.MongoDB +using Xunit; + +namespace Volo.Abp.Identity.MongoDB { + [Collection(MongoTestCollection.Name)] public class IdentityRoleRepository_Tests : IdentityRoleRepository_Tests { diff --git a/modules/identity/test/Volo.Abp.Identity.MongoDB.Tests/Volo/Abp/Identity/MongoDB/IdentityUserRepository_Tests.cs b/modules/identity/test/Volo.Abp.Identity.MongoDB.Tests/Volo/Abp/Identity/MongoDB/IdentityUserRepository_Tests.cs index 214d8f6986..e29a216ca7 100644 --- a/modules/identity/test/Volo.Abp.Identity.MongoDB.Tests/Volo/Abp/Identity/MongoDB/IdentityUserRepository_Tests.cs +++ b/modules/identity/test/Volo.Abp.Identity.MongoDB.Tests/Volo/Abp/Identity/MongoDB/IdentityUserRepository_Tests.cs @@ -1,5 +1,8 @@ -namespace Volo.Abp.Identity.MongoDB +using Xunit; + +namespace Volo.Abp.Identity.MongoDB { + [Collection(MongoTestCollection.Name)] public class IdentityUserRepository_Tests : IdentityUserRepository_Tests { diff --git a/modules/identity/test/Volo.Abp.Identity.MongoDB.Tests/Volo/Abp/Identity/MongoDB/Identity_Repository_Resolve_Tests.cs b/modules/identity/test/Volo.Abp.Identity.MongoDB.Tests/Volo/Abp/Identity/MongoDB/Identity_Repository_Resolve_Tests.cs index 5d6742adef..42020a4170 100644 --- a/modules/identity/test/Volo.Abp.Identity.MongoDB.Tests/Volo/Abp/Identity/MongoDB/Identity_Repository_Resolve_Tests.cs +++ b/modules/identity/test/Volo.Abp.Identity.MongoDB.Tests/Volo/Abp/Identity/MongoDB/Identity_Repository_Resolve_Tests.cs @@ -1,5 +1,8 @@ -namespace Volo.Abp.Identity.MongoDB +using Xunit; + +namespace Volo.Abp.Identity.MongoDB { + [Collection(MongoTestCollection.Name)] public class Identity_Repository_Resolve_Tests : Identity_Repository_Resolve_Tests { } diff --git a/modules/identity/test/Volo.Abp.Identity.MongoDB.Tests/Volo/Abp/Identity/MongoDB/MongoDbFixture.cs b/modules/identity/test/Volo.Abp.Identity.MongoDB.Tests/Volo/Abp/Identity/MongoDB/MongoDbFixture.cs new file mode 100644 index 0000000000..26de0a9399 --- /dev/null +++ b/modules/identity/test/Volo.Abp.Identity.MongoDB.Tests/Volo/Abp/Identity/MongoDB/MongoDbFixture.cs @@ -0,0 +1,16 @@ +using System; +using Mongo2Go; + +namespace Volo.Abp.Identity.MongoDB +{ + public class MongoDbFixture : IDisposable + { + private static readonly MongoDbRunner MongoDbRunner = MongoDbRunner.Start(); + public static readonly string ConnectionString = MongoDbRunner.ConnectionString; + + public void Dispose() + { + MongoDbRunner?.Dispose(); + } + } +} \ No newline at end of file diff --git a/modules/identity/test/Volo.Abp.Identity.MongoDB.Tests/Volo/Abp/Identity/MongoDB/MongoTestCollection.cs b/modules/identity/test/Volo.Abp.Identity.MongoDB.Tests/Volo/Abp/Identity/MongoDB/MongoTestCollection.cs new file mode 100644 index 0000000000..ae01262908 --- /dev/null +++ b/modules/identity/test/Volo.Abp.Identity.MongoDB.Tests/Volo/Abp/Identity/MongoDB/MongoTestCollection.cs @@ -0,0 +1,10 @@ +using Xunit; + +namespace Volo.Abp.Identity.MongoDB +{ + [CollectionDefinition(Name)] + public class MongoTestCollection : ICollectionFixture + { + public const string Name = "MongoDB Collection"; + } +} \ No newline at end of file From 18344cbdae4780a372b083dbc4f3129aaef15eeb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mehmet=20Tu=CC=88ken?= Date: Wed, 18 Dec 2019 03:37:57 +0300 Subject: [PATCH 10/88] [modules/identityserver] fix mongo.exe dispose --- .../AbpIdentityServerMongoDbTestModule.cs | 5 +---- .../ApiResourceRepository_Tests.cs | 4 +++- .../Abp/IdentityServer/ClientRepository_Tests.cs | 5 ++--- .../IdentityResourceRepository_Tests.cs | 5 ++--- .../Volo/Abp/IdentityServer/MongoDbFixture.cs | 16 ++++++++++++++++ .../Abp/IdentityServer/MongoTestCollection.cs | 10 ++++++++++ .../PersistentGrantRepository_Tests.cs | 5 ++--- 7 files changed, 36 insertions(+), 14 deletions(-) create mode 100644 modules/identityserver/test/Volo.Abp.IdentityServer.MongoDB.Tests/Volo/Abp/IdentityServer/MongoDbFixture.cs create mode 100644 modules/identityserver/test/Volo.Abp.IdentityServer.MongoDB.Tests/Volo/Abp/IdentityServer/MongoTestCollection.cs diff --git a/modules/identityserver/test/Volo.Abp.IdentityServer.MongoDB.Tests/Volo/Abp/IdentityServer/AbpIdentityServerMongoDbTestModule.cs b/modules/identityserver/test/Volo.Abp.IdentityServer.MongoDB.Tests/Volo/Abp/IdentityServer/AbpIdentityServerMongoDbTestModule.cs index ebfa34404d..d1721c720f 100644 --- a/modules/identityserver/test/Volo.Abp.IdentityServer.MongoDB.Tests/Volo/Abp/IdentityServer/AbpIdentityServerMongoDbTestModule.cs +++ b/modules/identityserver/test/Volo.Abp.IdentityServer.MongoDB.Tests/Volo/Abp/IdentityServer/AbpIdentityServerMongoDbTestModule.cs @@ -1,5 +1,4 @@ using System; -using Mongo2Go; using Volo.Abp.Data; using Volo.Abp.Identity.MongoDB; using Volo.Abp.IdentityServer.MongoDB; @@ -15,11 +14,9 @@ namespace Volo.Abp.IdentityServer )] public class AbpIdentityServerMongoDbTestModule : AbpModule { - private static readonly MongoDbRunner MongoDbRunner = MongoDbRunner.Start(); - public override void ConfigureServices(ServiceConfigurationContext context) { - var connectionString = MongoDbRunner.ConnectionString.EnsureEndsWith('/') + + var connectionString = MongoDbFixture.ConnectionString.EnsureEndsWith('/') + "Db_" + Guid.NewGuid().ToString("N"); diff --git a/modules/identityserver/test/Volo.Abp.IdentityServer.MongoDB.Tests/Volo/Abp/IdentityServer/ApiResourceRepository_Tests.cs b/modules/identityserver/test/Volo.Abp.IdentityServer.MongoDB.Tests/Volo/Abp/IdentityServer/ApiResourceRepository_Tests.cs index 032505266d..dfe00ab4dd 100644 --- a/modules/identityserver/test/Volo.Abp.IdentityServer.MongoDB.Tests/Volo/Abp/IdentityServer/ApiResourceRepository_Tests.cs +++ b/modules/identityserver/test/Volo.Abp.IdentityServer.MongoDB.Tests/Volo/Abp/IdentityServer/ApiResourceRepository_Tests.cs @@ -1,6 +1,8 @@ - +using Xunit; + namespace Volo.Abp.IdentityServer { + [Collection(MongoTestCollection.Name)] public class ApiResourceRepository_Tests : ApiResourceRepository_Tests { } diff --git a/modules/identityserver/test/Volo.Abp.IdentityServer.MongoDB.Tests/Volo/Abp/IdentityServer/ClientRepository_Tests.cs b/modules/identityserver/test/Volo.Abp.IdentityServer.MongoDB.Tests/Volo/Abp/IdentityServer/ClientRepository_Tests.cs index 29b006cd99..766448daeb 100644 --- a/modules/identityserver/test/Volo.Abp.IdentityServer.MongoDB.Tests/Volo/Abp/IdentityServer/ClientRepository_Tests.cs +++ b/modules/identityserver/test/Volo.Abp.IdentityServer.MongoDB.Tests/Volo/Abp/IdentityServer/ClientRepository_Tests.cs @@ -1,9 +1,8 @@ -using System; -using System.Collections.Generic; -using System.Text; +using Xunit; namespace Volo.Abp.IdentityServer { + [Collection(MongoTestCollection.Name)] public class ClientRepository_Tests : ClientRepository_Tests { diff --git a/modules/identityserver/test/Volo.Abp.IdentityServer.MongoDB.Tests/Volo/Abp/IdentityServer/IdentityResourceRepository_Tests.cs b/modules/identityserver/test/Volo.Abp.IdentityServer.MongoDB.Tests/Volo/Abp/IdentityServer/IdentityResourceRepository_Tests.cs index 2b44b2c6a0..36ca210b36 100644 --- a/modules/identityserver/test/Volo.Abp.IdentityServer.MongoDB.Tests/Volo/Abp/IdentityServer/IdentityResourceRepository_Tests.cs +++ b/modules/identityserver/test/Volo.Abp.IdentityServer.MongoDB.Tests/Volo/Abp/IdentityServer/IdentityResourceRepository_Tests.cs @@ -1,9 +1,8 @@ -using System; -using System.Collections.Generic; -using System.Text; +using Xunit; namespace Volo.Abp.IdentityServer { + [Collection(MongoTestCollection.Name)] public class IdentityResourceRepository_Tests : IdentityResourceRepository_Tests { } diff --git a/modules/identityserver/test/Volo.Abp.IdentityServer.MongoDB.Tests/Volo/Abp/IdentityServer/MongoDbFixture.cs b/modules/identityserver/test/Volo.Abp.IdentityServer.MongoDB.Tests/Volo/Abp/IdentityServer/MongoDbFixture.cs new file mode 100644 index 0000000000..22bbf08ef4 --- /dev/null +++ b/modules/identityserver/test/Volo.Abp.IdentityServer.MongoDB.Tests/Volo/Abp/IdentityServer/MongoDbFixture.cs @@ -0,0 +1,16 @@ +using System; +using Mongo2Go; + +namespace Volo.Abp.IdentityServer +{ + public class MongoDbFixture : IDisposable + { + private static readonly MongoDbRunner MongoDbRunner = MongoDbRunner.Start(); + public static readonly string ConnectionString = MongoDbRunner.ConnectionString; + + public void Dispose() + { + MongoDbRunner?.Dispose(); + } + } +} \ No newline at end of file diff --git a/modules/identityserver/test/Volo.Abp.IdentityServer.MongoDB.Tests/Volo/Abp/IdentityServer/MongoTestCollection.cs b/modules/identityserver/test/Volo.Abp.IdentityServer.MongoDB.Tests/Volo/Abp/IdentityServer/MongoTestCollection.cs new file mode 100644 index 0000000000..8ac0a73624 --- /dev/null +++ b/modules/identityserver/test/Volo.Abp.IdentityServer.MongoDB.Tests/Volo/Abp/IdentityServer/MongoTestCollection.cs @@ -0,0 +1,10 @@ +using Xunit; + +namespace Volo.Abp.IdentityServer +{ + [CollectionDefinition(Name)] + public class MongoTestCollection : ICollectionFixture + { + public const string Name = "MongoDB Collection"; + } +} \ No newline at end of file diff --git a/modules/identityserver/test/Volo.Abp.IdentityServer.MongoDB.Tests/Volo/Abp/IdentityServer/PersistentGrantRepository_Tests.cs b/modules/identityserver/test/Volo.Abp.IdentityServer.MongoDB.Tests/Volo/Abp/IdentityServer/PersistentGrantRepository_Tests.cs index fd2763dc6c..834d18fcf9 100644 --- a/modules/identityserver/test/Volo.Abp.IdentityServer.MongoDB.Tests/Volo/Abp/IdentityServer/PersistentGrantRepository_Tests.cs +++ b/modules/identityserver/test/Volo.Abp.IdentityServer.MongoDB.Tests/Volo/Abp/IdentityServer/PersistentGrantRepository_Tests.cs @@ -1,9 +1,8 @@ -using System; -using System.Collections.Generic; -using System.Text; +using Xunit; namespace Volo.Abp.IdentityServer { + [Collection(MongoTestCollection.Name)] public class PersistentGrantRepository_Tests : PersistentGrantRepository_Tests { From cf995af8bf534a1ee329c620d5623c56a2406f26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mehmet=20Tu=CC=88ken?= Date: Wed, 18 Dec 2019 03:38:33 +0300 Subject: [PATCH 11/88] [modules/permissionmanagement] fix mongo.exe dispose --- .../AbpPermissionManagementMongoDbTestModule.cs | 5 +---- .../MongoDb/MongoDbFixture.cs | 16 ++++++++++++++++ .../MongoDb/MongoTestCollection.cs | 10 ++++++++++ .../MongoDb/PermissionGrantRepository_Tests.cs | 5 ++++- 4 files changed, 31 insertions(+), 5 deletions(-) create mode 100644 modules/permission-management/test/Volo.Abp.PermissionManagement.MongoDB.Tests/Volo/Abp/PermissionManagement/MongoDb/MongoDbFixture.cs create mode 100644 modules/permission-management/test/Volo.Abp.PermissionManagement.MongoDB.Tests/Volo/Abp/PermissionManagement/MongoDb/MongoTestCollection.cs diff --git a/modules/permission-management/test/Volo.Abp.PermissionManagement.MongoDB.Tests/Volo/Abp/PermissionManagement/MongoDb/AbpPermissionManagementMongoDbTestModule.cs b/modules/permission-management/test/Volo.Abp.PermissionManagement.MongoDB.Tests/Volo/Abp/PermissionManagement/MongoDb/AbpPermissionManagementMongoDbTestModule.cs index d3d4d5d6e9..8e3c7b2c22 100644 --- a/modules/permission-management/test/Volo.Abp.PermissionManagement.MongoDB.Tests/Volo/Abp/PermissionManagement/MongoDb/AbpPermissionManagementMongoDbTestModule.cs +++ b/modules/permission-management/test/Volo.Abp.PermissionManagement.MongoDB.Tests/Volo/Abp/PermissionManagement/MongoDb/AbpPermissionManagementMongoDbTestModule.cs @@ -1,5 +1,4 @@ using System; -using Mongo2Go; using Volo.Abp.Data; using Volo.Abp.Modularity; @@ -10,11 +9,9 @@ namespace Volo.Abp.PermissionManagement.MongoDB typeof(AbpPermissionManagementTestBaseModule))] public class AbpPermissionManagementMongoDbTestModule : AbpModule { - private static readonly MongoDbRunner MongoDbRunner = MongoDbRunner.Start(); - public override void ConfigureServices(ServiceConfigurationContext context) { - var connectionString = MongoDbRunner.ConnectionString.EnsureEndsWith('/') + + var connectionString = MongoDbFixture.ConnectionString.EnsureEndsWith('/') + "Db_" + Guid.NewGuid().ToString("N"); diff --git a/modules/permission-management/test/Volo.Abp.PermissionManagement.MongoDB.Tests/Volo/Abp/PermissionManagement/MongoDb/MongoDbFixture.cs b/modules/permission-management/test/Volo.Abp.PermissionManagement.MongoDB.Tests/Volo/Abp/PermissionManagement/MongoDb/MongoDbFixture.cs new file mode 100644 index 0000000000..3a09e6e1a4 --- /dev/null +++ b/modules/permission-management/test/Volo.Abp.PermissionManagement.MongoDB.Tests/Volo/Abp/PermissionManagement/MongoDb/MongoDbFixture.cs @@ -0,0 +1,16 @@ +using System; +using Mongo2Go; + +namespace Volo.Abp.PermissionManagement.MongoDB +{ + public class MongoDbFixture : IDisposable + { + private static readonly MongoDbRunner MongoDbRunner = MongoDbRunner.Start(); + public static readonly string ConnectionString = MongoDbRunner.ConnectionString; + + public void Dispose() + { + MongoDbRunner?.Dispose(); + } + } +} \ No newline at end of file diff --git a/modules/permission-management/test/Volo.Abp.PermissionManagement.MongoDB.Tests/Volo/Abp/PermissionManagement/MongoDb/MongoTestCollection.cs b/modules/permission-management/test/Volo.Abp.PermissionManagement.MongoDB.Tests/Volo/Abp/PermissionManagement/MongoDb/MongoTestCollection.cs new file mode 100644 index 0000000000..a1f2eb6558 --- /dev/null +++ b/modules/permission-management/test/Volo.Abp.PermissionManagement.MongoDB.Tests/Volo/Abp/PermissionManagement/MongoDb/MongoTestCollection.cs @@ -0,0 +1,10 @@ +using Xunit; + +namespace Volo.Abp.PermissionManagement.MongoDB +{ + [CollectionDefinition(Name)] + public class MongoTestCollection : ICollectionFixture + { + public const string Name = "MongoDB Collection"; + } +} \ No newline at end of file diff --git a/modules/permission-management/test/Volo.Abp.PermissionManagement.MongoDB.Tests/Volo/Abp/PermissionManagement/MongoDb/PermissionGrantRepository_Tests.cs b/modules/permission-management/test/Volo.Abp.PermissionManagement.MongoDB.Tests/Volo/Abp/PermissionManagement/MongoDb/PermissionGrantRepository_Tests.cs index 98db0640c5..dd3c42da15 100644 --- a/modules/permission-management/test/Volo.Abp.PermissionManagement.MongoDB.Tests/Volo/Abp/PermissionManagement/MongoDb/PermissionGrantRepository_Tests.cs +++ b/modules/permission-management/test/Volo.Abp.PermissionManagement.MongoDB.Tests/Volo/Abp/PermissionManagement/MongoDb/PermissionGrantRepository_Tests.cs @@ -1,5 +1,8 @@ -namespace Volo.Abp.PermissionManagement.MongoDB +using Xunit; + +namespace Volo.Abp.PermissionManagement.MongoDB { + [Collection(MongoTestCollection.Name)] public class PermissionGrantRepository_Tests : PermissionGrantRepository_Tests { From be9b73b83528a3e19964bae8940b2226d8092280 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mehmet=20Tu=CC=88ken?= Date: Wed, 18 Dec 2019 03:42:34 +0300 Subject: [PATCH 12/88] [modules/settingmanagement] fix mongo.exe dispose --- .../AbpSettingManagementMongoDbTestModule.cs | 5 +---- .../SettingManagement/MongoDB/MongoDbFixture.cs | 16 ++++++++++++++++ .../MongoDB/MongoTestCollection.cs | 10 ++++++++++ .../MongoDB/SettingRepository_Tests.cs | 5 ++++- 4 files changed, 31 insertions(+), 5 deletions(-) create mode 100644 modules/setting-management/test/Volo.Abp.SettingManagement.MongoDB.Tests/Volo/Abp/SettingManagement/MongoDB/MongoDbFixture.cs create mode 100644 modules/setting-management/test/Volo.Abp.SettingManagement.MongoDB.Tests/Volo/Abp/SettingManagement/MongoDB/MongoTestCollection.cs diff --git a/modules/setting-management/test/Volo.Abp.SettingManagement.MongoDB.Tests/Volo/Abp/SettingManagement/MongoDB/AbpSettingManagementMongoDbTestModule.cs b/modules/setting-management/test/Volo.Abp.SettingManagement.MongoDB.Tests/Volo/Abp/SettingManagement/MongoDB/AbpSettingManagementMongoDbTestModule.cs index 1b9faefdbd..ec221eba15 100644 --- a/modules/setting-management/test/Volo.Abp.SettingManagement.MongoDB.Tests/Volo/Abp/SettingManagement/MongoDB/AbpSettingManagementMongoDbTestModule.cs +++ b/modules/setting-management/test/Volo.Abp.SettingManagement.MongoDB.Tests/Volo/Abp/SettingManagement/MongoDB/AbpSettingManagementMongoDbTestModule.cs @@ -1,5 +1,4 @@ using System; -using Mongo2Go; using Volo.Abp.Data; using Volo.Abp.Modularity; @@ -11,11 +10,9 @@ namespace Volo.Abp.SettingManagement.MongoDB )] public class AbpSettingManagementMongoDbTestModule : AbpModule { - private static readonly MongoDbRunner MongoDbRunner = MongoDbRunner.Start(); - public override void ConfigureServices(ServiceConfigurationContext context) { - var connectionString = MongoDbRunner.ConnectionString.EnsureEndsWith('/') + + var connectionString = MongoDbFixture.ConnectionString.EnsureEndsWith('/') + "Db_" + Guid.NewGuid().ToString("N"); diff --git a/modules/setting-management/test/Volo.Abp.SettingManagement.MongoDB.Tests/Volo/Abp/SettingManagement/MongoDB/MongoDbFixture.cs b/modules/setting-management/test/Volo.Abp.SettingManagement.MongoDB.Tests/Volo/Abp/SettingManagement/MongoDB/MongoDbFixture.cs new file mode 100644 index 0000000000..31ccdcc4f7 --- /dev/null +++ b/modules/setting-management/test/Volo.Abp.SettingManagement.MongoDB.Tests/Volo/Abp/SettingManagement/MongoDB/MongoDbFixture.cs @@ -0,0 +1,16 @@ +using System; +using Mongo2Go; + +namespace Volo.Abp.SettingManagement.MongoDB +{ + public class MongoDbFixture : IDisposable + { + private static readonly MongoDbRunner MongoDbRunner = MongoDbRunner.Start(); + public static readonly string ConnectionString = MongoDbRunner.ConnectionString; + + public void Dispose() + { + MongoDbRunner?.Dispose(); + } + } +} \ No newline at end of file diff --git a/modules/setting-management/test/Volo.Abp.SettingManagement.MongoDB.Tests/Volo/Abp/SettingManagement/MongoDB/MongoTestCollection.cs b/modules/setting-management/test/Volo.Abp.SettingManagement.MongoDB.Tests/Volo/Abp/SettingManagement/MongoDB/MongoTestCollection.cs new file mode 100644 index 0000000000..11ed1cbb55 --- /dev/null +++ b/modules/setting-management/test/Volo.Abp.SettingManagement.MongoDB.Tests/Volo/Abp/SettingManagement/MongoDB/MongoTestCollection.cs @@ -0,0 +1,10 @@ +using Xunit; + +namespace Volo.Abp.SettingManagement.MongoDB +{ + [CollectionDefinition(Name)] + public class MongoTestCollection : ICollectionFixture + { + public const string Name = "MongoDB Collection"; + } +} \ No newline at end of file diff --git a/modules/setting-management/test/Volo.Abp.SettingManagement.MongoDB.Tests/Volo/Abp/SettingManagement/MongoDB/SettingRepository_Tests.cs b/modules/setting-management/test/Volo.Abp.SettingManagement.MongoDB.Tests/Volo/Abp/SettingManagement/MongoDB/SettingRepository_Tests.cs index 7e35eff799..a1a2d1428c 100644 --- a/modules/setting-management/test/Volo.Abp.SettingManagement.MongoDB.Tests/Volo/Abp/SettingManagement/MongoDB/SettingRepository_Tests.cs +++ b/modules/setting-management/test/Volo.Abp.SettingManagement.MongoDB.Tests/Volo/Abp/SettingManagement/MongoDB/SettingRepository_Tests.cs @@ -1,5 +1,8 @@ -namespace Volo.Abp.SettingManagement.MongoDB +using Xunit; + +namespace Volo.Abp.SettingManagement.MongoDB { + [Collection(MongoTestCollection.Name)] public class SettingRepository_Tests : SettingRepository_Tests { From 7fa2dbc886bf93b0e303f9257fd1766924749eb8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mehmet=20Tu=CC=88ken?= Date: Wed, 18 Dec 2019 03:45:39 +0300 Subject: [PATCH 13/88] [modules/tenantmanagement] fix mongo.exe dispose --- .../AbpTenantManagementMongoDbTestModule.cs | 6 +----- .../TenantManagement/MongoDb/MongoDbFixture.cs | 16 ++++++++++++++++ .../MongoDb/MongoTestCollection.cs | 10 ++++++++++ .../MongoDb/TenantRepository_Tests.cs | 5 ++++- 4 files changed, 31 insertions(+), 6 deletions(-) create mode 100644 modules/tenant-management/test/Volo.Abp.TenantManagement.MongoDB.Tests/Volo/Abp/TenantManagement/MongoDb/MongoDbFixture.cs create mode 100644 modules/tenant-management/test/Volo.Abp.TenantManagement.MongoDB.Tests/Volo/Abp/TenantManagement/MongoDb/MongoTestCollection.cs diff --git a/modules/tenant-management/test/Volo.Abp.TenantManagement.MongoDB.Tests/Volo/Abp/TenantManagement/MongoDb/AbpTenantManagementMongoDbTestModule.cs b/modules/tenant-management/test/Volo.Abp.TenantManagement.MongoDB.Tests/Volo/Abp/TenantManagement/MongoDb/AbpTenantManagementMongoDbTestModule.cs index 911839d510..9584ec2d44 100644 --- a/modules/tenant-management/test/Volo.Abp.TenantManagement.MongoDB.Tests/Volo/Abp/TenantManagement/MongoDb/AbpTenantManagementMongoDbTestModule.cs +++ b/modules/tenant-management/test/Volo.Abp.TenantManagement.MongoDB.Tests/Volo/Abp/TenantManagement/MongoDb/AbpTenantManagementMongoDbTestModule.cs @@ -1,6 +1,4 @@ using System; -using Microsoft.Extensions.DependencyInjection; -using Mongo2Go; using Volo.Abp.Data; using Volo.Abp.Modularity; @@ -12,11 +10,9 @@ namespace Volo.Abp.TenantManagement.MongoDB )] public class AbpTenantManagementMongoDbTestModule : AbpModule { - private static readonly MongoDbRunner MongoDbRunner = MongoDbRunner.Start(); - public override void ConfigureServices(ServiceConfigurationContext context) { - var connectionString = MongoDbRunner.ConnectionString.EnsureEndsWith('/') + + var connectionString = MongoDbFixture.ConnectionString.EnsureEndsWith('/') + "Db_" + Guid.NewGuid().ToString("N"); diff --git a/modules/tenant-management/test/Volo.Abp.TenantManagement.MongoDB.Tests/Volo/Abp/TenantManagement/MongoDb/MongoDbFixture.cs b/modules/tenant-management/test/Volo.Abp.TenantManagement.MongoDB.Tests/Volo/Abp/TenantManagement/MongoDb/MongoDbFixture.cs new file mode 100644 index 0000000000..be115d9dff --- /dev/null +++ b/modules/tenant-management/test/Volo.Abp.TenantManagement.MongoDB.Tests/Volo/Abp/TenantManagement/MongoDb/MongoDbFixture.cs @@ -0,0 +1,16 @@ +using System; +using Mongo2Go; + +namespace Volo.Abp.TenantManagement.MongoDB +{ + public class MongoDbFixture : IDisposable + { + private static readonly MongoDbRunner MongoDbRunner = MongoDbRunner.Start(); + public static readonly string ConnectionString = MongoDbRunner.ConnectionString; + + public void Dispose() + { + MongoDbRunner?.Dispose(); + } + } +} \ No newline at end of file diff --git a/modules/tenant-management/test/Volo.Abp.TenantManagement.MongoDB.Tests/Volo/Abp/TenantManagement/MongoDb/MongoTestCollection.cs b/modules/tenant-management/test/Volo.Abp.TenantManagement.MongoDB.Tests/Volo/Abp/TenantManagement/MongoDb/MongoTestCollection.cs new file mode 100644 index 0000000000..1719b7dbdd --- /dev/null +++ b/modules/tenant-management/test/Volo.Abp.TenantManagement.MongoDB.Tests/Volo/Abp/TenantManagement/MongoDb/MongoTestCollection.cs @@ -0,0 +1,10 @@ +using Xunit; + +namespace Volo.Abp.TenantManagement.MongoDB +{ + [CollectionDefinition(Name)] + public class MongoTestCollection : ICollectionFixture + { + public const string Name = "MongoDB Collection"; + } +} \ No newline at end of file diff --git a/modules/tenant-management/test/Volo.Abp.TenantManagement.MongoDB.Tests/Volo/Abp/TenantManagement/MongoDb/TenantRepository_Tests.cs b/modules/tenant-management/test/Volo.Abp.TenantManagement.MongoDB.Tests/Volo/Abp/TenantManagement/MongoDb/TenantRepository_Tests.cs index b1ae97b021..0a980be37d 100644 --- a/modules/tenant-management/test/Volo.Abp.TenantManagement.MongoDB.Tests/Volo/Abp/TenantManagement/MongoDb/TenantRepository_Tests.cs +++ b/modules/tenant-management/test/Volo.Abp.TenantManagement.MongoDB.Tests/Volo/Abp/TenantManagement/MongoDb/TenantRepository_Tests.cs @@ -1,5 +1,8 @@ -namespace Volo.Abp.TenantManagement.MongoDB +using Xunit; + +namespace Volo.Abp.TenantManagement.MongoDB { + [Collection(MongoTestCollection.Name)] public class TenantRepository_Tests : TenantRepository_Tests { From 6f0db0b9b0a7d3734f72d1e79adffe710901d150 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mehmet=20Tu=CC=88ken?= Date: Wed, 18 Dec 2019 03:58:14 +0300 Subject: [PATCH 14/88] [templates/app] fix mongo.exe dispose --- .../MongoDb/MongoDbFixture.cs | 16 ++++++++++++++++ .../MongoDb/MongoTestCollection.cs | 10 ++++++++++ .../MongoDb/MyProjectNameMongoDbTestModule.cs | 5 +---- .../MongoDb/Samples/SampleRepositoryTests.cs | 1 + 4 files changed, 28 insertions(+), 4 deletions(-) create mode 100644 templates/app/aspnet-core/test/MyCompanyName.MyProjectName.MongoDB.Tests/MongoDb/MongoDbFixture.cs create mode 100644 templates/app/aspnet-core/test/MyCompanyName.MyProjectName.MongoDB.Tests/MongoDb/MongoTestCollection.cs diff --git a/templates/app/aspnet-core/test/MyCompanyName.MyProjectName.MongoDB.Tests/MongoDb/MongoDbFixture.cs b/templates/app/aspnet-core/test/MyCompanyName.MyProjectName.MongoDB.Tests/MongoDb/MongoDbFixture.cs new file mode 100644 index 0000000000..0feac4eebf --- /dev/null +++ b/templates/app/aspnet-core/test/MyCompanyName.MyProjectName.MongoDB.Tests/MongoDb/MongoDbFixture.cs @@ -0,0 +1,16 @@ +using System; +using Mongo2Go; + +namespace MyCompanyName.MyProjectName.MongoDB +{ + public class MongoDbFixture : IDisposable + { + private static readonly MongoDbRunner MongoDbRunner = MongoDbRunner.Start(); + public static readonly string ConnectionString = MongoDbRunner.ConnectionString; + + public void Dispose() + { + MongoDbRunner?.Dispose(); + } + } +} \ No newline at end of file diff --git a/templates/app/aspnet-core/test/MyCompanyName.MyProjectName.MongoDB.Tests/MongoDb/MongoTestCollection.cs b/templates/app/aspnet-core/test/MyCompanyName.MyProjectName.MongoDB.Tests/MongoDb/MongoTestCollection.cs new file mode 100644 index 0000000000..42c85760c3 --- /dev/null +++ b/templates/app/aspnet-core/test/MyCompanyName.MyProjectName.MongoDB.Tests/MongoDb/MongoTestCollection.cs @@ -0,0 +1,10 @@ +using Xunit; + +namespace MyCompanyName.MyProjectName.MongoDB +{ + [CollectionDefinition(Name)] + public class MongoTestCollection : ICollectionFixture + { + public const string Name = "MongoDB Collection"; + } +} \ No newline at end of file diff --git a/templates/app/aspnet-core/test/MyCompanyName.MyProjectName.MongoDB.Tests/MongoDb/MyProjectNameMongoDbTestModule.cs b/templates/app/aspnet-core/test/MyCompanyName.MyProjectName.MongoDB.Tests/MongoDb/MyProjectNameMongoDbTestModule.cs index 270ad2102c..bcaf7494a7 100644 --- a/templates/app/aspnet-core/test/MyCompanyName.MyProjectName.MongoDB.Tests/MongoDb/MyProjectNameMongoDbTestModule.cs +++ b/templates/app/aspnet-core/test/MyCompanyName.MyProjectName.MongoDB.Tests/MongoDb/MyProjectNameMongoDbTestModule.cs @@ -1,5 +1,4 @@ using System; -using Mongo2Go; using Volo.Abp.Data; using Volo.Abp.Modularity; @@ -11,11 +10,9 @@ namespace MyCompanyName.MyProjectName.MongoDB )] public class MyProjectNameMongoDbTestModule : AbpModule { - private static readonly MongoDbRunner MongoDbRunner = MongoDbRunner.Start(); - public override void ConfigureServices(ServiceConfigurationContext context) { - var connectionString = MongoDbRunner.ConnectionString.EnsureEndsWith('/') + + var connectionString = MongoDbFixture.ConnectionString.EnsureEndsWith('/') + "Db_" + Guid.NewGuid().ToString("N"); diff --git a/templates/app/aspnet-core/test/MyCompanyName.MyProjectName.MongoDB.Tests/MongoDb/Samples/SampleRepositoryTests.cs b/templates/app/aspnet-core/test/MyCompanyName.MyProjectName.MongoDB.Tests/MongoDb/Samples/SampleRepositoryTests.cs index 27095ec117..17d8007c16 100644 --- a/templates/app/aspnet-core/test/MyCompanyName.MyProjectName.MongoDB.Tests/MongoDb/Samples/SampleRepositoryTests.cs +++ b/templates/app/aspnet-core/test/MyCompanyName.MyProjectName.MongoDB.Tests/MongoDb/Samples/SampleRepositoryTests.cs @@ -13,6 +13,7 @@ namespace MyCompanyName.MyProjectName.MongoDB.Samples * (like default AppUser repository IRepository here). * Only test your custom repository methods. */ + [Collection(MongoTestCollection.Name)] public class SampleRepositoryTests : MyProjectNameMongoDbTestBase { private readonly IRepository _appUserRepository; From e44efcb803659f07001b648afe8c58334581e84f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mehmet=20Tu=CC=88ken?= Date: Wed, 18 Dec 2019 04:01:55 +0300 Subject: [PATCH 15/88] [templates/module] fix mongo.exe dispose --- .../MongoDB/MongoDbFixture.cs | 16 ++++++++++++++++ .../MongoDB/MongoTestCollection.cs | 10 ++++++++++ .../MongoDB/MyProjectNameMongoDbTestModule.cs | 6 +----- .../MongoDB/Samples/SampleRepository_Tests.cs | 2 ++ 4 files changed, 29 insertions(+), 5 deletions(-) create mode 100644 templates/module/aspnet-core/test/MyCompanyName.MyProjectName.MongoDB.Tests/MongoDB/MongoDbFixture.cs create mode 100644 templates/module/aspnet-core/test/MyCompanyName.MyProjectName.MongoDB.Tests/MongoDB/MongoTestCollection.cs diff --git a/templates/module/aspnet-core/test/MyCompanyName.MyProjectName.MongoDB.Tests/MongoDB/MongoDbFixture.cs b/templates/module/aspnet-core/test/MyCompanyName.MyProjectName.MongoDB.Tests/MongoDB/MongoDbFixture.cs new file mode 100644 index 0000000000..0feac4eebf --- /dev/null +++ b/templates/module/aspnet-core/test/MyCompanyName.MyProjectName.MongoDB.Tests/MongoDB/MongoDbFixture.cs @@ -0,0 +1,16 @@ +using System; +using Mongo2Go; + +namespace MyCompanyName.MyProjectName.MongoDB +{ + public class MongoDbFixture : IDisposable + { + private static readonly MongoDbRunner MongoDbRunner = MongoDbRunner.Start(); + public static readonly string ConnectionString = MongoDbRunner.ConnectionString; + + public void Dispose() + { + MongoDbRunner?.Dispose(); + } + } +} \ No newline at end of file diff --git a/templates/module/aspnet-core/test/MyCompanyName.MyProjectName.MongoDB.Tests/MongoDB/MongoTestCollection.cs b/templates/module/aspnet-core/test/MyCompanyName.MyProjectName.MongoDB.Tests/MongoDB/MongoTestCollection.cs new file mode 100644 index 0000000000..42c85760c3 --- /dev/null +++ b/templates/module/aspnet-core/test/MyCompanyName.MyProjectName.MongoDB.Tests/MongoDB/MongoTestCollection.cs @@ -0,0 +1,10 @@ +using Xunit; + +namespace MyCompanyName.MyProjectName.MongoDB +{ + [CollectionDefinition(Name)] + public class MongoTestCollection : ICollectionFixture + { + public const string Name = "MongoDB Collection"; + } +} \ No newline at end of file diff --git a/templates/module/aspnet-core/test/MyCompanyName.MyProjectName.MongoDB.Tests/MongoDB/MyProjectNameMongoDbTestModule.cs b/templates/module/aspnet-core/test/MyCompanyName.MyProjectName.MongoDB.Tests/MongoDB/MyProjectNameMongoDbTestModule.cs index 149db59bcc..f29c713c05 100644 --- a/templates/module/aspnet-core/test/MyCompanyName.MyProjectName.MongoDB.Tests/MongoDB/MyProjectNameMongoDbTestModule.cs +++ b/templates/module/aspnet-core/test/MyCompanyName.MyProjectName.MongoDB.Tests/MongoDB/MyProjectNameMongoDbTestModule.cs @@ -1,6 +1,4 @@ using System; -using Mongo2Go; -using Volo.Abp; using Volo.Abp.Data; using Volo.Abp.Modularity; @@ -12,11 +10,9 @@ namespace MyCompanyName.MyProjectName.MongoDB )] public class MyProjectNameMongoDbTestModule : AbpModule { - private static readonly MongoDbRunner MongoDbRunner = MongoDbRunner.Start(); - public override void ConfigureServices(ServiceConfigurationContext context) { - var connectionString = MongoDbRunner.ConnectionString.EnsureEndsWith('/') + + var connectionString = MongoDbFixture.ConnectionString.EnsureEndsWith('/') + "Db_" + Guid.NewGuid().ToString("N"); diff --git a/templates/module/aspnet-core/test/MyCompanyName.MyProjectName.MongoDB.Tests/MongoDB/Samples/SampleRepository_Tests.cs b/templates/module/aspnet-core/test/MyCompanyName.MyProjectName.MongoDB.Tests/MongoDB/Samples/SampleRepository_Tests.cs index 6522b9884e..c16c416b2c 100644 --- a/templates/module/aspnet-core/test/MyCompanyName.MyProjectName.MongoDB.Tests/MongoDB/Samples/SampleRepository_Tests.cs +++ b/templates/module/aspnet-core/test/MyCompanyName.MyProjectName.MongoDB.Tests/MongoDB/Samples/SampleRepository_Tests.cs @@ -1,7 +1,9 @@ using MyCompanyName.MyProjectName.Samples; +using Xunit; namespace MyCompanyName.MyProjectName.MongoDB.Samples { + [Collection(MongoTestCollection.Name)] public class SampleRepository_Tests : SampleRepository_Tests { /* Don't write custom repository tests here, instead write to From c0d6582986007fb20a9fbce5fb3f1c97a1ee8592 Mon Sep 17 00:00:00 2001 From: Mehmet Perk Date: Thu, 16 Jan 2020 22:35:07 +0300 Subject: [PATCH 16/88] MethodInvocationAuthorizationService should check Roles --- .../MethodInvocationAuthorizationService.cs | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/MethodInvocationAuthorizationService.cs b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/MethodInvocationAuthorizationService.cs index 1e063f1f0e..82a0f9c2d1 100644 --- a/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/MethodInvocationAuthorizationService.cs +++ b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/MethodInvocationAuthorizationService.cs @@ -64,20 +64,26 @@ namespace Volo.Abp.Authorization protected async Task CheckAsync(IAuthorizeData authorizationAttribute) { - if (authorizationAttribute.Policy == null) + if (authorizationAttribute.Policy != null) { - //TODO: Can we find a better, unified, way of checking if current request has been authenticated - if (!_currentUser.IsAuthenticated && !_currentClient.IsAuthenticated) + await _authorizationService.CheckAsync(authorizationAttribute.Policy).ConfigureAwait(false); + } + else if (authorizationAttribute.Roles != null) + { + if(_currentUser.IsInRole(authorizationAttribute.Roles) == false) { - throw new AbpAuthorizationException("Authorization failed! User has not logged in."); + throw new AbpAuthorizationException("Authorization failed! Given roles has not granted: " + authorizationAttribute.Roles); } } else { - await _authorizationService.CheckAsync(authorizationAttribute.Policy).ConfigureAwait(false); + //TODO: Can we find a better, unified, way of checking if current request has been authenticated + if (!_currentUser.IsAuthenticated && !_currentClient.IsAuthenticated) + { + throw new AbpAuthorizationException("Authorization failed! User has not logged in."); + } } - //TODO: What about roles and other props? } } } \ No newline at end of file From 5016ba69a3cfc4e87e9db5fe651325cafcacc766 Mon Sep 17 00:00:00 2001 From: Mehmet Perk Date: Thu, 16 Jan 2020 23:33:05 +0300 Subject: [PATCH 17/88] authorization tests with role --- .../Volo/Abp/Authorization/Authorization_Tests.cs | 9 +++++++++ .../Authorization/TestServices/IMyAuthorizedService1.cs | 2 ++ .../Authorization/TestServices/MyAuthorizedService1.cs | 6 ++++++ 3 files changed, 17 insertions(+) diff --git a/framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/Authorization_Tests.cs b/framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/Authorization_Tests.cs index 2950c7c92a..3968d1baf5 100644 --- a/framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/Authorization_Tests.cs +++ b/framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/Authorization_Tests.cs @@ -52,5 +52,14 @@ namespace Volo.Abp.Authorization { _permissionDefinitionManager.GetGroups().Count.ShouldBe(1); } + + [Fact] + public async Task Should_Not_Allow_To_Call_Method_If_Has_No_Role_ProtectedByRole_Async() + { + await Assert.ThrowsAsync(async () => + { + await _myAuthorizedService1.ProtectedByRole().ConfigureAwait(false); + }).ConfigureAwait(false); + } } } \ No newline at end of file diff --git a/framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/TestServices/IMyAuthorizedService1.cs b/framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/TestServices/IMyAuthorizedService1.cs index b3841c4fed..077934c0d2 100644 --- a/framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/TestServices/IMyAuthorizedService1.cs +++ b/framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/TestServices/IMyAuthorizedService1.cs @@ -11,5 +11,7 @@ namespace Volo.Abp.Authorization.TestServices Task ProtectedByClass(); Task ProtectedByClassAsync(); + + Task ProtectedByRole(); } } \ No newline at end of file diff --git a/framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/TestServices/MyAuthorizedService1.cs b/framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/TestServices/MyAuthorizedService1.cs index 6d64ed80dd..07ccfa7deb 100644 --- a/framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/TestServices/MyAuthorizedService1.cs +++ b/framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/TestServices/MyAuthorizedService1.cs @@ -30,5 +30,11 @@ namespace Volo.Abp.Authorization.TestServices await Task.Delay(10).ConfigureAwait(false); return 42; } + + [Authorize(Roles = "MyRole")] + public virtual Task ProtectedByRole() + { + return Task.FromResult(42); + } } } \ No newline at end of file From 85f956f5aed8b50f5949fcd9ac325607f8a23d4d Mon Sep 17 00:00:00 2001 From: mperk Date: Sun, 19 Jan 2020 01:03:21 +0300 Subject: [PATCH 18/88] authorize check with combine --- .../MethodInvocationAuthorizationService.cs | 29 +++++-------------- .../Abp/Authorization/Authorization_Tests.cs | 16 ++++++++++ .../TestServices/IMyAuthorizedService1.cs | 2 ++ .../TestServices/MyAuthorizedService1.cs | 7 +++++ 4 files changed, 33 insertions(+), 21 deletions(-) diff --git a/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/MethodInvocationAuthorizationService.cs b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/MethodInvocationAuthorizationService.cs index 82a0f9c2d1..b2e06c0207 100644 --- a/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/MethodInvocationAuthorizationService.cs +++ b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/MethodInvocationAuthorizationService.cs @@ -14,15 +14,18 @@ namespace Volo.Abp.Authorization private readonly IAuthorizationService _authorizationService; private readonly ICurrentUser _currentUser; private readonly ICurrentClient _currentClient; + private readonly IAbpAuthorizationPolicyProvider _abpAuthorizationPolicyProvider; public MethodInvocationAuthorizationService( IAuthorizationService authorizationService, ICurrentUser currentUser, - ICurrentClient currentClient) + ICurrentClient currentClient, + IAbpAuthorizationPolicyProvider abpAuthorizationPolicyProvider) { _authorizationService = authorizationService; _currentUser = currentUser; _currentClient = currentClient; + _abpAuthorizationPolicyProvider = abpAuthorizationPolicyProvider; } public async Task CheckAsync(MethodInvocationAuthorizationContext context) @@ -64,26 +67,10 @@ namespace Volo.Abp.Authorization protected async Task CheckAsync(IAuthorizeData authorizationAttribute) { - if (authorizationAttribute.Policy != null) - { - await _authorizationService.CheckAsync(authorizationAttribute.Policy).ConfigureAwait(false); - } - else if (authorizationAttribute.Roles != null) - { - if(_currentUser.IsInRole(authorizationAttribute.Roles) == false) - { - throw new AbpAuthorizationException("Authorization failed! Given roles has not granted: " + authorizationAttribute.Roles); - } - } - else - { - //TODO: Can we find a better, unified, way of checking if current request has been authenticated - if (!_currentUser.IsAuthenticated && !_currentClient.IsAuthenticated) - { - throw new AbpAuthorizationException("Authorization failed! User has not logged in."); - } - } - + var authorizationPolicy = await AuthorizationPolicy.CombineAsync( + _abpAuthorizationPolicyProvider, + new List { authorizationAttribute }); + await _authorizationService.CheckAsync(authorizationPolicy).ConfigureAwait(false); } } } \ No newline at end of file diff --git a/framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/Authorization_Tests.cs b/framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/Authorization_Tests.cs index 3968d1baf5..827f7b676e 100644 --- a/framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/Authorization_Tests.cs +++ b/framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/Authorization_Tests.cs @@ -61,5 +61,21 @@ namespace Volo.Abp.Authorization await _myAuthorizedService1.ProtectedByRole().ConfigureAwait(false); }).ConfigureAwait(false); } + + [Fact] + public async Task Should_Allow_To_Call_Method_If_Has_No_Role_ProtectedByRole_Async() + { + int result = await _myAuthorizedService1.ProtectedByRole().ConfigureAwait(false); + result.ShouldBe(42); + } + + [Fact] + public async Task Should_Not_Allow_To_Call_Method_If_Has_No_Role_ProtectedByScheme_Async() + { + await Assert.ThrowsAsync(async () => + { + await _myAuthorizedService1.ProtectedByScheme().ConfigureAwait(false); + }).ConfigureAwait(false); + } } } \ No newline at end of file diff --git a/framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/TestServices/IMyAuthorizedService1.cs b/framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/TestServices/IMyAuthorizedService1.cs index 077934c0d2..6c4042168c 100644 --- a/framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/TestServices/IMyAuthorizedService1.cs +++ b/framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/TestServices/IMyAuthorizedService1.cs @@ -13,5 +13,7 @@ namespace Volo.Abp.Authorization.TestServices Task ProtectedByClassAsync(); Task ProtectedByRole(); + + Task ProtectedByScheme(); } } \ No newline at end of file diff --git a/framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/TestServices/MyAuthorizedService1.cs b/framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/TestServices/MyAuthorizedService1.cs index 07ccfa7deb..a25227babf 100644 --- a/framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/TestServices/MyAuthorizedService1.cs +++ b/framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/TestServices/MyAuthorizedService1.cs @@ -36,5 +36,12 @@ namespace Volo.Abp.Authorization.TestServices { return Task.FromResult(42); } + + [Authorize(AuthenticationSchemes = "Bearer")] + [Authorize(Roles = "MyRole")] + public virtual Task ProtectedByScheme() + { + return Task.FromResult(42); + } } } \ No newline at end of file From 9617efc5e977c1894aeff00f423643a53d0fda90 Mon Sep 17 00:00:00 2001 From: mperk Date: Mon, 20 Jan 2020 15:07:39 +0300 Subject: [PATCH 19/88] change authorization service to abpauthorization service --- .../MethodInvocationAuthorizationService.cs | 16 +++++----------- .../Abp/Authorization/Authorization_Tests.cs | 7 ------- 2 files changed, 5 insertions(+), 18 deletions(-) diff --git a/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/MethodInvocationAuthorizationService.cs b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/MethodInvocationAuthorizationService.cs index b2e06c0207..4d0589486b 100644 --- a/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/MethodInvocationAuthorizationService.cs +++ b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/MethodInvocationAuthorizationService.cs @@ -11,21 +11,15 @@ namespace Volo.Abp.Authorization { public class MethodInvocationAuthorizationService : IMethodInvocationAuthorizationService, ITransientDependency { - private readonly IAuthorizationService _authorizationService; - private readonly ICurrentUser _currentUser; - private readonly ICurrentClient _currentClient; private readonly IAbpAuthorizationPolicyProvider _abpAuthorizationPolicyProvider; + private readonly IAbpAuthorizationService _abpAuthorizationService; public MethodInvocationAuthorizationService( - IAuthorizationService authorizationService, - ICurrentUser currentUser, - ICurrentClient currentClient, - IAbpAuthorizationPolicyProvider abpAuthorizationPolicyProvider) + IAbpAuthorizationPolicyProvider abpAuthorizationPolicyProvider, + IAbpAuthorizationService abpAuthorizationService) { - _authorizationService = authorizationService; - _currentUser = currentUser; - _currentClient = currentClient; _abpAuthorizationPolicyProvider = abpAuthorizationPolicyProvider; + _abpAuthorizationService = abpAuthorizationService; } public async Task CheckAsync(MethodInvocationAuthorizationContext context) @@ -70,7 +64,7 @@ namespace Volo.Abp.Authorization var authorizationPolicy = await AuthorizationPolicy.CombineAsync( _abpAuthorizationPolicyProvider, new List { authorizationAttribute }); - await _authorizationService.CheckAsync(authorizationPolicy).ConfigureAwait(false); + await _abpAuthorizationService.CheckAsync(authorizationPolicy).ConfigureAwait(false); } } } \ No newline at end of file diff --git a/framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/Authorization_Tests.cs b/framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/Authorization_Tests.cs index 827f7b676e..9be90dc045 100644 --- a/framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/Authorization_Tests.cs +++ b/framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/Authorization_Tests.cs @@ -62,13 +62,6 @@ namespace Volo.Abp.Authorization }).ConfigureAwait(false); } - [Fact] - public async Task Should_Allow_To_Call_Method_If_Has_No_Role_ProtectedByRole_Async() - { - int result = await _myAuthorizedService1.ProtectedByRole().ConfigureAwait(false); - result.ShouldBe(42); - } - [Fact] public async Task Should_Not_Allow_To_Call_Method_If_Has_No_Role_ProtectedByScheme_Async() { From cfba92293294b523fe1683ab9c1d309d1a7e73f9 Mon Sep 17 00:00:00 2001 From: Mehmet Perk Date: Mon, 20 Jan 2020 21:04:31 +0300 Subject: [PATCH 20/88] authorization tests with role --- .../Authorization/AuthorizationTestBase.cs | 25 +++++++++++++++-- .../Abp/Authorization/Authorization_Tests.cs | 14 ++++++++-- .../TestServices/IMyAuthorizedService1.cs | 3 --- .../IMyAuthorizedServiceWithRole.cs | 13 +++++++++ .../TestServices/MyAuthorizedService1.cs | 15 +---------- .../MyAuthorizedServiceWithRole.cs | 27 +++++++++++++++++++ 6 files changed, 76 insertions(+), 21 deletions(-) create mode 100644 framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/TestServices/IMyAuthorizedServiceWithRole.cs create mode 100644 framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/TestServices/MyAuthorizedServiceWithRole.cs diff --git a/framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/AuthorizationTestBase.cs b/framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/AuthorizationTestBase.cs index 8ab051d97e..5cf9976e46 100644 --- a/framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/AuthorizationTestBase.cs +++ b/framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/AuthorizationTestBase.cs @@ -1,4 +1,10 @@ -using Volo.Abp.Testing; +using Microsoft.Extensions.DependencyInjection; +using NSubstitute; +using System.Collections.Generic; +using System.Security.Claims; +using System.Threading; +using Volo.Abp.Security.Claims; +using Volo.Abp.Testing; namespace Volo.Abp.Authorization { @@ -8,5 +14,20 @@ namespace Volo.Abp.Authorization { options.UseAutofac(); } + + protected override void AfterAddApplication(IServiceCollection services) + { + var claims = new List() { + new Claim(AbpClaimTypes.UserName, "Douglas"), + new Claim(AbpClaimTypes.UserId, "1fcf46b2-28c3-48d0-8bac-fa53268a2775"), + new Claim(AbpClaimTypes.Role, "MyRole") + }; + + var identity = new ClaimsIdentity(claims); + var claimsPrincipal = new ClaimsPrincipal(identity); + var principalAccessor = Substitute.For(); + principalAccessor.Principal.Returns(ci => claimsPrincipal); + Thread.CurrentPrincipal = claimsPrincipal; + } } -} \ No newline at end of file +} diff --git a/framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/Authorization_Tests.cs b/framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/Authorization_Tests.cs index 9be90dc045..e886d2f1c4 100644 --- a/framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/Authorization_Tests.cs +++ b/framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/Authorization_Tests.cs @@ -9,11 +9,13 @@ namespace Volo.Abp.Authorization public class Authorization_Tests : AuthorizationTestBase { private readonly IMyAuthorizedService1 _myAuthorizedService1; + private readonly IMyAuthorizedServiceWithRole _myAuthorizedServiceWithRole; private readonly IPermissionDefinitionManager _permissionDefinitionManager; public Authorization_Tests() { _myAuthorizedService1 = GetRequiredService(); + _myAuthorizedServiceWithRole = GetRequiredService(); _permissionDefinitionManager = GetRequiredService(); } @@ -58,16 +60,24 @@ namespace Volo.Abp.Authorization { await Assert.ThrowsAsync(async () => { - await _myAuthorizedService1.ProtectedByRole().ConfigureAwait(false); + await _myAuthorizedServiceWithRole.ProtectedByAnotherRole().ConfigureAwait(false); }).ConfigureAwait(false); } + [Fact] + public async Task Should_Allow_To_Call_Method_If_Has_No_Role_ProtectedByRole_Async() + { + int result = await _myAuthorizedServiceWithRole.ProtectedByRole().ConfigureAwait(false); + result.ShouldBe(42); + } + + [Fact] public async Task Should_Not_Allow_To_Call_Method_If_Has_No_Role_ProtectedByScheme_Async() { await Assert.ThrowsAsync(async () => { - await _myAuthorizedService1.ProtectedByScheme().ConfigureAwait(false); + await _myAuthorizedServiceWithRole.ProtectedByScheme().ConfigureAwait(false); }).ConfigureAwait(false); } } diff --git a/framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/TestServices/IMyAuthorizedService1.cs b/framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/TestServices/IMyAuthorizedService1.cs index 6c4042168c..4c693993cf 100644 --- a/framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/TestServices/IMyAuthorizedService1.cs +++ b/framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/TestServices/IMyAuthorizedService1.cs @@ -12,8 +12,5 @@ namespace Volo.Abp.Authorization.TestServices Task ProtectedByClassAsync(); - Task ProtectedByRole(); - - Task ProtectedByScheme(); } } \ No newline at end of file diff --git a/framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/TestServices/IMyAuthorizedServiceWithRole.cs b/framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/TestServices/IMyAuthorizedServiceWithRole.cs new file mode 100644 index 0000000000..52b860d774 --- /dev/null +++ b/framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/TestServices/IMyAuthorizedServiceWithRole.cs @@ -0,0 +1,13 @@ +using System.Threading.Tasks; + +namespace Volo.Abp.Authorization.TestServices +{ + public interface IMyAuthorizedServiceWithRole + { + Task ProtectedByRole(); + + Task ProtectedByScheme(); + + Task ProtectedByAnotherRole(); + } +} diff --git a/framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/TestServices/MyAuthorizedService1.cs b/framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/TestServices/MyAuthorizedService1.cs index a25227babf..02f234fe99 100644 --- a/framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/TestServices/MyAuthorizedService1.cs +++ b/framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/TestServices/MyAuthorizedService1.cs @@ -30,18 +30,5 @@ namespace Volo.Abp.Authorization.TestServices await Task.Delay(10).ConfigureAwait(false); return 42; } - - [Authorize(Roles = "MyRole")] - public virtual Task ProtectedByRole() - { - return Task.FromResult(42); - } - - [Authorize(AuthenticationSchemes = "Bearer")] - [Authorize(Roles = "MyRole")] - public virtual Task ProtectedByScheme() - { - return Task.FromResult(42); - } } -} \ No newline at end of file +} diff --git a/framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/TestServices/MyAuthorizedServiceWithRole.cs b/framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/TestServices/MyAuthorizedServiceWithRole.cs new file mode 100644 index 0000000000..d660b040c1 --- /dev/null +++ b/framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/TestServices/MyAuthorizedServiceWithRole.cs @@ -0,0 +1,27 @@ +using Microsoft.AspNetCore.Authorization; +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.Authorization.TestServices +{ + [Authorize(Roles = "MyRole")] + public class MyAuthorizedServiceWithRole : IMyAuthorizedServiceWithRole, ITransientDependency + { + public virtual Task ProtectedByRole() + { + return Task.FromResult(42); + } + + [Authorize(Roles = "MyAnotherRole")] + public virtual Task ProtectedByAnotherRole() + { + return Task.FromResult(42); + } + + [Authorize(AuthenticationSchemes = "Bearer")] + public virtual Task ProtectedByScheme() + { + return Task.FromResult(42); + } + } +} From 583cdbac1cba2c7ad756200d469bb4470f97294c Mon Sep 17 00:00:00 2001 From: maliming Date: Tue, 21 Jan 2020 10:08:17 +0800 Subject: [PATCH 21/88] Check all authorization attributes at the same time. --- .../MethodInvocationAuthorizationService.cs | 20 +++++-------------- 1 file changed, 5 insertions(+), 15 deletions(-) diff --git a/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/MethodInvocationAuthorizationService.cs b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/MethodInvocationAuthorizationService.cs index 4d0589486b..b0d53355fc 100644 --- a/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/MethodInvocationAuthorizationService.cs +++ b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/MethodInvocationAuthorizationService.cs @@ -3,9 +3,7 @@ using System.Linq; using System.Reflection; using System.Threading.Tasks; using Microsoft.AspNetCore.Authorization; -using Volo.Abp.Clients; using Volo.Abp.DependencyInjection; -using Volo.Abp.Users; namespace Volo.Abp.Authorization { @@ -29,10 +27,10 @@ namespace Volo.Abp.Authorization return; } - foreach (var authorizationAttribute in GetAuthorizationDataAttributes(context.Method)) - { - await CheckAsync(authorizationAttribute).ConfigureAwait(false); - } + var authorizationPolicy = await AuthorizationPolicy.CombineAsync(_abpAuthorizationPolicyProvider, + GetAuthorizationDataAttributes(context.Method)).ConfigureAwait(false); + + await _abpAuthorizationService.CheckAsync(authorizationPolicy).ConfigureAwait(false); } protected virtual bool AllowAnonymous(MethodInvocationAuthorizationContext context) @@ -46,7 +44,7 @@ namespace Volo.Abp.Authorization .GetCustomAttributes(true) .OfType(); - if (methodInfo.IsPublic) + if (methodInfo.IsPublic && methodInfo.DeclaringType != null) { attributes = attributes .Union( @@ -58,13 +56,5 @@ namespace Volo.Abp.Authorization return attributes; } - - protected async Task CheckAsync(IAuthorizeData authorizationAttribute) - { - var authorizationPolicy = await AuthorizationPolicy.CombineAsync( - _abpAuthorizationPolicyProvider, - new List { authorizationAttribute }); - await _abpAuthorizationService.CheckAsync(authorizationPolicy).ConfigureAwait(false); - } } } \ No newline at end of file From 9f2b49c2d5a6c365845cf93e1e8caa13a610408d Mon Sep 17 00:00:00 2001 From: maliming Date: Wed, 19 Feb 2020 16:42:05 +0800 Subject: [PATCH 22/88] Fix build error. --- .../Abp/Authorization/MethodInvocationAuthorizationService.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/MethodInvocationAuthorizationService.cs b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/MethodInvocationAuthorizationService.cs index 6518b7ad75..32fd611b9a 100644 --- a/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/MethodInvocationAuthorizationService.cs +++ b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/MethodInvocationAuthorizationService.cs @@ -27,7 +27,8 @@ namespace Volo.Abp.Authorization return; } - var authorizationPolicy = await AuthorizationPolicy.CombineAsync(_abpAuthorizationPolicyProvider, GetAuthorizationDataAttributes(context.Method)) + var authorizationPolicy = await AuthorizationPolicy.CombineAsync(_abpAuthorizationPolicyProvider, + GetAuthorizationDataAttributes(context.Method)); await _abpAuthorizationService.CheckAsync(authorizationPolicy); } From 88b8f6ed836f2675ad562c27cb759ee20848d824 Mon Sep 17 00:00:00 2001 From: maliming Date: Wed, 4 Mar 2020 09:18:39 +0800 Subject: [PATCH 23/88] Check if authorizationPolicy is null. --- .../Authorization/MethodInvocationAuthorizationService.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/MethodInvocationAuthorizationService.cs b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/MethodInvocationAuthorizationService.cs index 32fd611b9a..6293c0d034 100644 --- a/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/MethodInvocationAuthorizationService.cs +++ b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/MethodInvocationAuthorizationService.cs @@ -29,6 +29,11 @@ namespace Volo.Abp.Authorization var authorizationPolicy = await AuthorizationPolicy.CombineAsync(_abpAuthorizationPolicyProvider, GetAuthorizationDataAttributes(context.Method)); + if (authorizationPolicy == null) + { + return; + } + await _abpAuthorizationService.CheckAsync(authorizationPolicy); } From f2d3b712247111a6c869fb85457dca734b7b2985 Mon Sep 17 00:00:00 2001 From: maliming Date: Wed, 25 Mar 2020 18:08:13 +0800 Subject: [PATCH 24/88] Introducing DynamicProxyIgnoreTypes. Resolve #3180 --- .../AspNetCore/Mvc/AbpAspNetCoreMvcModule.cs | 6 +++++ .../Auditing/AuditingInterceptorRegistrar.cs | 3 ++- .../AuthorizationInterceptorRegistrar.cs | 3 ++- .../DynamicProxy/DynamicProxyIgnoreTypes.cs | 24 +++++++++++++++++++ .../Features/FeatureInterceptorRegistrar.cs | 3 ++- .../Abp/Uow/UnitOfWorkInterceptorRegistrar.cs | 3 ++- .../ValidationInterceptorRegistrar.cs | 3 ++- .../AbpAuthorizationTestModule.cs | 4 +++- ...plicationService_FluentValidation_Tests.cs | 4 +++- .../ApplicationService_Validation_Tests.cs | 4 +++- 10 files changed, 49 insertions(+), 8 deletions(-) create mode 100644 framework/src/Volo.Abp.Core/Volo/Abp/DynamicProxy/DynamicProxyIgnoreTypes.cs diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcModule.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcModule.cs index 21a675ddc4..e609b0a601 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcModule.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcModule.cs @@ -12,6 +12,7 @@ using System; using System.Collections.Generic; using System.Linq; using System.Reflection; +using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.Extensions.Hosting; using Volo.Abp.ApiVersioning; using Volo.Abp.AspNetCore.Mvc.Conventions; @@ -20,6 +21,7 @@ using Volo.Abp.AspNetCore.Mvc.Json; using Volo.Abp.AspNetCore.Mvc.Localization; using Volo.Abp.AspNetCore.VirtualFileSystem; using Volo.Abp.DependencyInjection; +using Volo.Abp.DynamicProxy; using Volo.Abp.Http.Modeling; using Volo.Abp.Localization; using Volo.Abp.Modularity; @@ -38,6 +40,10 @@ namespace Volo.Abp.AspNetCore.Mvc { public override void PreConfigureServices(ServiceConfigurationContext context) { + DynamicProxyIgnoreTypes.IgnoreTypes.AddIfNotContains(typeof(ControllerBase)); + DynamicProxyIgnoreTypes.IgnoreTypes.AddIfNotContains(typeof(PageModel)); + DynamicProxyIgnoreTypes.IgnoreTypes.AddIfNotContains(typeof(ViewComponent)); + context.Services.AddConventionalRegistrar(new AbpAspNetCoreMvcConventionalRegistrar()); } diff --git a/framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/AuditingInterceptorRegistrar.cs b/framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/AuditingInterceptorRegistrar.cs index 94920fe1be..6790995331 100644 --- a/framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/AuditingInterceptorRegistrar.cs +++ b/framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/AuditingInterceptorRegistrar.cs @@ -1,6 +1,7 @@ using System; using System.Linq; using Volo.Abp.DependencyInjection; +using Volo.Abp.DynamicProxy; namespace Volo.Abp.Auditing { @@ -8,7 +9,7 @@ namespace Volo.Abp.Auditing { public static void RegisterIfNeeded(IOnServiceRegistredContext context) { - if (ShouldIntercept(context.ImplementationType)) + if (ShouldIntercept(context.ImplementationType) && !DynamicProxyIgnoreTypes.Contains(context.ImplementationType)) { context.Interceptors.TryAdd(); } diff --git a/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/AuthorizationInterceptorRegistrar.cs b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/AuthorizationInterceptorRegistrar.cs index 69a285ddc8..b44c299b28 100644 --- a/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/AuthorizationInterceptorRegistrar.cs +++ b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/AuthorizationInterceptorRegistrar.cs @@ -3,6 +3,7 @@ using System.Linq; using System.Reflection; using Microsoft.AspNetCore.Authorization; using Volo.Abp.DependencyInjection; +using Volo.Abp.DynamicProxy; namespace Volo.Abp.Authorization { @@ -10,7 +11,7 @@ namespace Volo.Abp.Authorization { public static void RegisterIfNeeded(IOnServiceRegistredContext context) { - if (ShouldIntercept(context.ImplementationType)) + if (ShouldIntercept(context.ImplementationType) && !DynamicProxyIgnoreTypes.Contains(context.ImplementationType)) { context.Interceptors.TryAdd(); } diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/DynamicProxy/DynamicProxyIgnoreTypes.cs b/framework/src/Volo.Abp.Core/Volo/Abp/DynamicProxy/DynamicProxyIgnoreTypes.cs new file mode 100644 index 0000000000..5eae6ef092 --- /dev/null +++ b/framework/src/Volo.Abp.Core/Volo/Abp/DynamicProxy/DynamicProxyIgnoreTypes.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Volo.Abp.DynamicProxy +{ + /// + /// Castle's dynamic proxy class feature will have performance issues for some components, such as the controller of Asp net core MVC. + /// For related discussions, see: https://github.com/castleproject/Core/issues/486 https://github.com/abpframework/abp/issues/3180 + /// The Abp framework may enable interceptors for certain components (UOW, Auditing, Authorization, etc.), which requires dynamic proxy classes, but will cause application performance to decline. + /// We need to use other methods for the controller to implement interception, such as middleware or MVC / Page filters. + /// So we provide some ignored types to avoid enabling dynamic proxy classes. + /// By default it is empty. When you use middleware or filters for these components in your application, you can add these types to the list. + /// + public static class DynamicProxyIgnoreTypes + { + public static List IgnoreTypes { get; } = new List(); + + public static bool Contains(Type type, bool includeDerivedTypes = true) + { + return includeDerivedTypes ? IgnoreTypes.Any(t => t.IsAssignableFrom(type)) : IgnoreTypes.Contains(type); + } + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.Features/Volo/Abp/Features/FeatureInterceptorRegistrar.cs b/framework/src/Volo.Abp.Features/Volo/Abp/Features/FeatureInterceptorRegistrar.cs index 8cb6cd7ea5..b2caa734b5 100644 --- a/framework/src/Volo.Abp.Features/Volo/Abp/Features/FeatureInterceptorRegistrar.cs +++ b/framework/src/Volo.Abp.Features/Volo/Abp/Features/FeatureInterceptorRegistrar.cs @@ -2,6 +2,7 @@ using System.Linq; using System.Reflection; using Volo.Abp.DependencyInjection; +using Volo.Abp.DynamicProxy; namespace Volo.Abp.Features { @@ -9,7 +10,7 @@ namespace Volo.Abp.Features { public static void RegisterIfNeeded(IOnServiceRegistredContext context) { - if (ShouldIntercept(context.ImplementationType)) + if (ShouldIntercept(context.ImplementationType) && !DynamicProxyIgnoreTypes.Contains(context.ImplementationType)) { context.Interceptors.TryAdd(); } diff --git a/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/UnitOfWorkInterceptorRegistrar.cs b/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/UnitOfWorkInterceptorRegistrar.cs index 849ca8ffd8..c01e760d58 100644 --- a/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/UnitOfWorkInterceptorRegistrar.cs +++ b/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/UnitOfWorkInterceptorRegistrar.cs @@ -1,5 +1,6 @@ using System.Reflection; using Volo.Abp.DependencyInjection; +using Volo.Abp.DynamicProxy; namespace Volo.Abp.Uow { @@ -7,7 +8,7 @@ namespace Volo.Abp.Uow { public static void RegisterIfNeeded(IOnServiceRegistredContext context) { - if (UnitOfWorkHelper.IsUnitOfWorkType(context.ImplementationType.GetTypeInfo())) + if (UnitOfWorkHelper.IsUnitOfWorkType(context.ImplementationType.GetTypeInfo()) && !DynamicProxyIgnoreTypes.Contains(context.ImplementationType)) { context.Interceptors.TryAdd(); } diff --git a/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/ValidationInterceptorRegistrar.cs b/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/ValidationInterceptorRegistrar.cs index 81f6eb6597..187f64436e 100644 --- a/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/ValidationInterceptorRegistrar.cs +++ b/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/ValidationInterceptorRegistrar.cs @@ -1,4 +1,5 @@ using Volo.Abp.DependencyInjection; +using Volo.Abp.DynamicProxy; namespace Volo.Abp.Validation { @@ -6,7 +7,7 @@ namespace Volo.Abp.Validation { public static void RegisterIfNeeded(IOnServiceRegistredContext context) { - if (typeof(IValidationEnabled).IsAssignableFrom(context.ImplementationType)) + if (typeof(IValidationEnabled).IsAssignableFrom(context.ImplementationType) && !DynamicProxyIgnoreTypes.Contains(context.ImplementationType)) { context.Interceptors.TryAdd(); } diff --git a/framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/AbpAuthorizationTestModule.cs b/framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/AbpAuthorizationTestModule.cs index 51337ae871..492a36f8b9 100644 --- a/framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/AbpAuthorizationTestModule.cs +++ b/framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/AbpAuthorizationTestModule.cs @@ -1,6 +1,7 @@ using Microsoft.Extensions.DependencyInjection; using Volo.Abp.Authorization.TestServices; using Volo.Abp.Autofac; +using Volo.Abp.DynamicProxy; using Volo.Abp.Modularity; namespace Volo.Abp.Authorization @@ -13,7 +14,8 @@ namespace Volo.Abp.Authorization { context.Services.OnRegistred(onServiceRegistredContext => { - if (typeof(IMyAuthorizedService1).IsAssignableFrom(onServiceRegistredContext.ImplementationType)) + if (typeof(IMyAuthorizedService1).IsAssignableFrom(onServiceRegistredContext.ImplementationType) && + !DynamicProxyIgnoreTypes.Contains(onServiceRegistredContext.ImplementationType)) { onServiceRegistredContext.Interceptors.TryAdd(); } diff --git a/framework/test/Volo.Abp.FluentValidation.Tests/Volo/Abp/FluentValidation/ApplicationService_FluentValidation_Tests.cs b/framework/test/Volo.Abp.FluentValidation.Tests/Volo/Abp/FluentValidation/ApplicationService_FluentValidation_Tests.cs index 5bf11b6d5e..a93eabda1d 100644 --- a/framework/test/Volo.Abp.FluentValidation.Tests/Volo/Abp/FluentValidation/ApplicationService_FluentValidation_Tests.cs +++ b/framework/test/Volo.Abp.FluentValidation.Tests/Volo/Abp/FluentValidation/ApplicationService_FluentValidation_Tests.cs @@ -5,6 +5,7 @@ using Microsoft.Extensions.DependencyInjection; using Shouldly; using Volo.Abp.Autofac; using Volo.Abp.DependencyInjection; +using Volo.Abp.DynamicProxy; using Volo.Abp.Modularity; using Volo.Abp.Testing; using Volo.Abp.Validation; @@ -108,7 +109,8 @@ namespace Volo.Abp.FluentValidation { context.Services.OnRegistred(onServiceRegistredContext => { - if (typeof(IMyAppService).IsAssignableFrom(onServiceRegistredContext.ImplementationType)) + if (typeof(IMyAppService).IsAssignableFrom(onServiceRegistredContext.ImplementationType) && + !DynamicProxyIgnoreTypes.Contains(onServiceRegistredContext.ImplementationType)) { onServiceRegistredContext.Interceptors.TryAdd(); } diff --git a/framework/test/Volo.Abp.Validation.Tests/Volo/Abp/Validation/ApplicationService_Validation_Tests.cs b/framework/test/Volo.Abp.Validation.Tests/Volo/Abp/Validation/ApplicationService_Validation_Tests.cs index 0d13867819..de9067e2f7 100644 --- a/framework/test/Volo.Abp.Validation.Tests/Volo/Abp/Validation/ApplicationService_Validation_Tests.cs +++ b/framework/test/Volo.Abp.Validation.Tests/Volo/Abp/Validation/ApplicationService_Validation_Tests.cs @@ -8,6 +8,7 @@ using Shouldly; using Volo.Abp.Application.Dtos; using Volo.Abp.Autofac; using Volo.Abp.DependencyInjection; +using Volo.Abp.DynamicProxy; using Volo.Abp.Modularity; using Volo.Abp.Testing; using Xunit; @@ -198,7 +199,8 @@ namespace Volo.Abp.Validation { context.Services.OnRegistred(onServiceRegistredContext => { - if (typeof(IMyAppService).IsAssignableFrom(onServiceRegistredContext.ImplementationType)) + if (typeof(IMyAppService).IsAssignableFrom(onServiceRegistredContext.ImplementationType) && + !DynamicProxyIgnoreTypes.Contains(onServiceRegistredContext.ImplementationType)) { onServiceRegistredContext.Interceptors.TryAdd(); } From 1475940d853379a867bef3d899c9000199144a95 Mon Sep 17 00:00:00 2001 From: maliming Date: Fri, 27 Mar 2020 10:24:51 +0800 Subject: [PATCH 25/88] Refactor. --- .../Abp/AspNetCore/Mvc/AbpAspNetCoreMvcModule.cs | 8 ++++---- .../Abp/Auditing/AuditingInterceptorRegistrar.cs | 7 ++++++- .../AuthorizationInterceptorRegistrar.cs | 6 +++--- .../Volo/Abp/DynamicProxy/DynamicProxyIgnoreTypes.cs | 12 +++++++++--- .../Volo/Abp/Features/FeatureInterceptorRegistrar.cs | 7 ++++--- .../Volo/Abp/Uow/UnitOfWorkInterceptorRegistrar.cs | 10 ++++++++-- .../Abp/Validation/ValidationInterceptorRegistrar.cs | 10 ++++++++-- 7 files changed, 42 insertions(+), 18 deletions(-) diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcModule.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcModule.cs index e609b0a601..668e7a77dc 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcModule.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcModule.cs @@ -40,10 +40,10 @@ namespace Volo.Abp.AspNetCore.Mvc { public override void PreConfigureServices(ServiceConfigurationContext context) { - DynamicProxyIgnoreTypes.IgnoreTypes.AddIfNotContains(typeof(ControllerBase)); - DynamicProxyIgnoreTypes.IgnoreTypes.AddIfNotContains(typeof(PageModel)); - DynamicProxyIgnoreTypes.IgnoreTypes.AddIfNotContains(typeof(ViewComponent)); - + DynamicProxyIgnoreTypes.Add(); + DynamicProxyIgnoreTypes.Add(); + DynamicProxyIgnoreTypes.Add(); + context.Services.AddConventionalRegistrar(new AbpAspNetCoreMvcConventionalRegistrar()); } diff --git a/framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/AuditingInterceptorRegistrar.cs b/framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/AuditingInterceptorRegistrar.cs index 6790995331..a407335f3d 100644 --- a/framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/AuditingInterceptorRegistrar.cs +++ b/framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/AuditingInterceptorRegistrar.cs @@ -9,7 +9,7 @@ namespace Volo.Abp.Auditing { public static void RegisterIfNeeded(IOnServiceRegistredContext context) { - if (ShouldIntercept(context.ImplementationType) && !DynamicProxyIgnoreTypes.Contains(context.ImplementationType)) + if (ShouldIntercept(context.ImplementationType)) { context.Interceptors.TryAdd(); } @@ -17,6 +17,11 @@ namespace Volo.Abp.Auditing private static bool ShouldIntercept(Type type) { + if (DynamicProxyIgnoreTypes.Contains(type)) + { + return false; + } + if (ShouldAuditTypeByDefault(type)) { return true; diff --git a/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/AuthorizationInterceptorRegistrar.cs b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/AuthorizationInterceptorRegistrar.cs index b44c299b28..e33a8fca7e 100644 --- a/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/AuthorizationInterceptorRegistrar.cs +++ b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/AuthorizationInterceptorRegistrar.cs @@ -11,7 +11,7 @@ namespace Volo.Abp.Authorization { public static void RegisterIfNeeded(IOnServiceRegistredContext context) { - if (ShouldIntercept(context.ImplementationType) && !DynamicProxyIgnoreTypes.Contains(context.ImplementationType)) + if (ShouldIntercept(context.ImplementationType)) { context.Interceptors.TryAdd(); } @@ -19,8 +19,8 @@ namespace Volo.Abp.Authorization private static bool ShouldIntercept(Type type) { - return type.IsDefined(typeof(AuthorizeAttribute), true) || - AnyMethodHasAuthorizeAttribute(type); + return !DynamicProxyIgnoreTypes.Contains(type) && + (type.IsDefined(typeof(AuthorizeAttribute), true) || AnyMethodHasAuthorizeAttribute(type)); } private static bool AnyMethodHasAuthorizeAttribute(Type implementationType) diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/DynamicProxy/DynamicProxyIgnoreTypes.cs b/framework/src/Volo.Abp.Core/Volo/Abp/DynamicProxy/DynamicProxyIgnoreTypes.cs index 5eae6ef092..6cdefb6705 100644 --- a/framework/src/Volo.Abp.Core/Volo/Abp/DynamicProxy/DynamicProxyIgnoreTypes.cs +++ b/framework/src/Volo.Abp.Core/Volo/Abp/DynamicProxy/DynamicProxyIgnoreTypes.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using Volo.Abp.Threading; namespace Volo.Abp.DynamicProxy { @@ -14,11 +15,16 @@ namespace Volo.Abp.DynamicProxy /// public static class DynamicProxyIgnoreTypes { - public static List IgnoreTypes { get; } = new List(); - + private static HashSet IgnoredTypes { get; } = new HashSet(); + + public static void Add() + { + IgnoredTypes.Locking(() => IgnoredTypes.AddIfNotContains(typeof(T))); + } + public static bool Contains(Type type, bool includeDerivedTypes = true) { - return includeDerivedTypes ? IgnoreTypes.Any(t => t.IsAssignableFrom(type)) : IgnoreTypes.Contains(type); + return includeDerivedTypes ? IgnoredTypes.Any(t => t.IsAssignableFrom(type)) : IgnoredTypes.Contains(type); } } } \ No newline at end of file diff --git a/framework/src/Volo.Abp.Features/Volo/Abp/Features/FeatureInterceptorRegistrar.cs b/framework/src/Volo.Abp.Features/Volo/Abp/Features/FeatureInterceptorRegistrar.cs index b2caa734b5..c20b98c143 100644 --- a/framework/src/Volo.Abp.Features/Volo/Abp/Features/FeatureInterceptorRegistrar.cs +++ b/framework/src/Volo.Abp.Features/Volo/Abp/Features/FeatureInterceptorRegistrar.cs @@ -10,7 +10,7 @@ namespace Volo.Abp.Features { public static void RegisterIfNeeded(IOnServiceRegistredContext context) { - if (ShouldIntercept(context.ImplementationType) && !DynamicProxyIgnoreTypes.Contains(context.ImplementationType)) + if (ShouldIntercept(context.ImplementationType)) { context.Interceptors.TryAdd(); } @@ -18,8 +18,9 @@ namespace Volo.Abp.Features private static bool ShouldIntercept(Type type) { - return type.IsDefined(typeof(RequiresFeatureAttribute), true) || - AnyMethodHasRequiresFeatureAttribute(type); + return !DynamicProxyIgnoreTypes.Contains(type) && + (type.IsDefined(typeof(RequiresFeatureAttribute), true) || + AnyMethodHasRequiresFeatureAttribute(type)); } private static bool AnyMethodHasRequiresFeatureAttribute(Type implementationType) diff --git a/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/UnitOfWorkInterceptorRegistrar.cs b/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/UnitOfWorkInterceptorRegistrar.cs index c01e760d58..5331cb1d0e 100644 --- a/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/UnitOfWorkInterceptorRegistrar.cs +++ b/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/UnitOfWorkInterceptorRegistrar.cs @@ -1,4 +1,5 @@ -using System.Reflection; +using System; +using System.Reflection; using Volo.Abp.DependencyInjection; using Volo.Abp.DynamicProxy; @@ -8,10 +9,15 @@ namespace Volo.Abp.Uow { public static void RegisterIfNeeded(IOnServiceRegistredContext context) { - if (UnitOfWorkHelper.IsUnitOfWorkType(context.ImplementationType.GetTypeInfo()) && !DynamicProxyIgnoreTypes.Contains(context.ImplementationType)) + if (ShouldIntercept(context.ImplementationType)) { context.Interceptors.TryAdd(); } } + + private static bool ShouldIntercept(Type type) + { + return !DynamicProxyIgnoreTypes.Contains(type) && UnitOfWorkHelper.IsUnitOfWorkType(type.GetTypeInfo()); + } } } \ No newline at end of file diff --git a/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/ValidationInterceptorRegistrar.cs b/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/ValidationInterceptorRegistrar.cs index 187f64436e..1474efd710 100644 --- a/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/ValidationInterceptorRegistrar.cs +++ b/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/ValidationInterceptorRegistrar.cs @@ -1,4 +1,5 @@ -using Volo.Abp.DependencyInjection; +using System; +using Volo.Abp.DependencyInjection; using Volo.Abp.DynamicProxy; namespace Volo.Abp.Validation @@ -7,10 +8,15 @@ namespace Volo.Abp.Validation { public static void RegisterIfNeeded(IOnServiceRegistredContext context) { - if (typeof(IValidationEnabled).IsAssignableFrom(context.ImplementationType) && !DynamicProxyIgnoreTypes.Contains(context.ImplementationType)) + if (ShouldIntercept(context.ImplementationType)) { context.Interceptors.TryAdd(); } } + + private static bool ShouldIntercept(Type type) + { + return !DynamicProxyIgnoreTypes.Contains(type) && typeof(IValidationEnabled).IsAssignableFrom(type); + } } } \ No newline at end of file From 0b1606f40bc9d207b73844ad56b2c7cf43806c2e Mon Sep 17 00:00:00 2001 From: maliming Date: Fri, 27 Mar 2020 11:20:17 +0800 Subject: [PATCH 26/88] Add AbpAuditPageFilter, AbpFeaturePageFilter, AbpUowPageFilter, AbpExceptionPageFilter. --- .../ActionDescriptorExtensions.cs | 31 +++++ .../AspNetCore/Mvc/AbpMvcOptionsExtensions.cs | 13 +- .../Mvc/Auditing/AbpAuditPageFilter.cs | 103 ++++++++++++++++ .../AbpExceptionPageFilter.cs | 112 ++++++++++++++++++ .../Mvc/Features/AbpFeaturePageFilter.cs | 44 +++++++ .../AspNetCore/Mvc/Uow/AbpUowPageFilter.cs | 105 ++++++++++++++++ 6 files changed, 406 insertions(+), 2 deletions(-) create mode 100644 framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Auditing/AbpAuditPageFilter.cs create mode 100644 framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ExceptionHandling/AbpExceptionPageFilter.cs create mode 100644 framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Features/AbpFeaturePageFilter.cs create mode 100644 framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Uow/AbpUowPageFilter.cs diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Microsoft/AspNetCore/Mvc/Abstractions/ActionDescriptorExtensions.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Microsoft/AspNetCore/Mvc/Abstractions/ActionDescriptorExtensions.cs index fb992cb4af..97b5a6c61b 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Microsoft/AspNetCore/Mvc/Abstractions/ActionDescriptorExtensions.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Microsoft/AspNetCore/Mvc/Abstractions/ActionDescriptorExtensions.cs @@ -1,6 +1,7 @@ using System; using System.Reflection; using Microsoft.AspNetCore.Mvc.Controllers; +using Microsoft.AspNetCore.Mvc.RazorPages; using Volo.Abp; using Volo.Abp.AspNetCore.Mvc; @@ -37,5 +38,35 @@ namespace Microsoft.AspNetCore.Mvc.Abstractions { return actionDescriptor is ControllerActionDescriptor; } + + public static PageActionDescriptor AsPageActionDescriptor(this ActionDescriptor actionDescriptor) + { + if (!actionDescriptor.IsPageAction()) + { + throw new AbpException($"{nameof(actionDescriptor)} should be type of {typeof(PageActionDescriptor).AssemblyQualifiedName}"); + } + + return actionDescriptor as PageActionDescriptor; + } + + public static MethodInfo GetPageActionMethodInfo(this ActionDescriptor actionDescriptor) + { + return actionDescriptor.AsPageActionDescriptor().GetMethodInfo(); + } + + public static Type GetPageActionReturnType(this PageActionDescriptor actionDescriptor) + { + return actionDescriptor.GetPageActionMethodInfo().ReturnType; + } + + public static bool HasObjectResult(this PageActionDescriptor actionDescriptor) + { + return ActionResultHelper.IsObjectResult(actionDescriptor.GetReturnType()); + } + + public static bool IsPageAction(this ActionDescriptor actionDescriptor) + { + return actionDescriptor is PageActionDescriptor; + } } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpMvcOptionsExtensions.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpMvcOptionsExtensions.cs index 4aedf0b087..64d9daca93 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpMvcOptionsExtensions.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpMvcOptionsExtensions.cs @@ -16,7 +16,8 @@ namespace Volo.Abp.AspNetCore.Mvc public static void AddAbp(this MvcOptions options, IServiceCollection services) { AddConventions(options, services); - AddFilters(options); + AddActionFilters(options); + AddPageFilters(options); AddModelBinders(options); AddMetadataProviders(options, services); } @@ -26,7 +27,7 @@ namespace Volo.Abp.AspNetCore.Mvc options.Conventions.Add(new AbpServiceConventionWrapper(services)); } - private static void AddFilters(MvcOptions options) + private static void AddActionFilters(MvcOptions options) { options.Filters.AddService(typeof(AbpAuditActionFilter)); options.Filters.AddService(typeof(AbpNoContentActionFilter)); @@ -36,6 +37,14 @@ namespace Volo.Abp.AspNetCore.Mvc options.Filters.AddService(typeof(AbpExceptionFilter)); } + private static void AddPageFilters(MvcOptions options) + { + options.Filters.AddService(typeof(AbpAuditPageFilter)); + options.Filters.AddService(typeof(AbpFeaturePageFilter)); + options.Filters.AddService(typeof(AbpUowPageFilter)); + options.Filters.AddService(typeof(AbpExceptionPageFilter)); + } + private static void AddModelBinders(MvcOptions options) { options.ModelBinderProviders.Insert(0, new AbpDateTimeModelBinderProvider()); diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Auditing/AbpAuditPageFilter.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Auditing/AbpAuditPageFilter.cs new file mode 100644 index 0000000000..23e94790e9 --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Auditing/AbpAuditPageFilter.cs @@ -0,0 +1,103 @@ +using System; +using System.Diagnostics; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc.Abstractions; +using Microsoft.AspNetCore.Mvc.Filters; +using Microsoft.Extensions.Options; +using Volo.Abp.Aspects; +using Volo.Abp.Auditing; +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.AspNetCore.Mvc.Auditing +{ + public class AbpAuditPageFilter : IAsyncPageFilter, ITransientDependency + { + protected AbpAuditingOptions Options { get; } + private readonly IAuditingHelper _auditingHelper; + private readonly IAuditingManager _auditingManager; + + public AbpAuditPageFilter(IOptions options, IAuditingHelper auditingHelper, IAuditingManager auditingManager) + { + Options = options.Value; + _auditingHelper = auditingHelper; + _auditingManager = auditingManager; + } + + public Task OnPageHandlerSelectionAsync(PageHandlerSelectedContext context) + { + return Task.CompletedTask; + } + + public async Task OnPageHandlerExecutionAsync(PageHandlerExecutingContext context, PageHandlerExecutionDelegate next) + { + if (context.HandlerMethod == null || !ShouldSaveAudit(context, out var auditLog, out var auditLogAction)) + { + await next(); + return; + } + + using (AbpCrossCuttingConcerns.Applying(context.HandlerInstance, AbpCrossCuttingConcerns.Auditing)) + { + var stopwatch = Stopwatch.StartNew(); + + try + { + var result = await next(); + + if (result.Exception != null && !result.ExceptionHandled) + { + auditLog.Exceptions.Add(result.Exception); + } + } + catch (Exception ex) + { + auditLog.Exceptions.Add(ex); + throw; + } + finally + { + stopwatch.Stop(); + auditLogAction.ExecutionDuration = Convert.ToInt32(stopwatch.Elapsed.TotalMilliseconds); + auditLog.Actions.Add(auditLogAction); + } + } + } + + private bool ShouldSaveAudit(PageHandlerExecutingContext context, out AuditLogInfo auditLog, out AuditLogActionInfo auditLogAction) + { + auditLog = null; + auditLogAction = null; + + if (!Options.IsEnabled) + { + return false; + } + + if (!context.ActionDescriptor.IsPageAction()) + { + return false; + } + + var auditLogScope = _auditingManager.Current; + if (auditLogScope == null) + { + return false; + } + + if (!_auditingHelper.ShouldSaveAudit(context.ActionDescriptor.GetMethodInfo(), true)) + { + return false; + } + + auditLog = auditLogScope.Log; + auditLogAction = _auditingHelper.CreateAuditLogAction( + auditLog, + context.ActionDescriptor.AsControllerActionDescriptor().ControllerTypeInfo.AsType(), + context.ActionDescriptor.AsControllerActionDescriptor().MethodInfo, + context.HandlerArguments + ); + + return true; + } + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ExceptionHandling/AbpExceptionPageFilter.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ExceptionHandling/AbpExceptionPageFilter.cs new file mode 100644 index 0000000000..8aa45688ca --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ExceptionHandling/AbpExceptionPageFilter.cs @@ -0,0 +1,112 @@ +using System; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.Abstractions; +using Microsoft.AspNetCore.Mvc.Filters; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; +using Volo.Abp.AspNetCore.ExceptionHandling; +using Volo.Abp.DependencyInjection; +using Volo.Abp.ExceptionHandling; +using Volo.Abp.Http; +using Volo.Abp.Json; + +namespace Volo.Abp.AspNetCore.Mvc.ExceptionHandling +{ + public class AbpExceptionPageFilter : IAsyncPageFilter, ITransientDependency + { + public ILogger Logger { get; set; } + + private readonly IExceptionToErrorInfoConverter _errorInfoConverter; + private readonly IHttpExceptionStatusCodeFinder _statusCodeFinder; + private readonly IJsonSerializer _jsonSerializer; + + public AbpExceptionPageFilter( + IExceptionToErrorInfoConverter errorInfoConverter, + IHttpExceptionStatusCodeFinder statusCodeFinder, + IJsonSerializer jsonSerializer) + { + _errorInfoConverter = errorInfoConverter; + _statusCodeFinder = statusCodeFinder; + _jsonSerializer = jsonSerializer; + + Logger = NullLogger.Instance; + } + + + public Task OnPageHandlerSelectionAsync(PageHandlerSelectedContext context) + { + return Task.CompletedTask; + } + + public async Task OnPageHandlerExecutionAsync(PageHandlerExecutingContext context, PageHandlerExecutionDelegate next) + { + if (context.HandlerMethod == null || !ShouldHandleException(context)) + { + await next(); + return; + } + + var pageHandlerExecutedContext = await next(); + if (pageHandlerExecutedContext.Exception == null) + { + return;; + } + + await HandleAndWrapException(pageHandlerExecutedContext); + } + + protected virtual bool ShouldHandleException(PageHandlerExecutingContext context) + { + //TODO: Create DontWrap attribute to control wrapping..? + + if (context.ActionDescriptor.IsPageAction() && + context.ActionDescriptor.HasObjectResult()) + { + return true; + } + + if (context.HttpContext.Request.CanAccept(MimeTypes.Application.Json)) + { + return true; + } + + if (context.HttpContext.Request.IsAjax()) + { + return true; + } + + return false; + } + + protected virtual async Task HandleAndWrapException(PageHandlerExecutedContext context) + { + //TODO: Trigger an AbpExceptionHandled event or something like that. + + context.HttpContext.Response.Headers.Add(AbpHttpConsts.AbpErrorFormat, "true"); + context.HttpContext.Response.StatusCode = (int)_statusCodeFinder.GetStatusCode(context.HttpContext, context.Exception); + + var remoteServiceErrorInfo = _errorInfoConverter.Convert(context.Exception); + + context.Result = new ObjectResult(new RemoteServiceErrorResponse(remoteServiceErrorInfo)); + + var logLevel = context.Exception.GetLogLevel(); + + Logger.LogWithLevel(logLevel, $"---------- {nameof(RemoteServiceErrorInfo)} ----------"); + Logger.LogWithLevel(logLevel, _jsonSerializer.Serialize(remoteServiceErrorInfo, indented: true)); + Logger.LogException(context.Exception, logLevel); + + await context.HttpContext + .RequestServices + .GetRequiredService() + .NotifyAsync( + new ExceptionNotificationContext(context.Exception) + ); + + context.Exception = null; //Handled! + } + + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Features/AbpFeaturePageFilter.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Features/AbpFeaturePageFilter.cs new file mode 100644 index 0000000000..ceb117d2ff --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Features/AbpFeaturePageFilter.cs @@ -0,0 +1,44 @@ +using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc.Abstractions; +using Microsoft.AspNetCore.Mvc.Filters; +using Volo.Abp.Aspects; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Features; + +namespace Volo.Abp.AspNetCore.Mvc.Features +{ + public class AbpFeaturePageFilter : IAsyncPageFilter, ITransientDependency + { + private readonly IMethodInvocationFeatureCheckerService _methodInvocationAuthorizationService; + + public AbpFeaturePageFilter(IMethodInvocationFeatureCheckerService methodInvocationAuthorizationService) + { + _methodInvocationAuthorizationService = methodInvocationAuthorizationService; + } + + public Task OnPageHandlerSelectionAsync(PageHandlerSelectedContext context) + { + return Task.CompletedTask; + } + + public async Task OnPageHandlerExecutionAsync(PageHandlerExecutingContext context, PageHandlerExecutionDelegate next) + { + if (context.HandlerMethod == null || !context.ActionDescriptor.IsPageAction()) + { + await next(); + return; + } + + var methodInfo = context.ActionDescriptor.GetMethodInfo(); + + using (AbpCrossCuttingConcerns.Applying(context.HandlerInstance, AbpCrossCuttingConcerns.FeatureChecking)) + { + await _methodInvocationAuthorizationService.CheckAsync( + new MethodInvocationFeatureCheckerContext(methodInfo) + ); + + await next(); + } + } + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Uow/AbpUowPageFilter.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Uow/AbpUowPageFilter.cs new file mode 100644 index 0000000000..aeed982173 --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Uow/AbpUowPageFilter.cs @@ -0,0 +1,105 @@ +using System; +using System.Net.Http; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc.Abstractions; +using Microsoft.AspNetCore.Mvc.Filters; +using Microsoft.Extensions.Options; +using Volo.Abp.AspNetCore.Uow; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Uow; + +namespace Volo.Abp.AspNetCore.Mvc.Uow +{ + public class AbpUowPageFilter : IAsyncPageFilter, ITransientDependency + { + private readonly IUnitOfWorkManager _unitOfWorkManager; + private readonly AbpUnitOfWorkDefaultOptions _defaultOptions; + + public AbpUowPageFilter(IUnitOfWorkManager unitOfWorkManager, IOptions options) + { + _unitOfWorkManager = unitOfWorkManager; + _defaultOptions = options.Value; + } + public Task OnPageHandlerSelectionAsync(PageHandlerSelectedContext context) + { + return Task.CompletedTask; + } + + public async Task OnPageHandlerExecutionAsync(PageHandlerExecutingContext context, PageHandlerExecutionDelegate next) + { + if (context.HandlerMethod == null || !context.ActionDescriptor.IsPageAction()) + { + await next(); + return; + } + + var methodInfo = context.ActionDescriptor.GetMethodInfo(); + var unitOfWorkAttr = UnitOfWorkHelper.GetUnitOfWorkAttributeOrNull(methodInfo); + + context.HttpContext.Items["_AbpActionInfo"] = new AbpActionInfoInHttpContext + { + IsObjectResult = context.ActionDescriptor.HasObjectResult() + }; + + if (unitOfWorkAttr?.IsDisabled == true) + { + await next(); + return; + } + + var options = CreateOptions(context, unitOfWorkAttr); + + //Trying to begin a reserved UOW by AbpUnitOfWorkMiddleware + if (_unitOfWorkManager.TryBeginReserved(AbpUnitOfWorkMiddleware.UnitOfWorkReservationName, options)) + { + var result = await next(); + if (!Succeed(result)) + { + await RollbackAsync(context); + } + + return; + } + + //Begin a new, independent unit of work + using (var uow = _unitOfWorkManager.Begin(options)) + { + var result = await next(); + if (Succeed(result)) + { + await uow.CompleteAsync(context.HttpContext.RequestAborted); + } + } + } + + private AbpUnitOfWorkOptions CreateOptions(PageHandlerExecutingContext context, UnitOfWorkAttribute unitOfWorkAttribute) + { + var options = new AbpUnitOfWorkOptions(); + + unitOfWorkAttribute?.SetOptions(options); + + if (unitOfWorkAttribute?.IsTransactional == null) + { + options.IsTransactional = _defaultOptions.CalculateIsTransactional( + autoValue: !string.Equals(context.HttpContext.Request.Method, HttpMethod.Get.Method, StringComparison.OrdinalIgnoreCase) + ); + } + + return options; + } + + private async Task RollbackAsync(PageHandlerExecutingContext context) + { + var currentUow = _unitOfWorkManager.Current; + if (currentUow != null) + { + await currentUow.RollbackAsync(context.HttpContext.RequestAborted); + } + } + + private static bool Succeed(PageHandlerExecutedContext result) + { + return result.Exception == null || result.ExceptionHandled; + } + } +} \ No newline at end of file From fd5eda2b7f533aa4b0cf51a7384c8ebfd15293da Mon Sep 17 00:00:00 2001 From: maliming Date: Fri, 27 Mar 2020 16:32:21 +0800 Subject: [PATCH 27/88] Add unit tests for razor page filters. --- .../ActionDescriptorExtensions.cs | 25 ------- .../AspNetCore/Mvc/AbpAspNetCoreMvcModule.cs | 7 +- .../AspNetCore/Mvc/AbpMvcOptionsExtensions.cs | 2 +- .../Mvc/Auditing/AbpAuditPageFilter.cs | 6 +- .../AbpExceptionPageFilter.cs | 2 +- .../Mvc/Features/AbpFeaturePageFilter.cs | 2 +- .../AspNetCore/Mvc/Uow/AbpUowPageFilter.cs | 4 +- .../Volo.Abp.AspNetCore.Mvc.Tests.csproj | 19 ++++++ .../Mvc/AbpAspNetCoreMvcTestModule.cs | 10 ++- .../Mvc/Auditing/AuditTestController_Tests.cs | 1 + .../Mvc/Auditing/AuditTestPage.cshtml | 19 ++++++ .../Mvc/Auditing/AuditTestPage.cshtml.cs | 33 ++++++++++ .../Mvc/Auditing/AuditTestPage_Tests.cs | 65 +++++++++++++++++++ .../ExceptionTestController_Tests.cs | 4 ++ .../ExceptionTestPage.cshtml | 19 ++++++ .../ExceptionTestPage.cshtml.cs | 18 +++++ .../ExceptionTestPage_Tests.cs | 56 ++++++++++++++++ .../Mvc/Features/FeatureTestPage.cshtml | 19 ++++++ .../Mvc/Features/FeatureTestPage.cshtml.cs | 27 ++++++++ .../Mvc/Features/FeatureTestPage_Tests.cs | 34 ++++++++++ ...WorkPageFilter_Exception_Rollback_Tests.cs | 37 +++++++++++ .../Mvc/Uow/UnitOfWorkPageFilter_Tests.cs | 22 +++++++ .../Mvc/Uow/UnitOfWorkTestPage.cshtml | 19 ++++++ .../Mvc/Uow/UnitOfWorkTestPage.cshtml.cs | 54 +++++++++++++++ 24 files changed, 469 insertions(+), 35 deletions(-) create mode 100644 framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Auditing/AuditTestPage.cshtml create mode 100644 framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Auditing/AuditTestPage.cshtml.cs create mode 100644 framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Auditing/AuditTestPage_Tests.cs create mode 100644 framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/ExceptionHandling/ExceptionTestPage.cshtml create mode 100644 framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/ExceptionHandling/ExceptionTestPage.cshtml.cs create mode 100644 framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/ExceptionHandling/ExceptionTestPage_Tests.cs create mode 100644 framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Features/FeatureTestPage.cshtml create mode 100644 framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Features/FeatureTestPage.cshtml.cs create mode 100644 framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Features/FeatureTestPage_Tests.cs create mode 100644 framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Uow/UnitOfWorkPageFilter_Exception_Rollback_Tests.cs create mode 100644 framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Uow/UnitOfWorkPageFilter_Tests.cs create mode 100644 framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Uow/UnitOfWorkTestPage.cshtml create mode 100644 framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Uow/UnitOfWorkTestPage.cshtml.cs diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Microsoft/AspNetCore/Mvc/Abstractions/ActionDescriptorExtensions.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Microsoft/AspNetCore/Mvc/Abstractions/ActionDescriptorExtensions.cs index 97b5a6c61b..f54375c844 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Microsoft/AspNetCore/Mvc/Abstractions/ActionDescriptorExtensions.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Microsoft/AspNetCore/Mvc/Abstractions/ActionDescriptorExtensions.cs @@ -38,31 +38,6 @@ namespace Microsoft.AspNetCore.Mvc.Abstractions { return actionDescriptor is ControllerActionDescriptor; } - - public static PageActionDescriptor AsPageActionDescriptor(this ActionDescriptor actionDescriptor) - { - if (!actionDescriptor.IsPageAction()) - { - throw new AbpException($"{nameof(actionDescriptor)} should be type of {typeof(PageActionDescriptor).AssemblyQualifiedName}"); - } - - return actionDescriptor as PageActionDescriptor; - } - - public static MethodInfo GetPageActionMethodInfo(this ActionDescriptor actionDescriptor) - { - return actionDescriptor.AsPageActionDescriptor().GetMethodInfo(); - } - - public static Type GetPageActionReturnType(this PageActionDescriptor actionDescriptor) - { - return actionDescriptor.GetPageActionMethodInfo().ReturnType; - } - - public static bool HasObjectResult(this PageActionDescriptor actionDescriptor) - { - return ActionResultHelper.IsObjectResult(actionDescriptor.GetReturnType()); - } public static bool IsPageAction(this ActionDescriptor actionDescriptor) { diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcModule.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcModule.cs index 668e7a77dc..4d970acd45 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcModule.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcModule.cs @@ -1,4 +1,4 @@ -using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.ApplicationParts; using Microsoft.AspNetCore.Mvc.Controllers; using Microsoft.AspNetCore.Mvc.Filters; @@ -12,7 +12,9 @@ using System; using System.Collections.Generic; using System.Linq; using System.Reflection; +using Microsoft.AspNetCore.Mvc.Razor; using Microsoft.AspNetCore.Mvc.RazorPages; +using Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure; using Microsoft.Extensions.Hosting; using Volo.Abp.ApiVersioning; using Volo.Abp.AspNetCore.Mvc.Conventions; @@ -114,6 +116,9 @@ namespace Volo.Abp.AspNetCore.Mvc //Use DI to create view components context.Services.Replace(ServiceDescriptor.Singleton()); + //Use DI to create razor page + context.Services.Replace(ServiceDescriptor.Singleton()); + //Add feature providers var partManager = context.Services.GetSingletonInstance(); var application = context.Services.GetSingletonInstance(); diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpMvcOptionsExtensions.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpMvcOptionsExtensions.cs index 64d9daca93..f1225f1abf 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpMvcOptionsExtensions.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpMvcOptionsExtensions.cs @@ -39,10 +39,10 @@ namespace Volo.Abp.AspNetCore.Mvc private static void AddPageFilters(MvcOptions options) { + options.Filters.AddService(typeof(AbpExceptionPageFilter)); options.Filters.AddService(typeof(AbpAuditPageFilter)); options.Filters.AddService(typeof(AbpFeaturePageFilter)); options.Filters.AddService(typeof(AbpUowPageFilter)); - options.Filters.AddService(typeof(AbpExceptionPageFilter)); } private static void AddModelBinders(MvcOptions options) diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Auditing/AbpAuditPageFilter.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Auditing/AbpAuditPageFilter.cs index 23e94790e9..6e9996574c 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Auditing/AbpAuditPageFilter.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Auditing/AbpAuditPageFilter.cs @@ -84,7 +84,7 @@ namespace Volo.Abp.AspNetCore.Mvc.Auditing return false; } - if (!_auditingHelper.ShouldSaveAudit(context.ActionDescriptor.GetMethodInfo(), true)) + if (!_auditingHelper.ShouldSaveAudit(context.HandlerMethod.MethodInfo, true)) { return false; } @@ -92,8 +92,8 @@ namespace Volo.Abp.AspNetCore.Mvc.Auditing auditLog = auditLogScope.Log; auditLogAction = _auditingHelper.CreateAuditLogAction( auditLog, - context.ActionDescriptor.AsControllerActionDescriptor().ControllerTypeInfo.AsType(), - context.ActionDescriptor.AsControllerActionDescriptor().MethodInfo, + context.HandlerMethod.GetType(), + context.HandlerMethod.MethodInfo, context.HandlerArguments ); diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ExceptionHandling/AbpExceptionPageFilter.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ExceptionHandling/AbpExceptionPageFilter.cs index 8aa45688ca..fb0a7c5a1f 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ExceptionHandling/AbpExceptionPageFilter.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ExceptionHandling/AbpExceptionPageFilter.cs @@ -63,7 +63,7 @@ namespace Volo.Abp.AspNetCore.Mvc.ExceptionHandling //TODO: Create DontWrap attribute to control wrapping..? if (context.ActionDescriptor.IsPageAction() && - context.ActionDescriptor.HasObjectResult()) + ActionResultHelper.IsObjectResult(context.HandlerMethod.MethodInfo.ReturnType)) { return true; } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Features/AbpFeaturePageFilter.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Features/AbpFeaturePageFilter.cs index ceb117d2ff..83e26ace9c 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Features/AbpFeaturePageFilter.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Features/AbpFeaturePageFilter.cs @@ -29,7 +29,7 @@ namespace Volo.Abp.AspNetCore.Mvc.Features return; } - var methodInfo = context.ActionDescriptor.GetMethodInfo(); + var methodInfo = context.HandlerMethod.MethodInfo; using (AbpCrossCuttingConcerns.Applying(context.HandlerInstance, AbpCrossCuttingConcerns.FeatureChecking)) { diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Uow/AbpUowPageFilter.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Uow/AbpUowPageFilter.cs index aeed982173..993a12b0e7 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Uow/AbpUowPageFilter.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Uow/AbpUowPageFilter.cs @@ -33,12 +33,12 @@ namespace Volo.Abp.AspNetCore.Mvc.Uow return; } - var methodInfo = context.ActionDescriptor.GetMethodInfo(); + var methodInfo = context.HandlerMethod.MethodInfo; var unitOfWorkAttr = UnitOfWorkHelper.GetUnitOfWorkAttributeOrNull(methodInfo); context.HttpContext.Items["_AbpActionInfo"] = new AbpActionInfoInHttpContext { - IsObjectResult = context.ActionDescriptor.HasObjectResult() + IsObjectResult = ActionResultHelper.IsObjectResult(context.HandlerMethod.MethodInfo.ReturnType) }; if (unitOfWorkAttr?.IsDisabled == true) diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo.Abp.AspNetCore.Mvc.Tests.csproj b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo.Abp.AspNetCore.Mvc.Tests.csproj index ddb3f5bc44..d47b369902 100644 --- a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo.Abp.AspNetCore.Mvc.Tests.csproj +++ b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo.Abp.AspNetCore.Mvc.Tests.csproj @@ -24,6 +24,7 @@ + @@ -39,6 +40,24 @@ PreserveNewest + + + true + PreserveNewest + + + true + PreserveNewest + + + true + PreserveNewest + + + true + PreserveNewest + + diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcTestModule.cs b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcTestModule.cs index 5e74ec4bfa..39b7d9af5f 100644 --- a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcTestModule.cs +++ b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcTestModule.cs @@ -1,6 +1,9 @@ -using System; +using System; +using System.Linq; using Localization.Resources.AbpUi; using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Mvc.ApplicationModels; +using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.Extensions.DependencyInjection; using Volo.Abp.AspNetCore.Mvc.Authorization; using Volo.Abp.AspNetCore.Mvc.Localization; @@ -73,6 +76,11 @@ namespace Volo.Abp.AspNetCore.Mvc options.Languages.Add(new LanguageInfo("en", "en", "English")); options.Languages.Add(new LanguageInfo("tr", "tr", "Türkçe")); }); + + Configure(options => + { + options.RootDirectory = "/Volo/Abp/AspNetCore/Mvc"; + }); } public override void OnApplicationInitialization(ApplicationInitializationContext context) diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Auditing/AuditTestController_Tests.cs b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Auditing/AuditTestController_Tests.cs index 49bc689e14..3f934d5fe8 100644 --- a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Auditing/AuditTestController_Tests.cs +++ b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Auditing/AuditTestController_Tests.cs @@ -51,6 +51,7 @@ namespace Volo.Abp.AspNetCore.Mvc.Auditing await _auditingStore.Received().SaveAsync(Arg.Any()); } + [Fact] public async Task Should_Trigger_Middleware_And_AuditLog_Exception_When_Returns_Object() { diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Auditing/AuditTestPage.cshtml b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Auditing/AuditTestPage.cshtml new file mode 100644 index 0000000000..bf85af77ef --- /dev/null +++ b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Auditing/AuditTestPage.cshtml @@ -0,0 +1,19 @@ +@page +@model Volo.Abp.AspNetCore.Mvc.Auditing.AuditTestPage + +@{ + Layout = null; +} + + + + + + + + +
+ +
+ + \ No newline at end of file diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Auditing/AuditTestPage.cshtml.cs b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Auditing/AuditTestPage.cshtml.cs new file mode 100644 index 0000000000..6425d6585b --- /dev/null +++ b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Auditing/AuditTestPage.cshtml.cs @@ -0,0 +1,33 @@ +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.RazorPages; +using Microsoft.Extensions.Options; +using Volo.Abp.AspNetCore.Mvc.UI.RazorPages; +using Volo.Abp.Auditing; + +namespace Volo.Abp.AspNetCore.Mvc.Auditing +{ + public class AuditTestPage : AbpPageModel + { + private readonly AbpAuditingOptions _options; + + public AuditTestPage(IOptions options) + { + _options = options.Value; + } + + public IActionResult OnGetAuditSuccessForGetRequests() + { + return new OkResult(); + } + + public IActionResult OnGetAuditFailForGetRequests() + { + throw new UserFriendlyException("Exception occurred!"); + } + + public ObjectResult OnGetAuditFailForGetRequestsReturningObject() + { + throw new UserFriendlyException("Exception occurred!"); + } + } +} \ No newline at end of file diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Auditing/AuditTestPage_Tests.cs b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Auditing/AuditTestPage_Tests.cs new file mode 100644 index 0000000000..7d5298e253 --- /dev/null +++ b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Auditing/AuditTestPage_Tests.cs @@ -0,0 +1,65 @@ +using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Options; +using NSubstitute; +using Volo.Abp.Auditing; +using Xunit; + +namespace Volo.Abp.AspNetCore.Mvc.Auditing +{ + public class AuditTestPage_Tests : AspNetCoreMvcTestBase + { + private readonly AbpAuditingOptions _options; + private IAuditingStore _auditingStore; + + public AuditTestPage_Tests() + { + _options = ServiceProvider.GetRequiredService>().Value; + _auditingStore = ServiceProvider.GetRequiredService(); + } + + protected override void ConfigureServices(HostBuilderContext context, IServiceCollection services) + { + _auditingStore = Substitute.For(); + services.Replace(ServiceDescriptor.Singleton(_auditingStore)); + base.ConfigureServices(context, services); + } + + [Fact] + public async Task Should_Trigger_Middleware_And_AuditLog_Success_For_GetRequests() + { + _options.IsEnabledForGetRequests = true; + _options.AlwaysLogOnException = false; + await GetResponseAsync("/Auditing/AuditTestPage?handler=AuditSuccessForGetRequests"); + await _auditingStore.Received().SaveAsync(Arg.Any()); + } + + [Fact] + public async Task Should_Trigger_Middleware_And_AuditLog_Exception_Always() + { + _options.IsEnabled = true; + _options.AlwaysLogOnException = true; + + try + { + await GetResponseAsync("/Auditing/AuditTestPage?handler=AuditFailForGetRequests", System.Net.HttpStatusCode.Forbidden); + } + catch { } + + await _auditingStore.Received().SaveAsync(Arg.Any()); + } + + [Fact] + public async Task Should_Trigger_Middleware_And_AuditLog_Exception_When_Returns_Object() + { + _options.IsEnabled = true; + _options.AlwaysLogOnException = true; + + await GetResponseAsync("/Auditing/AuditTestPage?handler=AuditFailForGetRequestsReturningObject", System.Net.HttpStatusCode.Forbidden); + + await _auditingStore.Received().SaveAsync(Arg.Any()); + } + } +} \ No newline at end of file diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/ExceptionHandling/ExceptionTestController_Tests.cs b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/ExceptionHandling/ExceptionTestController_Tests.cs index 0de46fbe55..46cdd073e7 100644 --- a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/ExceptionHandling/ExceptionTestController_Tests.cs +++ b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/ExceptionHandling/ExceptionTestController_Tests.cs @@ -30,9 +30,11 @@ namespace Volo.Abp.AspNetCore.Mvc.ExceptionHandling result.Error.ShouldNotBeNull(); result.Error.Message.ShouldBe("This is a sample exception!"); +#pragma warning disable 4014 _fakeExceptionSubscriber .Received() .HandleAsync(Arg.Any()); +#pragma warning restore 4014 } [Fact] @@ -44,9 +46,11 @@ namespace Volo.Abp.AspNetCore.Mvc.ExceptionHandling ) ); +#pragma warning disable 4014 _fakeExceptionSubscriber .DidNotReceive() .HandleAsync(Arg.Any()); +#pragma warning restore 4014 } } } diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/ExceptionHandling/ExceptionTestPage.cshtml b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/ExceptionHandling/ExceptionTestPage.cshtml new file mode 100644 index 0000000000..7ba36da037 --- /dev/null +++ b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/ExceptionHandling/ExceptionTestPage.cshtml @@ -0,0 +1,19 @@ +@page +@model Volo.Abp.AspNetCore.Mvc.ExceptionHandling.ExceptionTestPage + +@{ + Layout = null; +} + + + + + + + + +
+ +
+ + \ No newline at end of file diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/ExceptionHandling/ExceptionTestPage.cshtml.cs b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/ExceptionHandling/ExceptionTestPage.cshtml.cs new file mode 100644 index 0000000000..717d31effe --- /dev/null +++ b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/ExceptionHandling/ExceptionTestPage.cshtml.cs @@ -0,0 +1,18 @@ +using Microsoft.AspNetCore.Mvc; +using Volo.Abp.AspNetCore.Mvc.UI.RazorPages; + +namespace Volo.Abp.AspNetCore.Mvc.ExceptionHandling +{ + public class ExceptionTestPage : AbpPageModel + { + public void OnGetUserFriendlyException1() + { + throw new UserFriendlyException("This is a sample exception!"); + } + + public IActionResult OnGetUserFriendlyException2() + { + throw new UserFriendlyException("This is a sample exception!"); + } + } +} \ No newline at end of file diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/ExceptionHandling/ExceptionTestPage_Tests.cs b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/ExceptionHandling/ExceptionTestPage_Tests.cs new file mode 100644 index 0000000000..7013c0c676 --- /dev/null +++ b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/ExceptionHandling/ExceptionTestPage_Tests.cs @@ -0,0 +1,56 @@ +using System.Net; +using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using NSubstitute; +using Shouldly; +using Volo.Abp.ExceptionHandling; +using Volo.Abp.Http; +using Xunit; + +namespace Volo.Abp.AspNetCore.Mvc.ExceptionHandling +{ + public class ExceptionTestPage_Tests : AspNetCoreMvcTestBase + { + private IExceptionSubscriber _fakeExceptionSubscriber; + + protected override void ConfigureServices(HostBuilderContext context, IServiceCollection services) + { + base.ConfigureServices(context, services); + + _fakeExceptionSubscriber = Substitute.For(); + + services.AddSingleton(_fakeExceptionSubscriber); + } + + [Fact] + public async Task Should_Return_RemoteServiceErrorResponse_For_UserFriendlyException_For_Void_Return_Value() + { + var result = await GetResponseAsObjectAsync("/ExceptionHandling/ExceptionTestPage?handler=UserFriendlyException1", HttpStatusCode.Forbidden); + result.Error.ShouldNotBeNull(); + result.Error.Message.ShouldBe("This is a sample exception!"); + +#pragma warning disable 4014 + _fakeExceptionSubscriber + .Received() + .HandleAsync(Arg.Any()); +#pragma warning restore 4014 + } + + [Fact] + public async Task Should_Not_Handle_Exceptions_For_ActionResult_Return_Values() + { + await Assert.ThrowsAsync( + async () => await GetResponseAsObjectAsync( + "/ExceptionHandling/ExceptionTestPage?handler=UserFriendlyException2" + ) + ); + +#pragma warning disable 4014 + _fakeExceptionSubscriber + .DidNotReceive() + .HandleAsync(Arg.Any()); +#pragma warning restore 4014 + } + } +} \ No newline at end of file diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Features/FeatureTestPage.cshtml b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Features/FeatureTestPage.cshtml new file mode 100644 index 0000000000..8f0450becb --- /dev/null +++ b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Features/FeatureTestPage.cshtml @@ -0,0 +1,19 @@ +@page +@model Volo.Abp.AspNetCore.Mvc.Features.FeatureTestPage + +@{ + Layout = null; +} + + + + + + + + +
+ +
+ + \ No newline at end of file diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Features/FeatureTestPage.cshtml.cs b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Features/FeatureTestPage.cshtml.cs new file mode 100644 index 0000000000..6a051a29ee --- /dev/null +++ b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Features/FeatureTestPage.cshtml.cs @@ -0,0 +1,27 @@ +using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc; +using Volo.Abp.AspNetCore.Mvc.UI.RazorPages; +using Volo.Abp.Features; + +namespace Volo.Abp.AspNetCore.Mvc.Features +{ + public class FeatureTestPage : AbpPageModel + { + [RequiresFeature("AllowedFeature")] + public Task OnGetAllowedFeatureAsync() + { + return Task.CompletedTask; + } + + [RequiresFeature("NotAllowedFeature")] + public void OnGetNotAllowedFeature() + { + + } + + public ObjectResult OnGetNoFeature() + { + return new ObjectResult(42); + } + } +} \ No newline at end of file diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Features/FeatureTestPage_Tests.cs b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Features/FeatureTestPage_Tests.cs new file mode 100644 index 0000000000..91226f1938 --- /dev/null +++ b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Features/FeatureTestPage_Tests.cs @@ -0,0 +1,34 @@ +using System.Net; +using System.Threading.Tasks; +using Xunit; + +namespace Volo.Abp.AspNetCore.Mvc.Features +{ + public class FeatureTestPage_Tests : AspNetCoreMvcTestBase + { + [Fact] + public async Task Should_Allow_Enabled_Features() + { + await GetResponseAsStringAsync( + "/Features/FeatureTestPage?handler=AllowedFeature" + ); + } + + [Fact] + public async Task Should_Not_Allow_Not_Enabled_Features() + { + await GetResponseAsStringAsync( + "/Features/FeatureTestPage?handler=NotAllowedFeature", + HttpStatusCode.Unauthorized + ); + } + + [Fact] + public async Task Should_Allow_Actions_With_No_Feature() + { + await GetResponseAsStringAsync( + "/Features/FeatureTestPage?handler=NoFeature" + ); + } + } +} \ No newline at end of file diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Uow/UnitOfWorkPageFilter_Exception_Rollback_Tests.cs b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Uow/UnitOfWorkPageFilter_Exception_Rollback_Tests.cs new file mode 100644 index 0000000000..b09d3ca2c9 --- /dev/null +++ b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Uow/UnitOfWorkPageFilter_Exception_Rollback_Tests.cs @@ -0,0 +1,37 @@ +using System.Linq; +using System.Net; +using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; +using Shouldly; +using Volo.Abp.Http; +using Volo.Abp.Json; +using Xunit; + +namespace Volo.Abp.AspNetCore.Mvc.Uow +{ + public class UnitOfWorkPageFilter_Exception_Rollback_Tests : AspNetCoreMvcTestBase + { + [Fact] + public async Task Should_Rollback_Transaction_For_Handled_Exceptions() + { + var result = await GetResponseAsObjectAsync("/Uow/UnitOfWorkTestPage?handler=HandledException", HttpStatusCode.Forbidden); + result.Error.ShouldNotBeNull(); + result.Error.Message.ShouldBe("This is a sample exception!"); + } + + [Fact] + public async Task Should_Gracefully_Handle_Exceptions_On_Complete() + { + var response = await GetResponseAsync("/Uow/UnitOfWorkTestPage?handler=ExceptionOnComplete", HttpStatusCode.Forbidden); + + response.Headers.GetValues(AbpHttpConsts.AbpErrorFormat).FirstOrDefault().ShouldBe("true"); + + var resultAsString = await response.Content.ReadAsStringAsync(); + + var result = ServiceProvider.GetRequiredService().Deserialize(resultAsString); + + result.Error.ShouldNotBeNull(); + result.Error.Message.ShouldBe(TestUnitOfWorkConfig.ExceptionOnCompleteMessage); + } + } +} \ No newline at end of file diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Uow/UnitOfWorkPageFilter_Tests.cs b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Uow/UnitOfWorkPageFilter_Tests.cs new file mode 100644 index 0000000000..820ccf91b7 --- /dev/null +++ b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Uow/UnitOfWorkPageFilter_Tests.cs @@ -0,0 +1,22 @@ +using System.Threading.Tasks; +using Shouldly; +using Xunit; + +namespace Volo.Abp.AspNetCore.Mvc.Uow +{ + public class UnitOfWorkPageFilter_Tests: AspNetCoreMvcTestBase + { + [Fact] + public async Task Get_Actions_Should_Not_Be_Transactional() + { + await GetResponseAsStringAsync("/Uow/UnitOfWorkTestPage?handler=RequiresUow"); + } + + [Fact] + public async Task Non_Get_Actions_Should_Be_Transactional() + { + var result = await Client.PostAsync("/Uow/UnitOfWorkTestPage?handler=RequiresUow", null); + result.IsSuccessStatusCode.ShouldBeTrue(); + } + } +} \ No newline at end of file diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Uow/UnitOfWorkTestPage.cshtml b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Uow/UnitOfWorkTestPage.cshtml new file mode 100644 index 0000000000..da30a64818 --- /dev/null +++ b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Uow/UnitOfWorkTestPage.cshtml @@ -0,0 +1,19 @@ +@page +@model Volo.Abp.AspNetCore.Mvc.Uow.UnitOfWorkTestPage + +@{ + Layout = null; +} + + + + + + + + +
+ +
+ + \ No newline at end of file diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Uow/UnitOfWorkTestPage.cshtml.cs b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Uow/UnitOfWorkTestPage.cshtml.cs new file mode 100644 index 0000000000..ce54e8d34f --- /dev/null +++ b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Uow/UnitOfWorkTestPage.cshtml.cs @@ -0,0 +1,54 @@ +using Microsoft.AspNetCore.Mvc; +using Shouldly; +using Volo.Abp.AspNetCore.Mvc.UI.RazorPages; +using Volo.Abp.Uow; + +namespace Volo.Abp.AspNetCore.Mvc.Uow +{ + [IgnoreAntiforgeryToken] + public class UnitOfWorkTestPage : AbpPageModel + { + private readonly TestUnitOfWorkConfig _testUnitOfWorkConfig; + + public UnitOfWorkTestPage(TestUnitOfWorkConfig testUnitOfWorkConfig) + { + _testUnitOfWorkConfig = testUnitOfWorkConfig; + } + + public IActionResult OnGetRequiresUow() + { + CurrentUnitOfWork.ShouldNotBeNull(); + CurrentUnitOfWork.Options.IsTransactional.ShouldBeFalse(); + + return Content("OK"); + } + + public IActionResult OnPostRequiresUow() + { + CurrentUnitOfWork.ShouldNotBeNull(); + CurrentUnitOfWork.Options.IsTransactional.ShouldBeTrue(); + + return Content("OK"); + } + + [UnitOfWork(isTransactional: true)] + public void OnGetHandledException() + { + CurrentUnitOfWork.ShouldNotBeNull(); + CurrentUnitOfWork.Options.IsTransactional.ShouldBeTrue(); + + throw new UserFriendlyException("This is a sample exception!"); + } + + public ObjectResult OnGetExceptionOnComplete() + { + CurrentUnitOfWork.ShouldNotBeNull(); + CurrentUnitOfWork.Options.IsTransactional.ShouldBeFalse(); + + _testUnitOfWorkConfig.ThrowExceptionOnComplete = true; + + //Prevent rendering of pages. + return new ObjectResult(""); + } + } +} \ No newline at end of file From 406d1cdb9b22c22d028043790d2f0bfc8aed015a Mon Sep 17 00:00:00 2001 From: maliming Date: Fri, 27 Mar 2020 16:34:21 +0800 Subject: [PATCH 28/88] Remove ViewComponent in DynamicProxyIgnoreTypes. --- .../Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcModule.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcModule.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcModule.cs index 4d970acd45..b3f70b161d 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcModule.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcModule.cs @@ -44,7 +44,6 @@ namespace Volo.Abp.AspNetCore.Mvc { DynamicProxyIgnoreTypes.Add(); DynamicProxyIgnoreTypes.Add(); - DynamicProxyIgnoreTypes.Add(); context.Services.AddConventionalRegistrar(new AbpAspNetCoreMvcConventionalRegistrar()); } From abda1104aed9ec70b2a08e6ced5399b1cdf29f80 Mon Sep 17 00:00:00 2001 From: maliming Date: Fri, 27 Mar 2020 21:23:30 +0800 Subject: [PATCH 29/88] Add authorization unit test for razor page. --- .../Volo.Abp.AspNetCore.Mvc.Tests.csproj | 4 ++ .../Mvc/Authorization/AuthTestPage.cshtml | 19 +++++++++ .../Mvc/Authorization/AuthTestPage.cshtml.cs | 18 +++++++++ .../Mvc/Authorization/AuthTestPage_Tests.cs | 40 +++++++++++++++++++ 4 files changed, 81 insertions(+) create mode 100644 framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Authorization/AuthTestPage.cshtml create mode 100644 framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Authorization/AuthTestPage.cshtml.cs create mode 100644 framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Authorization/AuthTestPage_Tests.cs diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo.Abp.AspNetCore.Mvc.Tests.csproj b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo.Abp.AspNetCore.Mvc.Tests.csproj index d47b369902..bb841bc085 100644 --- a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo.Abp.AspNetCore.Mvc.Tests.csproj +++ b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo.Abp.AspNetCore.Mvc.Tests.csproj @@ -57,6 +57,10 @@ true PreserveNewest + + true + PreserveNewest + diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Authorization/AuthTestPage.cshtml b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Authorization/AuthTestPage.cshtml new file mode 100644 index 0000000000..cf94310510 --- /dev/null +++ b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Authorization/AuthTestPage.cshtml @@ -0,0 +1,19 @@ +@page +@model Volo.Abp.AspNetCore.Mvc.Authorization.AuthTestPage + +@{ + Layout = null; +} + + + + + + + + +
+ +
+ + \ No newline at end of file diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Authorization/AuthTestPage.cshtml.cs b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Authorization/AuthTestPage.cshtml.cs new file mode 100644 index 0000000000..5ae66edb5f --- /dev/null +++ b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Authorization/AuthTestPage.cshtml.cs @@ -0,0 +1,18 @@ +using System; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using Volo.Abp.AspNetCore.Mvc.UI.RazorPages; + +namespace Volo.Abp.AspNetCore.Mvc.Authorization +{ + [Authorize] + public class AuthTestPage : AbpPageModel + { + public static Guid FakeUserId { get; } = Guid.NewGuid(); + + public ActionResult OnGet() + { + return Content("OK"); + } + } +} \ No newline at end of file diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Authorization/AuthTestPage_Tests.cs b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Authorization/AuthTestPage_Tests.cs new file mode 100644 index 0000000000..ec8a043fbe --- /dev/null +++ b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Authorization/AuthTestPage_Tests.cs @@ -0,0 +1,40 @@ +using System.Security.Claims; +using System.Threading.Tasks; +using Shouldly; +using Volo.Abp.AspNetCore.TestBase; +using Volo.Abp.Autofac; +using Volo.Abp.MemoryDb; +using Volo.Abp.Modularity; +using Volo.Abp.Security.Claims; +using Xunit; + +namespace Volo.Abp.AspNetCore.Mvc.Authorization +{ + [DependsOn( + typeof(AbpAspNetCoreTestBaseModule), + typeof(AbpMemoryDbTestModule), + typeof(AbpAspNetCoreMvcModule), + typeof(AbpAutofacModule) + )] + public class AuthTestPage_Tests: AspNetCoreMvcTestBase + { + private readonly FakeUserClaims _fakeRequiredService; + + public AuthTestPage_Tests() + { + _fakeRequiredService = GetRequiredService(); + } + + [Fact] + public async Task Should_Call_Simple_Authorized_Method_With_Authenticated_User() + { + _fakeRequiredService.Claims.AddRange(new[] + { + new Claim(AbpClaimTypes.UserId, AuthTestController.FakeUserId.ToString()) + }); + + var result = await GetResponseAsStringAsync("/Authorization/AuthTestPage"); + result.ShouldBe("OK"); + } + } +} \ No newline at end of file From 65a7ea84a2173a1b900f4426d0b2dd799750d19e Mon Sep 17 00:00:00 2001 From: maliming Date: Mon, 30 Mar 2020 14:54:03 +0800 Subject: [PATCH 30/88] Removed UnitOfWork attribute in razor page model. --- .../src/Volo.Abp.Account.Web/Pages/Account/Login.cshtml.cs | 3 --- .../src/Volo.Abp.Account.Web/Pages/Account/Register.cshtml.cs | 1 - 2 files changed, 4 deletions(-) diff --git a/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Login.cshtml.cs b/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Login.cshtml.cs index 014088983a..db0cf372d7 100644 --- a/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Login.cshtml.cs +++ b/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Login.cshtml.cs @@ -87,7 +87,6 @@ namespace Volo.Abp.Account.Web.Pages.Account return Page(); } - [UnitOfWork] //TODO: Will be removed when we implement action filter public virtual async Task OnPostAsync(string action) { await CheckLocalLoginAsync(); @@ -140,7 +139,6 @@ namespace Volo.Abp.Account.Web.Pages.Account return RedirectSafely(ReturnUrl, ReturnUrlHash); } - [UnitOfWork] public virtual async Task OnPostExternalLogin(string provider) { var redirectUrl = Url.Page("./Login", pageHandler: "ExternalLoginCallback", values: new { ReturnUrl, ReturnUrlHash }); @@ -150,7 +148,6 @@ namespace Volo.Abp.Account.Web.Pages.Account return await Task.FromResult(Challenge(properties, provider)); } - [UnitOfWork] public virtual async Task OnGetExternalLoginCallbackAsync(string returnUrl = "", string returnUrlHash = "", string remoteError = null) { //TODO: Did not implemented Identity Server 4 sample for this method (see ExternalLoginCallback in Quickstart of IDS4 sample) diff --git a/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Register.cshtml.cs b/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Register.cshtml.cs index 0cb71f2ed9..db085d6587 100644 --- a/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Register.cshtml.cs +++ b/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Register.cshtml.cs @@ -36,7 +36,6 @@ namespace Volo.Abp.Account.Web.Pages.Account await CheckSelfRegistrationAsync(); } - [UnitOfWork] //TODO: Will be removed when we implement action filter public virtual async Task OnPostAsync() { ValidateModel(); From ea9118dfee97fd2583d0d3da3a89876df73a69e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leon=20Ko=C5=A1ak?= Date: Tue, 31 Mar 2020 08:51:27 +0200 Subject: [PATCH 31/88] Slovenian translations for Volo.Abp.UI --- .../Localization/Resources/AbpUi/sl.json | 62 +++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/sl.json diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/sl.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/sl.json new file mode 100644 index 0000000000..641de8a242 --- /dev/null +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/sl.json @@ -0,0 +1,62 @@ +{ + "culture": "sl", + "texts": { + "InternalServerErrorMessage": "Zgodila se je napaka na strežniku!", + "ValidationErrorMessage": "Vaš zahtevek ni veljaven!", + "ValidationNarrativeErrorMessageTitle": "Pri preverjanju so bile zaznane sledeče napake.", + "DefaultErrorMessage": "Zgodila se je napaka!", + "DefaultErrorMessageDetail": "Strežnik ni poslal podrobnosti o napaki.", + "DefaultErrorMessage401": "Niste prijavljeni!", + "DefaultErrorMessage401Detail": "Za izvedbo te operacije se morate prijaviti.", + "DefaultErrorMessage403": "Nimate pravic!", + "DefaultErrorMessage403Detail": "Nimate dovoljenja za izvedbo te operacije!", + "DefaultErrorMessage404": "Vir ni bil najden!", + "DefaultErrorMessage404Detail": "Zahtevanega vira ni bilo mogoče najti na strežniku!", + "EntityNotFoundErrorMessage": "Ni entitete {0} z id-jem = {1}!", + "Languages": "Jeziki", + "Error": "Napaka", + "AreYouSure": "Ali ste prepričani?", + "Cancel": "Prekliči", + "Yes": "Da", + "No": "Ne", + "Ok": "V redu", + "Close": "Zapri", + "Save": "Shrani", + "SavingWithThreeDot": "Shranjujem...", + "Actions": "Dejanja", + "Delete": "Izbriši", + "Edit": "Uredi", + "Refresh": "Osveži", + "Language": "Jezik", + "LoadMore": "Naloži več", + "ProcessingWithThreeDot": "Procesiram...", + "LoadingWithThreeDot": "Nalagam...", + "Welcome": "Dobrodošli", + "Login": "Prijava", + "Register": "Registracija", + "Logout": "Odjava", + "Submit": "Pošlji", + "Back": "Nazaj", + "PagerSearch": "Iskanje", + "PagerNext": "Naslednja", + "PagerPrevious": "Prejšnja", + "PagerFirst": "Prva", + "PagerLast": "Zadnja", + "PagerInfo": "Prikazanih _START_ do _END_ od _TOTAL_ zapisov", + "PagerInfoEmpty": "Prikazanih 0 do 0 od 0 zapisov", + "PagerInfoFiltered": "(filtrirano od vseh _MAX_ zapisov)", + "NoDataAvailableInDatatable": "V tabeli ni na voljo podatkov", + "PagerShowMenuEntries": "Prikaži _MENU_ zapise", + "DatatableActionDropdownDefaultText": "Dejanja", + "ChangePassword": "Zamenjaj geslo", + "PersonalInfo": "Moj profil", + "AreYouSureYouWantToCancelEditingWarningMessage": "Imate neshranjene spremembe.", + "UnhandledException": "Neobravnavana napaka!", + "401Message": "Nepooblaščeno", + "403Message": "Prepovedano", + "404Message": "Strani ni mogoče najti", + "500Message": "Napaka na strani strežnika", + "GoHomePage": "Pojdi na osnovno stran", + "GoBack": "Nazaj" + } +} From 8df24a62fd35acd64b7f1f79a8c30f74c6d20805 Mon Sep 17 00:00:00 2001 From: Oliver Cooper Date: Thu, 2 Apr 2020 17:44:17 +0100 Subject: [PATCH 32/88] Add Quartz StartupDelay option. --- .../Volo/Abp/Quartz/AbpQuartzModule.cs | 9 ++++++++- .../Volo/Abp/Quartz/AbpQuartzPreOptions.cs | 11 ++++++++++- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/framework/src/Volo.Abp.Quartz/Volo/Abp/Quartz/AbpQuartzModule.cs b/framework/src/Volo.Abp.Quartz/Volo/Abp/Quartz/AbpQuartzModule.cs index c16ab14f4d..615009f914 100644 --- a/framework/src/Volo.Abp.Quartz/Volo/Abp/Quartz/AbpQuartzModule.cs +++ b/framework/src/Volo.Abp.Quartz/Volo/Abp/Quartz/AbpQuartzModule.cs @@ -1,4 +1,5 @@ using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; using Quartz; using Quartz.Impl; using Quartz.Spi; @@ -20,9 +21,15 @@ namespace Volo.Abp.Quartz public override void OnApplicationInitialization(ApplicationInitializationContext context) { + var options = context.ServiceProvider.GetRequiredService>().Value; + _scheduler = context.ServiceProvider.GetService(); _scheduler.JobFactory = context.ServiceProvider.GetService(); - _scheduler.Start(); + + if (options.StartDelay != null && options.StartDelay.Ticks > 0) + _scheduler.StartDelayed(options.StartDelay); + else + _scheduler.Start(); } public override void OnApplicationShutdown(ApplicationShutdownContext context) diff --git a/framework/src/Volo.Abp.Quartz/Volo/Abp/Quartz/AbpQuartzPreOptions.cs b/framework/src/Volo.Abp.Quartz/Volo/Abp/Quartz/AbpQuartzPreOptions.cs index e86f993d1d..9e48744d96 100644 --- a/framework/src/Volo.Abp.Quartz/Volo/Abp/Quartz/AbpQuartzPreOptions.cs +++ b/framework/src/Volo.Abp.Quartz/Volo/Abp/Quartz/AbpQuartzPreOptions.cs @@ -1,14 +1,23 @@ -using System.Collections.Specialized; +using System; +using System.Collections.Specialized; namespace Volo.Abp.Quartz { public class AbpQuartzPreOptions { + /// + /// The quartz configuration. Available properties can be found within Quartz.Impl.StdSchedulerFactory. + /// public NameValueCollection Properties { get; set; } + /// + /// How long Quartz should wait before starting. Default: 0. + /// + public TimeSpan StartDelay { get; set; } public AbpQuartzPreOptions() { Properties = new NameValueCollection(); + StartDelay = new TimeSpan(0); } } } From b0f954036be466f40c35166ab321118429d24826 Mon Sep 17 00:00:00 2001 From: Oliver Cooper Date: Fri, 3 Apr 2020 07:30:40 +0000 Subject: [PATCH 33/88] Added braces and removed null check on StartDelay. --- .../src/Volo.Abp.Quartz/Volo/Abp/Quartz/AbpQuartzModule.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/framework/src/Volo.Abp.Quartz/Volo/Abp/Quartz/AbpQuartzModule.cs b/framework/src/Volo.Abp.Quartz/Volo/Abp/Quartz/AbpQuartzModule.cs index 615009f914..ccd0327ecf 100644 --- a/framework/src/Volo.Abp.Quartz/Volo/Abp/Quartz/AbpQuartzModule.cs +++ b/framework/src/Volo.Abp.Quartz/Volo/Abp/Quartz/AbpQuartzModule.cs @@ -26,10 +26,14 @@ namespace Volo.Abp.Quartz _scheduler = context.ServiceProvider.GetService(); _scheduler.JobFactory = context.ServiceProvider.GetService(); - if (options.StartDelay != null && options.StartDelay.Ticks > 0) + if (options.StartDelay.Ticks > 0) + { _scheduler.StartDelayed(options.StartDelay); + } else + { _scheduler.Start(); + } } public override void OnApplicationShutdown(ApplicationShutdownContext context) From fb8dee5cccff615c8f92b8734a292721986294ea Mon Sep 17 00:00:00 2001 From: maliming Date: Tue, 7 Apr 2020 11:13:42 +0800 Subject: [PATCH 34/88] Enhance EntityHelper's TrySetId method. Resolve #3461 --- .../Volo/Abp/Domain/Entities/EntityHelper.cs | 46 +++++++++++-------- .../Abp/Domain/Entities/EntityHelper_Tests.cs | 19 ++++++++ 2 files changed, 47 insertions(+), 18 deletions(-) diff --git a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/EntityHelper.cs b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/EntityHelper.cs index 2b38059ef8..5233f2accc 100644 --- a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/EntityHelper.cs +++ b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/EntityHelper.cs @@ -1,5 +1,7 @@ using System; +using System.Collections.Concurrent; using System.Collections.Generic; +using System.Linq; using System.Linq.Expressions; using System.Reflection; using JetBrains.Annotations; @@ -95,32 +97,40 @@ namespace Volo.Abp.Domain.Entities var lambdaBody = Expression.Equal(leftExpression, rightExpression); return Expression.Lambda>(lambdaBody, lambdaParam); } - + + private static readonly ConcurrentDictionary CachedPropertyInfo = + new ConcurrentDictionary(); + public static void TrySetId( IEntity entity, Func idFactory, bool checkForDisableGuidGenerationAttribute = false) { - //TODO: Can be optimized (by caching per entity type)? - var entityType = entity.GetType(); - var idProperty = entityType.GetProperty( - nameof(entity.Id) - ); + var property = CachedPropertyInfo.GetOrAdd( + entity.GetType().FullName + checkForDisableGuidGenerationAttribute, () => + { + var entityType = entity.GetType(); + var idProperty = entityType.GetProperties() + .Where(x => x.GetSetMethod(true) != null) + .FirstOrDefault(x => x.Name == nameof(entity.Id)); - if (idProperty == null || idProperty.GetSetMethod(true) == null) - { - return; - } + if (idProperty == null) + { + return null; + } - if (checkForDisableGuidGenerationAttribute) - { - if (idProperty.IsDefined(typeof(DisableIdGenerationAttribute), true)) - { - return; - } - } + if (checkForDisableGuidGenerationAttribute) + { + if (idProperty.IsDefined(typeof(DisableIdGenerationAttribute), true)) + { + return null; + } + } + + return idProperty; + }); - idProperty.SetValue(entity, idFactory()); + property?.SetValue(entity, idFactory()); } } } diff --git a/framework/test/Volo.Abp.Ddd.Tests/Volo/Abp/Domain/Entities/EntityHelper_Tests.cs b/framework/test/Volo.Abp.Ddd.Tests/Volo/Abp/Domain/Entities/EntityHelper_Tests.cs index 2ad6a45b05..8d405f6907 100644 --- a/framework/test/Volo.Abp.Ddd.Tests/Volo/Abp/Domain/Entities/EntityHelper_Tests.cs +++ b/framework/test/Volo.Abp.Ddd.Tests/Volo/Abp/Domain/Entities/EntityHelper_Tests.cs @@ -1,4 +1,5 @@ using System; +using System.ComponentModel; using Shouldly; using Xunit; @@ -33,6 +34,15 @@ namespace Volo.Abp.Domain.Entities myEntityDisablesIdGeneration.Id.ShouldBe(default); } + [Fact] + public static void SetId_NewIdFromBaseClass() + { + var idValue = Guid.NewGuid(); + var myNewIdEntity = new NewIdEntity(); + EntityHelper.TrySetId(myNewIdEntity, () => idValue, true); + myNewIdEntity.Id.ShouldBe(idValue); + } + private class MyEntityDerivedFromAggregateRoot : AggregateRoot { @@ -53,5 +63,14 @@ namespace Volo.Abp.Domain.Entities [DisableIdGeneration] public override Guid Id { get; protected set; } } + + public class NewIdEntity : Entity + { + public new Guid Id + { + get => base.Id; + set => base.Id = value; + } + } } } From c1e969cc3cdd619c436d6bfa281a6139451d2d00 Mon Sep 17 00:00:00 2001 From: Weihan Li Date: Tue, 7 Apr 2020 11:38:36 +0800 Subject: [PATCH 35/88] update IsRelational extension for EntityFramework --- .../Volo/Abp/EntityFrameworkCore/DatabaseFacadeExtensions.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DatabaseFacadeExtensions.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DatabaseFacadeExtensions.cs index f663f43a0d..fbea680be1 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DatabaseFacadeExtensions.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DatabaseFacadeExtensions.cs @@ -8,7 +8,9 @@ namespace Volo.Abp.EntityFrameworkCore { public static bool IsRelational(this DatabaseFacade database) { - return database.GetInfrastructure().GetService() != null; +#pragma warning disable EF1001 // Internal EF Core API usage. + return ((IDatabaseFacadeDependenciesAccessor)database).Dependencies is IRelationalDatabaseFacadeDependencies; +#pragma warning restore EF1001 // Internal EF Core API usage. } } } From 5ae4dccb96a03690d610de5416ae4f2d9c0dbafb Mon Sep 17 00:00:00 2001 From: maliming Date: Wed, 8 Apr 2020 22:17:48 +0800 Subject: [PATCH 36/88] Use the tempkey.rsa file in memory. Resolve #3515 --- .../MyProjectNameTestBaseModule.cs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/templates/app/aspnet-core/test/MyCompanyName.MyProjectName.TestBase/MyProjectNameTestBaseModule.cs b/templates/app/aspnet-core/test/MyCompanyName.MyProjectName.TestBase/MyProjectNameTestBaseModule.cs index 974a91dcf6..1dfc546ad6 100644 --- a/templates/app/aspnet-core/test/MyCompanyName.MyProjectName.TestBase/MyProjectNameTestBaseModule.cs +++ b/templates/app/aspnet-core/test/MyCompanyName.MyProjectName.TestBase/MyProjectNameTestBaseModule.cs @@ -4,6 +4,7 @@ using Volo.Abp.Authorization; using Volo.Abp.Autofac; using Volo.Abp.BackgroundJobs; using Volo.Abp.Data; +using Volo.Abp.IdentityServer; using Volo.Abp.Modularity; using Volo.Abp.Threading; @@ -17,6 +18,19 @@ namespace MyCompanyName.MyProjectName )] public class MyProjectNameTestBaseModule : AbpModule { + public override void PreConfigureServices(ServiceConfigurationContext context) + { + PreConfigure(options => + { + options.AddDeveloperSigningCredential = false; + }); + + PreConfigure(identityServerBuilder => + { + identityServerBuilder.AddDeveloperSigningCredential(false, System.Guid.NewGuid().ToString()); + }); + } + public override void ConfigureServices(ServiceConfigurationContext context) { Configure(options => From 6e6c884eaf5ad437042cd131f40afadbd94a181e Mon Sep 17 00:00:00 2001 From: maliming Date: Thu, 9 Apr 2020 09:11:55 +0800 Subject: [PATCH 37/88] Remove Microsoft.AspNetCore.Mvc.DataAnnotations package. Resolve #3511 --- .../MyCompanyName.MyProjectName.Domain.csproj | 1 - 1 file changed, 1 deletion(-) diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Domain/MyCompanyName.MyProjectName.Domain.csproj b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Domain/MyCompanyName.MyProjectName.Domain.csproj index 2078a20b56..5f7dc8c7b0 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Domain/MyCompanyName.MyProjectName.Domain.csproj +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Domain/MyCompanyName.MyProjectName.Domain.csproj @@ -12,7 +12,6 @@ - From c3f38382d0d5bc4b95cec63a2398a04cd0bfc082 Mon Sep 17 00:00:00 2001 From: maliming Date: Thu, 9 Apr 2020 13:34:40 +0800 Subject: [PATCH 38/88] Introducing AbpRemoteServiceApiDescriptionProvider Resolve #3458 --- .../AspNetCore/Mvc/AbpAspNetCoreMvcModule.cs | 23 +++++ .../AbpRemoteServiceApiDescriptionProvider.cs | 92 +++++++++++++++++++ ...oteServiceApiDescriptionProviderOptions.cs | 10 ++ 3 files changed, 125 insertions(+) create mode 100644 framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ApiExploring/AbpRemoteServiceApiDescriptionProvider.cs create mode 100644 framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ApiExploring/AbpRemoteServiceApiDescriptionProviderOptions.cs diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcModule.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcModule.cs index 21a675ddc4..9a6a224c48 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcModule.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcModule.cs @@ -11,15 +11,19 @@ using Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation; using System; using System.Collections.Generic; using System.Linq; +using System.Net; using System.Reflection; +using Microsoft.AspNetCore.Mvc.ApiExplorer; using Microsoft.Extensions.Hosting; using Volo.Abp.ApiVersioning; +using Volo.Abp.AspNetCore.Mvc.ApiExploring; using Volo.Abp.AspNetCore.Mvc.Conventions; using Volo.Abp.AspNetCore.Mvc.DependencyInjection; using Volo.Abp.AspNetCore.Mvc.Json; using Volo.Abp.AspNetCore.Mvc.Localization; using Volo.Abp.AspNetCore.VirtualFileSystem; using Volo.Abp.DependencyInjection; +using Volo.Abp.Http; using Volo.Abp.Http.Modeling; using Volo.Abp.Localization; using Volo.Abp.Modularity; @@ -50,6 +54,25 @@ namespace Volo.Abp.AspNetCore.Mvc options.IgnoredInterfaces.AddIfNotContains(typeof(IActionFilter)); }); + Configure(options => + { + var statusCodes = new List + { + (int) HttpStatusCode.Forbidden, + (int) HttpStatusCode.Unauthorized, + (int) HttpStatusCode.BadRequest, + (int) HttpStatusCode.NotFound, + (int) HttpStatusCode.NotImplemented, + (int) HttpStatusCode.InternalServerError + }; + + options.SupportedResponseTypes.AddIfNotContains(statusCodes.Select(statusCode => new ApiResponseType + { + Type = typeof(RemoteServiceErrorResponse), + StatusCode = statusCode + })); + }); + context.Services.PostConfigure(options => { if (options.MinifyGeneratedScript == null) diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ApiExploring/AbpRemoteServiceApiDescriptionProvider.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ApiExploring/AbpRemoteServiceApiDescriptionProvider.cs new file mode 100644 index 0000000000..1714d74e65 --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ApiExploring/AbpRemoteServiceApiDescriptionProvider.cs @@ -0,0 +1,92 @@ +using System.Collections.Generic; +using System.Linq; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.Abstractions; +using Microsoft.AspNetCore.Mvc.ApiExplorer; +using Microsoft.AspNetCore.Mvc.Controllers; +using Microsoft.AspNetCore.Mvc.Formatters; +using Microsoft.AspNetCore.Mvc.ModelBinding; +using Microsoft.Extensions.Options; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Reflection; + +namespace Volo.Abp.AspNetCore.Mvc.ApiExploring +{ + public class AbpRemoteServiceApiDescriptionProvider : IApiDescriptionProvider, ITransientDependency + { + private readonly IModelMetadataProvider _modelMetadataProvider; + private readonly MvcOptions _mvcOptions; + private readonly AbpRemoteServiceApiDescriptionProviderOptions _options; + + public AbpRemoteServiceApiDescriptionProvider( + IModelMetadataProvider modelMetadataProvider, + IOptions mvcOptionsAccessor, + IOptions optionsAccessor) + { + _modelMetadataProvider = modelMetadataProvider; + _mvcOptions = mvcOptionsAccessor.Value; + _options = optionsAccessor.Value; + } + + public void OnProvidersExecuted(ApiDescriptionProviderContext context) + { + } + + /// + /// The order -999 ensures that this provider is executed right after the + /// Microsoft.AspNetCore.Mvc.ApiExplorer.DefaultApiDescriptionProvider. + /// + public int Order => -999; + + public void OnProvidersExecuting(ApiDescriptionProviderContext context) + { + foreach (var apiResponseType in GetApiResponseTypes()) + { + foreach (var result in context.Results.Where(x => ShouldAddResponseTypes(x.ActionDescriptor))) + { + result.SupportedResponseTypes.AddIfNotContains(x => x.StatusCode == apiResponseType.StatusCode, () => apiResponseType); + } + } + } + + protected virtual IEnumerable GetApiResponseTypes() + { + foreach (var apiResponse in _options.SupportedResponseTypes) + { + apiResponse.ModelMetadata = _modelMetadataProvider.GetMetadataForType(apiResponse.Type); + + foreach (var responseTypeMetadataProvider in _mvcOptions.OutputFormatters.OfType()) + { + var formatterSupportedContentTypes = responseTypeMetadataProvider.GetSupportedContentTypes(null, apiResponse.Type); + if (formatterSupportedContentTypes == null) + { + continue; + } + + foreach (var formatterSupportedContentType in formatterSupportedContentTypes) + { + apiResponse.ApiResponseFormats.Add(new ApiResponseFormat + { + Formatter = (IOutputFormatter) responseTypeMetadataProvider, + MediaType = formatterSupportedContentType + }); + } + } + } + + return _options.SupportedResponseTypes; + } + + protected virtual bool ShouldAddResponseTypes(ActionDescriptor actionDescriptor) + { + if (ReflectionHelper.GetSingleAttributeOfMemberOrDeclaringTypeOrDefault(actionDescriptor.GetMethodInfo()) != null || + ReflectionHelper.GetSingleAttributeOfMemberOrDeclaringTypeOrDefault(actionDescriptor.GetMethodInfo()) != null) + { + return false; + } + + var remoteServiceAttr = ReflectionHelper.GetSingleAttributeOfMemberOrDeclaringTypeOrDefault(actionDescriptor.GetMethodInfo()); + return remoteServiceAttr != null && remoteServiceAttr.IsEnabled; + } + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ApiExploring/AbpRemoteServiceApiDescriptionProviderOptions.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ApiExploring/AbpRemoteServiceApiDescriptionProviderOptions.cs new file mode 100644 index 0000000000..74e631c53c --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ApiExploring/AbpRemoteServiceApiDescriptionProviderOptions.cs @@ -0,0 +1,10 @@ +using System.Collections.Generic; +using Microsoft.AspNetCore.Mvc.ApiExplorer; + +namespace Volo.Abp.AspNetCore.Mvc.ApiExploring +{ + public class AbpRemoteServiceApiDescriptionProviderOptions + { + public HashSet SupportedResponseTypes { get; set; } = new HashSet(); + } +} \ No newline at end of file From 0999be319d3a5c6411ed6e679ae5778a7be61a2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Fri, 10 Apr 2020 12:10:20 +0300 Subject: [PATCH 39/88] Add IHasExtraProperties Interface section --- docs/en/Object-Extensions.md | 106 ++++++++++++++++++++++++++++++++++- 1 file changed, 105 insertions(+), 1 deletion(-) diff --git a/docs/en/Object-Extensions.md b/docs/en/Object-Extensions.md index fad3ff2b0c..70a83e8ef2 100644 --- a/docs/en/Object-Extensions.md +++ b/docs/en/Object-Extensions.md @@ -1,3 +1,107 @@ # Object Extensions -TODO \ No newline at end of file +ABP Framework provides an **object extension system** to allow you to **add extra properties** to an existing object **without modifying** the related class. This allows to extend functionalities implemented by a depended [application module](Modules/Index.md), especially when you want to [extend entities](Customizing-Application-Modules-Extending-Entities.md) and [DTOs](Customizing-Application-Modules-Overriding-Services.md) defined by the module. + +> Object extension system is not normally not needed for your own objects since you can easily add regular properties to your own classes. + +## IHasExtraProperties Interface + +This is the interface to make a class extensible. It simply defines a `Dictionary` property: + +````csharp +Dictionary ExtraProperties { get; } +```` + +Then you can add or get extra properties using this dictionary. + +### Base Classes + +`IHasExtraProperties` interface is implemented by several base classes by default: + +* Implemented by the `AggregateRoot` class (see [entities](Entities.md)). +* Implemented by `ExtensibleEntityDto`, `ExtensibleAuditedEntityDto`... base [DTO](Data-Transfer-Objects.md) classes. +* Implemented by the `ExtensibleObject`, which is a simple base class can be inherited for any type of object. + +So, if you inherit from these classes, your class will also be extensible. If not, you can always implement it manually. + +### Fundamental Extension Methods + +While you can directly use the `ExtraProperties` property of a class, it is suggested to use the following extension methods while working with the extra properties. + +#### SetProperty + +Used to set the value of an extra property: + +````csharp +user.SetProperty("Title", "My Title"); +user.SetProperty("IsSuperUser", true); +```` + +`SetProperty` returns the same object, so you can chain it: + +````csharp +user.SetProperty("Title", "My Title") + .SetProperty("IsSuperUser", true); +```` + +#### GetProperty + +Used to read the value of an extra property: + +````csharp +var title = user.GetProperty("Title"); + +if (user.GetProperty("IsSuperUser")) +{ + //... +} +```` + +* `GetProperty` is a generic method and takes the object type as the generic parameter. +* Returns the default value if given property was not set before (default value is `0` for `int`, `false` for `bool`... etc). + +##### Non Primitive Property Types + +If your property type is not a primitive (int, bool, enum, string... etc) type, then you need to use non-generic version of the `GetProperty` which returns an `object`. + +#### HasProperty + +Used to check if the object has a property set before. + +#### RemoveProperty + +Used to remove a property from the object. Use this methods instead of setting a `null` value for the property. + +### Some Best Practices + +Using magic strings for the property names is dangerous since you can easily type the property name wrong - it is not type safe. Instead; + +* Define a constant for your extra property names +* Create extension methods to easily set your extra properties. + +Example: + +````csharp +public static class IdentityUserExtensions +{ + private const string TitlePropertyName = "Title"; + + public static void SetTitle(this IdentityUser user, string title) + { + user.SetProperty(TitlePropertyName, title); + } + + public static string GetTitle(this IdentityUser user) + { + return user.GetProperty(TitlePropertyName); + } +} +```` + +Then you can easily set or get the `Title` property: + +````csharp +user.SetTitle("My Title"); +var title = user.GetTitle(); +```` + From 98f97f0228970c8f8f00554790c70bdddb4b7056 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Fri, 10 Apr 2020 12:10:40 +0300 Subject: [PATCH 40/88] Rename ExtensibleObjectMapper file. --- .../{ExtendedObjectMapper.cs => ExtensibleObjectMapper.cs} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/{ExtendedObjectMapper.cs => ExtensibleObjectMapper.cs} (100%) diff --git a/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/ExtendedObjectMapper.cs b/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/ExtensibleObjectMapper.cs similarity index 100% rename from framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/ExtendedObjectMapper.cs rename to framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/ExtensibleObjectMapper.cs From 04cd0eae4d82232fc68c2fd99c1d92bfddb4b533 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Fri, 10 Apr 2020 14:46:11 +0300 Subject: [PATCH 41/88] Update Object-Extensions.md --- docs/en/Object-Extensions.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/docs/en/Object-Extensions.md b/docs/en/Object-Extensions.md index 70a83e8ef2..5841eb739c 100644 --- a/docs/en/Object-Extensions.md +++ b/docs/en/Object-Extensions.md @@ -105,3 +105,15 @@ user.SetTitle("My Title"); var title = user.GetTitle(); ```` +## Object Extension Manager + +While you can set arbitrary properties to an extensible object (which implements the `IHasExtraProperties` interface), `ObjectExtensionManager` is used to explicitly define extra properties for extensible classes. + +Explicitly defining an extra property has some use cases: + +* Allows to control how the extra property is handled on object to object mapping (see the section below). +* Allows to define metadata for the property. For example, you can map an extra property to a table field in the database while using the [EF Core](Entity-Framework-Core.md). + +### AddOrUpdate + +`AddOrUpdate` is the main method to define a new extra property or update an extra property definition. \ No newline at end of file From 0072dec0b6f782e1a306c0d714dc0dc607efaa52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Fri, 10 Apr 2020 16:18:45 +0300 Subject: [PATCH 42/88] complete the object extension manager document. --- docs/en/Object-Extensions.md | 150 +++++++++++++++++- docs/en/docs-nav.json | 4 + .../ObjectExtending/ExtensibleObjectMapper.cs | 2 - 3 files changed, 153 insertions(+), 3 deletions(-) diff --git a/docs/en/Object-Extensions.md b/docs/en/Object-Extensions.md index 5841eb739c..bbcb96374c 100644 --- a/docs/en/Object-Extensions.md +++ b/docs/en/Object-Extensions.md @@ -114,6 +114,154 @@ Explicitly defining an extra property has some use cases: * Allows to control how the extra property is handled on object to object mapping (see the section below). * Allows to define metadata for the property. For example, you can map an extra property to a table field in the database while using the [EF Core](Entity-Framework-Core.md). +> `ObjectExtensionManager` implements the singleton pattern (`ObjectExtensionManager.Instance`) and you should define object extensions before your application startup. The [application startup template](Startup-Templates/Application.md) has some pre-defined static classes to safely define object extensions inside. + ### AddOrUpdate -`AddOrUpdate` is the main method to define a new extra property or update an extra property definition. \ No newline at end of file +`AddOrUpdate` is the main method to define a extra properties or update extra properties for an object. + +Example: Define extra properties for the `IdentityUser` entity: + +````csharp +ObjectExtensionManager.Instance + .AddOrUpdate(options => + { + options.AddOrUpdateProperty("SocialSecurityNumber"); + options.AddOrUpdateProperty("IsSuperUser"); + } + ); +```` + +### AddOrUpdateProperty + +While `AddOrUpdateProperty` can be used on the `options` as shown before, if you want to define a single extra property, you can use the shortcut extension method too: + +````csharp +ObjectExtensionManager.Instance + .AddOrUpdateProperty("SocialSecurityNumber"); +```` + +Sometimes it would be practical to define a single extra property to multiple types. Instead of defining one by one, you can use the following code: + +````csharp +ObjectExtensionManager.Instance + .AddOrUpdateProperty( + new[] + { + typeof(IdentityUserDto), + typeof(IdentityUserCreateDto), + typeof(IdentityUserUpdateDto) + }, + "SocialSecurityNumber" + ); +```` + +#### Property Configuration + +`AddOrUpdateProperty` can also get an action that can perform additional configuration on the property definition. + +Example: + +````csharp +ObjectExtensionManager.Instance + .AddOrUpdateProperty( + "SocialSecurityNumber", + options => + { + options.CheckPairDefinitionOnMapping = false; + }); +```` + +> See the "Object to Object Mapping" section to understand the `CheckPairDefinitionOnMapping` option. + +`options` has a dictionary, named `Configuration` which makes the object extension definitions even extensible. It is used by the EF Core to map extra properties to table fields in the database. See the [extending entities](Customizing-Application-Modules-Extending-Entities.md) document. + +## Object to Object Mapping + +Assume that you've added an extra property to an extensible entity object and used auto [object to object mapping](Object-To-Object-Mapping.md) to map this entity to an extensible DTO class. You need to be careful in such a case, because the extra property may contain a **sensitive data** that should not be available to clients. + +This section offers some **good practices** to control your extra properties on object mapping. + +### MapExtraPropertiesTo + +`MapExtraPropertiesTo` is an extension method provided by the ABP Framework to copy extra properties from an object to another in a controlled manner. Example usage: + +````csharp +identityUser.MapExtraPropertiesTo(identityUserDto); +```` + +`MapExtraPropertiesTo` **requires to define properties** (as described above) in **both sides** (`IdentityUser` and `IdentityUserDto` in this case) in order to copy the value to the target object. Otherwise, it doesn't copy the value even if it does exists in the source object (`identityUser` in this example). There are some ways to overload this restriction. + +#### MappingPropertyDefinitionChecks + +`MapExtraPropertiesTo` gets an additional parameter to control the definition check for a single mapping operation: + +````csharp +identityUser.MapExtraPropertiesTo( + identityUserDto, + MappingPropertyDefinitionChecks.None +); +```` + +> Be careful since `MappingPropertyDefinitionChecks.None` copies all extra properties without any check. `MappingPropertyDefinitionChecks` enum has other members too. + +If you want to completely disable definition check for a property, you can do it while defining the extra property (or update an existing definition) as shown below: + +````csharp +ObjectExtensionManager.Instance + .AddOrUpdateProperty( + "SocialSecurityNumber", + options => + { + options.CheckPairDefinitionOnMapping = false; + }); +```` + +#### Ignored Properties + +You may want to ignore some properties on a specific mapping operation: + +````csharp +identityUser.MapExtraPropertiesTo( + identityUserDto, + ignoredProperties: new[] {"MySensitiveProp"} +); +```` + +Ignored properties are not copied to the target object. + +#### AutoMapper Integration + +If you're using the [AutoMapper](https://automapper.org/) library, the ABP Framework also provides an extension method to utilize the `MapExtraPropertiesTo` method defined above. + +You can use the `MapExtraProperties()` method inside your mapping profile. + +````csharp +public class MyProfile : Profile +{ + public MyProfile() + { + CreateMap() + .MapExtraProperties(); + } +} +```` + +It has the same parameters with the `MapExtraPropertiesTo` method. + +## Entity Framework Core Database Mapping + +If you're using the EF Core, you can map an extra property to a table field in the database. Example: + +````csharp +ObjectExtensionManager.Instance + .AddOrUpdateProperty( + "SocialSecurityNumber", + options => + { + options.MapEfCore(b => b.HasMaxLength(32)); + } + ); +```` + +See the [Entity Framework Core Integration document](Entity-Framework-Core.md) for more. \ No newline at end of file diff --git a/docs/en/docs-nav.json b/docs/en/docs-nav.json index 471e215e3a..f45a4192bb 100644 --- a/docs/en/docs-nav.json +++ b/docs/en/docs-nav.json @@ -155,6 +155,10 @@ { "text": "Data Filtering", "path": "Data-Filtering.md" + }, + { + "text": "Object Extensions", + "path": "Object-Extensions.md" } ] }, diff --git a/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/ExtensibleObjectMapper.cs b/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/ExtensibleObjectMapper.cs index f2b7aeecdb..671aff40f2 100644 --- a/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/ExtensibleObjectMapper.cs +++ b/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/ExtensibleObjectMapper.cs @@ -122,8 +122,6 @@ namespace Volo.Abp.ObjectExtending } } - //TODO: Move these methods to a class like ObjectExtensionHelper - public static bool CanMapProperty( [NotNull] string propertyName, MappingPropertyDefinitionChecks? definitionChecks = null, From 88768be435a86e3ece3e80c5b455fdd81341c04d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Fri, 10 Apr 2020 16:31:40 +0300 Subject: [PATCH 43/88] Update best practices guide --- .../en/Best-Practices/Application-Services.md | 26 ++++++++++++------- .../Best-Practices/Data-Transfer-Objects.md | 1 + 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/docs/en/Best-Practices/Application-Services.md b/docs/en/Best-Practices/Application-Services.md index 0979304931..876105c214 100644 --- a/docs/en/Best-Practices/Application-Services.md +++ b/docs/en/Best-Practices/Application-Services.md @@ -17,17 +17,18 @@ ##### Basic DTO -**Do** define a **basic** DTO for an entity. +**Do** define a **basic** DTO for an aggregate root. -- Include all the **primitive properties** directly on the entity. - - Exception: Can **exclude** properties for **security** reasons (like User.Password). +- Include all the **primitive properties** directly on the aggregate root. + - Exception: Can **exclude** properties for **security** reasons (like `User.Password`). - Include all the **sub collections** of the entity where every item in the collection is a simple **relation DTO**. +- Inherit from one of the **extensible entity DTO** classes for aggregate roots (and entities implement the `IHasExtraProperties`). Example: ```c# [Serializable] -public class IssueDto : FullAuditedEntityDto +public class IssueDto : ExtensibleFullAuditedEntityDto { public string Title { get; set; } public string Text { get; set; } @@ -57,7 +58,7 @@ Example: ````C# [Serializable] -public class IssueWithDetailsDto : FullAuditedEntityDto +public class IssueWithDetailsDto : ExtensibleFullAuditedEntityDto { public string Title { get; set; } public string Text { get; set; } @@ -66,14 +67,14 @@ public class IssueWithDetailsDto : FullAuditedEntityDto } [Serializable] -public class MilestoneDto : EntityDto +public class MilestoneDto : ExtensibleEntityDto { public string Name { get; set; } public bool IsClosed { get; set; } } [Serializable] -public class LabelDto : EntityDto +public class LabelDto : ExtensibleEntityDto { public string Name { get; set; } public string Color { get; set; } @@ -120,6 +121,7 @@ Task> GetListAsync(QuestionListQueryDto queryDto); * **Do** use the `CreateAsync` **method name**. * **Do** get a **specialized input** DTO to create the entity. +* **Do** inherit the DTO class from the `ExtensibleObject` (or any other class implements the `IHasExtraProperties`) to allow to pass extra properties if needed. * **Do** use **data annotations** for input validation. * Share constants between domain wherever possible (via constants defined in the **domain shared** package). * **Do** return **the detailed** DTO for new created entity. @@ -135,10 +137,11 @@ The related **DTO**: ````C# [Serializable] -public class CreateQuestionDto +public class CreateQuestionDto : ExtensibleObject { [Required] - [StringLength(QuestionConsts.MaxTitleLength, MinimumLength = QuestionConsts.MinTitleLength)] + [StringLength(QuestionConsts.MaxTitleLength, + MinimumLength = QuestionConsts.MinTitleLength)] public string Title { get; set; } [StringLength(QuestionConsts.MaxTextLength)] @@ -152,6 +155,7 @@ public class CreateQuestionDto - **Do** use the `UpdateAsync` **method name**. - **Do** get a **specialized input** DTO to update the entity. +- **Do** inherit the DTO class from the `ExtensibleObject` (or any other class implements the `IHasExtraProperties`) to allow to pass extra properties if needed. - **Do** get the Id of the entity as a separated primitive parameter. Do not include to the update DTO. - **Do** use **data annotations** for input validation. - Share constants between domain wherever possible (via constants defined in the **domain shared** package). @@ -200,6 +204,10 @@ This method votes a question and returns the current score of the question. * **Do not** use LINQ/SQL for querying data from database inside the application service methods. It's repository's responsibility to perform LINQ/SQL queries from the data source. +#### Extra Properties + +* **Do** use either `MapExtraPropertiesTo` extension method ([see](Object-Extensions.md)) or configure the object mapper (`MapExtraProperties`) to allow application developers to be able to extend the objects and services. + #### Manipulating / Deleting Entities * **Do** always get all the related entities from repositories to perform the operations on them. diff --git a/docs/en/Best-Practices/Data-Transfer-Objects.md b/docs/en/Best-Practices/Data-Transfer-Objects.md index 0c8580abb7..0fca0e86f2 100644 --- a/docs/en/Best-Practices/Data-Transfer-Objects.md +++ b/docs/en/Best-Practices/Data-Transfer-Objects.md @@ -2,6 +2,7 @@ * **Do** define DTOs in the **application contracts** package. * **Do** inherit from the pre-built **base DTO classes** where possible and necessary (like `EntityDto`, `CreationAuditedEntityDto`, `AuditedEntityDto`, `FullAuditedEntityDto` and so on). + * **Do** inherit from the **extensible DTO** classes for the **aggregate roots** (like `ExtensibleAuditedEntityDto`), because aggregate roots are extensible objects and extra properties are mapped to DTOs in this way. * **Do** define DTO members with **public getter and setter**. * **Do** use **data annotations** for **validation** on the properties of DTOs those are inputs of the service. * **Do** not add any **logic** into DTOs except implementing `IValidatableObject` when necessary. From fd8cd3a001acb86af4cdcfc604ce49a24135c279 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Fri, 10 Apr 2020 16:33:25 +0300 Subject: [PATCH 44/88] remove unused doc --- docs/en/AutoMapper-Integration.md | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 docs/en/AutoMapper-Integration.md diff --git a/docs/en/AutoMapper-Integration.md b/docs/en/AutoMapper-Integration.md deleted file mode 100644 index d197861f25..0000000000 --- a/docs/en/AutoMapper-Integration.md +++ /dev/null @@ -1,3 +0,0 @@ -## AutoMapper Integration - -TODO \ No newline at end of file From 72c679329115c0d99d43eaf5336129fe395b1001 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Fri, 10 Apr 2020 16:37:46 +0300 Subject: [PATCH 45/88] Resolved #3405 Document the object extension system. --- docs/en/Object-To-Object-Mapping.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/docs/en/Object-To-Object-Mapping.md b/docs/en/Object-To-Object-Mapping.md index 52260402f1..b7463607e9 100644 --- a/docs/en/Object-To-Object-Mapping.md +++ b/docs/en/Object-To-Object-Mapping.md @@ -145,6 +145,23 @@ options.AddProfile(validate: true); > If you have multiple profiles and need to enable validation only for a few of them, first use `AddMaps` without validation, then use `AddProfile` for each profile you want to validate. +### Mapping the Object Extensions + +[Object extension system](Object-Extensions.md) allows to define extra properties for existing classes. ABP Framework provides a mapping definition extension to properly map extra properties of two objects. + +````csharp +public class MyProfile : Profile +{ + public MyProfile() + { + CreateMap() + .MapExtraProperties(); + } +} +```` + +It is suggested to use the `MapExtraProperties()` method if both classes are extensible objects (implement the `IHasExtraProperties` interface). See the [object extension document](Object-Extensions.md) for more. + ## Advanced Topics ### IObjectMapper Interface From 66595e35f55fb1d79e690a2ac8e6b5634c8b05d6 Mon Sep 17 00:00:00 2001 From: liangshiwei Date: Fri, 10 Apr 2020 22:57:10 +0800 Subject: [PATCH 46/88] Translate object extensions document --- docs/zh-Hans/AutoMapper-Integration.md | 3 - .../Best-Practices/Application-Services.md | 18 +- .../Best-Practices/Data-Transfer-Objects.md | 1 + docs/zh-Hans/Object-Extensions.md | 267 ++++++++++++++++++ docs/zh-Hans/Object-To-Object-Mapping.md | 17 ++ docs/zh-Hans/docs-nav.json | 4 + 6 files changed, 301 insertions(+), 9 deletions(-) delete mode 100644 docs/zh-Hans/AutoMapper-Integration.md create mode 100644 docs/zh-Hans/Object-Extensions.md diff --git a/docs/zh-Hans/AutoMapper-Integration.md b/docs/zh-Hans/AutoMapper-Integration.md deleted file mode 100644 index d197861f25..0000000000 --- a/docs/zh-Hans/AutoMapper-Integration.md +++ /dev/null @@ -1,3 +0,0 @@ -## AutoMapper Integration - -TODO \ No newline at end of file diff --git a/docs/zh-Hans/Best-Practices/Application-Services.md b/docs/zh-Hans/Best-Practices/Application-Services.md index 6c8d11b32b..6c681edde1 100644 --- a/docs/zh-Hans/Best-Practices/Application-Services.md +++ b/docs/zh-Hans/Best-Practices/Application-Services.md @@ -17,7 +17,7 @@ ##### 基础DTO -**推荐** 为实体定义一个**基础**DTO. +**推荐** 为聚合根定义一个**基础**DTO. - 直接包含实体中所有的**原始属性**. - 例外: 出于**安全**原因,可以**排除**某些属性(像 `User.Password`). @@ -27,7 +27,7 @@ ```c# [Serializable] -public class IssueDto : FullAuditedEntityDto +public class IssueDto : ExtensibleFullAuditedEntityDto { public string Title { get; set; } public string Text { get; set; } @@ -57,7 +57,7 @@ public class IssueLabelDto ````C# [Serializable] -public class IssueWithDetailsDto : FullAuditedEntityDto +public class IssueWithDetailsDto : ExtensibleFullAuditedEntityDto { public string Title { get; set; } public string Text { get; set; } @@ -66,14 +66,14 @@ public class IssueWithDetailsDto : FullAuditedEntityDto } [Serializable] -public class MilestoneDto : EntityDto +public class MilestoneDto : ExtensibleEntityDto { public string Name { get; set; } public bool IsClosed { get; set; } } [Serializable] -public class LabelDto : EntityDto +public class LabelDto : ExtensibleEntityDto { public string Name { get; set; } public string Color { get; set; } @@ -120,6 +120,7 @@ Task> GetListAsync(QuestionListQueryDto queryDto); * **推荐** 使用 `CreateAsync` 做为**方法名**. * **推荐** 使用**专门的输入DTO**来创建实体. +* **推荐** DTO类从 `ExtensibleObject` 类继承(或任何实现 `ExtensibleObject`的类) 以允许在需要时传递额外的属性. * **推荐** 使用 **data annotations** 进行输入验证. * 尽可能在**领域**之间共享常量(通过**domain shared** package定义的常量). * **推荐** 只需要创建实体的**最少**信息, 但是提供了其他可选属性. @@ -134,7 +135,7 @@ Task CreateAsync(CreateQuestionDto questionDto); ````C# [Serializable] -public class CreateQuestionDto +public class CreateQuestionDto : ExtensibleObject { [Required] [StringLength(QuestionConsts.MaxTitleLength, MinimumLength = QuestionConsts.MinTitleLength)] @@ -151,6 +152,7 @@ public class CreateQuestionDto - **推荐** 使用 `UpdateAsync` 做为**方法名**. - **推荐** 使用**专门的输入DTO**来更新实体. +- **推荐** DTO类从 `ExtensibleObject` 类继承(或任何实现 `ExtensibleObject`的类) 以允许在需要时传递额外的属性. - **推荐** 获取实体的id做为分离的原始参数. 不要包含更新DTO. - **推荐** 使用 **data annotations** 进行输入验证. - 尽可能在**领域**之间共享常量(通过**domain shared** package定义的常量). @@ -199,6 +201,10 @@ Task VoteAsync(Guid id, VoteType type); * **不推荐** 在应用程序服务方法中使用linq/sql查询来自数据库的数据. 让仓储负责从数据源执行linq/sql查询. +#### 额外的属性 + +* **推荐** 使用 `MapExtraPropertiesTo` 扩展方法 ([参阅](Object-Extensions.md)) 或配置对象映射 (`MapExtraProperties`) 以允许应用开发人员能够扩展对象和服务. + #### 操作/删除 实体 * **推荐** 总是从数据库中获取所有的相关实体以对他们执行操作. diff --git a/docs/zh-Hans/Best-Practices/Data-Transfer-Objects.md b/docs/zh-Hans/Best-Practices/Data-Transfer-Objects.md index 0c6017e6e7..29e51501ea 100644 --- a/docs/zh-Hans/Best-Practices/Data-Transfer-Objects.md +++ b/docs/zh-Hans/Best-Practices/Data-Transfer-Objects.md @@ -2,6 +2,7 @@ * **推荐** 在 **application.contracts** 层中定义DTO. * **推荐** 在可能和必要的情况下从预构建的 **基础DTO类** 继承 (如 `EntityDto`, `CreationAuditedEntityDto`, `AuditedEntityDto`, `FullAuditedEntityDto` 等). +* **推荐** 从**聚合根**的**扩展DTO**继承(如 `ExtensibleAuditedEntityDto`), 因为聚合根是可扩展的额外的属性使用这种方式映射到DTO. * **推荐** 定义 **public getter 和 setter** 的DTO成员 . * **推荐** 使用 **data annotations** **验证** service输入DTO的属性. * **不推荐** 在DTO中添加任何 **逻辑**, 在必要的时候可以实现 `IValidatableObject` 接口. diff --git a/docs/zh-Hans/Object-Extensions.md b/docs/zh-Hans/Object-Extensions.md new file mode 100644 index 0000000000..27957708f4 --- /dev/null +++ b/docs/zh-Hans/Object-Extensions.md @@ -0,0 +1,267 @@ +# 对象扩展 + +ABP框架提供了 **实体扩展系统** 允许你 **添加额外属性** 到已存在的对象 **无需修改相关类**. 它允许你扩展[应用程序依赖模块](Modules/Index.md)实现的功能,尤其是当你要扩展[模块定义的实体](Customizing-Application-Modules-Extending-Entities.md)和[DTO](Customizing-Application-Modules-Overriding-Services.md)时. + +> 你自己的对象通常不需要对象扩展系统,因为你可以轻松的添加常规属性到你的类中. + +## IHasExtraProperties 接口 + +这是一个使类可扩展的接口. 它定义了 `Dictionary` 属性: + +````csharp +Dictionary ExtraProperties { get; } +```` + +然后你可以使用此字典添加或获取其他属性. + +### 基类 + +默认以下基类实现了 `IHasExtraProperties` 接口: + +* 由 `AggregateRoot` 类实现 (参阅 [entities](Entities.md)). +* 由 `ExtensibleEntityDto`, `ExtensibleAuditedEntityDto`... [DTO](Data-Transfer-Objects.md)基类实现. +* 由 `ExtensibleObject` 实现, 它是一个简单的基类,任何类型的对象都可以继承. + +如果你的类从这些类继承,那么你的类也是可扩展的,如果没有,你也可以随时手动继承. + +### 基本扩展方法 + +虽然可以直接使用类的 `ExtraProperties` 属性,但建议使用以下扩展方法使用额外属性. + +#### SetProperty + +用于设置额外属性值: + +````csharp +user.SetProperty("Title", "My Title"); +user.SetProperty("IsSuperUser", true); +```` + +`SetProperty` 返回相同的对象, 你可以使用链式编程: + +````csharp +user.SetProperty("Title", "My Title") + .SetProperty("IsSuperUser", true); +```` + +#### GetProperty + +用于读取额外属性的值: + +````csharp +var title = user.GetProperty("Title"); + +if (user.GetProperty("IsSuperUser")) +{ + //... +} +```` + +* `GetProperty` 是一个泛型方法,对象类型做为泛型参数. +* 如果未设置给定的属性,则返回默认值 (`int` 的默认值为 `0` , `bool` 的默认值是 `false` ... 等). + +##### 非基本属性类型 + +如果您的属性类型不是原始类型(int,bool,枚举,字符串等),你需要使用 `GetProperty` 的非泛型版本,它会返回 `object`. + +#### HasProperty + +用于检查对象之前是否设置了属性. + +#### RemoveProperty + +用于从对象中删除属性. 使用此方法代替为属性设置 `null` 值. + +### 一些最佳实践 + +为属性名称使用魔术字符串很危险,因为你很容易输入错误的属性名称-这并不安全; + +* 为你的额外属性名称定义一个常量. +* 使用扩展方法轻松设置你的属性. + +示例: + +````csharp +public static class IdentityUserExtensions +{ + private const string TitlePropertyName = "Title"; + + public static void SetTitle(this IdentityUser user, string title) + { + user.SetProperty(TitlePropertyName, title); + } + + public static string GetTitle(this IdentityUser user) + { + return user.GetProperty(TitlePropertyName); + } +} +```` + +然后, 你可以很容易地设置或获取 `Title` 属性: + +````csharp +user.SetTitle("My Title"); +var title = user.GetTitle(); +```` + +## Object Extension Manager + +你可以为可扩展对象(实现 `IHasExtraProperties`接口)设置任意属性, `ObjectExtensionManager` 用于显式定义可扩展类的其他属性. + +显式定义额外的属性有一些用例: + +* 允许控制如何在对象到对象的映射上处理额外的属性 (参阅下面的部分). +* 允许定义属性的元数据. 例如你可以在使用[EF Core](Entity-Framework-Core.md)时将额外的属性映射到数据库中的表字段. + +> `ObjectExtensionManager` 实现单例模式 (`ObjectExtensionManager.Instance`) ,你应该在应用程序启动之前定义对象扩展. [应用程序启动模板](Startup-Templates/Application.md) 有一些预定义的静态类,可以安全在内部定义对象扩展. + +### AddOrUpdate + +`AddOrUpdate` 是定义对象额外属性或更新对象额外属性的主要方法. + +示例: 为 `IdentityUser` 实体定义额外属性: + +````csharp +ObjectExtensionManager.Instance + .AddOrUpdate(options => + { + options.AddOrUpdateProperty("SocialSecurityNumber"); + options.AddOrUpdateProperty("IsSuperUser"); + } + ); +```` + +### AddOrUpdateProperty + +虽然可以如上所示使用 `AddOrUpdateProperty`, 但如果要定义单个额外的属性,也可以使用快捷的扩展方法: + +````csharp +ObjectExtensionManager.Instance + .AddOrUpdateProperty("SocialSecurityNumber"); +```` + +有时将单个额外属性定义为多种类型是可行的. 你可以使用以下代码,而不是一个一个地定义: + +````csharp +ObjectExtensionManager.Instance + .AddOrUpdateProperty( + new[] + { + typeof(IdentityUserDto), + typeof(IdentityUserCreateDto), + typeof(IdentityUserUpdateDto) + }, + "SocialSecurityNumber" + ); +```` + +#### 属性配置 + +`AddOrUpdateProperty` 还可以为属性定义执行其他配置的操作. + +Example: + +````csharp +ObjectExtensionManager.Instance + .AddOrUpdateProperty( + "SocialSecurityNumber", + options => + { + options.CheckPairDefinitionOnMapping = false; + }); +```` + +> 参阅 "对象到对象映射" 部分了解 `CheckPairDefinitionOnMapping` 选项. + +`options` 有一个名为 `Configuration` 的字典,该字典存储对象扩展定义甚至可以扩展. EF Core使用它来将其他属性映射到数据库中的表字段. 请参阅[扩展实体文档](Customizing-Application-Modules-Extending-Entities.md). + +## 对象到对象映射 + +假设你已向可扩展的实体对象添加了额外的属性并使用了自动[对象到对象的映射](Object-To-Object-Mapping.md)将该实体映射到可扩展的DTO类. 在这种情况下你需要格外小心,因为额外属性可能包含**敏感数据**,这些数据对于客户端不可用. + +本节提供了一些**好的做法**,可以控制对象映射的额外属性。 + +### MapExtraPropertiesTo + +`MapExtraPropertiesTo` 是ABP框架提供的扩展方法,用于以受控方式将额外的属性从一个对象复制到另一个对象. 示例: + +````csharp +identityUser.MapExtraPropertiesTo(identityUserDto); +```` + +`MapExtraPropertiesTo` 需要在**两侧**(本例中是`IdentityUser` 和 `IdentityUserDto`)**定义属性**. 以将值复制到目标对象. 否则即使源对象(在此示例中为 `identityUser` )中确实存在该值,它也不会复制. 有一些重载此限制的方法. + +#### MappingPropertyDefinitionChecks + +`MapExtraPropertiesTo` 获取一个附加参数来控制单个映射操作的定义检查: + +````csharp +identityUser.MapExtraPropertiesTo( + identityUserDto, + MappingPropertyDefinitionChecks.None +); +```` + +> 要小心,因为 `MappingPropertyDefinitionChecks.None` 会复制所有的额外属性而不进行任何检查. `MappingPropertyDefinitionChecks` 枚举还有其他成员. + +如果要完全禁用属性的定义检查,可以在定义额外的属性(或更新现有定义)时进行,如下所示: + +````csharp +ObjectExtensionManager.Instance + .AddOrUpdateProperty( + "SocialSecurityNumber", + options => + { + options.CheckPairDefinitionOnMapping = false; + }); +```` + +#### 忽略属性 + +你可能要在映射操作忽略某些属性: + +````csharp +identityUser.MapExtraPropertiesTo( + identityUserDto, + ignoredProperties: new[] {"MySensitiveProp"} +); +```` + +忽略的属性不会复制到目标对象. + +#### AutoMapper集成 + +如果您使用的是[AutoMapper](https://automapper.org/)库,ABP框架还提供了一种扩展方法来利用上面定义的 `MapExtraPropertiesTo` 方法. + +你可以在映射配置文件中使用 `MapExtraProperties()` 方法. + +````csharp +public class MyProfile : Profile +{ + public MyProfile() + { + CreateMap() + .MapExtraProperties(); + } +} +```` + +它与 `MapExtraPropertiesTo()` 方法具有相同的参数。 + +## Entity Framework Core 数据库映射 + +如果你使用的是EF Core,可以将额外的属性映射到数据库中的表字段. 例: + +````csharp +ObjectExtensionManager.Instance + .AddOrUpdateProperty( + "SocialSecurityNumber", + options => + { + options.MapEfCore(b => b.HasMaxLength(32)); + } + ); +```` + +参阅 [Entity Framework Core 集成文档](Entity-Framework-Core.md) 了解更多内容. \ No newline at end of file diff --git a/docs/zh-Hans/Object-To-Object-Mapping.md b/docs/zh-Hans/Object-To-Object-Mapping.md index 67d580ae54..57b744e0bf 100644 --- a/docs/zh-Hans/Object-To-Object-Mapping.md +++ b/docs/zh-Hans/Object-To-Object-Mapping.md @@ -145,6 +145,23 @@ options.AddProfile(validate: true); > 如果你有多个配置文件,并且只需要为其中几个启用验证,那么首先使用`AddMaps`而不进行验证,然后为你想要验证的每个配置文件使用`AddProfile`. +### 映射对象扩展 + +[对象扩展系统](Object-Extensions.md) 允许为已存在的类定义额外属性. ABP 框架提供了一个映射定义扩展可以正确的映射两个对象的额外属性. + +````csharp +public class MyProfile : Profile +{ + public MyProfile() + { + CreateMap() + .MapExtraProperties(); + } +} +```` + +如果两个类都是可扩展对象(实现了 `IHasExtraProperties` 接口),建议使用 `MapExtraProperties` 方法. 更多信息请参阅[对象扩展文档](Object-Extensions.md). + ## 高级主题 ### IObjectMapper 接口 diff --git a/docs/zh-Hans/docs-nav.json b/docs/zh-Hans/docs-nav.json index f01ce04bc9..893e1c3236 100644 --- a/docs/zh-Hans/docs-nav.json +++ b/docs/zh-Hans/docs-nav.json @@ -140,6 +140,10 @@ { "text": "设置管理", "path": "Settings.md" + }, + { + "text": "对象扩展", + "path": "Object-Extensions.md" } ] }, From 43dedc8e7a604cd31a0610dfaee907180b069350 Mon Sep 17 00:00:00 2001 From: liangshiwei Date: Fri, 10 Apr 2020 22:59:56 +0800 Subject: [PATCH 47/88] Add data-filtering document nav --- docs/zh-Hans/docs-nav.json | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/zh-Hans/docs-nav.json b/docs/zh-Hans/docs-nav.json index 893e1c3236..59b91f8e4f 100644 --- a/docs/zh-Hans/docs-nav.json +++ b/docs/zh-Hans/docs-nav.json @@ -141,6 +141,10 @@ "text": "设置管理", "path": "Settings.md" }, + { + "text": "数据过滤", + "path": "Data-Filtering.md" + }, { "text": "对象扩展", "path": "Object-Extensions.md" From e26e7ab48d81a91dc143afe2c7f9f836873ff430 Mon Sep 17 00:00:00 2001 From: Yunus Emre Kalkan Date: Fri, 10 Apr 2020 18:35:29 +0300 Subject: [PATCH 48/88] fix mac download error --- .../Building/Steps/ProjectReferenceReplaceStep.cs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/ProjectReferenceReplaceStep.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/ProjectReferenceReplaceStep.cs index 63f63bef19..c7a6cc90f0 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/ProjectReferenceReplaceStep.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/ProjectReferenceReplaceStep.cs @@ -110,7 +110,7 @@ namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps var oldNodeIncludeValue = oldNode.Attributes["Include"].Value; // ReSharper disable once PossibleNullReferenceException : Can not be null because nodes are selected with include attribute filter in previous method - if (oldNodeIncludeValue.Contains(_projectName) && _entries.Any(e=>e.Name.EndsWith(Path.GetFileName(oldNodeIncludeValue)))) + if (oldNodeIncludeValue.Contains(_projectName) && _entries.Any(e=>e.Name.EndsWith(GetProjectNameWithExtensionFromProjectReference(oldNodeIncludeValue)))) { continue; } @@ -125,6 +125,16 @@ namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps return doc.OuterXml; } + private string GetProjectNameWithExtensionFromProjectReference(string oldNodeIncludeValue) + { + if (string.IsNullOrWhiteSpace(oldNodeIncludeValue)) + { + return oldNodeIncludeValue; + } + + return oldNodeIncludeValue.Split('\\', '/').Last(); + } + protected abstract XmlElement GetNewReferenceNode(XmlDocument doc, string oldNodeIncludeValue); From 85f1fc5496144dea0f58f1cc3f450e08f633f6da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Fri, 10 Apr 2020 22:21:28 +0300 Subject: [PATCH 49/88] Create ObjectExtensionPropertyInfoValidationExtensions. --- ...tensionPropertyInfoValidationExtensions.cs | 68 +++++++++++++++++++ ...tExtensionPropertyInfoValidationOptions.cs | 25 +++++++ .../Abp/Validation/AbpValidationModule.cs | 1 + 3 files changed, 94 insertions(+) create mode 100644 framework/src/Volo.Abp.Validation/Volo/Abp/ObjectExtending/ObjectExtensionPropertyInfoValidationExtensions.cs create mode 100644 framework/src/Volo.Abp.Validation/Volo/Abp/ObjectExtending/ObjectExtensionPropertyInfoValidationOptions.cs diff --git a/framework/src/Volo.Abp.Validation/Volo/Abp/ObjectExtending/ObjectExtensionPropertyInfoValidationExtensions.cs b/framework/src/Volo.Abp.Validation/Volo/Abp/ObjectExtending/ObjectExtensionPropertyInfoValidationExtensions.cs new file mode 100644 index 0000000000..926e086d21 --- /dev/null +++ b/framework/src/Volo.Abp.Validation/Volo/Abp/ObjectExtending/ObjectExtensionPropertyInfoValidationExtensions.cs @@ -0,0 +1,68 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using JetBrains.Annotations; + +namespace Volo.Abp.ObjectExtending +{ + public static class ObjectExtensionPropertyInfoValidationExtensions + { + public const string ValidationConfigurationName = "Validation"; + + [NotNull] + public static ObjectExtensionPropertyInfo ConfigureValidation( + [NotNull] this ObjectExtensionPropertyInfo propertyExtension, + [NotNull] Action configureAction) + { + Check.NotNull(propertyExtension, nameof(propertyExtension)); + Check.NotNull(configureAction, nameof(configureAction)); + + configureAction(propertyExtension.GetOrAddValidationConfiguration()); + + return propertyExtension; + } + + [NotNull] + public static ObjectExtensionPropertyInfo AddValidationAttributes( + [NotNull] this ObjectExtensionPropertyInfo propertyExtension, + [NotNull] params ValidationAttribute[] validationAttributes) + { + Check.NotNull(propertyExtension, nameof(propertyExtension)); + Check.NotNullOrEmpty(validationAttributes, nameof(validationAttributes)); + + propertyExtension + .GetOrAddValidationConfiguration() + .ValidationAttributes + .AddRange(validationAttributes); + + return propertyExtension; + } + + [CanBeNull] + public static ObjectExtensionPropertyInfoValidationOptions GetValidationConfigurationOrNull( + [NotNull] this ObjectExtensionPropertyInfo propertyExtension) + { + Check.NotNull(propertyExtension, nameof(propertyExtension)); + + return propertyExtension.Configuration.GetOrDefault(ValidationConfigurationName) + as ObjectExtensionPropertyInfoValidationOptions; + } + + [NotNull] + public static ObjectExtensionPropertyInfoValidationOptions GetOrAddValidationConfiguration( + [NotNull] this ObjectExtensionPropertyInfo propertyExtension) + { + Check.NotNull(propertyExtension, nameof(propertyExtension)); + + var validationConfiguration = propertyExtension.GetValidationConfigurationOrNull(); + + if (validationConfiguration == null) + { + validationConfiguration = new ObjectExtensionPropertyInfoValidationOptions(propertyExtension); + propertyExtension.Configuration[ValidationConfigurationName] = validationConfiguration; + } + + return validationConfiguration; + } + } +} diff --git a/framework/src/Volo.Abp.Validation/Volo/Abp/ObjectExtending/ObjectExtensionPropertyInfoValidationOptions.cs b/framework/src/Volo.Abp.Validation/Volo/Abp/ObjectExtending/ObjectExtensionPropertyInfoValidationOptions.cs new file mode 100644 index 0000000000..e28efc14df --- /dev/null +++ b/framework/src/Volo.Abp.Validation/Volo/Abp/ObjectExtending/ObjectExtensionPropertyInfoValidationOptions.cs @@ -0,0 +1,25 @@ +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using JetBrains.Annotations; + +namespace Volo.Abp.ObjectExtending +{ + public class ObjectExtensionPropertyInfoValidationOptions + { + [NotNull] + public ObjectExtensionPropertyInfo ExtensionProperty { get; } + + [NotNull] + public ObjectExtensionInfo ObjectExtension => ExtensionProperty.ObjectExtension; + + [NotNull] + public List ValidationAttributes { get; } + + public ObjectExtensionPropertyInfoValidationOptions( + [NotNull] ObjectExtensionPropertyInfo extensionProperty) + { + ExtensionProperty = Check.NotNull(extensionProperty, nameof(extensionProperty)); + ValidationAttributes = new List(); + } + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/AbpValidationModule.cs b/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/AbpValidationModule.cs index ad2be911de..9da6766a5d 100644 --- a/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/AbpValidationModule.cs +++ b/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/AbpValidationModule.cs @@ -18,6 +18,7 @@ namespace Volo.Abp.Validation context.Services.OnRegistred(ValidationInterceptorRegistrar.RegisterIfNeeded); AutoAddObjectValidationContributors(context.Services); } + public override void ConfigureServices(ServiceConfigurationContext context) { Configure(options => From 2a061874b6936ba69e68b823cb4050f767b04a23 Mon Sep 17 00:00:00 2001 From: Arman Ozak Date: Sat, 11 Apr 2020 00:32:22 +0300 Subject: [PATCH 50/88] feat: add an empty modal container component --- .../modal/modal-container.component.ts | 12 +++++++ .../tests/modal-container.component.spec.ts | 34 +++++++++++++++++++ .../src/lib/theme-shared.module.ts | 16 +++++---- 3 files changed, 55 insertions(+), 7 deletions(-) create mode 100644 npm/ng-packs/packages/theme-shared/src/lib/components/modal/modal-container.component.ts create mode 100644 npm/ng-packs/packages/theme-shared/src/lib/tests/modal-container.component.spec.ts diff --git a/npm/ng-packs/packages/theme-shared/src/lib/components/modal/modal-container.component.ts b/npm/ng-packs/packages/theme-shared/src/lib/components/modal/modal-container.component.ts new file mode 100644 index 0000000000..bd24bd84d2 --- /dev/null +++ b/npm/ng-packs/packages/theme-shared/src/lib/components/modal/modal-container.component.ts @@ -0,0 +1,12 @@ +import { Component, ViewChild, ViewContainerRef } from '@angular/core'; + +@Component({ + selector: 'abp-modal-container', + template: ` + + `, +}) +export class ModalContainerComponent { + @ViewChild('container', { static: true, read: ViewContainerRef }) + container: ViewContainerRef; +} diff --git a/npm/ng-packs/packages/theme-shared/src/lib/tests/modal-container.component.spec.ts b/npm/ng-packs/packages/theme-shared/src/lib/tests/modal-container.component.spec.ts new file mode 100644 index 0000000000..4ee654e9bd --- /dev/null +++ b/npm/ng-packs/packages/theme-shared/src/lib/tests/modal-container.component.spec.ts @@ -0,0 +1,34 @@ +import { Component, ComponentFactoryResolver, ComponentRef } from '@angular/core'; +import { createComponentFactory, Spectator } from '@ngneat/spectator/jest'; +import { ModalContainerComponent } from '../components/modal/modal-container.component'; + +describe('ModalContainerComponent', () => { + @Component({ template: '
bar
' }) + class TestComponent {} + + let componentRef: ComponentRef; + let spectator: Spectator; + + const createComponent = createComponentFactory({ + component: ModalContainerComponent, + entryComponents: [TestComponent], + }); + + beforeEach(() => (spectator = createComponent())); + + afterEach(() => componentRef.destroy()); + + describe('#container', () => { + it('should be a ViewContainerRef', () => { + let foo = document.querySelector('div.foo'); + expect(foo).toBeNull(); + + const cfResolver = spectator.get(ComponentFactoryResolver); + const factory = cfResolver.resolveComponentFactory(TestComponent); + componentRef = spectator.component.container.createComponent(factory); + + foo = document.querySelector('div.foo'); + expect(foo.textContent).toBe('bar'); + }); + }); +}); diff --git a/npm/ng-packs/packages/theme-shared/src/lib/theme-shared.module.ts b/npm/ng-packs/packages/theme-shared/src/lib/theme-shared.module.ts index 15ba212944..f23410d6d0 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/theme-shared.module.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/theme-shared.module.ts @@ -1,4 +1,4 @@ -import { CoreModule, noop, LazyLoadService } from '@abp/ng.core'; +import { CoreModule, LazyLoadService, noop } from '@abp/ng.core'; import { DatePipe } from '@angular/common'; import { APP_INITIALIZER, Injector, ModuleWithProviders, NgModule } from '@angular/core'; import { NgbDateParserFormatter, NgbPaginationModule } from '@ng-bootstrap/ng-bootstrap'; @@ -9,23 +9,24 @@ import { ChartComponent } from './components/chart/chart.component'; import { ConfirmationComponent } from './components/confirmation/confirmation.component'; import { HttpErrorWrapperComponent } from './components/http-error-wrapper/http-error-wrapper.component'; import { LoaderBarComponent } from './components/loader-bar/loader-bar.component'; +import { LoadingComponent } from './components/loading/loading.component'; +import { ModalContainerComponent } from './components/modal/modal-container.component'; import { ModalComponent } from './components/modal/modal.component'; +import { PaginationComponent } from './components/pagination/pagination.component'; import { SortOrderIconComponent } from './components/sort-order-icon/sort-order-icon.component'; import { TableEmptyMessageComponent } from './components/table-empty-message/table-empty-message.component'; -import { ToastContainerComponent } from './components/toast-container/toast-container.component'; import { TableComponent } from './components/table/table.component'; +import { ToastContainerComponent } from './components/toast-container/toast-container.component'; import { ToastComponent } from './components/toast/toast.component'; import styles from './constants/styles'; +import { LoadingDirective } from './directives/loading.directive'; import { TableSortDirective } from './directives/table-sort.directive'; import { ErrorHandler } from './handlers/error.handler'; import { RootParams } from './models/common'; +import { THEME_SHARED_APPEND_CONTENT } from './tokens/append-content.token'; import { httpErrorConfigFactory, HTTP_ERROR_CONFIG } from './tokens/http-error.token'; import { DateParserFormatter } from './utils/date-parser-formatter'; import { chartJsLoaded$ } from './utils/widget-utils'; -import { PaginationComponent } from './components/pagination/pagination.component'; -import { LoadingComponent } from './components/loading/loading.component'; -import { LoadingDirective } from './directives/loading.directive'; -import { THEME_SHARED_APPEND_CONTENT } from './tokens/append-content.token'; /** * @@ -54,6 +55,7 @@ export function appendScript(injector: Injector) { LoaderBarComponent, LoadingComponent, ModalComponent, + ModalContainerComponent, PaginationComponent, TableComponent, TableEmptyMessageComponent, @@ -81,7 +83,7 @@ export function appendScript(injector: Injector) { TableSortDirective, ], providers: [DatePipe], - entryComponents: [HttpErrorWrapperComponent, LoadingComponent], + entryComponents: [HttpErrorWrapperComponent, LoadingComponent, ModalContainerComponent], }) export class ThemeSharedModule { constructor(private errorHandler: ErrorHandler) {} From 146c8631606a0f0b45547a996ce2a36c032907c5 Mon Sep 17 00:00:00 2001 From: Arman Ozak Date: Sat, 11 Apr 2020 00:33:49 +0300 Subject: [PATCH 51/88] feat: add a service that projects to modal container --- .../theme-shared/src/lib/services/index.ts | 1 + .../src/lib/services/modal.service.ts | 47 ++++++++++ .../src/lib/tests/modal.service.spec.ts | 87 +++++++++++++++++++ 3 files changed, 135 insertions(+) create mode 100644 npm/ng-packs/packages/theme-shared/src/lib/services/modal.service.ts create mode 100644 npm/ng-packs/packages/theme-shared/src/lib/tests/modal.service.spec.ts diff --git a/npm/ng-packs/packages/theme-shared/src/lib/services/index.ts b/npm/ng-packs/packages/theme-shared/src/lib/services/index.ts index c53455a433..c363a56894 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/services/index.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/services/index.ts @@ -1,2 +1,3 @@ export * from './confirmation.service'; +export * from './modal.service'; export * from './toaster.service'; diff --git a/npm/ng-packs/packages/theme-shared/src/lib/services/modal.service.ts b/npm/ng-packs/packages/theme-shared/src/lib/services/modal.service.ts new file mode 100644 index 0000000000..ac481f68ea --- /dev/null +++ b/npm/ng-packs/packages/theme-shared/src/lib/services/modal.service.ts @@ -0,0 +1,47 @@ +import { ContentProjectionService, PROJECTION_STRATEGY } from '@abp/ng.core'; +import { ComponentRef, Injectable, TemplateRef, ViewContainerRef } from '@angular/core'; +import { ModalContainerComponent } from '../components/modal/modal-container.component'; + +@Injectable({ + providedIn: 'root', +}) +export class ModalService { + private containerComponentRef: ComponentRef; + + constructor(private contentProjectionService: ContentProjectionService) { + this.setContainer(); + } + + private setContainer() { + this.containerComponentRef = this.contentProjectionService.projectContent( + PROJECTION_STRATEGY.AppendComponentToBody(ModalContainerComponent), + ); + + this.containerComponentRef.changeDetectorRef.detectChanges(); + } + + clearModal() { + this.getContainer().clear(); + this.detectChanges(); + } + + detectChanges() { + this.containerComponentRef.changeDetectorRef.detectChanges(); + } + + getContainer(): ViewContainerRef { + return this.containerComponentRef.instance.container; + } + + renderTemplate(template: TemplateRef, context?: T) { + const containerRef = this.getContainer(); + + const strategy = PROJECTION_STRATEGY.ProjectTemplateToContainer( + template, + containerRef, + context, + ); + + this.contentProjectionService.projectContent(strategy); + } +} diff --git a/npm/ng-packs/packages/theme-shared/src/lib/tests/modal.service.spec.ts b/npm/ng-packs/packages/theme-shared/src/lib/tests/modal.service.spec.ts new file mode 100644 index 0000000000..e1a2e8bf51 --- /dev/null +++ b/npm/ng-packs/packages/theme-shared/src/lib/tests/modal.service.spec.ts @@ -0,0 +1,87 @@ +import { Component, TemplateRef, ViewChild } from '@angular/core'; +import { createComponentFactory, Spectator } from '@ngneat/spectator/jest'; +import { ModalContainerComponent } from '../components/modal/modal-container.component'; +import { ModalService } from '../services'; + +describe('ModalContainerComponent', () => { + @Component({ + template: ` + +
bar
+
+ `, + }) + class TestComponent { + @ViewChild('ref', { static: true }) + template: TemplateRef; + + constructor(public service: ModalService) {} + } + + let spectator: Spectator; + let service: ModalService; + + const createComponent = createComponentFactory({ + component: TestComponent, + entryComponents: [ModalContainerComponent], + }); + + beforeEach(() => { + spectator = createComponent(); + service = spectator.component.service; + }); + + afterEach(() => { + service.getContainer().clear(); + service['containerComponentRef'].changeDetectorRef.detectChanges(); + service['containerComponentRef'].destroy(); + }); + + describe('#getContainer', () => { + it('should return the ViewContainerRef of ModalContainerComponent', () => { + let foo = document.querySelector('div.foo'); + expect(foo).toBeNull(); + + const containerRef = service.getContainer(); + const embeddedViewRef = containerRef.createEmbeddedView(spectator.component.template); + + foo = document.querySelector('div.foo'); + expect(foo).toBe(embeddedViewRef.rootNodes[0]); + expect(foo.textContent).toBe('bar'); + }); + }); + + describe('#renderTemplate', () => { + it('should render given template using the ViewContainerRef of ModalContainerComponent', () => { + let foo = document.querySelector('div.foo'); + expect(foo).toBeNull(); + + service.renderTemplate(spectator.component.template); + + foo = document.querySelector('div.foo'); + expect(foo.textContent).toBe('bar'); + }); + }); + + describe('#detectChanges', () => { + it('should call detectChanges on the containerComponentRef', () => { + const spy = jest.spyOn(service['containerComponentRef'].changeDetectorRef, 'detectChanges'); + + service.detectChanges(); + + expect(spy).toHaveBeenCalledTimes(1); + }); + }); + + describe('#clearModal', () => { + it('should call clear on the ViewContainerRef and detectChanges', () => { + const clear = jest.spyOn(service.getContainer(), 'clear'); + const detectChanges = jest.spyOn(service, 'detectChanges'); + + service.clearModal(); + + expect(clear).toHaveBeenCalledTimes(1); + expect(detectChanges).toHaveBeenCalledTimes(1); + }); + }); +}); From 0cf7d1d261661776d4ad62927b8586f9f0e6c0a7 Mon Sep 17 00:00:00 2001 From: Arman Ozak Date: Sat, 11 Apr 2020 00:34:09 +0300 Subject: [PATCH 52/88] feat: use modal service to project modal --- .../lib/components/modal/modal.component.html | 67 +++--- .../lib/components/modal/modal.component.ts | 60 +++-- .../src/lib/tests/modal.component.spec.ts | 224 ++++++++++++------ 3 files changed, 236 insertions(+), 115 deletions(-) diff --git a/npm/ng-packs/packages/theme-shared/src/lib/components/modal/modal.component.html b/npm/ng-packs/packages/theme-shared/src/lib/components/modal/modal.component.html index c3168bad92..b37f5b6ce3 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/components/modal/modal.component.html +++ b/npm/ng-packs/packages/theme-shared/src/lib/components/modal/modal.component.html @@ -1,34 +1,43 @@ -