Browse Source

Merge branch 'dev' of https://github.com/abpframework/abp into feat/volo-5292

pull/7861/head
mehmet-erim 6 years ago
parent
commit
5545541ecd
  1. 6
      docs/en/Best-Practices/Entity-Framework-Core-Integration.md
  2. 2
      docs/en/Blob-Storing-Aliyun.md
  3. 2
      docs/en/Blob-Storing-Aws.md
  4. 2
      docs/en/Blob-Storing-Azure.md
  5. 8
      docs/en/Customizing-Application-Modules-Overriding-Services.md
  6. 2
      docs/zh-Hans/Blob-Storing-Aliyun.md
  7. 2
      docs/zh-Hans/Blob-Storing-Aws.md
  8. 2
      docs/zh-Hans/Blob-Storing-Azure.md
  9. 14
      framework/Volo.Abp.sln
  10. 1
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AspNetCoreApiDescriptionModelProvider.cs
  11. 27
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AspNetCoreApiDescriptionModelProviderOptions.cs
  12. 33
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Conventions/AbpServiceConvention.cs
  13. 5
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Uow/AbpUowActionFilter.cs
  14. 5
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Uow/AbpUowPageFilter.cs
  15. 6
      framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/Builder/AbpApplicationBuilderExtensions.cs
  16. 30
      framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Security/AbpSecurityHeadersMiddleware.cs
  17. 11
      framework/src/Volo.Abp.BlobStoring.Aliyun/Volo/Abp/BlobStoring/Aliyun/AliyunBlobProvider.cs
  18. 2
      framework/src/Volo.Abp.BlobStoring.Aliyun/Volo/Abp/BlobStoring/Aliyun/AliyunBlobProviderConfiguration.cs
  19. 14
      framework/src/Volo.Abp.BlobStoring.Aws/Volo/Abp/BlobStoring/Aws/AwsBlobProvider.cs
  20. 2
      framework/src/Volo.Abp.BlobStoring.Aws/Volo/Abp/BlobStoring/Aws/AwsBlobProviderConfiguration.cs
  21. 14
      framework/src/Volo.Abp.BlobStoring.Azure/Volo/Abp/BlobStoring/Azure/AzureBlobProvider.cs
  22. 2
      framework/src/Volo.Abp.BlobStoring.Azure/Volo/Abp/BlobStoring/Azure/AzureBlobProviderConfiguration.cs
  23. 1
      framework/src/Volo.Abp.BlobStoring.Minio/Volo/Abp/BlobStoring/Minio/MinioBlobContainerConfigurationExtensions.cs
  24. 12
      framework/src/Volo.Abp.BlobStoring.Minio/Volo/Abp/BlobStoring/Minio/MinioBlobProvider.cs
  25. 2
      framework/src/Volo.Abp.BlobStoring.Minio/Volo/Abp/BlobStoring/Minio/MinioBlobProviderConfiguration.cs
  26. 59
      framework/src/Volo.Abp.BlobStoring/Volo/Abp/BlobStoring/BlobContainer.cs
  27. 7
      framework/src/Volo.Abp.BlobStoring/Volo/Abp/BlobStoring/BlobContainerFactory.cs
  28. 15
      framework/src/Volo.Abp.BlobStoring/Volo/Abp/BlobStoring/BlobNormalizeNaming.cs
  29. 64
      framework/src/Volo.Abp.BlobStoring/Volo/Abp/BlobStoring/BlobNormalizeNamingService.cs
  30. 2
      framework/src/Volo.Abp.BlobStoring/Volo/Abp/BlobStoring/BlobProviderBase.cs
  31. 11
      framework/src/Volo.Abp.BlobStoring/Volo/Abp/BlobStoring/IBlobNormalizeNamingService.cs
  32. 62
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs
  33. 30
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/ProjectReferenceReplaceStep.cs
  34. 4
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/RemoveProjectFromSolutionStep.cs
  35. 28
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/SolutionRenameStep.cs
  36. 3
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/TemplateProjectBuildPipelineBuilder.cs
  37. 7
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/SolutionName.cs
  38. 4
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/TemplateInfoProvider.cs
  39. 16
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/Microservice/MicroserviceServiceProTemplate.cs
  40. 62
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/Microservice/MicroserviceServiceTemplateBase.cs
  41. 26
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/Microservice/MicroserviceTemplateBase.cs
  42. 63
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/AngularModuleSourceCodeAdder.cs
  43. 19
      framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/DependencyInjection/AbpCommonDbContextRegistrationOptions.cs
  44. 14
      framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/DependencyInjection/IAbpCommonDbContextRegistrationOptionsBuilder.cs
  45. 10
      framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/EntityHelper.cs
  46. 30
      framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Repositories/RepositoryRegistrarBase.cs
  47. 5
      framework/src/Volo.Abp.Http/Volo/Abp/Http/Modeling/ParameterApiDescriptionModel.cs
  48. 4
      framework/src/Volo.Abp.Http/Volo/Abp/Http/Modeling/PropertyApiDescriptionModel.cs
  49. 22
      framework/src/Volo.Abp.Http/Volo/Abp/Http/ProxyScripting/Configuration/AbpApiProxyScriptingOptions.cs
  50. 3
      framework/src/Volo.Abp.Sms.Aliyun/FodyWeavers.xml
  51. 30
      framework/src/Volo.Abp.Sms.Aliyun/FodyWeavers.xsd
  52. 24
      framework/src/Volo.Abp.Sms.Aliyun/Volo.Abp.Sms.Aliyun.csproj
  53. 11
      framework/src/Volo.Abp.Sms.Aliyun/Volo/Abp/Sms/Aliyun/AbpAliyunSmsOptions.cs
  54. 16
      framework/src/Volo.Abp.Sms.Aliyun/Volo/Abp/Sms/Aliyun/AbpSmsAliyunModule.cs
  55. 43
      framework/src/Volo.Abp.Sms.Aliyun/Volo/Abp/Sms/Aliyun/AliyunSmsSender.cs
  56. 1
      framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcTestModule.cs
  57. 10
      framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Authorization/AuthTestController_Tests.cs
  58. 143
      framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Conventions/AbpServiceConvention_Tests.cs
  59. 10
      framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Security/Claims/ClaimsMapTestController_Tests.cs
  60. 12
      framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Security/Headers/SecurityHeadersTestController.cs
  61. 19
      framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Security/Headers/SecurityHeadersTestController_Tests.cs
  62. 54
      framework/test/Volo.Abp.Ddd.Tests/Volo/Abp/Domain/Repositories/RepositoryRegistration_Tests.cs
  63. 26
      framework/test/Volo.Abp.Sms.Aliyun.Tests/Volo.Abp.Sms.Aliyun.Tests.csproj
  64. 12
      framework/test/Volo.Abp.Sms.Aliyun.Tests/Volo/Abp/Sms/Aliyun/AbpSmsAliyunTestBase.cs
  65. 18
      framework/test/Volo.Abp.Sms.Aliyun.Tests/Volo/Abp/Sms/Aliyun/AbpSmsAliyunTestsModule.cs
  66. 37
      framework/test/Volo.Abp.Sms.Aliyun.Tests/Volo/Abp/Sms/Aliyun/AliyunSmsSender_Tests.cs
  67. 11
      framework/test/Volo.Abp.Sms.Aliyun.Tests/appsettings.json
  68. 2
      modules/audit-logging/src/Volo.Abp.AuditLogging.EntityFrameworkCore/Volo/Abp/AuditLogging/EntityFrameworkCore/IAuditLoggingDbContext.cs
  69. 10
      modules/blogging/src/Volo.Blogging.EntityFrameworkCore/Volo/Blogging/EntityFrameworkCore/IBloggingDbContext.cs
  70. 2018
      modules/cms-kit/host/Volo.CmsKit.Web.Unified/Migrations/20210225092130_Page_Remove_Description.Designer.cs
  71. 24
      modules/cms-kit/host/Volo.CmsKit.Web.Unified/Migrations/20210225092130_Page_Remove_Description.cs
  72. 4
      modules/cms-kit/host/Volo.CmsKit.Web.Unified/Migrations/UnifiedDbContextModelSnapshot.cs
  73. 8
      modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Blogs/BlogDto.cs
  74. 5
      modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Blogs/BlogFeatureInputDto.cs
  75. 4
      modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Blogs/BlogGetListInput.cs
  76. 1
      modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Blogs/BlogPostDto.cs
  77. 17
      modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Blogs/CreateBlogDto.cs
  78. 6
      modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Blogs/CreateBlogPostDto.cs
  79. 2
      modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Blogs/IBlogAdminAppService.cs
  80. 2
      modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Blogs/IBlogPostAdminAppService.cs
  81. 17
      modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Blogs/UpdateBlogDto.cs
  82. 9
      modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Blogs/UpdateBlogPostDto.cs
  83. 1
      modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Comments/CmsUserDto.cs
  84. 1
      modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Comments/CommentDto.cs
  85. 1
      modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Comments/CommentGetListInput.cs
  86. 1
      modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Comments/CommentWithAuthorDto.cs
  87. 4
      modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Contents/ContentCreateDto.cs
  88. 1
      modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Contents/ContentDto.cs
  89. 1
      modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Contents/ContentGetListDto.cs
  90. 4
      modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Contents/ContentGetListInput.cs
  91. 4
      modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Contents/ContentUpdateDto.cs
  92. 0
      modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/MediaDescriptors/CreateMediaInputStream.cs
  93. 1
      modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/MediaDescriptors/MediaDescriptorDto.cs
  94. 7
      modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Pages/CreatePageInputDto.cs
  95. 4
      modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Pages/GetPagesInputDto.cs
  96. 3
      modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Pages/PageDto.cs
  97. 7
      modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Pages/UpdatePageInputDto.cs
  98. 4
      modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Tags/EntityTagCreateDto.cs
  99. 1
      modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Tags/EntityTagRemoveDto.cs
  100. 1
      modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Tags/EntityTagSetDto.cs

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

@ -16,11 +16,13 @@
[ConnectionStringName("AbpIdentity")]
public interface IIdentityDbContext : IEfCoreDbContext
{
DbSet<IdentityUser> Users { get; set; }
DbSet<IdentityRole> Roles { get; set; }
DbSet<IdentityUser> Users { get; }
DbSet<IdentityRole> Roles { get; }
}
````
* **Do not** define `set;` for the properties in this interface.
### DbContext class
* **Do** inherit the `DbContext` from the `AbpDbContext<TDbContext>` class.

2
docs/en/Blob-Storing-Aliyun.md

@ -36,7 +36,7 @@ Configure<AbpBlobStoringOptions>(options =>
aliyun.Policy = "policy";
aliyun.DurationSeconds = "expiration date";
aliyun.ContainerName = "your aliyun container name";
aliyun.CreateContainerIfNotExists = false;
aliyun.CreateContainerIfNotExists = true;
});
});
});

2
docs/en/Blob-Storing-Aws.md

@ -39,7 +39,7 @@ Configure<AbpBlobStoringOptions>(options =>
Aws.Policy = "policy";
Aws.DurationSeconds = "expiration date";
Aws.ContainerName = "your Aws container name";
Aws.CreateContainerIfNotExists = false;
Aws.CreateContainerIfNotExists = true;
});
});
});

2
docs/en/Blob-Storing-Azure.md

@ -29,7 +29,7 @@ Configure<AbpBlobStoringOptions>(options =>
{
azure.ConnectionString = "your azure connection string";
azure.ContainerName = "your azure container name";
azure.CreateContainerIfNotExists = false;
azure.CreateContainerIfNotExists = true;
});
});
});

8
docs/en/Customizing-Application-Modules-Overriding-Services.md

@ -196,12 +196,16 @@ This example replaces the `AccountController` (An API Controller defined in the
**`[ExposeServices(typeof(AccountController))]` is essential** here since it registers this controller for the `AccountController` in the dependency injection system. `[Dependency(ReplaceServices = true)]` is also recommended to clear the old registration (even the ASP.NET Core DI system selects the last registered one).
In addition, The `AccountController` will be removed from [`ApplicationModel`](https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.mvc.applicationmodels.applicationmodel.controllers) because it defines `ExposeServicesAttribute`. If you don't want to remove it, you can configure `AbpAspNetCoreMvcOptions`:
In addition, the `MyAccountController` will be removed from [`ApplicationModel`](https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.mvc.applicationmodels.applicationmodel.controllers) because it defines `ExposeServicesAttribute`.
If `IncludeSelf = true` is specified, i.e. `[ExposeServices(typeof(AccountController), IncludeSelf = true)]`, then `AccountController` will be removed instead. This is useful for **extending** a controller.
If you don't want to remove either controller, you can configure `AbpAspNetCoreMvcOptions`:
```csharp
Configure<AbpAspNetCoreMvcOptions>(options =>
{
options.IgnoredControllersOnModelExclusion.AddIfNotContains(typeof(AccountController));
options.IgnoredControllersOnModelExclusion.AddIfNotContains(typeof(MyAccountController));
});
```

2
docs/zh-Hans/Blob-Storing-Aliyun.md

@ -36,7 +36,7 @@ Configure<AbpBlobStoringOptions>(options =>
aliyun.Policy = "policy";
aliyun.DurationSeconds = "expiration date";
aliyun.ContainerName = "your aliyun container name";
aliyun.CreateContainerIfNotExists = false;
aliyun.CreateContainerIfNotExists = true;
});
});
});

2
docs/zh-Hans/Blob-Storing-Aws.md

@ -39,7 +39,7 @@ Configure<AbpBlobStoringOptions>(options =>
Aws.Policy = "policy";
Aws.DurationSeconds = "expiration date";
Aws.ContainerName = "your Aws container name";
Aws.CreateContainerIfNotExists = false;
Aws.CreateContainerIfNotExists = true;
});
});
});

2
docs/zh-Hans/Blob-Storing-Azure.md

@ -29,7 +29,7 @@ Configure<AbpBlobStoringOptions>(options =>
{
azure.ConnectionString = "your azure connection string";
azure.ContainerName = "your azure container name";
azure.CreateContainerIfNotExists = false;
azure.CreateContainerIfNotExists = true;
});
});
});

14
framework/Volo.Abp.sln

@ -361,6 +361,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.Http.Tests", "test
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.EventBus.Abstractions", "src\Volo.Abp.EventBus.Abstractions\Volo.Abp.EventBus.Abstractions.csproj", "{8FDB3BF7-AD89-43F6-8DEB-C3E29B8801FE}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.Sms.Aliyun", "src\Volo.Abp.Sms.Aliyun\Volo.Abp.Sms.Aliyun.csproj", "{ACFBA3FB-18CE-4655-9D14-1F1F5C3DFC30}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.Sms.Aliyun.Tests", "test\Volo.Abp.Sms.Aliyun.Tests\Volo.Abp.Sms.Aliyun.Tests.csproj", "{DADEA538-3CA1-4ADE-A7E6-EF77A0CE4401}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -1075,6 +1079,14 @@ Global
{8FDB3BF7-AD89-43F6-8DEB-C3E29B8801FE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8FDB3BF7-AD89-43F6-8DEB-C3E29B8801FE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8FDB3BF7-AD89-43F6-8DEB-C3E29B8801FE}.Release|Any CPU.Build.0 = Release|Any CPU
{ACFBA3FB-18CE-4655-9D14-1F1F5C3DFC30}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{ACFBA3FB-18CE-4655-9D14-1F1F5C3DFC30}.Debug|Any CPU.Build.0 = Debug|Any CPU
{ACFBA3FB-18CE-4655-9D14-1F1F5C3DFC30}.Release|Any CPU.ActiveCfg = Release|Any CPU
{ACFBA3FB-18CE-4655-9D14-1F1F5C3DFC30}.Release|Any CPU.Build.0 = Release|Any CPU
{DADEA538-3CA1-4ADE-A7E6-EF77A0CE4401}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DADEA538-3CA1-4ADE-A7E6-EF77A0CE4401}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DADEA538-3CA1-4ADE-A7E6-EF77A0CE4401}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DADEA538-3CA1-4ADE-A7E6-EF77A0CE4401}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -1257,6 +1269,8 @@ Global
{00D07595-993C-40FC-BD90-0DD6331414D3} = {447C8A77-E5F0-4538-8687-7383196D04EA}
{A37BFEB5-7C57-4CDC-93B8-B5CE4BB9ACE1} = {447C8A77-E5F0-4538-8687-7383196D04EA}
{8FDB3BF7-AD89-43F6-8DEB-C3E29B8801FE} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}
{ACFBA3FB-18CE-4655-9D14-1F1F5C3DFC30} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}
{DADEA538-3CA1-4ADE-A7E6-EF77A0CE4401} = {447C8A77-E5F0-4538-8687-7383196D04EA}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {BB97ECF4-9A84-433F-A80B-2A3285BDD1D5}

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

@ -271,6 +271,7 @@ namespace Volo.Abp.AspNetCore.Mvc
actionModel.AddParameter(ParameterApiDescriptionModel.Create(
parameterDescription.Name,
_options.ApiParameterNameGenerator?.Invoke(parameterDescription),
matchedMethodParamName,
parameterDescription.Type,
parameterDescription.RouteInfo?.IsOptional ?? false,

27
framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AspNetCoreApiDescriptionModelProviderOptions.cs

@ -2,6 +2,9 @@
using System.Linq;
using System.Reflection;
using System.Text;
using System.Text.Json.Serialization;
using Microsoft.AspNetCore.Mvc.ApiExplorer;
using Microsoft.AspNetCore.Mvc.ModelBinding.Metadata;
using Volo.Abp.Application.Services;
using Volo.Abp.AspNetCore.Mvc.Conventions;
@ -13,6 +16,8 @@ namespace Volo.Abp.AspNetCore.Mvc
public Func<MethodInfo, string> ActionNameGenerator { get; set; }
public Func<ApiParameterDescription, string> ApiParameterNameGenerator { get; set; }
public AspNetCoreApiDescriptionModelProviderOptions()
{
ControllerNameGenerator = (controllerType, setting) =>
@ -52,6 +57,28 @@ namespace Volo.Abp.AspNetCore.Mvc
return methodNameBuilder.ToString();
};
ApiParameterNameGenerator = (apiParameterDescription) =>
{
if (apiParameterDescription.ModelMetadata is DefaultModelMetadata defaultModelMetadata)
{
var jsonPropertyNameAttribute = (System.Text.Json.Serialization.JsonPropertyNameAttribute)
defaultModelMetadata?.Attributes?.PropertyAttributes?.FirstOrDefault(x => x is System.Text.Json.Serialization.JsonPropertyNameAttribute);
if (jsonPropertyNameAttribute != null)
{
return jsonPropertyNameAttribute.Name;
}
var jsonPropertyAttribute = (Newtonsoft.Json.JsonPropertyAttribute)
defaultModelMetadata?.Attributes?.PropertyAttributes?.FirstOrDefault(x => x is Newtonsoft.Json.JsonPropertyAttribute);
if (jsonPropertyAttribute != null)
{
return jsonPropertyAttribute.PropertyName;
}
}
return null;
};
}
}
}

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

@ -73,7 +73,7 @@ namespace Volo.Abp.AspNetCore.Mvc.Conventions
protected virtual void RemoveDuplicateControllers(ApplicationModel application)
{
var derivedControllerModels = new List<ControllerModel>();
var controllerModelsToRemove = new List<ControllerModel>();
foreach (var controllerModel in application.Controllers)
{
@ -87,19 +87,42 @@ namespace Volo.Abp.AspNetCore.Mvc.Conventions
continue;
}
var exposeServicesAttr = ReflectionHelper.GetSingleAttributeOrDefault<ExposeServicesAttribute>(controllerModel.ControllerType);
if (exposeServicesAttr.IncludeSelf)
{
var exposedControllerModels = application.Controllers
.Where(cm => exposeServicesAttr.ServiceTypes.Contains(cm.ControllerType))
.ToArray();
controllerModelsToRemove.AddRange(exposedControllerModels);
Logger.LogInformation($"Removing the controller{(exposedControllerModels.Length > 1 ? "s" : "")} {exposeServicesAttr.ServiceTypes.Select(c => c.AssemblyQualifiedName).JoinAsString(", ")} from the application model since {(exposedControllerModels.Length > 1 ? "they are" : "it is")} replaced by the controller: {controllerModel.ControllerType.AssemblyQualifiedName}");
continue;
}
var baseControllerTypes = controllerModel.ControllerType
.GetBaseClasses(typeof(Controller), includeObject: false)
.Where(t => !t.IsAbstract)
.ToArray();
if (baseControllerTypes.Length > 0)
if (baseControllerTypes.Length == 0)
{
derivedControllerModels.Add(controllerModel);
Logger.LogInformation($"Removing the controller {controllerModel.ControllerType.AssemblyQualifiedName} from the application model since it replaces the controller(s): {baseControllerTypes.Select(c => c.AssemblyQualifiedName).JoinAsString(", ")}");
continue;
}
var baseControllerModels = application.Controllers
.Where(cm => baseControllerTypes.Contains(cm.ControllerType))
.ToArray();
if (baseControllerModels.Length == 0)
{
continue;
}
controllerModelsToRemove.Add(controllerModel);
Logger.LogInformation($"Removing the controller {controllerModel.ControllerType.AssemblyQualifiedName} from the application model since it replaces the controller(s): {baseControllerTypes.Select(c => c.AssemblyQualifiedName).JoinAsString(", ")}");
}
application.Controllers.RemoveAll(derivedControllerModels);
application.Controllers.RemoveAll(controllerModelsToRemove);
}
protected virtual void ConfigureRemoteService(ControllerModel controller, [CanBeNull] ConventionalControllerSetting configuration)

5
framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Uow/AbpUowActionFilter.cs

@ -50,7 +50,6 @@ namespace Volo.Abp.AspNetCore.Mvc.Uow
return;
}
//Begin a new, independent unit of work
using (var uow = unitOfWorkManager.Begin(options))
{
var result = await next();
@ -58,6 +57,10 @@ namespace Volo.Abp.AspNetCore.Mvc.Uow
{
await uow.CompleteAsync(context.HttpContext.RequestAborted);
}
else
{
await uow.RollbackAsync(context.HttpContext.RequestAborted);
}
}
}

5
framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Uow/AbpUowPageFilter.cs

@ -55,7 +55,6 @@ namespace Volo.Abp.AspNetCore.Mvc.Uow
return;
}
//Begin a new, independent unit of work
using (var uow = unitOfWorkManager.Begin(options))
{
var result = await next();
@ -63,6 +62,10 @@ namespace Volo.Abp.AspNetCore.Mvc.Uow
{
await uow.CompleteAsync(context.HttpContext.RequestAborted);
}
else
{
await uow.RollbackAsync(context.HttpContext.RequestAborted);
}
}
}

6
framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/Builder/AbpApplicationBuilderExtensions.cs

@ -6,6 +6,7 @@ using Microsoft.Extensions.Hosting;
using Volo.Abp;
using Volo.Abp.AspNetCore.Auditing;
using Volo.Abp.AspNetCore.ExceptionHandling;
using Volo.Abp.AspNetCore.Security;
using Volo.Abp.AspNetCore.Security.Claims;
using Volo.Abp.AspNetCore.Tracing;
using Volo.Abp.AspNetCore.Uow;
@ -82,5 +83,10 @@ namespace Microsoft.AspNetCore.Builder
{
return app.UseMiddleware<AbpClaimsMapMiddleware>();
}
public static IApplicationBuilder UseAbpSecurityHeaders(this IApplicationBuilder app)
{
return app.UseMiddleware<AbpSecurityHeadersMiddleware>();
}
}
}

30
framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Security/AbpSecurityHeadersMiddleware.cs

@ -0,0 +1,30 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Primitives;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.AspNetCore.Security
{
public class AbpSecurityHeadersMiddleware : IMiddleware, ITransientDependency
{
public async Task InvokeAsync(HttpContext context, RequestDelegate next)
{
/*X-Content-Type-Options header tells the browser to not try and “guess” what a mimetype of a resource might be, and to just take what mimetype the server has returned as fact.*/
AddHeaderIfNotExists(context, "X-Content-Type-Options", "nosniff");
/*X-XSS-Protection is a feature of Internet Explorer, Chrome and Safari that stops pages from loading when they detect reflected cross-site scripting (XSS) attacks*/
AddHeaderIfNotExists(context, "X-XSS-Protection", "1; mode=block");
/*The X-Frame-Options HTTP response header can be used to indicate whether or not a browser should be allowed to render a page in a <frame>, <iframe> or <object>. SAMEORIGIN makes it being displayed in a frame on the same origin as the page itself. The spec leaves it up to browser vendors to decide whether this option applies to the top level, the parent, or the whole chain*/
AddHeaderIfNotExists(context, "X-Frame-Options", "SAMEORIGIN");
await next.Invoke(context);
}
protected virtual void AddHeaderIfNotExists(HttpContext context, string key, string value)
{
context.Response.Headers.AddIfNotContains(new KeyValuePair<string, StringValues>(key, value));
}
}
}

11
framework/src/Volo.Abp.BlobStoring.Aliyun/Volo/Abp/BlobStoring/Aliyun/AliyunBlobProvider.cs

@ -10,13 +10,16 @@ namespace Volo.Abp.BlobStoring.Aliyun
{
protected IOssClientFactory OssClientFactory { get; }
protected IAliyunBlobNameCalculator AliyunBlobNameCalculator { get; }
protected IBlobNormalizeNamingService BlobNormalizeNamingService { get; }
public AliyunBlobProvider(
IOssClientFactory ossClientFactory,
IAliyunBlobNameCalculator aliyunBlobNameCalculator)
IAliyunBlobNameCalculator aliyunBlobNameCalculator,
IBlobNormalizeNamingService blobNormalizeNamingService)
{
OssClientFactory = ossClientFactory;
AliyunBlobNameCalculator = aliyunBlobNameCalculator;
BlobNormalizeNamingService = blobNormalizeNamingService;
}
protected virtual IOss GetOssClient(BlobContainerConfiguration blobContainerConfiguration)
@ -88,15 +91,15 @@ namespace Volo.Abp.BlobStoring.Aliyun
return memoryStream;
}
private static string GetContainerName(BlobProviderArgs args)
protected virtual string GetContainerName(BlobProviderArgs args)
{
var configuration = args.Configuration.GetAliyunConfiguration();
return configuration.ContainerName.IsNullOrWhiteSpace()
? args.ContainerName
: configuration.ContainerName;
: BlobNormalizeNamingService.NormalizeContainerName(args.Configuration, configuration.ContainerName);
}
private bool BlobExists(IOss ossClient,string containerName, string blobName)
protected virtual bool BlobExists(IOss ossClient,string containerName, string blobName)
{
// Make sure Blob Container exists.
return ossClient.DoesBucketExist(containerName) &&

2
framework/src/Volo.Abp.BlobStoring.Aliyun/Volo/Abp/BlobStoring/Aliyun/AliyunBlobProviderConfiguration.cs

@ -82,7 +82,7 @@ namespace Volo.Abp.BlobStoring.Aliyun
public string ContainerName
{
get => _containerConfiguration.GetConfigurationOrDefault<string>(AliyunBlobProviderConfigurationNames.ContainerName);
set => _containerConfiguration.SetConfiguration(AliyunBlobProviderConfigurationNames.ContainerName, Check.NotNullOrWhiteSpace(value, nameof(value)));
set => _containerConfiguration.SetConfiguration(AliyunBlobProviderConfigurationNames.ContainerName, value);
}
/// <summary>

14
framework/src/Volo.Abp.BlobStoring.Aws/Volo/Abp/BlobStoring/Aws/AwsBlobProvider.cs

@ -12,12 +12,16 @@ namespace Volo.Abp.BlobStoring.Aws
{
protected IAwsBlobNameCalculator AwsBlobNameCalculator { get; }
protected IAmazonS3ClientFactory AmazonS3ClientFactory { get; }
protected IBlobNormalizeNamingService BlobNormalizeNamingService { get; }
public AwsBlobProvider(IAwsBlobNameCalculator awsBlobNameCalculator,
IAmazonS3ClientFactory amazonS3ClientFactory)
public AwsBlobProvider(
IAwsBlobNameCalculator awsBlobNameCalculator,
IAmazonS3ClientFactory amazonS3ClientFactory,
IBlobNormalizeNamingService blobNormalizeNamingService)
{
AwsBlobNameCalculator = awsBlobNameCalculator;
AmazonS3ClientFactory = amazonS3ClientFactory;
BlobNormalizeNamingService = blobNormalizeNamingService;
}
public override async Task SaveAsync(BlobProviderSaveArgs args)
@ -111,7 +115,7 @@ namespace Volo.Abp.BlobStoring.Aws
return await AmazonS3ClientFactory.GetAmazonS3Client(configuration);
}
private async Task<bool> BlobExistsAsync(AmazonS3Client amazonS3Client, string containerName, string blobName)
protected virtual async Task<bool> BlobExistsAsync(AmazonS3Client amazonS3Client, string containerName, string blobName)
{
// Make sure Blob Container exists.
if (!await AmazonS3Util.DoesS3BucketExistV2Async(amazonS3Client, containerName))
@ -147,12 +151,12 @@ namespace Volo.Abp.BlobStoring.Aws
}
}
private static string GetContainerName(BlobProviderArgs args)
protected virtual string GetContainerName(BlobProviderArgs args)
{
var configuration = args.Configuration.GetAwsConfiguration();
return configuration.ContainerName.IsNullOrWhiteSpace()
? args.ContainerName
: configuration.ContainerName;
: BlobNormalizeNamingService.NormalizeContainerName(args.Configuration, configuration.ContainerName);
}
}
}

2
framework/src/Volo.Abp.BlobStoring.Aws/Volo/Abp/BlobStoring/Aws/AwsBlobProviderConfiguration.cs

@ -82,7 +82,7 @@ namespace Volo.Abp.BlobStoring.Aws
public string ContainerName
{
get => _containerConfiguration.GetConfigurationOrDefault<string>(AwsBlobProviderConfigurationNames.ContainerName);
set => _containerConfiguration.SetConfiguration(AwsBlobProviderConfigurationNames.ContainerName, Check.NotNullOrWhiteSpace(value, nameof(value)));
set => _containerConfiguration.SetConfiguration(AwsBlobProviderConfigurationNames.ContainerName, value);
}
/// <summary>

14
framework/src/Volo.Abp.BlobStoring.Azure/Volo/Abp/BlobStoring/Azure/AzureBlobProvider.cs

@ -9,10 +9,14 @@ namespace Volo.Abp.BlobStoring.Azure
public class AzureBlobProvider : BlobProviderBase, ITransientDependency
{
protected IAzureBlobNameCalculator AzureBlobNameCalculator { get; }
protected IBlobNormalizeNamingService BlobNormalizeNamingService { get; }
public AzureBlobProvider(IAzureBlobNameCalculator azureBlobNameCalculator)
public AzureBlobProvider(
IAzureBlobNameCalculator azureBlobNameCalculator,
IBlobNormalizeNamingService blobNormalizeNamingService)
{
AzureBlobNameCalculator = azureBlobNameCalculator;
BlobNormalizeNamingService = blobNormalizeNamingService;
}
public override async Task SaveAsync(BlobProviderSaveArgs args)
@ -87,22 +91,22 @@ namespace Volo.Abp.BlobStoring.Azure
await blobContainerClient.CreateIfNotExistsAsync();
}
private async Task<bool> BlobExistsAsync(BlobProviderArgs args, string blobName)
protected virtual async Task<bool> BlobExistsAsync(BlobProviderArgs args, string blobName)
{
// Make sure Blob Container exists.
return await ContainerExistsAsync(GetBlobContainerClient(args)) &&
(await GetBlobClient(args, blobName).ExistsAsync()).Value;
}
private static string GetContainerName(BlobProviderArgs args)
protected virtual string GetContainerName(BlobProviderArgs args)
{
var configuration = args.Configuration.GetAzureConfiguration();
return configuration.ContainerName.IsNullOrWhiteSpace()
? args.ContainerName
: configuration.ContainerName;
: BlobNormalizeNamingService.NormalizeContainerName(args.Configuration, configuration.ContainerName);
}
private static async Task<bool> ContainerExistsAsync(BlobContainerClient blobContainerClient)
protected virtual async Task<bool> ContainerExistsAsync(BlobContainerClient blobContainerClient)
{
return (await blobContainerClient.ExistsAsync()).Value;
}

2
framework/src/Volo.Abp.BlobStoring.Azure/Volo/Abp/BlobStoring/Azure/AzureBlobProviderConfiguration.cs

@ -17,7 +17,7 @@
public string ContainerName
{
get => _containerConfiguration.GetConfigurationOrDefault<string>(AzureBlobProviderConfigurationNames.ContainerName);
set => _containerConfiguration.SetConfiguration(AzureBlobProviderConfigurationNames.ContainerName, Check.NotNullOrWhiteSpace(value, nameof(value)));
set => _containerConfiguration.SetConfiguration(AzureBlobProviderConfigurationNames.ContainerName, value);
}
/// <summary>

1
framework/src/Volo.Abp.BlobStoring.Minio/Volo/Abp/BlobStoring/Minio/MinioBlobContainerConfigurationExtensions.cs

@ -15,6 +15,7 @@ namespace Volo.Abp.BlobStoring.Minio
Action<MinioBlobProviderConfiguration> minioConfigureAction)
{
containerConfiguration.ProviderType = typeof(MinioBlobProvider);
containerConfiguration.NamingNormalizers.TryAdd<MinioBlobNamingNormalizer>();
minioConfigureAction(new MinioBlobProviderConfiguration(containerConfiguration));

12
framework/src/Volo.Abp.BlobStoring.Minio/Volo/Abp/BlobStoring/Minio/MinioBlobProvider.cs

@ -10,10 +10,14 @@ namespace Volo.Abp.BlobStoring.Minio
public class MinioBlobProvider : BlobProviderBase, ITransientDependency
{
protected IMinioBlobNameCalculator MinioBlobNameCalculator { get; }
protected IBlobNormalizeNamingService BlobNormalizeNamingService { get; }
public MinioBlobProvider(IMinioBlobNameCalculator minioBlobNameCalculator)
public MinioBlobProvider(
IMinioBlobNameCalculator minioBlobNameCalculator,
IBlobNormalizeNamingService blobNormalizeNamingService)
{
MinioBlobNameCalculator = minioBlobNameCalculator;
BlobNormalizeNamingService = blobNormalizeNamingService;
}
public override async Task SaveAsync(BlobProviderSaveArgs args)
@ -108,7 +112,7 @@ namespace Volo.Abp.BlobStoring.Minio
}
}
private async Task<bool> BlobExistsAsync(MinioClient client, string containerName , string blobName)
protected virtual async Task<bool> BlobExistsAsync(MinioClient client, string containerName , string blobName)
{
// Make sure Blob Container exists.
if (await client.BucketExistsAsync(containerName))
@ -133,13 +137,13 @@ namespace Volo.Abp.BlobStoring.Minio
return false;
}
private static string GetContainerName(BlobProviderArgs args)
protected virtual string GetContainerName(BlobProviderArgs args)
{
var configuration = args.Configuration.GetMinioConfiguration();
return configuration.BucketName.IsNullOrWhiteSpace()
? args.ContainerName
: configuration.BucketName;
: BlobNormalizeNamingService.NormalizeContainerName(args.Configuration, configuration.BucketName);
}
}
}

2
framework/src/Volo.Abp.BlobStoring.Minio/Volo/Abp/BlobStoring/Minio/MinioBlobProviderConfiguration.cs

@ -5,7 +5,7 @@
public string BucketName
{
get => _containerConfiguration.GetConfigurationOrDefault<string>(MinioBlobProviderConfigurationNames.BucketName);
set => _containerConfiguration.SetConfiguration(MinioBlobProviderConfigurationNames.BucketName, Check.NotNullOrWhiteSpace(value, nameof(value)));
set => _containerConfiguration.SetConfiguration(MinioBlobProviderConfigurationNames.BucketName, value);
}
/// <summary>

59
framework/src/Volo.Abp.BlobStoring/Volo/Abp/BlobStoring/BlobContainer.cs

@ -1,9 +1,7 @@
using System;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.MultiTenancy;
using Volo.Abp.Threading;
@ -88,12 +86,15 @@ namespace Volo.Abp.BlobStoring
protected IServiceProvider ServiceProvider { get; }
protected IBlobNormalizeNamingService BlobNormalizeNamingService { get; }
public BlobContainer(
string containerName,
BlobContainerConfiguration configuration,
IBlobProvider provider,
ICurrentTenant currentTenant,
ICancellationTokenProvider cancellationTokenProvider,
IBlobNormalizeNamingService blobNormalizeNamingService,
IServiceProvider serviceProvider)
{
ContainerName = containerName;
@ -101,6 +102,7 @@ namespace Volo.Abp.BlobStoring
Provider = provider;
CurrentTenant = currentTenant;
CancellationTokenProvider = cancellationTokenProvider;
BlobNormalizeNamingService = blobNormalizeNamingService;
ServiceProvider = serviceProvider;
}
@ -112,13 +114,13 @@ namespace Volo.Abp.BlobStoring
{
using (CurrentTenant.Change(GetTenantIdOrNull()))
{
var (normalizedContainerName, normalizedBlobName) = NormalizeNaming(ContainerName, name);
var blobNormalizeNaming = BlobNormalizeNamingService.NormalizeNaming(Configuration, ContainerName, name);
await Provider.SaveAsync(
new BlobProviderSaveArgs(
normalizedContainerName,
blobNormalizeNaming.ContainerName,
Configuration,
normalizedBlobName,
blobNormalizeNaming.BlobName,
stream,
overrideExisting,
CancellationTokenProvider.FallbackToProvider(cancellationToken)
@ -133,14 +135,14 @@ namespace Volo.Abp.BlobStoring
{
using (CurrentTenant.Change(GetTenantIdOrNull()))
{
var (normalizedContainerName, normalizedBlobName) =
NormalizeNaming(ContainerName, name);
var blobNormalizeNaming =
BlobNormalizeNamingService.NormalizeNaming(Configuration, ContainerName, name);
return await Provider.DeleteAsync(
new BlobProviderDeleteArgs(
normalizedContainerName,
blobNormalizeNaming.ContainerName,
Configuration,
normalizedBlobName,
blobNormalizeNaming.BlobName,
CancellationTokenProvider.FallbackToProvider(cancellationToken)
)
);
@ -153,14 +155,14 @@ namespace Volo.Abp.BlobStoring
{
using (CurrentTenant.Change(GetTenantIdOrNull()))
{
var (normalizedContainerName, normalizedBlobName) =
NormalizeNaming(ContainerName, name);
var blobNormalizeNaming =
BlobNormalizeNamingService.NormalizeNaming(Configuration, ContainerName, name);
return await Provider.ExistsAsync(
new BlobProviderExistsArgs(
normalizedContainerName,
blobNormalizeNaming.ContainerName,
Configuration,
normalizedBlobName,
blobNormalizeNaming.BlobName,
CancellationTokenProvider.FallbackToProvider(cancellationToken)
)
);
@ -189,14 +191,14 @@ namespace Volo.Abp.BlobStoring
{
using (CurrentTenant.Change(GetTenantIdOrNull()))
{
var (normalizedContainerName, normalizedBlobName) =
NormalizeNaming(ContainerName, name);
var blobNormalizeNaming =
BlobNormalizeNamingService.NormalizeNaming(Configuration, ContainerName, name);
return await Provider.GetOrNullAsync(
new BlobProviderGetArgs(
normalizedContainerName,
blobNormalizeNaming.ContainerName,
Configuration,
normalizedBlobName,
blobNormalizeNaming.BlobName,
CancellationTokenProvider.FallbackToProvider(cancellationToken)
)
);
@ -212,28 +214,5 @@ namespace Volo.Abp.BlobStoring
return CurrentTenant.Id;
}
protected virtual (string, string) NormalizeNaming(string containerName, string blobName)
{
if (!Configuration.NamingNormalizers.Any())
{
return (containerName, blobName);
}
using (var scope = ServiceProvider.CreateScope())
{
foreach (var normalizerType in Configuration.NamingNormalizers)
{
var normalizer = scope.ServiceProvider
.GetRequiredService(normalizerType)
.As<IBlobNamingNormalizer>();
containerName = normalizer.NormalizeContainerName(containerName);
blobName = normalizer.NormalizeBlobName(blobName);
}
return (containerName, blobName);
}
}
}
}

7
framework/src/Volo.Abp.BlobStoring/Volo/Abp/BlobStoring/BlobContainerFactory.cs

@ -17,18 +17,22 @@ namespace Volo.Abp.BlobStoring
protected IServiceProvider ServiceProvider { get; }
protected IBlobNormalizeNamingService BlobNormalizeNamingService { get; }
public BlobContainerFactory(
IBlobContainerConfigurationProvider configurationProvider,
ICurrentTenant currentTenant,
ICancellationTokenProvider cancellationTokenProvider,
IBlobProviderSelector providerSelector,
IServiceProvider serviceProvider)
IServiceProvider serviceProvider,
IBlobNormalizeNamingService blobNormalizeNamingService)
{
ConfigurationProvider = configurationProvider;
CurrentTenant = currentTenant;
CancellationTokenProvider = cancellationTokenProvider;
ProviderSelector = providerSelector;
ServiceProvider = serviceProvider;
BlobNormalizeNamingService = blobNormalizeNamingService;
}
public virtual IBlobContainer Create(string name)
@ -41,6 +45,7 @@ namespace Volo.Abp.BlobStoring
ProviderSelector.Get(name),
CurrentTenant,
CancellationTokenProvider,
BlobNormalizeNamingService,
ServiceProvider
);
}

15
framework/src/Volo.Abp.BlobStoring/Volo/Abp/BlobStoring/BlobNormalizeNaming.cs

@ -0,0 +1,15 @@
namespace Volo.Abp.BlobStoring
{
public class BlobNormalizeNaming
{
public string ContainerName { get; }
public string BlobName { get; }
public BlobNormalizeNaming(string containerName, string blobName)
{
ContainerName = containerName;
BlobName = blobName;
}
}
}

64
framework/src/Volo.Abp.BlobStoring/Volo/Abp/BlobStoring/BlobNormalizeNamingService.cs

@ -0,0 +1,64 @@
using System;
using System.Linq;
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.BlobStoring
{
public class BlobNormalizeNamingService : IBlobNormalizeNamingService, ITransientDependency
{
protected IServiceProvider ServiceProvider { get; }
public BlobNormalizeNamingService(IServiceProvider serviceProvider)
{
ServiceProvider = serviceProvider;
}
public BlobNormalizeNaming NormalizeNaming(
BlobContainerConfiguration configuration,
string containerName,
string blobName)
{
if (!configuration.NamingNormalizers.Any())
{
return new BlobNormalizeNaming(containerName, blobName);
}
using (var scope = ServiceProvider.CreateScope())
{
foreach (var normalizerType in configuration.NamingNormalizers)
{
var normalizer = scope.ServiceProvider
.GetRequiredService(normalizerType)
.As<IBlobNamingNormalizer>();
containerName = containerName.IsNullOrWhiteSpace()? containerName: normalizer.NormalizeContainerName(containerName);
blobName = blobName.IsNullOrWhiteSpace()? blobName: normalizer.NormalizeBlobName(blobName);
}
return new BlobNormalizeNaming(containerName, blobName);
}
}
public string NormalizeContainerName(BlobContainerConfiguration configuration, string containerName)
{
if (!configuration.NamingNormalizers.Any())
{
return containerName;
}
return NormalizeNaming(configuration, containerName, null).ContainerName;
}
public string NormalizeBlobName(BlobContainerConfiguration configuration, string blobName)
{
if (!configuration.NamingNormalizers.Any())
{
return blobName;
}
return NormalizeNaming(configuration, null, blobName).BlobName;
}
}
}

2
framework/src/Volo.Abp.BlobStoring/Volo/Abp/BlobStoring/BlobProviderBase.cs

@ -13,4 +13,4 @@ namespace Volo.Abp.BlobStoring
public abstract Task<Stream> GetOrNullAsync(BlobProviderGetArgs args);
}
}
}

11
framework/src/Volo.Abp.BlobStoring/Volo/Abp/BlobStoring/IBlobNormalizeNamingService.cs

@ -0,0 +1,11 @@
namespace Volo.Abp.BlobStoring
{
public interface IBlobNormalizeNamingService
{
BlobNormalizeNaming NormalizeNaming(BlobContainerConfiguration configuration, string containerName, string blobName);
string NormalizeContainerName(BlobContainerConfiguration configuration, string containerName);
string NormalizeBlobName(BlobContainerConfiguration configuration, string blobName);
}
}

62
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs

@ -147,19 +147,34 @@ namespace Volo.Abp.Cli.Commands
}
var createSolutionFolder = GetCreateSolutionFolderPreference(commandLineArgs);
if (!createSolutionFolder)
{
Logger.LogInformation("Create Solution Folder: no");
}
var outputFolder = commandLineArgs.Options.GetOrNull(Options.OutputFolder.Short, Options.OutputFolder.Long);
var outputFolderRoot =
outputFolder != null ? Path.GetFullPath(outputFolder) : Directory.GetCurrentDirectory();
outputFolder = createSolutionFolder ?
Path.Combine(outputFolderRoot, SolutionName.Parse(projectName).FullName) :
outputFolderRoot;
SolutionName solutionName;
if (MicroserviceServiceTemplateBase.IsMicroserviceServiceTemplate(template))
{
var microserviceSolutionName = FindMicroserviceSolutionName(outputFolderRoot);
if (microserviceSolutionName == null)
{
throw new CliUsageException("This command should be run inside a folder that contains a microservice solution!");
}
solutionName = SolutionName.Parse(microserviceSolutionName, projectName);
outputFolder = MicroserviceServiceTemplateBase.CalculateTargetFolder(outputFolderRoot, projectName);
uiFramework = uiFramework == UiFramework.NotSpecified ? FindMicroserviceSolutionUiFramework(outputFolderRoot) : uiFramework;
}
else
{
solutionName = SolutionName.Parse(projectName);
outputFolder = createSolutionFolder ?
Path.Combine(outputFolderRoot, SolutionName.Parse(projectName).FullName) :
outputFolderRoot;
}
Volo.Abp.IO.DirectoryHelper.CreateIfNotExists(outputFolder);
@ -176,7 +191,7 @@ namespace Volo.Abp.Cli.Commands
var result = await TemplateProjectBuilder.BuildAsync(
new ProjectBuildArgs(
SolutionName.Parse(projectName),
solutionName,
template,
version,
databaseProvider,
@ -245,6 +260,32 @@ namespace Volo.Abp.Cli.Commands
}
}
private string FindMicroserviceSolutionName(string outputFolderRoot)
{
var slnFile = Directory.GetFiles(outputFolderRoot, "*.sln").FirstOrDefault();
if (slnFile == null)
{
return null;
}
return Path.GetFileName(slnFile).RemovePostFix(".sln");
}
private UiFramework FindMicroserviceSolutionUiFramework(string outputFolderRoot)
{
if (Directory.Exists(Path.Combine(outputFolderRoot, "applications", "blazor")))
{
return UiFramework.Blazor;
}
if (Directory.Exists(Path.Combine(outputFolderRoot, "applications", "web")))
{
return UiFramework.Mvc;
}
return UiFramework.None;
}
private void OpenThanksPage(UiFramework uiFramework, DatabaseProvider databaseProvider, bool tiered, bool commercial)
{
uiFramework = uiFramework == UiFramework.NotSpecified || uiFramework == UiFramework.None ? UiFramework.Mvc : uiFramework;
@ -383,6 +424,11 @@ namespace Volo.Abp.Cli.Commands
protected virtual UiFramework GetUiFramework(CommandLineArgs commandLineArgs)
{
if (commandLineArgs.Options.ContainsKey("no-ui"))
{
return UiFramework.None;
}
var optionValue = commandLineArgs.Options.GetOrNull(Options.UiFramework.Short, Options.UiFramework.Long);
switch (optionValue)
{

30
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/ProjectReferenceReplaceStep.cs

@ -5,6 +5,7 @@ using System.Linq;
using System.Text.RegularExpressions;
using System.Xml;
using Volo.Abp.Cli.ProjectBuilding.Files;
using Volo.Abp.Cli.ProjectBuilding.Templates.Microservice;
using Volo.Abp.Cli.Utils;
namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps
@ -25,7 +26,7 @@ namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps
var localVoloRepoPath = context.BuildArgs.VoloGitHubLocalRepositoryPath;
new ProjectReferenceReplacer.LocalProjectPathReferenceReplacer(
context.Files,
context,
context.Module?.Namespace ?? "MyCompanyName.MyProjectName",
localAbpRepoPath,
localVoloRepoPath
@ -41,7 +42,7 @@ namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps
}
new ProjectReferenceReplacer.NugetReferenceReplacer(
context.Files,
context,
context.Module?.Namespace ?? "MyCompanyName.MyProjectName",
nugetPackageVersion
).Run();
@ -70,13 +71,15 @@ namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps
private abstract class ProjectReferenceReplacer
{
private readonly List<FileEntry> _entries;
private readonly bool _isMicroserviceServiceTemplate;
private readonly string _projectName;
protected ProjectReferenceReplacer(
List<FileEntry> entries,
ProjectBuildContext context,
string projectName)
{
_entries = entries;
_entries = context.Files;
_isMicroserviceServiceTemplate = MicroserviceServiceTemplateBase.IsMicroserviceServiceTemplate(context.Template?.Name);
_projectName = projectName;
}
@ -113,14 +116,15 @@ 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(GetProjectNameWithExtensionFromProjectReference(oldNodeIncludeValue))))
if (oldNodeIncludeValue.Contains(_projectName))
{
continue;
if (_isMicroserviceServiceTemplate || _entries.Any(e=>e.Name.EndsWith(GetProjectNameWithExtensionFromProjectReference(oldNodeIncludeValue))))
{
continue;
}
}
XmlNode newNode = null;
newNode = GetNewReferenceNode(doc, oldNodeIncludeValue);
XmlNode newNode = GetNewReferenceNode(doc, oldNodeIncludeValue);
oldNode.ParentNode.ReplaceChild(newNode, oldNode);
}
@ -145,8 +149,8 @@ namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps
{
private readonly string _nugetPackageVersion;
public NugetReferenceReplacer(List<FileEntry> entries, string projectName, string nugetPackageVersion)
: base(entries, projectName)
public NugetReferenceReplacer(ProjectBuildContext context, string projectName, string nugetPackageVersion)
: base(context, projectName)
{
_nugetPackageVersion = nugetPackageVersion;
}
@ -183,8 +187,8 @@ namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps
private readonly string _gitHubAbpLocalRepositoryPath;
private readonly string _gitHubVoloLocalRepositoryPath;
public LocalProjectPathReferenceReplacer(List<FileEntry> entries, string projectName, string gitHubAbpLocalRepositoryPath, string gitHubVoloLocalRepositoryPath)
: base(entries, projectName)
public LocalProjectPathReferenceReplacer(ProjectBuildContext context, string projectName, string gitHubAbpLocalRepositoryPath, string gitHubVoloLocalRepositoryPath)
: base(context, projectName)
{
_gitHubAbpLocalRepositoryPath = gitHubAbpLocalRepositoryPath;
_gitHubVoloLocalRepositoryPath = gitHubVoloLocalRepositoryPath;

4
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/RemoveProjectFromSolutionStep.cs

@ -85,11 +85,11 @@ namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps
private void SetSolutionAndProjectPathsIfNull(ProjectBuildContext context)
{
if (_solutionFilePath == null)
{
_solutionFilePath = context.FindFile("/aspnet-core/MyCompanyName.MyProjectName.sln")?.Name ??
context.FindFile("/MyCompanyName.MyProjectName.sln")?.Name;
context.FindFile("/MyCompanyName.MyProjectName.sln")?.Name ??
context.FindFile("/MyCompanyName.MyProjectName.MicroserviceName.sln")?.Name;
}
if (_projectFolderPath == null)
{

28
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/SolutionRenameStep.cs

@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using Volo.Abp.Cli.ProjectBuilding.Files;
using Volo.Abp.Cli.ProjectBuilding.Templates.Microservice;
namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps
{
@ -8,13 +9,26 @@ namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps
{
public override void Execute(ProjectBuildContext context)
{
new SolutionRenamer(
context.Files,
"MyCompanyName",
"MyProjectName",
context.BuildArgs.SolutionName.CompanyName,
context.BuildArgs.SolutionName.ProjectName
).Run();
if (MicroserviceServiceTemplateBase.IsMicroserviceServiceTemplate(context.BuildArgs.TemplateName))
{
new SolutionRenamer(
context.Files,
"MyCompanyName.MyProjectName",
"MicroserviceName",
context.BuildArgs.SolutionName.CompanyName,
context.BuildArgs.SolutionName.ProjectName
).Run();
}
else
{
new SolutionRenamer(
context.Files,
"MyCompanyName",
"MyProjectName",
context.BuildArgs.SolutionName.CompanyName,
context.BuildArgs.SolutionName.ProjectName
).Run();
}
}
private class SolutionRenamer

3
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/TemplateProjectBuildPipelineBuilder.cs

@ -33,7 +33,8 @@ namespace Volo.Abp.Cli.ProjectBuilding.Building
}
if ((context.BuildArgs.UiFramework == UiFramework.Mvc || context.BuildArgs.UiFramework == UiFramework.Blazor)
&& context.BuildArgs.MobileApp == MobileApp.None && context.Template.Name != MicroserviceProTemplate.TemplateName)
&& context.BuildArgs.MobileApp == MobileApp.None && context.Template.Name != MicroserviceProTemplate.TemplateName
&& context.Template.Name != MicroserviceServiceProTemplate.TemplateName)
{
pipeline.Steps.Add(new RemoveRootFolderStep());
}

7
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/SolutionName.cs

@ -17,6 +17,11 @@ namespace Volo.Abp.Cli.ProjectBuilding
ProjectName = projectName;
}
public static SolutionName Parse(string fullName, string microserviceName)
{
return new SolutionName(fullName + "." + microserviceName, fullName, microserviceName);
}
public static SolutionName Parse(string fullName)
{
if (fullName.Length < 1)
@ -47,4 +52,4 @@ namespace Volo.Abp.Cli.ProjectBuilding
return new SolutionName(fullName, companyName, projectName);
}
}
}
}

4
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/TemplateInfoProvider.cs

@ -28,7 +28,7 @@ namespace Volo.Abp.Cli.ProjectBuilding
public TemplateInfoProvider(ICancellationTokenProvider cancellationTokenProvider,
IRemoteServiceExceptionHandler remoteServiceExceptionHandler,
AuthService authService,
AuthService authService,
CliHttpClientFactory cliHttpClientFactory)
{
CancellationTokenProvider = cancellationTokenProvider;
@ -56,6 +56,8 @@ namespace Volo.Abp.Cli.ProjectBuilding
return new AppProTemplate();
case MicroserviceProTemplate.TemplateName:
return new MicroserviceProTemplate();
case MicroserviceServiceProTemplate.TemplateName:
return new MicroserviceServiceProTemplate();
case ModuleTemplate.TemplateName:
return new ModuleTemplate();
case ModuleProTemplate.TemplateName:

16
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/Microservice/MicroserviceServiceProTemplate.cs

@ -0,0 +1,16 @@
namespace Volo.Abp.Cli.ProjectBuilding.Templates.Microservice
{
public class MicroserviceServiceProTemplate : MicroserviceServiceTemplateBase
{
/// <summary>
/// "microservice-service-pro".
/// </summary>
public const string TemplateName = "microservice-service-pro";
public MicroserviceServiceProTemplate()
: base(TemplateName)
{
DocumentUrl = null; // todo: set this
}
}
}

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

@ -0,0 +1,62 @@
using System;
using System.Collections.Generic;
using System.IO;
using JetBrains.Annotations;
using Volo.Abp.Cli.ProjectBuilding.Building;
using Volo.Abp.Cli.ProjectBuilding.Building.Steps;
namespace Volo.Abp.Cli.ProjectBuilding.Templates.Microservice
{
public abstract class MicroserviceServiceTemplateBase : TemplateInfo
{
protected MicroserviceServiceTemplateBase([NotNull] string name)
: base(name)
{
}
public static bool IsMicroserviceServiceTemplate(string templateName)
{
return templateName == MicroserviceServiceProTemplate.TemplateName;
}
public static string CalculateTargetFolder(string mainSolutionFolder, string serviceName)
{
serviceName = serviceName.ToCamelCase().RemovePostFix("Service");
return Path.Combine(mainSolutionFolder, "microservices", serviceName);
}
public override IEnumerable<ProjectBuildPipelineStep> GetCustomSteps(ProjectBuildContext context)
{
var steps = new List<ProjectBuildPipelineStep>();
DeleteUnrelatedUiProject(context, steps);
RandomizeStringEncryption(context, steps);
return steps;
}
private static void DeleteUnrelatedUiProject(ProjectBuildContext context, List<ProjectBuildPipelineStep> steps)
{
switch (context.BuildArgs.UiFramework)
{
case UiFramework.Blazor:
steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.MicroserviceName.Web"));
break;
case UiFramework.Mvc:
case UiFramework.NotSpecified:
steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.MicroserviceName.Blazor"));
break;
default:
steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.MicroserviceName.Blazor"));
steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.MicroserviceName.Web"));
break;
}
}
private static void RandomizeStringEncryption(ProjectBuildContext context, List<ProjectBuildPipelineStep> steps)
{
steps.Add(new RandomizeStringEncryptionStep());
}
}
}

26
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/Microservice/MicroserviceTemplateBase.cs

@ -33,27 +33,41 @@ namespace Volo.Abp.Cli.ProjectBuilding.Templates.Microservice
switch (context.BuildArgs.UiFramework)
{
case UiFramework.None:
steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.Web"));
steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.Blazor"));
steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.Web",null,
"/applications/web/src/MyCompanyName.MyProjectName.Web"));
steps.Add(new RemoveFolderStep("/applications/web"));
steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.Blazor",null,
"/applications/blazor/src/MyCompanyName.MyProjectName.Blazor"));
steps.Add(new RemoveFolderStep("/applications/blazor"));
steps.Add(new RemoveFolderStep("/angular"));
break;
case UiFramework.Angular:
steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.Web"));
steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.Blazor"));
steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.Web",null,
"/applications/web/src/MyCompanyName.MyProjectName.Web"));
steps.Add(new RemoveFolderStep("/applications/web"));
steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.Blazor",null,
"/applications/blazor/src/MyCompanyName.MyProjectName.Blazor"));
steps.Add(new RemoveFolderStep("/applications/blazor"));
break;
case UiFramework.Blazor:
steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.Web"));
steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.Web",null,
"/applications/web/src/MyCompanyName.MyProjectName.Web"));
steps.Add(new RemoveFolderStep("/applications/web"));
steps.Add(new RemoveFolderStep("/angular"));
break;
case UiFramework.Mvc:
case UiFramework.NotSpecified:
steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.Blazor"));
steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.Blazor",null,
"/applications/blazor/src/MyCompanyName.MyProjectName.Blazor"));
steps.Add(new RemoveFolderStep("/applications/blazor"));
steps.Add(new RemoveFolderStep("/angular"));
break;
}
steps.Add(new RemoveFolderStep("/microservices/template"));
}
private static void RandomizeStringEncryption(ProjectBuildContext context, List<ProjectBuildPipelineStep> steps)

63
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/AngularModuleSourceCodeAdder.cs

@ -34,7 +34,8 @@ namespace Volo.Abp.Cli.ProjectModification
}
await AddPathsToTsConfigAsync(angularPath, angularProjectsPath, projects);
await CreateTsConfigProdJsonAsync(angularPath);
await AddScriptsToPackageJsonAsync(angularPath);
await AddProjectToAngularJsonAsync(angularPath, projects);
}
catch (Exception e)
@ -93,6 +94,61 @@ namespace Volo.Abp.Cli.ProjectModification
File.WriteAllText(angularJsonFilePath, json.ToString(Formatting.Indented));
}
private async Task AddScriptsToPackageJsonAsync(string angularPath)
{
var packageJsonFilePath = Path.Combine(angularPath, "package.json");
var fileContent = File.ReadAllText(packageJsonFilePath);
var json = JObject.Parse(fileContent);
var scriptsJobject = (JObject) json["scripts"];
if (scriptsJobject == null || scriptsJobject["postinstall"] != null || scriptsJobject["compile:ivy"] != null)
{
return;
}
scriptsJobject["postinstall"] = "npm run compile:ivy";
scriptsJobject["compile:ivy"] = "yarn ngcc --properties es2015 browser module main --first-only --create-ivy-entry-points --tsconfig './tsconfig.prod.json' --source node_modules";
File.WriteAllText(packageJsonFilePath, json.ToString(Formatting.Indented));
}
private async Task CreateTsConfigProdJsonAsync(string angularPath)
{
var tsConfigProdJsonFilePath = Path.Combine(angularPath, "tsconfig.prod.json");
if (File.Exists(tsConfigProdJsonFilePath))
{
return;
}
var json = new JObject(
new JProperty("compileOnSave", false),
new JProperty("compilerOptions", new JObject(
new JProperty("baseUrl", "./"),
new JProperty("outDir", "./dist/out-tsc"),
new JProperty("sourceMap", true),
new JProperty("declaration", false),
new JProperty("downlevelIteration", true),
new JProperty("experimentalDecorators", true),
new JProperty("module", "esnext"),
new JProperty("moduleResolution", "node"),
new JProperty("importHelpers", true),
new JProperty("target", "es2015"),
new JProperty("typeRoots", new JArray(new JValue("node_modules/@types"))),
new JProperty("lib", new JArray(new JValue("es2018"), new JValue("dom"))),
new JProperty("types", new JArray(new JValue("jest")))
)),
new JProperty("angularCompilerOptions", new JObject(
new JProperty("fullTemplateTypeCheck", true),
new JProperty("strictInjectionParameters", true)
))
);
File.WriteAllText(tsConfigProdJsonFilePath, json.ToString(Formatting.Indented));
}
private async Task AddPathsToTsConfigAsync(string angularPath, string angularProjectsPath,
List<string> projects)
{
@ -105,7 +161,8 @@ namespace Volo.Abp.Cli.ProjectModification
{
var projectPackageName = await GetProjectPackageNameAsync(angularProjectsPath, project);
var publicApis = Directory.GetFiles(Path.Combine(angularProjectsPath, project), "*public-api.ts", SearchOption.AllDirectories)
var publicApis = Directory.GetFiles(Path.Combine(angularProjectsPath, project), "*public-api.ts",
SearchOption.AllDirectories)
.Where(p => !p.Contains("\\node_modules\\"))
.Select(p => p.RemovePreFix(angularPath).Replace("\\", "/").RemovePreFix("/"));
@ -171,8 +228,10 @@ namespace Volo.Abp.Cli.ProjectModification
{
continue;
}
Directory.Move(folderUnderProject, Path.Combine(folder, Path.GetFileName(folderUnderProject)));
}
projectsInFolder = Directory.GetDirectories(folder);
}

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

@ -29,6 +29,8 @@ namespace Volo.Abp.DependencyInjection
public Dictionary<Type, Type> CustomRepositories { get; }
public List<Type> SpecifiedDefaultRepositories { get; }
public bool SpecifiedDefaultRepositoryTypes => DefaultRepositoryImplementationType != null && DefaultRepositoryImplementationTypeWithoutKey != null;
protected AbpCommonDbContextRegistrationOptions(Type originalDbContextType, IServiceCollection services)
@ -38,6 +40,7 @@ namespace Volo.Abp.DependencyInjection
DefaultRepositoryDbContextType = originalDbContextType;
CustomRepositories = new Dictionary<Type, Type>();
ReplacedDbContextTypes = new List<Type>();
SpecifiedDefaultRepositories = new List<Type>();
}
public IAbpCommonDbContextRegistrationOptionsBuilder ReplaceDbContext<TOtherDbContext>()
@ -82,6 +85,20 @@ namespace Volo.Abp.DependencyInjection
return AddDefaultRepositories(typeof(TDefaultRepositoryDbContext), includeAllEntities);
}
public IAbpCommonDbContextRegistrationOptionsBuilder AddDefaultRepository<TEntity>()
{
return AddDefaultRepository(typeof(TEntity));
}
public IAbpCommonDbContextRegistrationOptionsBuilder AddDefaultRepository(Type entityType)
{
EntityHelper.CheckEntity(entityType);
SpecifiedDefaultRepositories.AddIfNotContains(entityType);
return this;
}
public IAbpCommonDbContextRegistrationOptionsBuilder AddRepository<TEntity, TRepository>()
{
AddCustomRepository(typeof(TEntity), typeof(TRepository));
@ -118,4 +135,4 @@ namespace Volo.Abp.DependencyInjection
CustomRepositories[entityType] = repositoryType;
}
}
}
}

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

@ -39,6 +39,20 @@ namespace Volo.Abp.DependencyInjection
/// </param>
IAbpCommonDbContextRegistrationOptionsBuilder AddDefaultRepositories(Type defaultRepositoryDbContextType, bool includeAllEntities = false);
/// <summary>
/// Registers custom repository for a specific entity.
/// </summary>
/// <typeparam name="TEntity">Entity type</typeparam>
IAbpCommonDbContextRegistrationOptionsBuilder AddDefaultRepository<TEntity>();
/// <summary>
/// Registers default repository for a specific entity.
/// </summary>
/// <param name="entityType"></param>
/// <returns></returns>
IAbpCommonDbContextRegistrationOptionsBuilder AddDefaultRepository(Type entityType);
/// <summary>
/// Registers custom repository for a specific entity.
/// Custom repositories overrides default repositories.

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

@ -118,9 +118,19 @@ namespace Volo.Abp.Domain.Entities
public static bool IsEntity([NotNull] Type type)
{
Check.NotNull(type, nameof(type));
return typeof(IEntity).IsAssignableFrom(type);
}
public static void CheckEntity([NotNull] Type type)
{
Check.NotNull(type, nameof(type));
if (!IsEntity(type))
{
throw new AbpException($"Given {nameof(type)} is not an entity: {type.AssemblyQualifiedName}. It must implement {typeof(IEntity).AssemblyQualifiedName}.");
}
}
public static bool IsEntityWithId([NotNull] Type type)
{
foreach (var interfaceType in type.GetInterfaces())

30
framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Repositories/RepositoryRegistrarBase.cs

@ -17,20 +17,27 @@ namespace Volo.Abp.Domain.Repositories
}
public virtual void AddRepositories()
{
RegisterCustomRepositories();
RegisterDefaultRepositories();
RegisterSpecifiedDefaultRepositories();
}
protected virtual void RegisterCustomRepositories()
{
foreach (var customRepository in Options.CustomRepositories)
{
Options.Services.AddDefaultRepository(customRepository.Key, customRepository.Value, replaceExisting: true);
}
if (Options.RegisterDefaultRepositories)
{
RegisterDefaultRepositories();
}
}
protected virtual void RegisterDefaultRepositories()
{
if (!Options.RegisterDefaultRepositories)
{
return;
}
foreach (var entityType in GetEntityTypes(Options.OriginalDbContextType))
{
if (!ShouldRegisterDefaultRepositoryFor(entityType))
@ -42,6 +49,17 @@ namespace Volo.Abp.Domain.Repositories
}
}
protected virtual void RegisterSpecifiedDefaultRepositories()
{
foreach (var entityType in Options.SpecifiedDefaultRepositories)
{
if (!Options.CustomRepositories.ContainsKey(entityType))
{
RegisterDefaultRepository(entityType);
}
}
}
protected virtual void RegisterDefaultRepository(Type entityType)
{
Options.Services.AddDefaultRepository(
@ -92,4 +110,4 @@ namespace Volo.Abp.Domain.Repositories
protected abstract Type GetRepositoryType(Type dbContextType, Type entityType, Type primaryKeyType);
}
}
}

5
framework/src/Volo.Abp.Http/Volo/Abp/Http/Modeling/ParameterApiDescriptionModel.cs

@ -10,6 +10,8 @@ namespace Volo.Abp.Http.Modeling
public string Name { get; set; }
public string JsonName { get; set; }
public string Type { get; set; }
public string TypeSimple { get; set; }
@ -29,11 +31,12 @@ namespace Volo.Abp.Http.Modeling
}
public static ParameterApiDescriptionModel Create(string name, string nameOnMethod, Type type, bool isOptional = false, object defaultValue = null, string[] constraintTypes = null, string bindingSourceId = null, string descriptorName = null)
public static ParameterApiDescriptionModel Create(string name, string jsonName, string nameOnMethod, Type type, bool isOptional = false, object defaultValue = null, string[] constraintTypes = null, string bindingSourceId = null, string descriptorName = null)
{
return new ParameterApiDescriptionModel
{
Name = name,
JsonName = jsonName,
NameOnMethod = nameOnMethod,
Type = type != null ? TypeHelper.GetFullNameHandlingNullableAndGenerics(type) : null,
TypeSimple = type != null ? ApiTypeNameHelper.GetSimpleTypeName(type) : null,

4
framework/src/Volo.Abp.Http/Volo/Abp/Http/Modeling/PropertyApiDescriptionModel.cs

@ -1,6 +1,7 @@
using System;
using System.ComponentModel.DataAnnotations;
using System.Reflection;
using Volo.Abp.Http.ProxyScripting.Configuration;
namespace Volo.Abp.Http.Modeling
{
@ -9,6 +10,8 @@ namespace Volo.Abp.Http.Modeling
{
public string Name { get; set; }
public string JsonName { get; set; }
public string Type { get; set; }
public string TypeSimple { get; set; }
@ -21,6 +24,7 @@ namespace Volo.Abp.Http.Modeling
return new PropertyApiDescriptionModel
{
Name = propertyInfo.Name,
JsonName = AbpApiProxyScriptingOptions.PropertyNameGenerator.Invoke(propertyInfo),
Type = ApiTypeNameHelper.GetTypeName(propertyInfo.PropertyType),
TypeSimple = ApiTypeNameHelper.GetSimpleTypeName(propertyInfo.PropertyType),
IsRequired = propertyInfo.IsDefined(typeof(RequiredAttribute), true)

22
framework/src/Volo.Abp.Http/Volo/Abp/Http/ProxyScripting/Configuration/AbpApiProxyScriptingOptions.cs

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Reflection;
namespace Volo.Abp.Http.ProxyScripting.Configuration
{
@ -7,9 +8,30 @@ namespace Volo.Abp.Http.ProxyScripting.Configuration
{
public IDictionary<string, Type> Generators { get; }
public static Func<PropertyInfo, string> PropertyNameGenerator { get; set; }
public AbpApiProxyScriptingOptions()
{
Generators = new Dictionary<string, Type>();
PropertyNameGenerator = propertyInfo =>
{
var jsonPropertyNameAttribute = propertyInfo.GetSingleAttributeOrNull<System.Text.Json.Serialization.JsonPropertyNameAttribute>(true);
if (jsonPropertyNameAttribute != null)
{
return jsonPropertyNameAttribute.Name;
}
var jsonPropertyAttribute = propertyInfo.GetSingleAttributeOrNull<Newtonsoft.Json.JsonPropertyAttribute>(true);
if (jsonPropertyAttribute != null)
{
return jsonPropertyAttribute.PropertyName;
}
return null;
};
}
}
}

3
framework/src/Volo.Abp.Sms.Aliyun/FodyWeavers.xml

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

30
framework/src/Volo.Abp.Sms.Aliyun/FodyWeavers.xsd

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

24
framework/src/Volo.Abp.Sms.Aliyun/Volo.Abp.Sms.Aliyun.csproj

@ -0,0 +1,24 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\configureawait.props"/>
<Import Project="..\..\..\common.props"/>
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<AssemblyName>Volo.Abp.Sms.Aliyun</AssemblyName>
<PackageId>Volo.Abp.Sms.Aliyun</PackageId>
<AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<RootNamespace/>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Volo.Abp.Sms\Volo.Abp.Sms.csproj"/>
</ItemGroup>
<ItemGroup>
<PackageReference Include="AlibabaCloud.SDK.Dysmsapi20170525" Version="1.0.2"/>
</ItemGroup>
</Project>

11
framework/src/Volo.Abp.Sms.Aliyun/Volo/Abp/Sms/Aliyun/AbpAliyunSmsOptions.cs

@ -0,0 +1,11 @@
namespace Volo.Abp.Sms.Aliyun
{
public class AbpAliyunSmsOptions
{
public string AccessKeySecret { get; set; }
public string AccessKeyId { get; set; }
public string EndPoint { get; set; }
}
}

16
framework/src/Volo.Abp.Sms.Aliyun/Volo/Abp/Sms/Aliyun/AbpSmsAliyunModule.cs

@ -0,0 +1,16 @@
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Modularity;
namespace Volo.Abp.Sms.Aliyun
{
[DependsOn(typeof(AbpSmsModule))]
public class AbpSmsAliyunModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
var configuration = context.Services.GetConfiguration();
Configure<AbpAliyunSmsOptions>(configuration.GetSection("AbpAliyunSms"));
}
}
}

43
framework/src/Volo.Abp.Sms.Aliyun/Volo/Abp/Sms/Aliyun/AliyunSmsSender.cs

@ -0,0 +1,43 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.Extensions.Options;
using Volo.Abp.DependencyInjection;
using AliyunClient = AlibabaCloud.SDK.Dysmsapi20170525.Client;
using AliyunConfig = AlibabaCloud.OpenApiClient.Models.Config;
using AliyunSendSmsRequest = AlibabaCloud.SDK.Dysmsapi20170525.Models.SendSmsRequest;
namespace Volo.Abp.Sms.Aliyun
{
public class AliyunSmsSender : ISmsSender, ITransientDependency
{
protected AbpAliyunSmsOptions Options { get; }
public AliyunSmsSender(IOptionsSnapshot<AbpAliyunSmsOptions> options)
{
Options = options.Value;
}
public async Task SendAsync(SmsMessage smsMessage)
{
var client = CreateClient();
await client.SendSmsAsync(new AliyunSendSmsRequest
{
PhoneNumbers = smsMessage.PhoneNumber,
SignName = smsMessage.Properties.GetOrDefault("SignName") as string,
TemplateCode = smsMessage.Properties.GetOrDefault("TemplateCode") as string,
TemplateParam = smsMessage.Text
});
}
protected virtual AliyunClient CreateClient()
{
return new(new AliyunConfig
{
AccessKeyId = Options.AccessKeyId,
AccessKeySecret = Options.AccessKeySecret,
Endpoint = Options.EndPoint
});
}
}
}

1
framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcTestModule.cs

@ -110,6 +110,7 @@ namespace Volo.Abp.AspNetCore.Mvc
app.UseCorrelationId();
app.UseVirtualFiles();
app.UseAbpRequestLocalization();
app.UseAbpSecurityHeaders();
app.UseRouting();
app.UseMiddleware<FakeAuthenticationMiddleware>();
app.UseAbpClaimsMap();

10
framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Authorization/AuthTestController_Tests.cs

@ -2,21 +2,11 @@
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 AuthTestController_Tests : AspNetCoreMvcTestBase
{
private readonly FakeUserClaims _fakeRequiredService;

143
framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Conventions/AbpServiceConvention_Tests.cs

@ -0,0 +1,143 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.ApplicationModels;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using Shouldly;
using System;
using System.Reflection;
using Volo.Abp.DependencyInjection;
using Xunit;
namespace Volo.Abp.AspNetCore.Mvc.Conventions
{
public class AbpServiceConvention_Tests : AspNetCoreMvcTestBase
{
private readonly IConventionalRouteBuilder _conventionalRouteBuilder;
private readonly IOptions<AbpAspNetCoreMvcOptions> _options;
public AbpServiceConvention_Tests()
{
_conventionalRouteBuilder = GetRequiredService<IConventionalRouteBuilder>();
_options = GetRequiredService<IOptions<AbpAspNetCoreMvcOptions>>();
}
[Fact]
public void Should_Not_Remove_Derived_Controller_If_Not_Expose_Service()
{
// Arrange
var applicationModel = new ApplicationModel();
var baseControllerModel = new ControllerModel(typeof(BaseController).GetTypeInfo(), Array.Empty<object>())
{
Application = applicationModel
};
applicationModel.Controllers.Add(baseControllerModel);
var derivedControllerModel = new ControllerModel(typeof(DerivedController).GetTypeInfo(), Array.Empty<object>())
{
Application = applicationModel
};
applicationModel.Controllers.Add(derivedControllerModel);
var abpServiceConvention = new AbpServiceConvention(_options, _conventionalRouteBuilder);
// Act
abpServiceConvention.Apply(applicationModel);
// Assert
applicationModel.Controllers.ShouldContain(baseControllerModel);
applicationModel.Controllers.ShouldContain(derivedControllerModel);
}
[Fact]
public void Should_Remove_Exposed_Controller_If_Expose_Self()
{
// Arrange
var applicationModel = new ApplicationModel();
var baseControllerModel = new ControllerModel(typeof(BaseController).GetTypeInfo(), Array.Empty<object>())
{
Application = applicationModel
};
applicationModel.Controllers.Add(baseControllerModel);
var derivedControllerModel = new ControllerModel(typeof(ExposeServiceIncludeSelfDerivedController).GetTypeInfo(), Array.Empty<object>())
{
Application = applicationModel
};
applicationModel.Controllers.Add(derivedControllerModel);
var abpServiceConvention = new AbpServiceConvention(_options, _conventionalRouteBuilder);
// Act
abpServiceConvention.Apply(applicationModel);
// Assert
applicationModel.Controllers.ShouldNotContain(baseControllerModel);
applicationModel.Controllers.ShouldContain(derivedControllerModel);
}
[Fact]
public void Should_Not_Remove_Derived_Controller_If_No_Base_Controller_Model()
{
// Arrange
var applicationModel = new ApplicationModel();
var derivedControllerModel = new ControllerModel(typeof(ExposeServiceDerivedController).GetTypeInfo(), Array.Empty<object>())
{
Application = applicationModel
};
applicationModel.Controllers.Add(derivedControllerModel);
var abpServiceConvention = new AbpServiceConvention(_options, _conventionalRouteBuilder);
// Act
abpServiceConvention.Apply(applicationModel);
// Assert
applicationModel.Controllers.ShouldContain(derivedControllerModel);
}
[Fact]
public void Should_Remove_Derived_Controller_If_Expose_Service()
{
// Arrange
var applicationModel = new ApplicationModel();
var baseControllerModel = new ControllerModel(typeof(BaseController).GetTypeInfo(), Array.Empty<object>())
{
Application = applicationModel
};
applicationModel.Controllers.Add(baseControllerModel);
var derivedControllerModel = new ControllerModel(typeof(ExposeServiceDerivedController).GetTypeInfo(), Array.Empty<object>())
{
Application = applicationModel
};
applicationModel.Controllers.Add(derivedControllerModel);
var abpServiceConvention = new AbpServiceConvention(_options, _conventionalRouteBuilder);
// Act
abpServiceConvention.Apply(applicationModel);
// Assert
applicationModel.Controllers.ShouldContain(baseControllerModel);
applicationModel.Controllers.ShouldNotContain(derivedControllerModel);
}
}
public class BaseController : Controller
{
}
public class DerivedController : BaseController
{
}
[ExposeServices(typeof(BaseController))]
public class ExposeServiceDerivedController : BaseController
{
}
[ExposeServices(typeof(BaseController), IncludeSelf = true)]
public class ExposeServiceIncludeSelfDerivedController : BaseController
{
}
}

10
framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Security/Claims/ClaimsMapTestController_Tests.cs

@ -2,20 +2,10 @@
using System.Threading.Tasks;
using Shouldly;
using Volo.Abp.AspNetCore.Mvc.Authorization;
using Volo.Abp.AspNetCore.TestBase;
using Volo.Abp.Autofac;
using Volo.Abp.MemoryDb;
using Volo.Abp.Modularity;
using Xunit;
namespace Volo.Abp.AspNetCore.Mvc.Security.Claims
{
[DependsOn(
typeof(AbpAspNetCoreTestBaseModule),
typeof(AbpMemoryDbTestModule),
typeof(AbpAspNetCoreMvcModule),
typeof(AbpAutofacModule)
)]
public class ClaimsMapTestController_Tests : AspNetCoreMvcTestBase
{
private readonly FakeUserClaims _fakeRequiredService;

12
framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Security/Headers/SecurityHeadersTestController.cs

@ -0,0 +1,12 @@
using Microsoft.AspNetCore.Mvc;
namespace Volo.Abp.AspNetCore.Mvc.Security.Headers
{
public class SecurityHeadersTestController : AbpController
{
public ActionResult Get()
{
return Content("OK");
}
}
}

19
framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Security/Headers/SecurityHeadersTestController_Tests.cs

@ -0,0 +1,19 @@
using System.Linq;
using System.Threading.Tasks;
using Shouldly;
using Xunit;
namespace Volo.Abp.AspNetCore.Mvc.Security.Headers
{
public class SecurityHeadersTestController_Tests : AspNetCoreMvcTestBase
{
[Fact]
public async Task SecurityHeaders_Should_Be_Added()
{
var responseMessage = await GetResponseAsync("/SecurityHeadersTest/Get");
responseMessage.Headers.ShouldContain(x => x.Key == "X-Content-Type-Options" & x.Value.First().ToString() == "nosniff");
responseMessage.Headers.ShouldContain(x => x.Key == "X-XSS-Protection" & x.Value.First().ToString() == "1; mode=block");
responseMessage.Headers.ShouldContain(x => x.Key == "X-Frame-Options" & x.Value.First().ToString() == "SAMEORIGIN");
}
}
}

54
framework/test/Volo.Abp.Ddd.Tests/Volo/Abp/Domain/Repositories/RepositoryRegistration_Tests.cs

@ -189,6 +189,60 @@ namespace Volo.Abp.Domain.Repositories
services.ShouldContainTransient(typeof(IRepository<MyTestEntityWithInt32Pk, int>), typeof(MyTestCustomBaseRepository<MyTestEntityWithInt32Pk, int>));
}
[Fact]
public void Should_Register_Default_Repository()
{
//Arrange
var services = new ServiceCollection();
var options = new TestDbContextRegistrationOptions(typeof(MyFakeDbContext), services);
options.AddDefaultRepository<MyTestAggregateRootWithGuidPk>();
//Act
new MyTestRepositoryRegistrar(options).AddRepositories();
//MyTestAggregateRootWithoutPk
services.ShouldNotContainService(typeof(IReadOnlyRepository<MyTestAggregateRootWithoutPk>));
services.ShouldNotContainService(typeof(IBasicRepository<MyTestAggregateRootWithoutPk>));
services.ShouldNotContainService(typeof(IRepository<MyTestAggregateRootWithoutPk>));
//MyTestAggregateRootWithGuidPk
services.ShouldContainTransient(typeof(IReadOnlyRepository<MyTestAggregateRootWithGuidPk>), typeof(MyTestDefaultRepository<MyTestAggregateRootWithGuidPk, Guid>));
services.ShouldContainTransient(typeof(IBasicRepository<MyTestAggregateRootWithGuidPk>), typeof(MyTestDefaultRepository<MyTestAggregateRootWithGuidPk, Guid>));
services.ShouldContainTransient(typeof(IRepository<MyTestAggregateRootWithGuidPk>), typeof(MyTestDefaultRepository<MyTestAggregateRootWithGuidPk, Guid>));
services.ShouldContainTransient(typeof(IReadOnlyRepository<MyTestAggregateRootWithGuidPk, Guid>), typeof(MyTestDefaultRepository<MyTestAggregateRootWithGuidPk, Guid>));
services.ShouldContainTransient(typeof(IBasicRepository<MyTestAggregateRootWithGuidPk, Guid>), typeof(MyTestDefaultRepository<MyTestAggregateRootWithGuidPk, Guid>));
services.ShouldContainTransient(typeof(IRepository<MyTestAggregateRootWithGuidPk, Guid>), typeof(MyTestDefaultRepository<MyTestAggregateRootWithGuidPk, Guid>));
}
[Fact]
public void Should_Not_Register_Default_Repository_If_Registered_Custom_Repository()
{
//Arrange
var services = new ServiceCollection();
var options = new TestDbContextRegistrationOptions(typeof(MyFakeDbContext), services);
options
.AddDefaultRepository<MyTestAggregateRootWithGuidPk>()
.AddRepository<MyTestAggregateRootWithGuidPk, MyTestAggregateRootWithDefaultPkCustomRepository>();;
//Act
new MyTestRepositoryRegistrar(options).AddRepositories();
//MyTestAggregateRootWithGuidPk
services.ShouldContainTransient(typeof(IReadOnlyRepository<MyTestAggregateRootWithGuidPk>), typeof(MyTestAggregateRootWithDefaultPkCustomRepository));
services.ShouldContainTransient(typeof(IBasicRepository<MyTestAggregateRootWithGuidPk>), typeof(MyTestAggregateRootWithDefaultPkCustomRepository));
services.ShouldContainTransient(typeof(IRepository<MyTestAggregateRootWithGuidPk>), typeof(MyTestAggregateRootWithDefaultPkCustomRepository));
services.ShouldContainTransient(typeof(IReadOnlyRepository<MyTestAggregateRootWithGuidPk, Guid>), typeof(MyTestAggregateRootWithDefaultPkCustomRepository));
services.ShouldContainTransient(typeof(IReadOnlyBasicRepository<MyTestAggregateRootWithGuidPk, Guid>), typeof(MyTestAggregateRootWithDefaultPkCustomRepository));
services.ShouldContainTransient(typeof(IBasicRepository<MyTestAggregateRootWithGuidPk, Guid>), typeof(MyTestAggregateRootWithDefaultPkCustomRepository));
services.ShouldContainTransient(typeof(IRepository<MyTestAggregateRootWithGuidPk, Guid>), typeof(MyTestAggregateRootWithDefaultPkCustomRepository));
}
public class MyTestRepositoryRegistrar : RepositoryRegistrarBase<AbpCommonDbContextRegistrationOptions>
{
public MyTestRepositoryRegistrar(AbpCommonDbContextRegistrationOptions options)

26
framework/test/Volo.Abp.Sms.Aliyun.Tests/Volo.Abp.Sms.Aliyun.Tests.csproj

@ -0,0 +1,26 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\common.test.props" />
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
<RootNamespace />
<UserSecretsId>9f0d2c00-80c1-435b-bfab-2c39c8249091</UserSecretsId>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Volo.Abp.Autofac\Volo.Abp.Autofac.csproj" />
<ProjectReference Include="..\..\src\Volo.Abp.Sms.Aliyun\Volo.Abp.Sms.Aliyun.csproj" />
<ProjectReference Include="..\AbpTestBase\AbpTestBase.csproj" />
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="$(MicrosoftPackageVersion)" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="$(MicrosoftNETTestSdkPackageVersion)" />
</ItemGroup>
<ItemGroup>
<None Remove="appsettings.json" />
<Content Include="appsettings.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup>
</Project>

12
framework/test/Volo.Abp.Sms.Aliyun.Tests/Volo/Abp/Sms/Aliyun/AbpSmsAliyunTestBase.cs

@ -0,0 +1,12 @@
using Volo.Abp.Testing;
namespace Volo.Abp.Sms.Aliyun
{
public class AbpSmsAliyunTestBase : AbpIntegratedTest<AbpSmsAliyunTestsModule>
{
protected override void SetAbpApplicationCreationOptions(AbpApplicationCreationOptions options)
{
options.UseAutofac();
}
}
}

18
framework/test/Volo.Abp.Sms.Aliyun.Tests/Volo/Abp/Sms/Aliyun/AbpSmsAliyunTestsModule.cs

@ -0,0 +1,18 @@
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Modularity;
namespace Volo.Abp.Sms.Aliyun
{
[DependsOn(typeof(AbpSmsAliyunModule))]
public class AbpSmsAliyunTestsModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
var configuration = context.Services.GetConfiguration();
Configure<AbpAliyunSmsOptions>(
configuration.GetSection("AbpAliyunSms")
);
}
}
}

37
framework/test/Volo.Abp.Sms.Aliyun.Tests/Volo/Abp/Sms/Aliyun/AliyunSmsSender_Tests.cs

@ -0,0 +1,37 @@
using System.Threading.Tasks;
using Microsoft.Extensions.Configuration;
using Xunit;
namespace Volo.Abp.Sms.Aliyun
{
public class AliyunSmsSender_Tests : AbpSmsAliyunTestBase
{
private readonly ISmsSender _smsSender;
private readonly IConfiguration _configuration;
public AliyunSmsSender_Tests()
{
_configuration = GetRequiredService<IConfiguration>();
_smsSender = GetRequiredService<ISmsSender>();
}
[Fact]
public async Task SendSms_Test()
{
var config = _configuration.GetSection("AbpAliyunSms");
// Please fill in the real parameters in the appsettings.json file.
if (config["AccessKeyId"] == "<Enter your AccessKeyId from Aliyun>")
{
return;
}
var msg = new SmsMessage(config["TargetPhoneNumber"],
config["TemplateParam"]);
msg.Properties.Add("SignName", config["SignName"]);
msg.Properties.Add("TemplateCode", config["TemplateCode"]);
await _smsSender.SendAsync(msg);
}
}
}

11
framework/test/Volo.Abp.Sms.Aliyun.Tests/appsettings.json

@ -0,0 +1,11 @@
{
"AbpAliyunSms": {
"AccessKeySecret": "<Enter your AccessKeySecret from Aliyun>",
"AccessKeyId": "<Enter your AccessKeyId from Aliyun>",
"EndPoint": "<Enter your EndPoint from Aliyun>",
"TargetPhoneNumber": "<Enter the target phone number to receive the SMS>",
"SignName": "<Enter the SignName from Aliyun>",
"TemplateCode": "<Enter the TemplateCode you need to send>",
"TemplateParam": "<Enter the template parameters>"
}
}

2
modules/audit-logging/src/Volo.Abp.AuditLogging.EntityFrameworkCore/Volo/Abp/AuditLogging/EntityFrameworkCore/IAuditLoggingDbContext.cs

@ -7,6 +7,6 @@ namespace Volo.Abp.AuditLogging.EntityFrameworkCore
[ConnectionStringName(AbpAuditLoggingDbProperties.ConnectionStringName)]
public interface IAuditLoggingDbContext : IEfCoreDbContext
{
DbSet<AuditLog> AuditLogs { get; set; }
DbSet<AuditLog> AuditLogs { get; }
}
}

10
modules/blogging/src/Volo.Blogging.EntityFrameworkCore/Volo/Blogging/EntityFrameworkCore/IBloggingDbContext.cs

@ -16,14 +16,14 @@ namespace Volo.Blogging.EntityFrameworkCore
{
DbSet<BlogUser> Users { get; }
DbSet<Blog> Blogs { get; set; }
DbSet<Blog> Blogs { get; }
DbSet<Post> Posts { get; set; }
DbSet<Post> Posts { get; }
DbSet<Comment> Comments { get; set; }
DbSet<Comment> Comments { get; }
DbSet<PostTag> PostTags { get; set; }
DbSet<PostTag> PostTags { get; }
DbSet<Tag> Tags { get; set; }
DbSet<Tag> Tags { get; }
}
}

2018
modules/cms-kit/host/Volo.CmsKit.Web.Unified/Migrations/20210225092130_Page_Remove_Description.Designer.cs

File diff suppressed because it is too large

24
modules/cms-kit/host/Volo.CmsKit.Web.Unified/Migrations/20210225092130_Page_Remove_Description.cs

@ -0,0 +1,24 @@
using Microsoft.EntityFrameworkCore.Migrations;
namespace Volo.CmsKit.Migrations
{
public partial class Page_Remove_Description : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "Description",
table: "CmsPages");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<string>(
name: "Description",
table: "CmsPages",
type: "nvarchar(512)",
maxLength: 512,
nullable: true);
}
}
}

4
modules/cms-kit/host/Volo.CmsKit.Web.Unified/Migrations/UnifiedDbContextModelSnapshot.cs

@ -1545,10 +1545,6 @@ namespace Volo.CmsKit.Migrations
.HasColumnType("datetime2")
.HasColumnName("DeletionTime");
b.Property<string>("Description")
.HasMaxLength(512)
.HasColumnType("nvarchar(512)");
b.Property<string>("ExtraProperties")
.HasColumnType("nvarchar(max)")
.HasColumnName("ExtraProperties");

8
modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Blogs/BlogDto.cs

@ -1,19 +1,13 @@
using System;
using System.ComponentModel.DataAnnotations;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Validation;
using Volo.CmsKit.Blogs;
namespace Volo.CmsKit.Admin.Blogs
{
[Serializable]
public class BlogDto : EntityDto<Guid>
{
[Required]
[DynamicMaxLength(typeof(BlogConsts), nameof(BlogConsts.MaxNameLength))]
public string Name { get; set; }
[Required]
[DynamicMaxLength(typeof(BlogConsts), nameof(BlogConsts.MaxSlugLength))]
public string Slug { get; set; }
}
}

5
modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Blogs/BlogFeatureInputDto.cs

@ -1,11 +1,14 @@
using System.ComponentModel.DataAnnotations;
using System;
using System.ComponentModel.DataAnnotations;
namespace Volo.CmsKit.Admin.Blogs
{
[Serializable]
public class BlogFeatureInputDto
{
[Required]
public string FeatureName { get; set; }
public bool IsEnabled { get; set; }
}
}

4
modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Blogs/BlogGetListInput.cs

@ -1,7 +1,9 @@
using Volo.Abp.Application.Dtos;
using System;
using Volo.Abp.Application.Dtos;
namespace Volo.CmsKit.Admin.Blogs
{
[Serializable]
public class BlogGetListInput : PagedAndSortedResultRequestDto
{
public string Filter { get; set; }

1
modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Blogs/BlogPostDto.cs

@ -3,6 +3,7 @@ using Volo.Abp.Application.Dtos;
namespace Volo.CmsKit.Admin.Blogs
{
[Serializable]
public class BlogPostDto : EntityDto<Guid>
{
public Guid BlogId { get; set; }

17
modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Blogs/CreateBlogDto.cs

@ -0,0 +1,17 @@
using System.ComponentModel.DataAnnotations;
using Volo.Abp.Validation;
using Volo.CmsKit.Blogs;
namespace Volo.CmsKit.Admin.Blogs
{
public class CreateBlogDto
{
[Required]
[DynamicMaxLength(typeof(BlogConsts), nameof(BlogConsts.MaxNameLength))]
public string Name { get; set; }
[Required]
[DynamicMaxLength(typeof(BlogConsts), nameof(BlogConsts.MaxSlugLength))]
public string Slug { get; set; }
}
}

6
modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Blogs/CreateBlogPostDto.cs

@ -5,6 +5,7 @@ using Volo.CmsKit.Blogs;
namespace Volo.CmsKit.Admin.Blogs
{
[Serializable]
public class CreateBlogPostDto
{
[Required]
@ -15,10 +16,7 @@ namespace Volo.CmsKit.Admin.Blogs
public string Title { get; set; }
[Required]
[DynamicStringLength(
typeof(BlogPostConsts),
nameof(BlogPostConsts.MaxSlugLength),
nameof(BlogPostConsts.MinSlugLength))]
[DynamicStringLength(typeof(BlogPostConsts), nameof(BlogPostConsts.MaxSlugLength), nameof(BlogPostConsts.MinSlugLength))]
public string Slug { get; set; }
[DynamicMaxLength(typeof(BlogPostConsts), nameof(BlogPostConsts.MaxShortDescriptionLength))]

2
modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Blogs/IBlogAdminAppService.cs

@ -3,7 +3,7 @@ using Volo.Abp.Application.Services;
namespace Volo.CmsKit.Admin.Blogs
{
public interface IBlogAdminAppService : ICrudAppService<BlogDto, Guid, BlogGetListInput>
public interface IBlogAdminAppService : ICrudAppService<BlogDto, Guid, BlogGetListInput, CreateBlogDto, UpdateBlogDto>
{
}
}

2
modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Blogs/IBlogPostAdminAppService.cs

@ -14,8 +14,6 @@ namespace Volo.CmsKit.Admin.Blogs
CreateBlogPostDto,
UpdateBlogPostDto>
{
Task<BlogPostDto> GetBySlugAsync(string blogSlug, string slug);
Task SetCoverImageAsync(Guid id, RemoteStreamContent streamContent);
Task<RemoteStreamContent> GetCoverImageAsync(Guid id);

17
modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Blogs/UpdateBlogDto.cs

@ -0,0 +1,17 @@
using System.ComponentModel.DataAnnotations;
using Volo.Abp.Validation;
using Volo.CmsKit.Blogs;
namespace Volo.CmsKit.Admin.Blogs
{
public class UpdateBlogDto
{
[Required]
[DynamicMaxLength(typeof(BlogConsts), nameof(BlogConsts.MaxNameLength))]
public string Name { get; set; }
[Required]
[DynamicMaxLength(typeof(BlogConsts), nameof(BlogConsts.MaxSlugLength))]
public string Slug { get; set; }
}
}

9
modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Blogs/UpdateBlogPostDto.cs

@ -1,9 +1,11 @@
using System.ComponentModel.DataAnnotations;
using System;
using System.ComponentModel.DataAnnotations;
using Volo.Abp.Validation;
using Volo.CmsKit.Blogs;
namespace Volo.CmsKit.Admin.Blogs
{
[Serializable]
public class UpdateBlogPostDto
{
[Required]
@ -11,10 +13,7 @@ namespace Volo.CmsKit.Admin.Blogs
public string Title { get; set; }
[Required]
[DynamicStringLength(
typeof(BlogPostConsts),
nameof(BlogPostConsts.MaxSlugLength),
nameof(BlogPostConsts.MinSlugLength))]
[DynamicStringLength(typeof(BlogPostConsts), nameof(BlogPostConsts.MaxSlugLength), nameof(BlogPostConsts.MinSlugLength))]
public string Slug { get; set; }
[DynamicMaxLength(typeof(BlogPostConsts), nameof(BlogPostConsts.MaxShortDescriptionLength))]

1
modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Comments/CmsUserDto.cs

@ -2,6 +2,7 @@
namespace Volo.CmsKit.Admin.Comments
{
[Serializable]
public class CmsUserDto
{
public Guid Id { get; set; }

1
modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Comments/CommentDto.cs

@ -2,6 +2,7 @@
namespace Volo.CmsKit.Admin.Comments
{
[Serializable]
public class CommentDto
{
public Guid Id { get; set; }

1
modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Comments/CommentGetListInput.cs

@ -3,6 +3,7 @@ using Volo.Abp.Application.Dtos;
namespace Volo.CmsKit.Admin.Comments
{
[Serializable]
public class CommentGetListInput : PagedAndSortedResultRequestDto
{
public string EntityType { get; set; }

1
modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Comments/CommentWithAuthorDto.cs

@ -4,6 +4,7 @@ using Volo.CmsKit.Users;
namespace Volo.CmsKit.Admin.Comments
{
[Serializable]
public class CommentWithAuthorDto
{
public Guid Id { get; set; }

4
modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Contents/ContentCreateDto.cs

@ -1,9 +1,11 @@
using System.ComponentModel.DataAnnotations;
using System;
using System.ComponentModel.DataAnnotations;
using Volo.Abp.Validation;
using Volo.CmsKit.Contents;
namespace Volo.CmsKit.Admin.Contents
{
[Serializable]
public class ContentCreateDto
{
[Required]

1
modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Contents/ContentDto.cs

@ -3,6 +3,7 @@ using Volo.Abp.Application.Dtos;
namespace Volo.CmsKit.Admin.Contents
{
[Serializable]
public class ContentDto : EntityDto<Guid>
{
public string EntityType { get; set; }

1
modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Contents/ContentGetListDto.cs

@ -3,6 +3,7 @@ using Volo.Abp.Application.Dtos;
namespace Volo.CmsKit.Admin.Contents
{
[Serializable]
public class ContentGetListDto : EntityDto<Guid>
{
public string EntityType { get; set; }

4
modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Contents/ContentGetListInput.cs

@ -1,7 +1,9 @@
using Volo.Abp.Application.Dtos;
using System;
using Volo.Abp.Application.Dtos;
namespace Volo.CmsKit.Admin.Contents
{
[Serializable]
public class ContentGetListInput : PagedAndSortedResultRequestDto
{
}

4
modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Contents/ContentUpdateDto.cs

@ -1,9 +1,11 @@
using System.ComponentModel.DataAnnotations;
using System;
using System.ComponentModel.DataAnnotations;
using Volo.Abp.Validation;
using Volo.CmsKit.Contents;
namespace Volo.CmsKit.Admin.Contents
{
[Serializable]
public class ContentUpdateDto
{
[Required]

0
modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/MediaDescriptors/CreateMediaInputDto.cs → modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/MediaDescriptors/CreateMediaInputStream.cs

1
modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/MediaDescriptors/MediaDescriptorDto.cs

@ -3,6 +3,7 @@ using Volo.Abp.Application.Dtos;
namespace Volo.CmsKit.Admin.MediaDescriptors
{
[Serializable]
public class MediaDescriptorDto : EntityDto<Guid>
{
public string Name { get; set; }

7
modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Pages/CreatePageInputDto.cs

@ -1,10 +1,12 @@
using System.ComponentModel.DataAnnotations;
using System;
using System.ComponentModel.DataAnnotations;
using Volo.Abp.Validation;
using Volo.CmsKit.Contents;
using Volo.CmsKit.Pages;
namespace Volo.CmsKit.Admin.Pages
{
[Serializable]
public class CreatePageInputDto
{
[Required]
@ -14,8 +16,5 @@ namespace Volo.CmsKit.Admin.Pages
[Required]
[DynamicMaxLength(typeof(PageConsts), nameof(PageConsts.MaxSlugLength))]
public string Slug { get; set; }
[DynamicMaxLength(typeof(PageConsts), nameof(PageConsts.MaxDescriptionLength))]
public string Description { get; set; }
}
}

4
modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Pages/GetPagesInputDto.cs

@ -1,7 +1,9 @@
using Volo.Abp.Application.Dtos;
using System;
using Volo.Abp.Application.Dtos;
namespace Volo.CmsKit.Admin.Pages
{
[Serializable]
public class GetPagesInputDto : PagedAndSortedResultRequestDto
{
public string Filter { get; set; }

3
modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Pages/PageDto.cs

@ -3,12 +3,11 @@ using Volo.Abp.Application.Dtos;
namespace Volo.CmsKit.Admin.Pages
{
[Serializable]
public class PageDto : AuditedEntityDto<Guid>
{
public string Title { get; set; }
public string Slug { get; set; }
public string Description { get; set; }
}
}

7
modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Pages/UpdatePageInputDto.cs

@ -1,10 +1,12 @@
using System.ComponentModel.DataAnnotations;
using System;
using System.ComponentModel.DataAnnotations;
using Volo.Abp.Validation;
using Volo.CmsKit.Contents;
using Volo.CmsKit.Pages;
namespace Volo.CmsKit.Admin.Pages
{
[Serializable]
public class UpdatePageInputDto
{
[Required]
@ -14,8 +16,5 @@ namespace Volo.CmsKit.Admin.Pages
[Required]
[DynamicMaxLength(typeof(PageConsts), nameof(PageConsts.MaxSlugLength))]
public string Slug { get; set; }
[DynamicMaxLength(typeof(PageConsts), nameof(PageConsts.MaxDescriptionLength))]
public string Description { get; set; }
}
}

4
modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Tags/EntityTagCreateDto.cs

@ -1,7 +1,9 @@
using System.ComponentModel.DataAnnotations;
using System;
using System.ComponentModel.DataAnnotations;
namespace Volo.CmsKit.Admin.Tags
{
[Serializable]
public class EntityTagCreateDto
{
[Required]

1
modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Tags/EntityTagRemoveDto.cs

@ -3,6 +3,7 @@ using System.ComponentModel.DataAnnotations;
namespace Volo.CmsKit.Admin.Tags
{
[Serializable]
public class EntityTagRemoveDto
{
[Required]

1
modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Tags/EntityTagSetDto.cs

@ -6,6 +6,7 @@ using System.Threading.Tasks;
namespace Volo.CmsKit.Admin.Tags
{
[Serializable]
public class EntityTagSetDto
{
public string EntityId { get; set; }

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

Loading…
Cancel
Save