From 712d547c4b2ca4f90d0254dab4483454596afb5b Mon Sep 17 00:00:00 2001 From: maliming Date: Mon, 11 Dec 2023 10:56:11 +0800 Subject: [PATCH 01/98] Add `NormalizedName` property to `Tenant`. Resolve #18394 --- .../MauiBlazor/MauiBlazorRemoteTenantStore.cs | 14 +++--- .../Mvc/Client/MvcRemoteTenantStore.cs | 12 ++--- .../Mvc/MultiTenancy/FindTenantResultDto.cs | 2 + .../Abp/MultiTenancy/AbpTenantAppService.cs | 8 +++- .../MultiTenancy/TenantSwitchModal.cshtml.cs | 5 ++- .../Abp/MultiTenancy/ITenantNormalizer.cs | 6 +++ .../Volo/Abp/MultiTenancy/ITenantStore.cs | 4 +- .../Abp/MultiTenancy/TenantConfiguration.cs | 10 +++++ .../UpperInvariantTenantNormalizer.cs | 11 +++++ .../ConfigurationStore/DefaultTenantStore.cs | 8 ++-- .../TenantConfigurationProvider.cs | 7 ++- ...reMultiTenancy_WithDomainResolver_Tests.cs | 3 +- ...ltiTenancy_Without_DomainResolver_Tests.cs | 3 +- .../Serilog/Serilog_Enrichers_Tests.cs | 3 +- .../Abp/TenantManagement/ITenantRepository.cs | 4 +- .../Volo/Abp/TenantManagement/Tenant.cs | 12 ++++- ...TenantConfigurationCacheItemInvalidator.cs | 8 ++-- .../Abp/TenantManagement/TenantManager.cs | 24 ++++++---- .../Volo/Abp/TenantManagement/TenantStore.cs | 28 ++++++------ ...agementDbContextModelCreatingExtensions.cs | 1 + .../EfCoreTenantRepository.cs | 8 ++-- .../MongoDb/MongoTenantRepository.cs | 8 ++-- .../TenantCacheItemInvalidator_Tests.cs | 44 ++++++++++--------- .../TenantManagement/TenantManager_Tests.cs | 11 +++-- .../Abp/TenantManagement/TenantStore_Tests.cs | 7 ++- .../Volo/Abp/TenantManagement/Tenant_Tests.cs | 7 ++- .../Abp/TenantManagement/LazyLoad_Tests.cs | 5 ++- .../TenantRepository_Tests.cs | 17 ++++--- 28 files changed, 178 insertions(+), 102 deletions(-) create mode 100644 framework/src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/ITenantNormalizer.cs create mode 100644 framework/src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/UpperInvariantTenantNormalizer.cs diff --git a/framework/src/Volo.Abp.AspNetCore.Components.MauiBlazor/Volo/Abp/AspNetCore/Components/MauiBlazor/MauiBlazorRemoteTenantStore.cs b/framework/src/Volo.Abp.AspNetCore.Components.MauiBlazor/Volo/Abp/AspNetCore/Components/MauiBlazor/MauiBlazorRemoteTenantStore.cs index d17a2b6f87..d06eb60566 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.MauiBlazor/Volo/Abp/AspNetCore/Components/MauiBlazor/MauiBlazorRemoteTenantStore.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components.MauiBlazor/Volo/Abp/AspNetCore/Components/MauiBlazor/MauiBlazorRemoteTenantStore.cs @@ -23,13 +23,13 @@ public class MauiBlazorRemoteTenantStore : ITenantStore, ITransientDependency Cache = cache; } - public async Task FindAsync(string name) + public async Task FindAsync(string normalizedName) { - var cacheKey = CreateCacheKey(name); + var cacheKey = CreateCacheKey(normalizedName); var tenantConfiguration = await Cache.GetOrAddAsync( cacheKey, - async () => CreateTenantConfiguration(await TenantAppService.FindTenantByNameAsync(name))!, + async () => CreateTenantConfiguration(await TenantAppService.FindTenantByNameAsync(normalizedName))!, () => new DistributedCacheEntryOptions { AbsoluteExpirationRelativeToNow = @@ -57,13 +57,13 @@ public class MauiBlazorRemoteTenantStore : ITenantStore, ITransientDependency return tenantConfiguration; } - public TenantConfiguration? Find(string name) + public TenantConfiguration? Find(string normalizedName) { - var cacheKey = CreateCacheKey(name); + var cacheKey = CreateCacheKey(normalizedName); var tenantConfiguration = Cache.GetOrAdd( cacheKey, - () => AsyncHelper.RunSync(async () => CreateTenantConfiguration(await TenantAppService.FindTenantByNameAsync(name)))!, + () => AsyncHelper.RunSync(async () => CreateTenantConfiguration(await TenantAppService.FindTenantByNameAsync(normalizedName)))!, () => new DistributedCacheEntryOptions { AbsoluteExpirationRelativeToNow = @@ -110,4 +110,4 @@ public class MauiBlazorRemoteTenantStore : ITenantStore, ITransientDependency { return $"RemoteTenantStore_Id_{tenantId:N}"; } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/MvcRemoteTenantStore.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/MvcRemoteTenantStore.cs index e0c450b8b4..1bc7856ca6 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/MvcRemoteTenantStore.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/MvcRemoteTenantStore.cs @@ -29,9 +29,9 @@ public class MvcRemoteTenantStore : ITenantStore, ITransientDependency Options = options.Value; } - public async Task FindAsync(string name) + public async Task FindAsync(string normalizedName) { - var cacheKey = TenantConfigurationCacheItem.CalculateCacheKey(name); + var cacheKey = TenantConfigurationCacheItem.CalculateCacheKey(normalizedName); var httpContext = HttpContextAccessor?.HttpContext; if (httpContext != null && httpContext.Items[cacheKey] is TenantConfigurationCacheItem tenantConfigurationInHttpContext) @@ -42,7 +42,7 @@ public class MvcRemoteTenantStore : ITenantStore, ITransientDependency var tenantConfiguration = await Cache.GetAsync(cacheKey); if (tenantConfiguration == null) { - await TenantAppService.FindTenantByNameAsync(name); + await TenantAppService.FindTenantByNameAsync(normalizedName); tenantConfiguration = await Cache.GetAsync(cacheKey); } @@ -79,9 +79,9 @@ public class MvcRemoteTenantStore : ITenantStore, ITransientDependency return tenantConfiguration?.Value; } - public TenantConfiguration? Find(string name) + public TenantConfiguration? Find(string normalizedName) { - var cacheKey = TenantConfigurationCacheItem.CalculateCacheKey(name); + var cacheKey = TenantConfigurationCacheItem.CalculateCacheKey(normalizedName); var httpContext = HttpContextAccessor?.HttpContext; if (httpContext != null && httpContext.Items[cacheKey] is TenantConfigurationCacheItem tenantConfigurationInHttpContext) @@ -92,7 +92,7 @@ public class MvcRemoteTenantStore : ITenantStore, ITransientDependency var tenantConfiguration = Cache.Get(cacheKey); if (tenantConfiguration == null) { - AsyncHelper.RunSync(async () => await TenantAppService.FindTenantByNameAsync(name)); + AsyncHelper.RunSync(async () => await TenantAppService.FindTenantByNameAsync(normalizedName)); tenantConfiguration = Cache.Get(cacheKey); } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/MultiTenancy/FindTenantResultDto.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/MultiTenancy/FindTenantResultDto.cs index 599b0b8a67..1de5f942dc 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/MultiTenancy/FindTenantResultDto.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/MultiTenancy/FindTenantResultDto.cs @@ -11,5 +11,7 @@ public class FindTenantResultDto public string? Name { get; set; } + public string? NormalizedName { get; set; } + public bool IsActive { get; set; } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Pages/Abp/MultiTenancy/AbpTenantAppService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Pages/Abp/MultiTenancy/AbpTenantAppService.cs index 279bcee8ad..75649c1f6b 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Pages/Abp/MultiTenancy/AbpTenantAppService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Pages/Abp/MultiTenancy/AbpTenantAppService.cs @@ -9,15 +9,17 @@ namespace Pages.Abp.MultiTenancy; public class AbpTenantAppService : ApplicationService, IAbpTenantAppService { protected ITenantStore TenantStore { get; } + protected ITenantNormalizer TenantNormalizer { get; } - public AbpTenantAppService(ITenantStore tenantStore) + public AbpTenantAppService(ITenantStore tenantStore, ITenantNormalizer tenantNormalizer) { TenantStore = tenantStore; + TenantNormalizer = tenantNormalizer; } public virtual async Task FindTenantByNameAsync(string name) { - var tenant = await TenantStore.FindAsync(name); + var tenant = await TenantStore.FindAsync(TenantNormalizer.NormalizeName(name)!); if (tenant == null) { @@ -29,6 +31,7 @@ public class AbpTenantAppService : ApplicationService, IAbpTenantAppService Success = true, TenantId = tenant.Id, Name = tenant.Name, + NormalizedName = tenant.NormalizedName, IsActive = tenant.IsActive }; } @@ -47,6 +50,7 @@ public class AbpTenantAppService : ApplicationService, IAbpTenantAppService Success = true, TenantId = tenant.Id, Name = tenant.Name, + NormalizedName = tenant.NormalizedName, IsActive = tenant.IsActive }; } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Pages/Abp/MultiTenancy/TenantSwitchModal.cshtml.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Pages/Abp/MultiTenancy/TenantSwitchModal.cshtml.cs index f6711be826..94a6760df3 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Pages/Abp/MultiTenancy/TenantSwitchModal.cshtml.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Pages/Abp/MultiTenancy/TenantSwitchModal.cshtml.cs @@ -18,13 +18,16 @@ public class TenantSwitchModalModel : AbpPageModel public TenantInfoModel Input { get; set; } = default!; protected ITenantStore TenantStore { get; } + protected ITenantNormalizer TenantNormalizer { get; } protected AbpAspNetCoreMultiTenancyOptions Options { get; } public TenantSwitchModalModel( ITenantStore tenantStore, + ITenantNormalizer tenantNormalizer, IOptions options) { TenantStore = tenantStore; + TenantNormalizer = tenantNormalizer; Options = options.Value; LocalizationResourceType = typeof(AbpUiMultiTenancyResource); } @@ -45,7 +48,7 @@ public class TenantSwitchModalModel : AbpPageModel Guid? tenantId = null; if (!Input.Name.IsNullOrEmpty()) { - var tenant = await TenantStore.FindAsync(Input.Name!); + var tenant = await TenantStore.FindAsync(TenantNormalizer.NormalizeName(Input.Name!)!); if (tenant == null) { throw new UserFriendlyException(L["GivenTenantIsNotExist", Input.Name!]); diff --git a/framework/src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/ITenantNormalizer.cs b/framework/src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/ITenantNormalizer.cs new file mode 100644 index 0000000000..1c5f0859f5 --- /dev/null +++ b/framework/src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/ITenantNormalizer.cs @@ -0,0 +1,6 @@ +namespace Volo.Abp.MultiTenancy; + +public interface ITenantNormalizer +{ + string? NormalizeName(string? name); +} diff --git a/framework/src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/ITenantStore.cs b/framework/src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/ITenantStore.cs index 93dd609cc4..d97d438b01 100644 --- a/framework/src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/ITenantStore.cs +++ b/framework/src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/ITenantStore.cs @@ -5,12 +5,12 @@ namespace Volo.Abp.MultiTenancy; public interface ITenantStore { - Task FindAsync(string name); + Task FindAsync(string normalizedName); Task FindAsync(Guid id); [Obsolete("Use FindAsync method.")] - TenantConfiguration? Find(string name); + TenantConfiguration? Find(string normalizedName); [Obsolete("Use FindAsync method.")] TenantConfiguration? Find(Guid id); diff --git a/framework/src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/TenantConfiguration.cs b/framework/src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/TenantConfiguration.cs index 0e5faf9386..29b0971708 100644 --- a/framework/src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/TenantConfiguration.cs +++ b/framework/src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/TenantConfiguration.cs @@ -11,6 +11,8 @@ public class TenantConfiguration public string Name { get; set; } = default!; + public string NormalizedName { get; set; } = default!; + public ConnectionStrings? ConnectionStrings { get; set; } public bool IsActive { get; set; } @@ -30,4 +32,12 @@ public class TenantConfiguration ConnectionStrings = new ConnectionStrings(); } + + public TenantConfiguration(Guid id, [NotNull] string name, [NotNull] string normalizedName) + : this(id, name) + { + Check.NotNull(normalizedName, nameof(normalizedName)); + + NormalizedName = normalizedName; + } } diff --git a/framework/src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/UpperInvariantTenantNormalizer.cs b/framework/src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/UpperInvariantTenantNormalizer.cs new file mode 100644 index 0000000000..cba6b32349 --- /dev/null +++ b/framework/src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/UpperInvariantTenantNormalizer.cs @@ -0,0 +1,11 @@ +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.MultiTenancy; + +public class UpperInvariantTenantNormalizer : ITenantNormalizer, ITransientDependency +{ + public virtual string? NormalizeName(string? name) + { + return name?.Normalize().ToUpperInvariant(); + } +} diff --git a/framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/ConfigurationStore/DefaultTenantStore.cs b/framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/ConfigurationStore/DefaultTenantStore.cs index d86d810d11..e91e749fe3 100644 --- a/framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/ConfigurationStore/DefaultTenantStore.cs +++ b/framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/ConfigurationStore/DefaultTenantStore.cs @@ -16,9 +16,9 @@ public class DefaultTenantStore : ITenantStore, ITransientDependency _options = options.CurrentValue; } - public Task FindAsync(string name) + public Task FindAsync(string normalizedName) { - return Task.FromResult(Find(name)); + return Task.FromResult(Find(normalizedName)); } public Task FindAsync(Guid id) @@ -26,9 +26,9 @@ public class DefaultTenantStore : ITenantStore, ITransientDependency return Task.FromResult(Find(id)); } - public TenantConfiguration? Find(string name) + public TenantConfiguration? Find(string normalizedName) { - return _options.Tenants?.FirstOrDefault(t => t.Name == name); + return _options.Tenants?.FirstOrDefault(t => t.NormalizedName == normalizedName); } public TenantConfiguration? Find(Guid id) diff --git a/framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/TenantConfigurationProvider.cs b/framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/TenantConfigurationProvider.cs index 7e93cf888a..79f07deb4a 100644 --- a/framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/TenantConfigurationProvider.cs +++ b/framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/TenantConfigurationProvider.cs @@ -10,6 +10,7 @@ public class TenantConfigurationProvider : ITenantConfigurationProvider, ITransi { protected virtual ITenantResolver TenantResolver { get; } protected virtual ITenantStore TenantStore { get; } + protected virtual ITenantNormalizer TenantNormalizer { get; } protected virtual ITenantResolveResultAccessor TenantResolveResultAccessor { get; } protected virtual IStringLocalizer StringLocalizer { get; } @@ -17,10 +18,12 @@ public class TenantConfigurationProvider : ITenantConfigurationProvider, ITransi ITenantResolver tenantResolver, ITenantStore tenantStore, ITenantResolveResultAccessor tenantResolveResultAccessor, - IStringLocalizer stringLocalizer) + IStringLocalizer stringLocalizer, + ITenantNormalizer tenantNormalizer) { TenantResolver = tenantResolver; TenantStore = tenantStore; + TenantNormalizer = tenantNormalizer; TenantResolveResultAccessor = tenantResolveResultAccessor; StringLocalizer = stringLocalizer; } @@ -69,7 +72,7 @@ public class TenantConfigurationProvider : ITenantConfigurationProvider, ITransi } else { - return await TenantStore.FindAsync(tenantIdOrName); + return await TenantStore.FindAsync(TenantNormalizer.NormalizeName(tenantIdOrName)!); } } } diff --git a/framework/test/Volo.Abp.AspNetCore.MultiTenancy.Tests/Volo/Abp/AspNetCore/MultiTenancy/AspNetCoreMultiTenancy_WithDomainResolver_Tests.cs b/framework/test/Volo.Abp.AspNetCore.MultiTenancy.Tests/Volo/Abp/AspNetCore/MultiTenancy/AspNetCoreMultiTenancy_WithDomainResolver_Tests.cs index e80b47b2a5..02d0288b4b 100644 --- a/framework/test/Volo.Abp.AspNetCore.MultiTenancy.Tests/Volo/Abp/AspNetCore/MultiTenancy/AspNetCoreMultiTenancy_WithDomainResolver_Tests.cs +++ b/framework/test/Volo.Abp.AspNetCore.MultiTenancy.Tests/Volo/Abp/AspNetCore/MultiTenancy/AspNetCoreMultiTenancy_WithDomainResolver_Tests.cs @@ -16,6 +16,7 @@ public class AspNetCoreMultiTenancy_WithDomainResolver_Tests : AspNetCoreMultiTe { private readonly Guid _testTenantId = Guid.NewGuid(); private readonly string _testTenantName = "acme"; + private readonly string _testTenantNormalizedName = "ACME"; private readonly AbpAspNetCoreMultiTenancyOptions _options; @@ -30,7 +31,7 @@ public class AspNetCoreMultiTenancy_WithDomainResolver_Tests : AspNetCoreMultiTe { options.Tenants = new[] { - new TenantConfiguration(_testTenantId, _testTenantName) + new TenantConfiguration(_testTenantId, _testTenantName, _testTenantNormalizedName) }; }); diff --git a/framework/test/Volo.Abp.AspNetCore.MultiTenancy.Tests/Volo/Abp/AspNetCore/MultiTenancy/AspNetCoreMultiTenancy_Without_DomainResolver_Tests.cs b/framework/test/Volo.Abp.AspNetCore.MultiTenancy.Tests/Volo/Abp/AspNetCore/MultiTenancy/AspNetCoreMultiTenancy_Without_DomainResolver_Tests.cs index 56da287ef8..71ee5f11df 100644 --- a/framework/test/Volo.Abp.AspNetCore.MultiTenancy.Tests/Volo/Abp/AspNetCore/MultiTenancy/AspNetCoreMultiTenancy_Without_DomainResolver_Tests.cs +++ b/framework/test/Volo.Abp.AspNetCore.MultiTenancy.Tests/Volo/Abp/AspNetCore/MultiTenancy/AspNetCoreMultiTenancy_Without_DomainResolver_Tests.cs @@ -17,6 +17,7 @@ public class AspNetCoreMultiTenancy_Without_DomainResolver_Tests : AspNetCoreMul { private readonly Guid _testTenantId = Guid.NewGuid(); private readonly string _testTenantName = "acme"; + private readonly string _testTenantNormalizedName = "ACME"; private readonly AbpAspNetCoreMultiTenancyOptions _options; @@ -31,7 +32,7 @@ public class AspNetCoreMultiTenancy_Without_DomainResolver_Tests : AspNetCoreMul { options.Tenants = new[] { - new TenantConfiguration(_testTenantId, _testTenantName) + new TenantConfiguration(_testTenantId, _testTenantName, _testTenantNormalizedName) }; }); diff --git a/framework/test/Volo.Abp.AspNetCore.Serilog.Tests/Volo/Abp/AspNetCore/Serilog/Serilog_Enrichers_Tests.cs b/framework/test/Volo.Abp.AspNetCore.Serilog.Tests/Volo/Abp/AspNetCore/Serilog/Serilog_Enrichers_Tests.cs index 4782a5e768..1fb1402b26 100644 --- a/framework/test/Volo.Abp.AspNetCore.Serilog.Tests/Volo/Abp/AspNetCore/Serilog/Serilog_Enrichers_Tests.cs +++ b/framework/test/Volo.Abp.AspNetCore.Serilog.Tests/Volo/Abp/AspNetCore/Serilog/Serilog_Enrichers_Tests.cs @@ -20,6 +20,7 @@ public class Serilog_Enrichers_Tests : AbpSerilogTestBase private readonly Guid _testTenantId = Guid.NewGuid(); private readonly string _testTenantName = "acme"; + private readonly string _testTenantNormalizedName = "ACME"; private readonly AbpAspNetCoreMultiTenancyOptions _tenancyOptions; private readonly AbpAspNetCoreSerilogOptions _serilogOptions; @@ -39,7 +40,7 @@ public class Serilog_Enrichers_Tests : AbpSerilogTestBase { options.Tenants = new[] { - new TenantConfiguration(_testTenantId, _testTenantName) + new TenantConfiguration(_testTenantId, _testTenantName, _testTenantNormalizedName) }; }); base.ConfigureServices(services); diff --git a/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/ITenantRepository.cs b/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/ITenantRepository.cs index 6412993d14..41ea978524 100644 --- a/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/ITenantRepository.cs +++ b/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/ITenantRepository.cs @@ -9,13 +9,13 @@ namespace Volo.Abp.TenantManagement; public interface ITenantRepository : IBasicRepository { Task FindByNameAsync( - string name, + string normalizedName, bool includeDetails = true, CancellationToken cancellationToken = default); [Obsolete("Use FindByNameAsync method.")] Tenant FindByName( - string name, + string normalizedName, bool includeDetails = true ); diff --git a/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/Tenant.cs b/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/Tenant.cs index 5275e39ab3..6567cf8efd 100644 --- a/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/Tenant.cs +++ b/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/Tenant.cs @@ -10,7 +10,9 @@ namespace Volo.Abp.TenantManagement; public class Tenant : FullAuditedAggregateRoot, IHasEntityVersion { public virtual string Name { get; protected set; } - + + public virtual string NormalizedName { get; protected set; } + public virtual int EntityVersion { get; protected set; } public virtual List ConnectionStrings { get; protected set; } @@ -20,10 +22,11 @@ public class Tenant : FullAuditedAggregateRoot, IHasEntityVersion } - protected internal Tenant(Guid id, [NotNull] string name) + protected internal Tenant(Guid id, [NotNull] string name, [CanBeNull] string normalizedTenantName) : base(id) { SetName(name); + SetNormalizedTenantName(normalizedTenantName); ConnectionStrings = new List(); } @@ -78,4 +81,9 @@ public class Tenant : FullAuditedAggregateRoot, IHasEntityVersion { Name = Check.NotNullOrWhiteSpace(name, nameof(name), TenantConsts.MaxNameLength); } + + protected internal virtual void SetNormalizedTenantName([CanBeNull] string normalizedTenantName) + { + NormalizedName = normalizedTenantName; + } } diff --git a/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/TenantConfigurationCacheItemInvalidator.cs b/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/TenantConfigurationCacheItemInvalidator.cs index e629186e20..09c1a9368f 100644 --- a/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/TenantConfigurationCacheItemInvalidator.cs +++ b/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/TenantConfigurationCacheItemInvalidator.cs @@ -22,21 +22,21 @@ public class TenantConfigurationCacheItemInvalidator : public virtual async Task HandleEventAsync(EntityChangedEventData eventData) { - await ClearCacheAsync(eventData.Entity.Id, eventData.Entity.Name); + await ClearCacheAsync(eventData.Entity.Id, eventData.Entity.NormalizedName); } public virtual async Task HandleEventAsync(EntityDeletedEventData eventData) { - await ClearCacheAsync(eventData.Entity.Id, eventData.Entity.Name); + await ClearCacheAsync(eventData.Entity.Id, eventData.Entity.NormalizedName); } - protected virtual async Task ClearCacheAsync(Guid? id, string name) + protected virtual async Task ClearCacheAsync(Guid? id, string normalizedName) { await Cache.RemoveManyAsync( new[] { TenantConfigurationCacheItem.CalculateCacheKey(id, null), - TenantConfigurationCacheItem.CalculateCacheKey(null, name), + TenantConfigurationCacheItem.CalculateCacheKey(null, normalizedName), }); } } diff --git a/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/TenantManager.cs b/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/TenantManager.cs index 1ad7324c35..43594dfde7 100644 --- a/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/TenantManager.cs +++ b/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/TenantManager.cs @@ -11,19 +11,22 @@ public class TenantManager : DomainService, ITenantManager protected ITenantRepository TenantRepository { get; } protected IDistributedCache Cache { get; } - public TenantManager(ITenantRepository tenantRepository, - IDistributedCache cache) + protected ITenantNormalizer TenantNormalizer { get; } + + public TenantManager(ITenantRepository tenantRepository, IDistributedCache cache, ITenantNormalizer tenantNormalizer) { TenantRepository = tenantRepository; Cache = cache; + TenantNormalizer = tenantNormalizer; } public virtual async Task CreateAsync(string name) { Check.NotNull(name, nameof(name)); - await ValidateNameAsync(name); - return new Tenant(GuidGenerator.Create(), name); + var normalizedTenantName = TenantNormalizer.NormalizeName(name); + await ValidateNameAsync(normalizedTenantName); + return new Tenant(GuidGenerator.Create(), name, normalizedTenantName); } public virtual async Task ChangeNameAsync(Tenant tenant, string name) @@ -31,17 +34,20 @@ public class TenantManager : DomainService, ITenantManager Check.NotNull(tenant, nameof(tenant)); Check.NotNull(name, nameof(name)); - await ValidateNameAsync(name, tenant.Id); - await Cache.RemoveAsync(TenantConfigurationCacheItem.CalculateCacheKey(tenant.Name)); + var normalizedTenantName = TenantNormalizer.NormalizeName(name); + + await ValidateNameAsync(normalizedTenantName, tenant.Id); + await Cache.RemoveAsync(TenantConfigurationCacheItem.CalculateCacheKey(tenant.NormalizedName)); tenant.SetName(name); + tenant.SetNormalizedTenantName(normalizedTenantName); } - protected virtual async Task ValidateNameAsync(string name, Guid? expectedId = null) + protected virtual async Task ValidateNameAsync(string normalizeName, Guid? expectedId = null) { - var tenant = await TenantRepository.FindByNameAsync(name); + var tenant = await TenantRepository.FindByNameAsync(normalizeName); if (tenant != null && tenant.Id != expectedId) { - throw new BusinessException("Volo.Abp.TenantManagement:DuplicateTenantName").WithData("Name", name); + throw new BusinessException("Volo.Abp.TenantManagement:DuplicateTenantName").WithData("Name", normalizeName); } } } diff --git a/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/TenantStore.cs b/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/TenantStore.cs index 5fd23add6b..f2ef1ed066 100644 --- a/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/TenantStore.cs +++ b/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/TenantStore.cs @@ -27,9 +27,9 @@ public class TenantStore : ITenantStore, ITransientDependency Cache = cache; } - public virtual async Task FindAsync(string name) + public virtual async Task FindAsync(string normalizedName) { - return (await GetCacheItemAsync(null, name)).Value; + return (await GetCacheItemAsync(null, normalizedName)).Value; } public virtual async Task FindAsync(Guid id) @@ -38,9 +38,9 @@ public class TenantStore : ITenantStore, ITransientDependency } [Obsolete("Use FindAsync method.")] - public virtual TenantConfiguration Find(string name) + public virtual TenantConfiguration Find(string normalizedName) { - return (GetCacheItem(null, name)).Value; + return (GetCacheItem(null, normalizedName)).Value; } [Obsolete("Use FindAsync method.")] @@ -49,9 +49,9 @@ public class TenantStore : ITenantStore, ITransientDependency return (GetCacheItem(id, null)).Value; } - protected virtual async Task GetCacheItemAsync(Guid? id, string name) + protected virtual async Task GetCacheItemAsync(Guid? id, string normalizedName) { - var cacheKey = CalculateCacheKey(id, name); + var cacheKey = CalculateCacheKey(id, normalizedName); var cacheItem = await Cache.GetAsync(cacheKey, considerUow: true); if (cacheItem != null) @@ -68,11 +68,11 @@ public class TenantStore : ITenantStore, ITransientDependency } } - if (!name.IsNullOrWhiteSpace()) + if (!normalizedName.IsNullOrWhiteSpace()) { using (CurrentTenant.Change(null)) //TODO: No need this if we can implement to define host side (or tenant-independent) entities! { - var tenant = await TenantRepository.FindByNameAsync(name); + var tenant = await TenantRepository.FindByNameAsync(normalizedName); return await SetCacheAsync(cacheKey, tenant); } } @@ -89,9 +89,9 @@ public class TenantStore : ITenantStore, ITransientDependency } [Obsolete("Use GetCacheItemAsync method.")] - protected virtual TenantConfigurationCacheItem GetCacheItem(Guid? id, string name) + protected virtual TenantConfigurationCacheItem GetCacheItem(Guid? id, string normalizedName) { - var cacheKey = CalculateCacheKey(id, name); + var cacheKey = CalculateCacheKey(id, normalizedName); var cacheItem = Cache.Get(cacheKey, considerUow: true); if (cacheItem != null) @@ -108,11 +108,11 @@ public class TenantStore : ITenantStore, ITransientDependency } } - if (!name.IsNullOrWhiteSpace()) + if (!normalizedName.IsNullOrWhiteSpace()) { using (CurrentTenant.Change(null)) //TODO: No need this if we can implement to define host side (or tenant-independent) entities! { - var tenant = TenantRepository.FindByName(name); + var tenant = TenantRepository.FindByName(normalizedName); return SetCache(cacheKey, tenant); } } @@ -129,8 +129,8 @@ public class TenantStore : ITenantStore, ITransientDependency return cacheItem; } - protected virtual string CalculateCacheKey(Guid? id, string name) + protected virtual string CalculateCacheKey(Guid? id, string normalizedName) { - return TenantConfigurationCacheItem.CalculateCacheKey(id, name); + return TenantConfigurationCacheItem.CalculateCacheKey(id, normalizedName); } } diff --git a/modules/tenant-management/src/Volo.Abp.TenantManagement.EntityFrameworkCore/Volo/Abp/TenantManagement/EntityFrameworkCore/AbpTenantManagementDbContextModelCreatingExtensions.cs b/modules/tenant-management/src/Volo.Abp.TenantManagement.EntityFrameworkCore/Volo/Abp/TenantManagement/EntityFrameworkCore/AbpTenantManagementDbContextModelCreatingExtensions.cs index 6b1d7f7e8e..bb189e72a1 100644 --- a/modules/tenant-management/src/Volo.Abp.TenantManagement.EntityFrameworkCore/Volo/Abp/TenantManagement/EntityFrameworkCore/AbpTenantManagementDbContextModelCreatingExtensions.cs +++ b/modules/tenant-management/src/Volo.Abp.TenantManagement.EntityFrameworkCore/Volo/Abp/TenantManagement/EntityFrameworkCore/AbpTenantManagementDbContextModelCreatingExtensions.cs @@ -23,6 +23,7 @@ public static class AbpTenantManagementDbContextModelCreatingExtensions b.ConfigureByConvention(); b.Property(t => t.Name).IsRequired().HasMaxLength(TenantConsts.MaxNameLength); + b.Property(t => t.NormalizedName).IsRequired().HasMaxLength(TenantConsts.MaxNameLength); b.HasMany(u => u.ConnectionStrings).WithOne().HasForeignKey(uc => uc.TenantId).IsRequired(); diff --git a/modules/tenant-management/src/Volo.Abp.TenantManagement.EntityFrameworkCore/Volo/Abp/TenantManagement/EntityFrameworkCore/EfCoreTenantRepository.cs b/modules/tenant-management/src/Volo.Abp.TenantManagement.EntityFrameworkCore/Volo/Abp/TenantManagement/EntityFrameworkCore/EfCoreTenantRepository.cs index 34d350d242..e58512dc13 100644 --- a/modules/tenant-management/src/Volo.Abp.TenantManagement.EntityFrameworkCore/Volo/Abp/TenantManagement/EntityFrameworkCore/EfCoreTenantRepository.cs +++ b/modules/tenant-management/src/Volo.Abp.TenantManagement.EntityFrameworkCore/Volo/Abp/TenantManagement/EntityFrameworkCore/EfCoreTenantRepository.cs @@ -19,23 +19,23 @@ public class EfCoreTenantRepository : EfCoreRepository FindByNameAsync( - string name, + string normalizedName, bool includeDetails = true, CancellationToken cancellationToken = default) { return await (await GetDbSetAsync()) .IncludeDetails(includeDetails) .OrderBy(t => t.Id) - .FirstOrDefaultAsync(t => t.Name == name, GetCancellationToken(cancellationToken)); + .FirstOrDefaultAsync(t => t.NormalizedName == normalizedName, GetCancellationToken(cancellationToken)); } [Obsolete("Use FindByNameAsync method.")] - public virtual Tenant FindByName(string name, bool includeDetails = true) + public virtual Tenant FindByName(string normalizedName, bool includeDetails = true) { return DbSet .IncludeDetails(includeDetails) .OrderBy(t => t.Id) - .FirstOrDefault(t => t.Name == name); + .FirstOrDefault(t => t.NormalizedName == normalizedName); } [Obsolete("Use FindAsync method.")] diff --git a/modules/tenant-management/src/Volo.Abp.TenantManagement.MongoDB/Volo/Abp/TenantManagement/MongoDb/MongoTenantRepository.cs b/modules/tenant-management/src/Volo.Abp.TenantManagement.MongoDB/Volo/Abp/TenantManagement/MongoDb/MongoTenantRepository.cs index 321dcf365f..049dc5e57c 100644 --- a/modules/tenant-management/src/Volo.Abp.TenantManagement.MongoDB/Volo/Abp/TenantManagement/MongoDb/MongoTenantRepository.cs +++ b/modules/tenant-management/src/Volo.Abp.TenantManagement.MongoDB/Volo/Abp/TenantManagement/MongoDb/MongoTenantRepository.cs @@ -20,19 +20,19 @@ public class MongoTenantRepository : MongoDbRepository FindByNameAsync( - string name, + string normalizedName, bool includeDetails = true, CancellationToken cancellationToken = default) { return await (await GetMongoQueryableAsync(cancellationToken)) - .FirstOrDefaultAsync(t => t.Name == name, GetCancellationToken(cancellationToken)); + .FirstOrDefaultAsync(t => t.NormalizedName == normalizedName, GetCancellationToken(cancellationToken)); } [Obsolete("Use FindByNameAsync method.")] - public virtual Tenant FindByName(string name, bool includeDetails = true) + public virtual Tenant FindByName(string normalizedName, bool includeDetails = true) { return GetMongoQueryable() - .FirstOrDefault(t => t.Name == name); + .FirstOrDefault(t => t.NormalizedName == normalizedName); } [Obsolete("Use FindAsync method.")] diff --git a/modules/tenant-management/test/Volo.Abp.TenantManagement.Domain.Tests/Volo/Abp/TenantManagement/TenantCacheItemInvalidator_Tests.cs b/modules/tenant-management/test/Volo.Abp.TenantManagement.Domain.Tests/Volo/Abp/TenantManagement/TenantCacheItemInvalidator_Tests.cs index 9671402560..2dc844d71e 100644 --- a/modules/tenant-management/test/Volo.Abp.TenantManagement.Domain.Tests/Volo/Abp/TenantManagement/TenantCacheItemInvalidator_Tests.cs +++ b/modules/tenant-management/test/Volo.Abp.TenantManagement.Domain.Tests/Volo/Abp/TenantManagement/TenantCacheItemInvalidator_Tests.cs @@ -12,6 +12,7 @@ public class TenantConfigurationCacheItemInvalidator_Tests : AbpTenantManagement private readonly ITenantStore _tenantStore; private readonly ITenantRepository _tenantRepository; private readonly ITenantManager _tenantManager; + private readonly ITenantNormalizer _tenantNormalizer; public TenantConfigurationCacheItemInvalidator_Tests() { @@ -19,86 +20,87 @@ public class TenantConfigurationCacheItemInvalidator_Tests : AbpTenantManagement _tenantStore = GetRequiredService(); _tenantRepository = GetRequiredService(); _tenantManager = GetRequiredService(); + _tenantNormalizer = GetRequiredService(); } [Fact] public async Task Get_Tenant_Should_Cached() { - var acme = await _tenantRepository.FindByNameAsync("acme"); + var acme = await _tenantRepository.FindByNameAsync(_tenantNormalizer.NormalizeName("acme")); acme.ShouldNotBeNull(); (await _cache.GetAsync(TenantConfigurationCacheItem.CalculateCacheKey(acme.Id, null))).ShouldBeNull(); - (await _cache.GetAsync(TenantConfigurationCacheItem.CalculateCacheKey(null, acme.Name))).ShouldBeNull(); + (await _cache.GetAsync(TenantConfigurationCacheItem.CalculateCacheKey(null, acme.NormalizedName))).ShouldBeNull(); await _tenantStore.FindAsync(acme.Id); (await _cache.GetAsync(TenantConfigurationCacheItem.CalculateCacheKey(acme.Id, null))).ShouldNotBeNull(); - await _tenantStore.FindAsync(acme.Name); - (await _cache.GetAsync(TenantConfigurationCacheItem.CalculateCacheKey(null, acme.Name))).ShouldNotBeNull(); + await _tenantStore.FindAsync(acme.NormalizedName); + (await _cache.GetAsync(TenantConfigurationCacheItem.CalculateCacheKey(null, acme.NormalizedName))).ShouldNotBeNull(); - var volosoft = _tenantRepository.FindByName("volosoft"); + var volosoft = _tenantRepository.FindByName(_tenantNormalizer.NormalizeName("volosoft")); volosoft.ShouldNotBeNull(); (_cache.Get(TenantConfigurationCacheItem.CalculateCacheKey(volosoft.Id, null))).ShouldBeNull(); - (_cache.Get(TenantConfigurationCacheItem.CalculateCacheKey(null, volosoft.Name))).ShouldBeNull(); + (_cache.Get(TenantConfigurationCacheItem.CalculateCacheKey(null, volosoft.NormalizedName))).ShouldBeNull(); _tenantStore.Find(volosoft.Id); (_cache.Get(TenantConfigurationCacheItem.CalculateCacheKey(volosoft.Id, null))).ShouldNotBeNull(); - _tenantStore.Find(volosoft.Name); - (_cache.Get(TenantConfigurationCacheItem.CalculateCacheKey(null, volosoft.Name))).ShouldNotBeNull(); + _tenantStore.Find(volosoft.NormalizedName); + (_cache.Get(TenantConfigurationCacheItem.CalculateCacheKey(null, volosoft.NormalizedName))).ShouldNotBeNull(); } [Fact] public async Task Cache_Should_Invalidator_When_Tenant_Changed() { - var acme = await _tenantRepository.FindByNameAsync("acme"); + var acme = await _tenantRepository.FindByNameAsync(_tenantNormalizer.NormalizeName("acme")); acme.ShouldNotBeNull(); // FindAsync will cache tenant. await _tenantStore.FindAsync(acme.Id); - await _tenantStore.FindAsync(acme.Name); + await _tenantStore.FindAsync(acme.NormalizedName); (await _cache.GetAsync(TenantConfigurationCacheItem.CalculateCacheKey(acme.Id, null))).ShouldNotBeNull(); - (await _cache.GetAsync(TenantConfigurationCacheItem.CalculateCacheKey(null, acme.Name))).ShouldNotBeNull(); + (await _cache.GetAsync(TenantConfigurationCacheItem.CalculateCacheKey(null, acme.NormalizedName))).ShouldNotBeNull(); await _tenantRepository.DeleteAsync(acme); (await _cache.GetAsync(TenantConfigurationCacheItem.CalculateCacheKey(acme.Id, null))).ShouldBeNull(); - (await _cache.GetAsync(TenantConfigurationCacheItem.CalculateCacheKey(null, acme.Name))).ShouldBeNull(); + (await _cache.GetAsync(TenantConfigurationCacheItem.CalculateCacheKey(null, acme.NormalizedName))).ShouldBeNull(); - var volosoft = await _tenantRepository.FindByNameAsync("volosoft"); + var volosoft = await _tenantRepository.FindByNameAsync(_tenantNormalizer.NormalizeName("volosoft")); volosoft.ShouldNotBeNull(); // Find will cache tenant. _tenantStore.Find(volosoft.Id); - _tenantStore.Find(volosoft.Name); + _tenantStore.Find(volosoft.NormalizedName); (_cache.Get(TenantConfigurationCacheItem.CalculateCacheKey(volosoft.Id, null))).ShouldNotBeNull(); - (_cache.Get(TenantConfigurationCacheItem.CalculateCacheKey(null, volosoft.Name))).ShouldNotBeNull(); + (_cache.Get(TenantConfigurationCacheItem.CalculateCacheKey(null, volosoft.NormalizedName))).ShouldNotBeNull(); await _tenantRepository.DeleteAsync(volosoft); (_cache.Get(TenantConfigurationCacheItem.CalculateCacheKey(volosoft.Id, null))).ShouldBeNull(); - (_cache.Get(TenantConfigurationCacheItem.CalculateCacheKey(null, volosoft.Name))).ShouldBeNull(); + (_cache.Get(TenantConfigurationCacheItem.CalculateCacheKey(null, volosoft.NormalizedName))).ShouldBeNull(); - var abp = await _tenantRepository.FindByNameAsync("abp"); + var abp = await _tenantRepository.FindByNameAsync(_tenantNormalizer.NormalizeName("abp")); abp.ShouldNotBeNull(); // Find will cache tenant. await _tenantStore.FindAsync(abp.Id); - await _tenantStore.FindAsync(abp.Name); + await _tenantStore.FindAsync(abp.NormalizedName); (await _cache.GetAsync(TenantConfigurationCacheItem.CalculateCacheKey(abp.Id, null))).ShouldNotBeNull(); - (await _cache.GetAsync(TenantConfigurationCacheItem.CalculateCacheKey(null, abp.Name))).ShouldNotBeNull(); + (await _cache.GetAsync(TenantConfigurationCacheItem.CalculateCacheKey(null, abp.NormalizedName))).ShouldNotBeNull(); await _tenantManager.ChangeNameAsync(abp, "abp2"); await _tenantRepository.UpdateAsync(abp); (await _cache.GetAsync(TenantConfigurationCacheItem.CalculateCacheKey(abp.Id, null))).ShouldBeNull(); - (await _cache.GetAsync(TenantConfigurationCacheItem.CalculateCacheKey(null, "abp"))).ShouldBeNull(); - (await _cache.GetAsync(TenantConfigurationCacheItem.CalculateCacheKey(null, "abp2"))).ShouldBeNull(); + (await _cache.GetAsync(TenantConfigurationCacheItem.CalculateCacheKey(null, _tenantNormalizer.NormalizeName("abp")))).ShouldBeNull(); + (await _cache.GetAsync(TenantConfigurationCacheItem.CalculateCacheKey(null, _tenantNormalizer.NormalizeName("abp2")))).ShouldBeNull(); } } diff --git a/modules/tenant-management/test/Volo.Abp.TenantManagement.Domain.Tests/Volo/Abp/TenantManagement/TenantManager_Tests.cs b/modules/tenant-management/test/Volo.Abp.TenantManagement.Domain.Tests/Volo/Abp/TenantManagement/TenantManager_Tests.cs index 161882e412..f46bcf8573 100644 --- a/modules/tenant-management/test/Volo.Abp.TenantManagement.Domain.Tests/Volo/Abp/TenantManagement/TenantManager_Tests.cs +++ b/modules/tenant-management/test/Volo.Abp.TenantManagement.Domain.Tests/Volo/Abp/TenantManagement/TenantManager_Tests.cs @@ -1,5 +1,6 @@ using System.Threading.Tasks; using Shouldly; +using Volo.Abp.MultiTenancy; using Xunit; namespace Volo.Abp.TenantManagement; @@ -8,19 +9,21 @@ public class TenantManager_Tests : AbpTenantManagementDomainTestBase { private readonly ITenantManager _tenantManager; private readonly ITenantRepository _tenantRepository; + private readonly ITenantNormalizer _tenantNormalizer; public TenantManager_Tests() { _tenantManager = GetRequiredService(); _tenantRepository = GetRequiredService(); + _tenantNormalizer = GetRequiredService(); } - [Fact] public async Task CreateAsync() { var tenant = await _tenantManager.CreateAsync("Test"); tenant.Name.ShouldBe("Test"); + tenant.NormalizedName.ShouldBe(_tenantNormalizer.NormalizeName("Test")); } [Fact] @@ -32,18 +35,20 @@ public class TenantManager_Tests : AbpTenantManagementDomainTestBase [Fact] public async Task ChangeNameAsync() { - var tenant = await _tenantRepository.FindByNameAsync("volosoft"); + var tenant = await _tenantRepository.FindByNameAsync(_tenantNormalizer.NormalizeName("volosoft")); tenant.ShouldNotBeNull(); + tenant.NormalizedName.ShouldBe(_tenantNormalizer.NormalizeName("volosoft")); await _tenantManager.ChangeNameAsync(tenant, "newVolosoft"); tenant.Name.ShouldBe("newVolosoft"); + tenant.NormalizedName.ShouldBe(_tenantNormalizer.NormalizeName("newVolosoft")); } [Fact] public async Task ChangeName_Tenant_Name_Can_Not_Duplicate() { - var tenant = await _tenantRepository.FindByNameAsync("acme"); + var tenant = await _tenantRepository.FindByNameAsync(_tenantNormalizer.NormalizeName("acme")); tenant.ShouldNotBeNull(); await Assert.ThrowsAsync(async () => await _tenantManager.ChangeNameAsync(tenant, "volosoft")); diff --git a/modules/tenant-management/test/Volo.Abp.TenantManagement.Domain.Tests/Volo/Abp/TenantManagement/TenantStore_Tests.cs b/modules/tenant-management/test/Volo.Abp.TenantManagement.Domain.Tests/Volo/Abp/TenantManagement/TenantStore_Tests.cs index 1af4ebd1ea..10f203eb43 100644 --- a/modules/tenant-management/test/Volo.Abp.TenantManagement.Domain.Tests/Volo/Abp/TenantManagement/TenantStore_Tests.cs +++ b/modules/tenant-management/test/Volo.Abp.TenantManagement.Domain.Tests/Volo/Abp/TenantManagement/TenantStore_Tests.cs @@ -9,25 +9,28 @@ public class TenantStore_Tests : AbpTenantManagementDomainTestBase { private readonly ITenantStore _tenantStore; private readonly ITenantRepository _tenantRepository; + private readonly ITenantNormalizer _tenantNormalizer; public TenantStore_Tests() { _tenantStore = GetRequiredService(); _tenantRepository = GetRequiredService(); + _tenantNormalizer = GetRequiredService(); } [Fact] public async Task FindAsyncByName() { - var acme = await _tenantStore.FindAsync("acme"); + var acme = await _tenantStore.FindAsync(_tenantNormalizer.NormalizeName("acme")!); acme.ShouldNotBeNull(); acme.Name.ShouldBe("acme"); + acme.NormalizedName.ShouldBe(_tenantNormalizer.NormalizeName("acme")!); } [Fact] public async Task FindAsyncById() { - var acme = await _tenantRepository.FindByNameAsync("acme"); + var acme = await _tenantRepository.FindByNameAsync(_tenantNormalizer.NormalizeName("acme")); acme.ShouldNotBeNull(); (await _tenantStore.FindAsync(acme.Id)).ShouldNotBeNull(); diff --git a/modules/tenant-management/test/Volo.Abp.TenantManagement.Domain.Tests/Volo/Abp/TenantManagement/Tenant_Tests.cs b/modules/tenant-management/test/Volo.Abp.TenantManagement.Domain.Tests/Volo/Abp/TenantManagement/Tenant_Tests.cs index dbe631d431..bcefc527e6 100644 --- a/modules/tenant-management/test/Volo.Abp.TenantManagement.Domain.Tests/Volo/Abp/TenantManagement/Tenant_Tests.cs +++ b/modules/tenant-management/test/Volo.Abp.TenantManagement.Domain.Tests/Volo/Abp/TenantManagement/Tenant_Tests.cs @@ -1,5 +1,6 @@ using System.Threading.Tasks; using Shouldly; +using Volo.Abp.MultiTenancy; using Xunit; namespace Volo.Abp.TenantManagement; @@ -7,16 +8,18 @@ namespace Volo.Abp.TenantManagement; public class Tenant_Tests : AbpTenantManagementDomainTestBase { private readonly ITenantRepository _tenantRepository; + private readonly ITenantNormalizer _tenantNormalizer; public Tenant_Tests() { _tenantRepository = GetRequiredService(); + _tenantNormalizer = GetRequiredService(); } [Fact] public async Task FindDefaultConnectionString() { - var acme = await _tenantRepository.FindByNameAsync("acme"); + var acme = await _tenantRepository.FindByNameAsync(_tenantNormalizer.NormalizeName("acme")); acme.ShouldNotBeNull(); acme.FindDefaultConnectionString().ShouldBe("DefaultConnString-Value"); @@ -25,7 +28,7 @@ public class Tenant_Tests : AbpTenantManagementDomainTestBase [Fact] public async Task FindConnectionString() { - var acme = await _tenantRepository.FindByNameAsync("acme"); + var acme = await _tenantRepository.FindByNameAsync(_tenantNormalizer.NormalizeName("acme")); acme.ShouldNotBeNull(); acme.FindConnectionString(Data.ConnectionStrings.DefaultConnectionStringName).ShouldBe("DefaultConnString-Value"); diff --git a/modules/tenant-management/test/Volo.Abp.TenantManagement.TestBase/Volo/Abp/TenantManagement/LazyLoad_Tests.cs b/modules/tenant-management/test/Volo.Abp.TenantManagement.TestBase/Volo/Abp/TenantManagement/LazyLoad_Tests.cs index 049d93cf65..9fe123d73b 100644 --- a/modules/tenant-management/test/Volo.Abp.TenantManagement.TestBase/Volo/Abp/TenantManagement/LazyLoad_Tests.cs +++ b/modules/tenant-management/test/Volo.Abp.TenantManagement.TestBase/Volo/Abp/TenantManagement/LazyLoad_Tests.cs @@ -2,6 +2,7 @@ using System.Threading.Tasks; using Shouldly; using Volo.Abp.Modularity; +using Volo.Abp.MultiTenancy; using Volo.Abp.Uow; using Xunit; @@ -11,10 +12,12 @@ public abstract class LazyLoad_Tests : TenantManagementTestBase< where TStartupModule : IAbpModule { public ITenantRepository TenantRepository { get; } + public ITenantNormalizer TenantNormalizer { get; } protected LazyLoad_Tests() { TenantRepository = GetRequiredService(); + TenantNormalizer = GetRequiredService(); } [Fact] @@ -22,7 +25,7 @@ public abstract class LazyLoad_Tests : TenantManagementTestBase< { using (var uow = GetRequiredService().Begin()) { - var role = await TenantRepository.FindByNameAsync("acme", includeDetails: false); + var role = await TenantRepository.FindByNameAsync(TenantNormalizer.NormalizeName("acme"), includeDetails: false); role.ConnectionStrings.ShouldNotBeNull(); role.ConnectionStrings.Any().ShouldBeTrue(); diff --git a/modules/tenant-management/test/Volo.Abp.TenantManagement.TestBase/Volo/Abp/TenantManagement/TenantRepository_Tests.cs b/modules/tenant-management/test/Volo.Abp.TenantManagement.TestBase/Volo/Abp/TenantManagement/TenantRepository_Tests.cs index c8ff94d069..6e4c3c8db5 100644 --- a/modules/tenant-management/test/Volo.Abp.TenantManagement.TestBase/Volo/Abp/TenantManagement/TenantRepository_Tests.cs +++ b/modules/tenant-management/test/Volo.Abp.TenantManagement.TestBase/Volo/Abp/TenantManagement/TenantRepository_Tests.cs @@ -3,6 +3,7 @@ using System.Linq; using System.Threading.Tasks; using Shouldly; using Volo.Abp.Modularity; +using Volo.Abp.MultiTenancy; using Xunit; namespace Volo.Abp.TenantManagement; @@ -11,22 +12,24 @@ public abstract class TenantRepository_Tests : TenantManagementT where TStartupModule : IAbpModule { public ITenantRepository TenantRepository { get; } + public ITenantNormalizer TenantNormalizer { get; } protected TenantRepository_Tests() { TenantRepository = GetRequiredService(); + TenantNormalizer = GetRequiredService(); } [Fact] public async Task FindByNameAsync() { - var tenant = await TenantRepository.FindByNameAsync("acme"); + var tenant = await TenantRepository.FindByNameAsync(TenantNormalizer.NormalizeName("acme")); tenant.ShouldNotBeNull(); - tenant = await TenantRepository.FindByNameAsync("undefined-tenant"); + tenant = await TenantRepository.FindByNameAsync(TenantNormalizer.NormalizeName("undefined-tenant")); tenant.ShouldBeNull(); - tenant = await TenantRepository.FindByNameAsync("acme", includeDetails: true); + tenant = await TenantRepository.FindByNameAsync(TenantNormalizer.NormalizeName("acme"), includeDetails: true); tenant.ShouldNotBeNull(); tenant.ConnectionStrings.Count.ShouldBeGreaterThanOrEqualTo(2); } @@ -34,7 +37,7 @@ public abstract class TenantRepository_Tests : TenantManagementT [Fact] public async Task FindAsync() { - var tenantId = (await TenantRepository.FindByNameAsync("acme")).Id; + var tenantId = (await TenantRepository.FindByNameAsync(TenantNormalizer.NormalizeName("acme"))).Id; var tenant = await TenantRepository.FindAsync(tenantId); tenant.ShouldNotBeNull(); @@ -51,14 +54,14 @@ public abstract class TenantRepository_Tests : TenantManagementT public async Task GetListAsync() { var tenants = await TenantRepository.GetListAsync(); - tenants.ShouldContain(t => t.Name == "acme"); - tenants.ShouldContain(t => t.Name == "volosoft"); + tenants.ShouldContain(t => t.Name == "acme" && t.NormalizedName == TenantNormalizer.NormalizeName("acme")); + tenants.ShouldContain(t => t.Name == "volosoft" && t.NormalizedName == TenantNormalizer.NormalizeName("volosoft")); } [Fact] public async Task Should_Eager_Load_Tenant_Collections() { - var role = await TenantRepository.FindByNameAsync("acme"); + var role = await TenantRepository.FindByNameAsync(TenantNormalizer.NormalizeName("acme")); role.ConnectionStrings.ShouldNotBeNull(); role.ConnectionStrings.Any().ShouldBeTrue(); } From ecc0562c7c5d649f3c70ca7acdbf9d1eac7f6ced Mon Sep 17 00:00:00 2001 From: maliming Date: Mon, 11 Dec 2023 15:08:13 +0800 Subject: [PATCH 02/98] Rename `NormalizedTenantName` to `NormalizedName`. --- .../MauiBlazor/MauiBlazorRemoteTenantStore.cs | 6 +++--- .../Volo/Abp/TenantManagement/Tenant.cs | 8 ++++---- .../Volo/Abp/TenantManagement/TenantManager.cs | 13 ++++++------- .../Volo/Abp/TenantManagement/TenantStore.cs | 4 ++-- 4 files changed, 15 insertions(+), 16 deletions(-) diff --git a/framework/src/Volo.Abp.AspNetCore.Components.MauiBlazor/Volo/Abp/AspNetCore/Components/MauiBlazor/MauiBlazorRemoteTenantStore.cs b/framework/src/Volo.Abp.AspNetCore.Components.MauiBlazor/Volo/Abp/AspNetCore/Components/MauiBlazor/MauiBlazorRemoteTenantStore.cs index d06eb60566..3873b48db3 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.MauiBlazor/Volo/Abp/AspNetCore/Components/MauiBlazor/MauiBlazorRemoteTenantStore.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components.MauiBlazor/Volo/Abp/AspNetCore/Components/MauiBlazor/MauiBlazorRemoteTenantStore.cs @@ -98,12 +98,12 @@ public class MauiBlazorRemoteTenantStore : ITenantStore, ITransientDependency return null; } - return new TenantConfiguration(tenantResultDto.TenantId.Value, tenantResultDto.Name!); + return new TenantConfiguration(tenantResultDto.TenantId.Value, tenantResultDto.Name!, tenantResultDto.NormalizedName!); } - protected virtual string CreateCacheKey(string tenantName) + protected virtual string CreateCacheKey(string normalizedName) { - return $"RemoteTenantStore_Name_{tenantName}"; + return $"RemoteTenantStore_Name_{normalizedName}"; } protected virtual string CreateCacheKey(Guid tenantId) diff --git a/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/Tenant.cs b/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/Tenant.cs index 6567cf8efd..c6c5c3edee 100644 --- a/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/Tenant.cs +++ b/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/Tenant.cs @@ -22,11 +22,11 @@ public class Tenant : FullAuditedAggregateRoot, IHasEntityVersion } - protected internal Tenant(Guid id, [NotNull] string name, [CanBeNull] string normalizedTenantName) + protected internal Tenant(Guid id, [NotNull] string name, [CanBeNull] string normalizedName) : base(id) { SetName(name); - SetNormalizedTenantName(normalizedTenantName); + SetNormalizedName(normalizedName); ConnectionStrings = new List(); } @@ -82,8 +82,8 @@ public class Tenant : FullAuditedAggregateRoot, IHasEntityVersion Name = Check.NotNullOrWhiteSpace(name, nameof(name), TenantConsts.MaxNameLength); } - protected internal virtual void SetNormalizedTenantName([CanBeNull] string normalizedTenantName) + protected internal virtual void SetNormalizedName([CanBeNull] string normalizedName) { - NormalizedName = normalizedTenantName; + NormalizedName = normalizedName; } } diff --git a/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/TenantManager.cs b/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/TenantManager.cs index 43594dfde7..648e02d381 100644 --- a/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/TenantManager.cs +++ b/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/TenantManager.cs @@ -10,7 +10,6 @@ public class TenantManager : DomainService, ITenantManager { protected ITenantRepository TenantRepository { get; } protected IDistributedCache Cache { get; } - protected ITenantNormalizer TenantNormalizer { get; } public TenantManager(ITenantRepository tenantRepository, IDistributedCache cache, ITenantNormalizer tenantNormalizer) @@ -24,9 +23,9 @@ public class TenantManager : DomainService, ITenantManager { Check.NotNull(name, nameof(name)); - var normalizedTenantName = TenantNormalizer.NormalizeName(name); - await ValidateNameAsync(normalizedTenantName); - return new Tenant(GuidGenerator.Create(), name, normalizedTenantName); + var normalizedName = TenantNormalizer.NormalizeName(name); + await ValidateNameAsync(normalizedName); + return new Tenant(GuidGenerator.Create(), name, normalizedName); } public virtual async Task ChangeNameAsync(Tenant tenant, string name) @@ -34,12 +33,12 @@ public class TenantManager : DomainService, ITenantManager Check.NotNull(tenant, nameof(tenant)); Check.NotNull(name, nameof(name)); - var normalizedTenantName = TenantNormalizer.NormalizeName(name); + var normalizedName = TenantNormalizer.NormalizeName(name); - await ValidateNameAsync(normalizedTenantName, tenant.Id); + await ValidateNameAsync(normalizedName, tenant.Id); await Cache.RemoveAsync(TenantConfigurationCacheItem.CalculateCacheKey(tenant.NormalizedName)); tenant.SetName(name); - tenant.SetNormalizedTenantName(normalizedTenantName); + tenant.SetNormalizedName(normalizedName); } protected virtual async Task ValidateNameAsync(string normalizeName, Guid? expectedId = null) diff --git a/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/TenantStore.cs b/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/TenantStore.cs index f2ef1ed066..d334c124a6 100644 --- a/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/TenantStore.cs +++ b/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/TenantStore.cs @@ -77,7 +77,7 @@ public class TenantStore : ITenantStore, ITransientDependency } } - throw new AbpException("Both id and name can't be invalid."); + throw new AbpException("Both id and normalizedName can't be invalid."); } protected virtual async Task SetCacheAsync(string cacheKey, [CanBeNull] Tenant tenant) @@ -117,7 +117,7 @@ public class TenantStore : ITenantStore, ITransientDependency } } - throw new AbpException("Both id and name can't be invalid."); + throw new AbpException("Both id and normalizedName can't be invalid."); } [Obsolete("Use SetCacheAsync method.")] From 8810906cdcb2132fbc8df81a9d2894270e29c79c Mon Sep 17 00:00:00 2001 From: maliming Date: Wed, 20 Dec 2023 10:09:16 +0800 Subject: [PATCH 03/98] Update the migrations for template projects. --- ...tial.Designer.cs => 20231220020330_Initial.Designer.cs} | 7 ++++++- ...20231207053812_Initial.cs => 20231220020330_Initial.cs} | 1 + .../Migrations/MyProjectNameDbContextModelSnapshot.cs | 5 +++++ ...tial.Designer.cs => 20231220020415_Initial.Designer.cs} | 7 ++++++- .../Server/Migrations/20231220020415_Initial.cs} | 1 + .../Migrations/MyProjectNameDbContextModelSnapshot.cs | 5 +++++ ...tial.Designer.cs => 20231220020502_Initial.Designer.cs} | 7 ++++++- ...20231207053820_Initial.cs => 20231220020502_Initial.cs} | 1 + .../Migrations/MyProjectNameDbContextModelSnapshot.cs | 5 +++++ ...tial.Designer.cs => 20231220020554_Initial.Designer.cs} | 7 ++++++- ...20231207053825_Initial.cs => 20231220020554_Initial.cs} | 1 + .../Migrations/MyProjectNameDbContextModelSnapshot.cs | 5 +++++ ...tial.Designer.cs => 20231220020240_Initial.Designer.cs} | 7 ++++++- ...20231207053523_Initial.cs => 20231220020240_Initial.cs} | 1 + .../Migrations/MyProjectNameDbContextModelSnapshot.cs | 5 +++++ ...tial.Designer.cs => 20231220020703_Initial.Designer.cs} | 7 ++++++- .../Migrations/20231220020703_Initial.cs} | 1 + .../Migrations/AuthServerDbContextModelSnapshot.cs | 5 +++++ ...tial.Designer.cs => 20231220020754_Initial.Designer.cs} | 7 ++++++- ...20231115065621_Initial.cs => 20231220020754_Initial.cs} | 1 + .../Migrations/UnifiedDbContextModelSnapshot.cs | 5 +++++ ...tial.Designer.cs => 20231220020817_Initial.Designer.cs} | 7 ++++++- ...20231115065707_Initial.cs => 20231220020817_Initial.cs} | 1 + .../Migrations/UnifiedDbContextModelSnapshot.cs | 5 +++++ 24 files changed, 96 insertions(+), 8 deletions(-) rename templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/{20231207053812_Initial.Designer.cs => 20231220020330_Initial.Designer.cs} (99%) rename templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/{20231207053812_Initial.cs => 20231220020330_Initial.cs} (99%) rename templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/{20231207053830_Initial.Designer.cs => 20231220020415_Initial.Designer.cs} (99%) rename templates/{module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/20231207053828_Initial.cs => app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/20231220020415_Initial.cs} (99%) rename templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/{20231207053820_Initial.Designer.cs => 20231220020502_Initial.Designer.cs} (99%) rename templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/{20231207053820_Initial.cs => 20231220020502_Initial.cs} (99%) rename templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/{20231207053825_Initial.Designer.cs => 20231220020554_Initial.Designer.cs} (99%) rename templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/{20231207053825_Initial.cs => 20231220020554_Initial.cs} (99%) rename templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/{20231207053523_Initial.Designer.cs => 20231220020240_Initial.Designer.cs} (99%) rename templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/{20231207053523_Initial.cs => 20231220020240_Initial.cs} (99%) rename templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/{20231207053828_Initial.Designer.cs => 20231220020703_Initial.Designer.cs} (99%) rename templates/{app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/20231207053830_Initial.cs => module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/20231220020703_Initial.cs} (99%) rename templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/{20231115065621_Initial.Designer.cs => 20231220020754_Initial.Designer.cs} (99%) rename templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/{20231115065621_Initial.cs => 20231220020754_Initial.cs} (99%) rename templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/{20231115065707_Initial.Designer.cs => 20231220020817_Initial.Designer.cs} (99%) rename templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/{20231115065707_Initial.cs => 20231220020817_Initial.cs} (99%) diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/20231207053812_Initial.Designer.cs b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/20231220020330_Initial.Designer.cs similarity index 99% rename from templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/20231207053812_Initial.Designer.cs rename to templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/20231220020330_Initial.Designer.cs index 333df53077..b6afd36542 100644 --- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/20231207053812_Initial.Designer.cs +++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/20231220020330_Initial.Designer.cs @@ -13,7 +13,7 @@ using Volo.Abp.EntityFrameworkCore; namespace MyCompanyName.MyProjectName.Blazor.Server.Migrations { [DbContext(typeof(MyProjectNameDbContext))] - [Migration("20231207053812_Initial")] + [Migration("20231220020330_Initial")] partial class Initial { /// @@ -1687,6 +1687,11 @@ namespace MyCompanyName.MyProjectName.Blazor.Server.Migrations .HasMaxLength(64) .HasColumnType("nvarchar(64)"); + b.Property("NormalizedName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + b.HasKey("Id"); b.HasIndex("Name"); diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/20231207053812_Initial.cs b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/20231220020330_Initial.cs similarity index 99% rename from templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/20231207053812_Initial.cs rename to templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/20231220020330_Initial.cs index e993702885..8ce8dba759 100644 --- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/20231207053812_Initial.cs +++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/20231220020330_Initial.cs @@ -296,6 +296,7 @@ namespace MyCompanyName.MyProjectName.Blazor.Server.Migrations { Id = table.Column(type: "uniqueidentifier", nullable: false), Name = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: false), + NormalizedName = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: false), EntityVersion = table.Column(type: "int", nullable: false), ExtraProperties = table.Column(type: "nvarchar(max)", nullable: false), ConcurrencyStamp = table.Column(type: "nvarchar(40)", maxLength: 40, nullable: false), diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/MyProjectNameDbContextModelSnapshot.cs b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/MyProjectNameDbContextModelSnapshot.cs index 1def4a0ee9..d65c2397b7 100644 --- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/MyProjectNameDbContextModelSnapshot.cs +++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/MyProjectNameDbContextModelSnapshot.cs @@ -1684,6 +1684,11 @@ namespace MyCompanyName.MyProjectName.Blazor.Server.Migrations .HasMaxLength(64) .HasColumnType("nvarchar(64)"); + b.Property("NormalizedName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + b.HasKey("Id"); b.HasIndex("Name"); diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/20231207053830_Initial.Designer.cs b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/20231220020415_Initial.Designer.cs similarity index 99% rename from templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/20231207053830_Initial.Designer.cs rename to templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/20231220020415_Initial.Designer.cs index ac18b045c6..83eb21746a 100644 --- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/20231207053830_Initial.Designer.cs +++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/20231220020415_Initial.Designer.cs @@ -13,7 +13,7 @@ using Volo.Abp.EntityFrameworkCore; namespace MyCompanyName.MyProjectName.Migrations { [DbContext(typeof(MyProjectNameDbContext))] - [Migration("20231207053830_Initial")] + [Migration("20231220020415_Initial")] partial class Initial { /// @@ -1687,6 +1687,11 @@ namespace MyCompanyName.MyProjectName.Migrations .HasMaxLength(64) .HasColumnType("nvarchar(64)"); + b.Property("NormalizedName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + b.HasKey("Id"); b.HasIndex("Name"); diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/20231207053828_Initial.cs b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/20231220020415_Initial.cs similarity index 99% rename from templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/20231207053828_Initial.cs rename to templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/20231220020415_Initial.cs index 7a0019fbf6..da36f3081f 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/20231207053828_Initial.cs +++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/20231220020415_Initial.cs @@ -296,6 +296,7 @@ namespace MyCompanyName.MyProjectName.Migrations { Id = table.Column(type: "uniqueidentifier", nullable: false), Name = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: false), + NormalizedName = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: false), EntityVersion = table.Column(type: "int", nullable: false), ExtraProperties = table.Column(type: "nvarchar(max)", nullable: false), ConcurrencyStamp = table.Column(type: "nvarchar(40)", maxLength: 40, nullable: false), diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/MyProjectNameDbContextModelSnapshot.cs b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/MyProjectNameDbContextModelSnapshot.cs index 20542b282c..3c61917830 100644 --- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/MyProjectNameDbContextModelSnapshot.cs +++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/MyProjectNameDbContextModelSnapshot.cs @@ -1684,6 +1684,11 @@ namespace MyCompanyName.MyProjectName.Migrations .HasMaxLength(64) .HasColumnType("nvarchar(64)"); + b.Property("NormalizedName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + b.HasKey("Id"); b.HasIndex("Name"); diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/20231207053820_Initial.Designer.cs b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/20231220020502_Initial.Designer.cs similarity index 99% rename from templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/20231207053820_Initial.Designer.cs rename to templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/20231220020502_Initial.Designer.cs index 333258a426..249957c93c 100644 --- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/20231207053820_Initial.Designer.cs +++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/20231220020502_Initial.Designer.cs @@ -13,7 +13,7 @@ using Volo.Abp.EntityFrameworkCore; namespace MyCompanyName.MyProjectName.Host.Migrations { [DbContext(typeof(MyProjectNameDbContext))] - [Migration("20231207053820_Initial")] + [Migration("20231220020502_Initial")] partial class Initial { /// @@ -1687,6 +1687,11 @@ namespace MyCompanyName.MyProjectName.Host.Migrations .HasMaxLength(64) .HasColumnType("nvarchar(64)"); + b.Property("NormalizedName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + b.HasKey("Id"); b.HasIndex("Name"); diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/20231207053820_Initial.cs b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/20231220020502_Initial.cs similarity index 99% rename from templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/20231207053820_Initial.cs rename to templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/20231220020502_Initial.cs index 08eca1feca..ace742cda5 100644 --- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/20231207053820_Initial.cs +++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/20231220020502_Initial.cs @@ -296,6 +296,7 @@ namespace MyCompanyName.MyProjectName.Host.Migrations { Id = table.Column(type: "uniqueidentifier", nullable: false), Name = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: false), + NormalizedName = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: false), EntityVersion = table.Column(type: "int", nullable: false), ExtraProperties = table.Column(type: "nvarchar(max)", nullable: false), ConcurrencyStamp = table.Column(type: "nvarchar(40)", maxLength: 40, nullable: false), diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/MyProjectNameDbContextModelSnapshot.cs b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/MyProjectNameDbContextModelSnapshot.cs index 6475d362fa..a972acadeb 100644 --- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/MyProjectNameDbContextModelSnapshot.cs +++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/MyProjectNameDbContextModelSnapshot.cs @@ -1684,6 +1684,11 @@ namespace MyCompanyName.MyProjectName.Host.Migrations .HasMaxLength(64) .HasColumnType("nvarchar(64)"); + b.Property("NormalizedName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + b.HasKey("Id"); b.HasIndex("Name"); diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/20231207053825_Initial.Designer.cs b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/20231220020554_Initial.Designer.cs similarity index 99% rename from templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/20231207053825_Initial.Designer.cs rename to templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/20231220020554_Initial.Designer.cs index 11234086f3..143044a16c 100644 --- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/20231207053825_Initial.Designer.cs +++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/20231220020554_Initial.Designer.cs @@ -13,7 +13,7 @@ using Volo.Abp.EntityFrameworkCore; namespace MyCompanyName.MyProjectName.Mvc.Migrations { [DbContext(typeof(MyProjectNameDbContext))] - [Migration("20231207053825_Initial")] + [Migration("20231220020554_Initial")] partial class Initial { /// @@ -1687,6 +1687,11 @@ namespace MyCompanyName.MyProjectName.Mvc.Migrations .HasMaxLength(64) .HasColumnType("nvarchar(64)"); + b.Property("NormalizedName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + b.HasKey("Id"); b.HasIndex("Name"); diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/20231207053825_Initial.cs b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/20231220020554_Initial.cs similarity index 99% rename from templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/20231207053825_Initial.cs rename to templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/20231220020554_Initial.cs index ef1ec2fdd6..32fb8b2358 100644 --- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/20231207053825_Initial.cs +++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/20231220020554_Initial.cs @@ -296,6 +296,7 @@ namespace MyCompanyName.MyProjectName.Mvc.Migrations { Id = table.Column(type: "uniqueidentifier", nullable: false), Name = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: false), + NormalizedName = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: false), EntityVersion = table.Column(type: "int", nullable: false), ExtraProperties = table.Column(type: "nvarchar(max)", nullable: false), ConcurrencyStamp = table.Column(type: "nvarchar(40)", maxLength: 40, nullable: false), diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/MyProjectNameDbContextModelSnapshot.cs b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/MyProjectNameDbContextModelSnapshot.cs index 1e8916ad04..bab3848fb5 100644 --- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/MyProjectNameDbContextModelSnapshot.cs +++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/MyProjectNameDbContextModelSnapshot.cs @@ -1684,6 +1684,11 @@ namespace MyCompanyName.MyProjectName.Mvc.Migrations .HasMaxLength(64) .HasColumnType("nvarchar(64)"); + b.Property("NormalizedName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + b.HasKey("Id"); b.HasIndex("Name"); diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20231207053523_Initial.Designer.cs b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20231220020240_Initial.Designer.cs similarity index 99% rename from templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20231207053523_Initial.Designer.cs rename to templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20231220020240_Initial.Designer.cs index c52403afd3..cddfa265f4 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20231207053523_Initial.Designer.cs +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20231220020240_Initial.Designer.cs @@ -13,7 +13,7 @@ using Volo.Abp.EntityFrameworkCore; namespace MyCompanyName.MyProjectName.Migrations { [DbContext(typeof(MyProjectNameDbContext))] - [Migration("20231207053523_Initial")] + [Migration("20231220020240_Initial")] partial class Initial { /// @@ -1739,6 +1739,11 @@ namespace MyCompanyName.MyProjectName.Migrations .HasMaxLength(64) .HasColumnType("nvarchar(64)"); + b.Property("NormalizedName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + b.HasKey("Id"); b.HasIndex("Name"); diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20231207053523_Initial.cs b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20231220020240_Initial.cs similarity index 99% rename from templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20231207053523_Initial.cs rename to templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20231220020240_Initial.cs index a5027f58de..6c052b9dea 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20231207053523_Initial.cs +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20231220020240_Initial.cs @@ -317,6 +317,7 @@ namespace MyCompanyName.MyProjectName.Migrations { Id = table.Column(type: "uniqueidentifier", nullable: false), Name = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: false), + NormalizedName = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: false), EntityVersion = table.Column(type: "int", nullable: false), ExtraProperties = table.Column(type: "nvarchar(max)", nullable: false), ConcurrencyStamp = table.Column(type: "nvarchar(40)", maxLength: 40, nullable: false), diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/MyProjectNameDbContextModelSnapshot.cs b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/MyProjectNameDbContextModelSnapshot.cs index 8a0febed15..17dcf3ad28 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/MyProjectNameDbContextModelSnapshot.cs +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/MyProjectNameDbContextModelSnapshot.cs @@ -1736,6 +1736,11 @@ namespace MyCompanyName.MyProjectName.Migrations .HasMaxLength(64) .HasColumnType("nvarchar(64)"); + b.Property("NormalizedName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + b.HasKey("Id"); b.HasIndex("Name"); diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/20231207053828_Initial.Designer.cs b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/20231220020703_Initial.Designer.cs similarity index 99% rename from templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/20231207053828_Initial.Designer.cs rename to templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/20231220020703_Initial.Designer.cs index 389a2a8cc3..5b9f7049d4 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/20231207053828_Initial.Designer.cs +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/20231220020703_Initial.Designer.cs @@ -13,7 +13,7 @@ using Volo.Abp.EntityFrameworkCore; namespace MyCompanyName.MyProjectName.Migrations { [DbContext(typeof(AuthServerDbContext))] - [Migration("20231207053828_Initial")] + [Migration("20231220020703_Initial")] partial class Initial { /// @@ -1687,6 +1687,11 @@ namespace MyCompanyName.MyProjectName.Migrations .HasMaxLength(64) .HasColumnType("nvarchar(64)"); + b.Property("NormalizedName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + b.HasKey("Id"); b.HasIndex("Name"); diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/20231207053830_Initial.cs b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/20231220020703_Initial.cs similarity index 99% rename from templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/20231207053830_Initial.cs rename to templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/20231220020703_Initial.cs index 7a0019fbf6..da36f3081f 100644 --- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/20231207053830_Initial.cs +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/20231220020703_Initial.cs @@ -296,6 +296,7 @@ namespace MyCompanyName.MyProjectName.Migrations { Id = table.Column(type: "uniqueidentifier", nullable: false), Name = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: false), + NormalizedName = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: false), EntityVersion = table.Column(type: "int", nullable: false), ExtraProperties = table.Column(type: "nvarchar(max)", nullable: false), ConcurrencyStamp = table.Column(type: "nvarchar(40)", maxLength: 40, nullable: false), diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/AuthServerDbContextModelSnapshot.cs b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/AuthServerDbContextModelSnapshot.cs index c63e7d13e1..780558fcbc 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/AuthServerDbContextModelSnapshot.cs +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/AuthServerDbContextModelSnapshot.cs @@ -1684,6 +1684,11 @@ namespace MyCompanyName.MyProjectName.Migrations .HasMaxLength(64) .HasColumnType("nvarchar(64)"); + b.Property("NormalizedName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + b.HasKey("Id"); b.HasIndex("Name"); diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/20231115065621_Initial.Designer.cs b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/20231220020754_Initial.Designer.cs similarity index 99% rename from templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/20231115065621_Initial.Designer.cs rename to templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/20231220020754_Initial.Designer.cs index 86eca8fe53..cd7ee4b230 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/20231115065621_Initial.Designer.cs +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/20231220020754_Initial.Designer.cs @@ -13,7 +13,7 @@ using Volo.Abp.EntityFrameworkCore; namespace MyCompanyName.MyProjectName.Blazor.Server.Host.Migrations { [DbContext(typeof(UnifiedDbContext))] - [Migration("20231115065621_Initial")] + [Migration("20231220020754_Initial")] partial class Initial { /// @@ -1328,6 +1328,11 @@ namespace MyCompanyName.MyProjectName.Blazor.Server.Host.Migrations .HasMaxLength(64) .HasColumnType("nvarchar(64)"); + b.Property("NormalizedName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + b.HasKey("Id"); b.HasIndex("Name"); diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/20231115065621_Initial.cs b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/20231220020754_Initial.cs similarity index 99% rename from templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/20231115065621_Initial.cs rename to templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/20231220020754_Initial.cs index b21456cc73..6e5ae88b9f 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/20231115065621_Initial.cs +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/20231220020754_Initial.cs @@ -296,6 +296,7 @@ namespace MyCompanyName.MyProjectName.Blazor.Server.Host.Migrations { Id = table.Column(type: "uniqueidentifier", nullable: false), Name = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: false), + NormalizedName = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: false), EntityVersion = table.Column(type: "int", nullable: false), ExtraProperties = table.Column(type: "nvarchar(max)", nullable: false), ConcurrencyStamp = table.Column(type: "nvarchar(40)", maxLength: 40, nullable: false), diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/UnifiedDbContextModelSnapshot.cs b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/UnifiedDbContextModelSnapshot.cs index 92a676f756..c32f89f163 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/UnifiedDbContextModelSnapshot.cs +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/UnifiedDbContextModelSnapshot.cs @@ -1325,6 +1325,11 @@ namespace MyCompanyName.MyProjectName.Blazor.Server.Host.Migrations .HasMaxLength(64) .HasColumnType("nvarchar(64)"); + b.Property("NormalizedName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + b.HasKey("Id"); b.HasIndex("Name"); diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/20231115065707_Initial.Designer.cs b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/20231220020817_Initial.Designer.cs similarity index 99% rename from templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/20231115065707_Initial.Designer.cs rename to templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/20231220020817_Initial.Designer.cs index 16bf3345ff..ad8d576878 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/20231115065707_Initial.Designer.cs +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/20231220020817_Initial.Designer.cs @@ -13,7 +13,7 @@ using Volo.Abp.EntityFrameworkCore; namespace MyCompanyName.MyProjectName.Migrations { [DbContext(typeof(UnifiedDbContext))] - [Migration("20231115065707_Initial")] + [Migration("20231220020817_Initial")] partial class Initial { /// @@ -1328,6 +1328,11 @@ namespace MyCompanyName.MyProjectName.Migrations .HasMaxLength(64) .HasColumnType("nvarchar(64)"); + b.Property("NormalizedName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + b.HasKey("Id"); b.HasIndex("Name"); diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/20231115065707_Initial.cs b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/20231220020817_Initial.cs similarity index 99% rename from templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/20231115065707_Initial.cs rename to templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/20231220020817_Initial.cs index d19146cde5..695c5fc0ac 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/20231115065707_Initial.cs +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/20231220020817_Initial.cs @@ -296,6 +296,7 @@ namespace MyCompanyName.MyProjectName.Migrations { Id = table.Column(type: "uniqueidentifier", nullable: false), Name = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: false), + NormalizedName = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: false), EntityVersion = table.Column(type: "int", nullable: false), ExtraProperties = table.Column(type: "nvarchar(max)", nullable: false), ConcurrencyStamp = table.Column(type: "nvarchar(40)", maxLength: 40, nullable: false), diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/UnifiedDbContextModelSnapshot.cs b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/UnifiedDbContextModelSnapshot.cs index 56d7b7e9bd..bb83f23368 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/UnifiedDbContextModelSnapshot.cs +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/UnifiedDbContextModelSnapshot.cs @@ -1325,6 +1325,11 @@ namespace MyCompanyName.MyProjectName.Migrations .HasMaxLength(64) .HasColumnType("nvarchar(64)"); + b.Property("NormalizedName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + b.HasKey("Id"); b.HasIndex("Name"); From 1c72ce1a3a361999dfd4bb9613f6b7cbf75bff2d Mon Sep 17 00:00:00 2001 From: Salih Date: Sat, 23 Dec 2023 20:05:54 +0300 Subject: [PATCH 04/98] add localizations --- .../Admin/Localization/Resources/en.json | 25 ++++++++++++++++++- .../Commercial/Localization/Resources/en.json | 18 ++++++++++++- 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json index e2563fe684..e88dc12207 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json @@ -562,6 +562,29 @@ "SponsorLogo": "Sponsor Logo", "RegistrationUrl": "Registration Url", "AllowAbpStudioBetaAccess": "Allow ABP Studio Beta Access", - "TotalQuestionCanNotBeNullMessage": "Total Question can not be null" + "TotalQuestionCanNotBeNullMessage": "Total Question can not be null", + "Permission:OrganizationAutoRenewalPayments": "Organization Auto Renewal Payments", + "Permission:RetryFailedPayments": "Retry Failed Payments", + "AutoRenewalIsNotEnabled": "Auto Renewal is not enabled!", + "LicenseIsNotExpired": "License is not expired!", + "PaymentNotFound": "Payment not found!", + "PaymentAlreadyTried": "Payment already tried!", + "PaymentIsNotFailed": "Payment is not failed!", + "OrganizationIdIsNull": "OrganizationId is null!", + "Menu:OrganizationAutoRenewalPayments": "Organization Auto Renewal Payments", + "OrganizationAutoRenewalPayments": "Organization Auto Renewal Payments", + "PaymentDate": "Payment Date", + "TryCount": "Try Count", + "ErrorMessage": "Error Message", + "ErrorCode": "Error Code", + "CreditCard": "Credit Card", + "BuyerName": "Buyer Name", + "BuyerSurname": "Buyer Surname", + "BuyerEmail": "Buyer Email", + "AutoRenewalStartTime": "Auto Renewal Start Time", + "AutoRenewalEndTime": "Auto Renewal End Time", + "AutoRenewalEnabled": "Auto Renewal Enabled", + "LastAutoRenewalPaymentTime": "Last Auto Renewal Payment Time", + "OrganizationDoesNotHaveACreditCard": "Organization does not have a credit card!", } } diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json index 23e81238cd..217ca0fb34 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json @@ -1089,6 +1089,22 @@ "MultipleOrganizationInfo": "See All Your Organizations", "AbpStudioBetaAccessInfoTitle": "ABP Studio Beta Access", "AbpStudioBetaAccessInfoText": "We're thrilled to share with you the beta version of ABP Studio! This release marks a significant milestone in our development journey, and we're eager to gather your feedback to make the application even better.", - "YouAreNotAuthorizedToDownloadStudio": "You are not authorized to download ABP Studio." + "YouAreNotAuthorizedToDownloadStudio": "You are not authorized to download ABP Studio.", + "OrganizationHasNoDefaultCreditCard": "Your organization has no default credit card. Please add a credit card to your organization.", + "YouAreNotAuthorizedToPayThisPaymentRequest": "You are not authorized to pay this payment request.", + "YouAreNotAuthorizedToCreateBillingInfoForThisPaymentRequest": "You are not authorized to create billing info for this payment request.", + "OrganizationNotFound": "Organization not found.", + "CannotDeleteDefaultCardBecauseAutoRenewalEnabled": "You cannot delete this card because it is your default card and you have auto renewal enabled. Please disable auto renewal first.", + "AreYouSureWantToDeleteThisCard": "Are you sure you want to delete this card?", + "AreYouSureWantToSetThisCardAsDefault": "Are you sure you want to set this card as default?", + "OrganizationBillingInfoIsNotSuitableForIyzicoPayment": "Your organization's billing info is not suitable for iyzico payment.", + "AutomaticRenewal": "Automatic Renewal", + "AutomaticRenewal_Description": "Renewing a license before it expires lets you get a discount of up to %40. The auto-renewal process lets you renew your license without losing this discount, and your development will never interrupt. Auto-renewal is only available for credit cards. You can disable auto-renewal at any time by accessing your Organization Management page. ABP.io does not save your credit card information, but our global payment gateways do secure savings.", + "CardNotFoundMessage": "Do you want to add a new card?", + "CardNotFoundTitle": "Card Not Found", + "AutoRenewalEnabled": "Auto Renewal Enabled", + "AutoRenewalDisabled": "Auto Renewal Disabled", + "PaymentRequestIdIsNotProvided": "Payment request id is not provided.", + } } From bc13da3e9f4ce609dc8cab7dba5166f7c4044349 Mon Sep 17 00:00:00 2001 From: maliming Date: Sat, 30 Dec 2023 17:54:45 +0800 Subject: [PATCH 05/98] Provide a way for the controller to skip all interceptors and filters. Resolve #18635 --- .../MultiTenancy/MultiTenancyMiddleware.cs | 5 ++-- .../AspNetCore/Mvc/AbpAspNetCoreMvcModule.cs | 5 +++- .../Mvc/AbpMvcActionDescriptorProvider.cs | 30 +++++++++++++++++++ .../Mvc/Auditing/AbpAuditActionFilter.cs | 3 +- .../Mvc/Auditing/AbpAuditPageFilter.cs | 3 +- .../ExceptionHandling/AbpExceptionFilter.cs | 3 +- .../AbpExceptionPageFilter.cs | 3 +- .../Mvc/Features/AbpFeatureActionFilter.cs | 3 +- .../Mvc/Features/AbpFeaturePageFilter.cs | 3 +- .../GlobalFeatureActionFilter.cs | 3 +- .../GlobalFeatures/GlobalFeaturePageFilter.cs | 3 +- .../Mvc/Response/AbpNoContentActionFilter.cs | 3 +- .../AspNetCore/Mvc/Uow/AbpUowActionFilter.cs | 3 +- .../AspNetCore/Mvc/Uow/AbpUowPageFilter.cs | 3 +- .../Validation/AbpValidationActionFilter.cs | 3 +- .../Serilog/AbpSerilogMiddleware.cs | 5 ++-- .../AbpRequestLocalizationMiddleware.cs | 5 ++-- .../Auditing/AbpAuditingMiddleware.cs | 7 +++-- .../AbpExceptionHandlingMiddleware.cs | 5 ++-- .../Filters/DisableAbpFilterAttribute.cs | 19 ++++++++++++ .../Volo/Abp/AspNetCore/Filters/IAbpFilter.cs | 6 ++++ .../Middleware/AbpMiddlewareBase.cs | 20 +++++++++++++ .../Security/AbpSecurityHeadersMiddleware.cs | 5 ++-- .../Security/Claims/AbpClaimsMapMiddleware.cs | 5 ++-- .../Claims/AbpDynamicClaimsMiddleware.cs | 5 ++-- .../Tracing/AbpCorrelationIdMiddleware.cs | 5 ++-- .../AspNetCore/Uow/AbpUnitOfWorkMiddleware.cs | 7 +++-- .../AbpRegistrationBuilderExtensions.cs | 4 ++- .../DisableInterceptorAttribute.cs | 9 ++++++ .../Mvc/FakeAuthenticationMiddleware.cs | 5 ++-- 30 files changed, 150 insertions(+), 38 deletions(-) create mode 100644 framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpMvcActionDescriptorProvider.cs create mode 100644 framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Filters/DisableAbpFilterAttribute.cs create mode 100644 framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Filters/IAbpFilter.cs create mode 100644 framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Middleware/AbpMiddlewareBase.cs create mode 100644 framework/src/Volo.Abp.Core/Volo/Abp/DynamicProxy/DisableInterceptorAttribute.cs diff --git a/framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/MultiTenancyMiddleware.cs b/framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/MultiTenancyMiddleware.cs index 310add4bfc..520e2944f6 100644 --- a/framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/MultiTenancyMiddleware.cs +++ b/framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/MultiTenancyMiddleware.cs @@ -8,6 +8,7 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; using Microsoft.Extensions.Options; +using Volo.Abp.AspNetCore.Middleware; using Volo.Abp.DependencyInjection; using Volo.Abp.Localization; using Volo.Abp.MultiTenancy; @@ -15,7 +16,7 @@ using Volo.Abp.Settings; namespace Volo.Abp.AspNetCore.MultiTenancy; -public class MultiTenancyMiddleware : IMiddleware, ITransientDependency +public class MultiTenancyMiddleware : AbpMiddlewareBase, ITransientDependency { public ILogger Logger { get; set; } @@ -38,7 +39,7 @@ public class MultiTenancyMiddleware : IMiddleware, ITransientDependency _options = options.Value; } - public async Task InvokeAsync(HttpContext context, RequestDelegate next) + public async override Task InvokeAsync(HttpContext context, RequestDelegate next) { TenantConfiguration? tenant = null; try diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcModule.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcModule.cs index c9b5984843..a2f2c1c989 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcModule.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcModule.cs @@ -14,6 +14,7 @@ using System.Linq; using System.Net; using System.Reflection; using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Mvc.Abstractions; using Microsoft.AspNetCore.Mvc.ApiExplorer; using Microsoft.AspNetCore.Mvc.DataAnnotations; using Microsoft.AspNetCore.Mvc.RazorPages; @@ -25,6 +26,7 @@ using Volo.Abp.ApiVersioning; using Volo.Abp.Application; using Volo.Abp.AspNetCore.Mvc.AntiForgery; using Volo.Abp.AspNetCore.Mvc.ApiExploring; +using Volo.Abp.AspNetCore.Mvc.ApplicationModels; using Volo.Abp.AspNetCore.Mvc.Conventions; using Volo.Abp.AspNetCore.Mvc.DataAnnotations; using Volo.Abp.AspNetCore.Mvc.DependencyInjection; @@ -176,6 +178,7 @@ public class AbpAspNetCoreMvcModule : AbpModule context.Services.Replace(ServiceDescriptor.Singleton()); context.Services.AddSingleton(); + context.Services.TryAddEnumerable(ServiceDescriptor.Transient()); context.Services.AddOptions() .Configure((mvcOptions, serviceProvider) => { @@ -247,7 +250,7 @@ public class AbpAspNetCoreMvcModule : AbpModule .Distinct(); AddToApplicationParts(partManager, controllerAssemblies); - + var additionalAssemblies = moduleContainer .Modules .SelectMany(m => m.GetAdditionalAssemblies()) diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpMvcActionDescriptorProvider.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpMvcActionDescriptorProvider.cs new file mode 100644 index 0000000000..9131cd44d6 --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpMvcActionDescriptorProvider.cs @@ -0,0 +1,30 @@ +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.Abstractions; +using Microsoft.AspNetCore.Mvc.Controllers; +using Volo.Abp.AspNetCore.Filters; + +namespace Volo.Abp.AspNetCore.Mvc.ApplicationModels; + +public class AbpMvcActionDescriptorProvider : IActionDescriptorProvider +{ + public virtual int Order => -1000 + 10; + + public virtual void OnProvidersExecuting(ActionDescriptorProviderContext context) + { + } + + public virtual void OnProvidersExecuted(ActionDescriptorProviderContext context) + { + foreach (var action in context.Results.Where(x => x is ControllerActionDescriptor).Cast()) + { + var disableFilterAttribute = action.ControllerTypeInfo.GetCustomAttribute(true); + if (disableFilterAttribute != null) + { + action.FilterDescriptors.RemoveAll(x => x.Filter is ServiceFilterAttribute serviceFilterAttribute && typeof(IAbpFilter).IsAssignableFrom(serviceFilterAttribute.ServiceType)); + } + } + } +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Auditing/AbpAuditActionFilter.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Auditing/AbpAuditActionFilter.cs index 07101da0cb..d982adb12a 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Auditing/AbpAuditActionFilter.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Auditing/AbpAuditActionFilter.cs @@ -5,12 +5,13 @@ using Microsoft.AspNetCore.Mvc.Abstractions; using Microsoft.AspNetCore.Mvc.Filters; using Microsoft.Extensions.Options; using Volo.Abp.Aspects; +using Volo.Abp.AspNetCore.Filters; using Volo.Abp.Auditing; using Volo.Abp.DependencyInjection; namespace Volo.Abp.AspNetCore.Mvc.Auditing; -public class AbpAuditActionFilter : IAsyncActionFilter, ITransientDependency +public class AbpAuditActionFilter : IAsyncActionFilter, IAbpFilter, ITransientDependency { public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next) { diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Auditing/AbpAuditPageFilter.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Auditing/AbpAuditPageFilter.cs index 8445be60ae..6b97ac980a 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Auditing/AbpAuditPageFilter.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Auditing/AbpAuditPageFilter.cs @@ -5,12 +5,13 @@ using Microsoft.AspNetCore.Mvc.Abstractions; using Microsoft.AspNetCore.Mvc.Filters; using Microsoft.Extensions.Options; using Volo.Abp.Aspects; +using Volo.Abp.AspNetCore.Filters; using Volo.Abp.Auditing; using Volo.Abp.DependencyInjection; namespace Volo.Abp.AspNetCore.Mvc.Auditing; -public class AbpAuditPageFilter : IAsyncPageFilter, ITransientDependency +public class AbpAuditPageFilter : IAsyncPageFilter, IAbpFilter, ITransientDependency { public Task OnPageHandlerSelectionAsync(PageHandlerSelectedContext context) { diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ExceptionHandling/AbpExceptionFilter.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ExceptionHandling/AbpExceptionFilter.cs index 61e37104ee..a63e557198 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ExceptionHandling/AbpExceptionFilter.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ExceptionHandling/AbpExceptionFilter.cs @@ -10,6 +10,7 @@ using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; using Microsoft.Extensions.Options; using Volo.Abp.AspNetCore.ExceptionHandling; +using Volo.Abp.AspNetCore.Filters; using Volo.Abp.Authorization; using Volo.Abp.DependencyInjection; using Volo.Abp.ExceptionHandling; @@ -18,7 +19,7 @@ using Volo.Abp.Json; namespace Volo.Abp.AspNetCore.Mvc.ExceptionHandling; -public class AbpExceptionFilter : IAsyncExceptionFilter, ITransientDependency +public class AbpExceptionFilter : IAsyncExceptionFilter, IAbpFilter, ITransientDependency { public virtual async Task OnExceptionAsync(ExceptionContext context) { diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ExceptionHandling/AbpExceptionPageFilter.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ExceptionHandling/AbpExceptionPageFilter.cs index 31784cb6ea..97c21268fe 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ExceptionHandling/AbpExceptionPageFilter.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ExceptionHandling/AbpExceptionPageFilter.cs @@ -10,6 +10,7 @@ using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; using Microsoft.Extensions.Options; using Volo.Abp.AspNetCore.ExceptionHandling; +using Volo.Abp.AspNetCore.Filters; using Volo.Abp.Authorization; using Volo.Abp.DependencyInjection; using Volo.Abp.ExceptionHandling; @@ -18,7 +19,7 @@ using Volo.Abp.Json; namespace Volo.Abp.AspNetCore.Mvc.ExceptionHandling; -public class AbpExceptionPageFilter : IAsyncPageFilter, ITransientDependency +public class AbpExceptionPageFilter : IAsyncPageFilter, IAbpFilter, ITransientDependency { public Task OnPageHandlerSelectionAsync(PageHandlerSelectedContext context) { diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Features/AbpFeatureActionFilter.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Features/AbpFeatureActionFilter.cs index b4b70a5e1a..35bb9ba572 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Features/AbpFeatureActionFilter.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Features/AbpFeatureActionFilter.cs @@ -2,12 +2,13 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc.Abstractions; using Volo.Abp.Aspects; +using Volo.Abp.AspNetCore.Filters; using Volo.Abp.DependencyInjection; using Volo.Abp.Features; namespace Volo.Abp.AspNetCore.Mvc.Features; -public class AbpFeatureActionFilter : IAsyncActionFilter, ITransientDependency +public class AbpFeatureActionFilter : IAsyncActionFilter, IAbpFilter, ITransientDependency { public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next) { diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Features/AbpFeaturePageFilter.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Features/AbpFeaturePageFilter.cs index 3c586f762b..a35764c43c 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Features/AbpFeaturePageFilter.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Features/AbpFeaturePageFilter.cs @@ -2,12 +2,13 @@ using Microsoft.AspNetCore.Mvc.Abstractions; using Microsoft.AspNetCore.Mvc.Filters; using Volo.Abp.Aspects; +using Volo.Abp.AspNetCore.Filters; using Volo.Abp.DependencyInjection; using Volo.Abp.Features; namespace Volo.Abp.AspNetCore.Mvc.Features; -public class AbpFeaturePageFilter : IAsyncPageFilter, ITransientDependency +public class AbpFeaturePageFilter : IAsyncPageFilter, IAbpFilter, ITransientDependency { public Task OnPageHandlerSelectionAsync(PageHandlerSelectedContext context) { diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/GlobalFeatures/GlobalFeatureActionFilter.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/GlobalFeatures/GlobalFeatureActionFilter.cs index aae85e4d25..34f125f228 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/GlobalFeatures/GlobalFeatureActionFilter.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/GlobalFeatures/GlobalFeatureActionFilter.cs @@ -6,12 +6,13 @@ using Microsoft.AspNetCore.Mvc.Filters; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; using Volo.Abp.Aspects; +using Volo.Abp.AspNetCore.Filters; using Volo.Abp.DependencyInjection; using Volo.Abp.GlobalFeatures; namespace Volo.Abp.AspNetCore.Mvc.GlobalFeatures; -public class GlobalFeatureActionFilter : IAsyncActionFilter, ITransientDependency +public class GlobalFeatureActionFilter : IAsyncActionFilter, IAbpFilter, ITransientDependency { public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next) { diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/GlobalFeatures/GlobalFeaturePageFilter.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/GlobalFeatures/GlobalFeaturePageFilter.cs index 46455730a4..3c43301221 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/GlobalFeatures/GlobalFeaturePageFilter.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/GlobalFeatures/GlobalFeaturePageFilter.cs @@ -6,12 +6,13 @@ using Microsoft.AspNetCore.Mvc.Filters; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; using Volo.Abp.Aspects; +using Volo.Abp.AspNetCore.Filters; using Volo.Abp.DependencyInjection; using Volo.Abp.GlobalFeatures; namespace Volo.Abp.AspNetCore.Mvc.GlobalFeatures; -public class GlobalFeaturePageFilter : IAsyncPageFilter, ITransientDependency +public class GlobalFeaturePageFilter : IAsyncPageFilter, IAbpFilter, ITransientDependency { public Task OnPageHandlerSelectionAsync(PageHandlerSelectedContext context) { diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Response/AbpNoContentActionFilter.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Response/AbpNoContentActionFilter.cs index b0565cbc4d..455dd52f24 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Response/AbpNoContentActionFilter.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Response/AbpNoContentActionFilter.cs @@ -2,11 +2,12 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc.Abstractions; using Microsoft.AspNetCore.Mvc.Filters; +using Volo.Abp.AspNetCore.Filters; using Volo.Abp.DependencyInjection; namespace Volo.Abp.AspNetCore.Mvc.Response; -public class AbpNoContentActionFilter : IAsyncActionFilter, ITransientDependency +public class AbpNoContentActionFilter : IAsyncActionFilter, IAbpFilter, ITransientDependency { public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next) { diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Uow/AbpUowActionFilter.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Uow/AbpUowActionFilter.cs index 14032b52d5..4a6a04a554 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Uow/AbpUowActionFilter.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Uow/AbpUowActionFilter.cs @@ -4,12 +4,13 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc.Abstractions; using Microsoft.AspNetCore.Mvc.Filters; using Microsoft.Extensions.Options; +using Volo.Abp.AspNetCore.Filters; using Volo.Abp.DependencyInjection; using Volo.Abp.Uow; namespace Volo.Abp.AspNetCore.Mvc.Uow; -public class AbpUowActionFilter : IAsyncActionFilter, ITransientDependency +public class AbpUowActionFilter : IAsyncActionFilter, IAbpFilter, ITransientDependency { public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next) { diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Uow/AbpUowPageFilter.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Uow/AbpUowPageFilter.cs index 7cfc1f0492..f4a7be3333 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Uow/AbpUowPageFilter.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Uow/AbpUowPageFilter.cs @@ -4,13 +4,14 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc.Abstractions; using Microsoft.AspNetCore.Mvc.Filters; using Microsoft.Extensions.Options; +using Volo.Abp.AspNetCore.Filters; using Volo.Abp.AspNetCore.Uow; using Volo.Abp.DependencyInjection; using Volo.Abp.Uow; namespace Volo.Abp.AspNetCore.Mvc.Uow; -public class AbpUowPageFilter : IAsyncPageFilter, ITransientDependency +public class AbpUowPageFilter : IAsyncPageFilter, IAbpFilter, ITransientDependency { public Task OnPageHandlerSelectionAsync(PageHandlerSelectedContext context) { diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Validation/AbpValidationActionFilter.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Validation/AbpValidationActionFilter.cs index e88cee4eb6..f866c85585 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Validation/AbpValidationActionFilter.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Validation/AbpValidationActionFilter.cs @@ -3,13 +3,14 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc.Abstractions; using Microsoft.AspNetCore.Mvc.Filters; using Microsoft.Extensions.Options; +using Volo.Abp.AspNetCore.Filters; using Volo.Abp.DependencyInjection; using Volo.Abp.Reflection; using Volo.Abp.Validation; namespace Volo.Abp.AspNetCore.Mvc.Validation; -public class AbpValidationActionFilter : IAsyncActionFilter, ITransientDependency +public class AbpValidationActionFilter : IAsyncActionFilter, IAbpFilter, ITransientDependency { public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next) { diff --git a/framework/src/Volo.Abp.AspNetCore.Serilog/Volo/Abp/AspNetCore/Serilog/AbpSerilogMiddleware.cs b/framework/src/Volo.Abp.AspNetCore.Serilog/Volo/Abp/AspNetCore/Serilog/AbpSerilogMiddleware.cs index 1df327b742..52ee2e6b76 100644 --- a/framework/src/Volo.Abp.AspNetCore.Serilog/Volo/Abp/AspNetCore/Serilog/AbpSerilogMiddleware.cs +++ b/framework/src/Volo.Abp.AspNetCore.Serilog/Volo/Abp/AspNetCore/Serilog/AbpSerilogMiddleware.cs @@ -5,6 +5,7 @@ using Microsoft.Extensions.Options; using Serilog.Context; using Serilog.Core; using Serilog.Core.Enrichers; +using Volo.Abp.AspNetCore.Middleware; using Volo.Abp.Clients; using Volo.Abp.DependencyInjection; using Volo.Abp.MultiTenancy; @@ -13,7 +14,7 @@ using Volo.Abp.Users; namespace Volo.Abp.AspNetCore.Serilog; -public class AbpSerilogMiddleware : IMiddleware, ITransientDependency +public class AbpSerilogMiddleware : AbpMiddlewareBase, ITransientDependency { private readonly ICurrentClient _currentClient; private readonly ICurrentTenant _currentTenant; @@ -35,7 +36,7 @@ public class AbpSerilogMiddleware : IMiddleware, ITransientDependency _options = options.Value; } - public async Task InvokeAsync(HttpContext context, RequestDelegate next) + public async override Task InvokeAsync(HttpContext context, RequestDelegate next) { var enrichers = new List(); diff --git a/framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/RequestLocalization/AbpRequestLocalizationMiddleware.cs b/framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/RequestLocalization/AbpRequestLocalizationMiddleware.cs index 6fd02a0470..cb531762ba 100644 --- a/framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/RequestLocalization/AbpRequestLocalizationMiddleware.cs +++ b/framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/RequestLocalization/AbpRequestLocalizationMiddleware.cs @@ -4,11 +4,12 @@ using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Localization; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; +using Volo.Abp.AspNetCore.Middleware; using Volo.Abp.DependencyInjection; namespace Microsoft.AspNetCore.RequestLocalization; -public class AbpRequestLocalizationMiddleware : IMiddleware, ITransientDependency +public class AbpRequestLocalizationMiddleware : AbpMiddlewareBase, ITransientDependency { public const string HttpContextItemName = "__AbpSetCultureCookie"; @@ -23,7 +24,7 @@ public class AbpRequestLocalizationMiddleware : IMiddleware, ITransientDependenc _loggerFactory = loggerFactory; } - public async Task InvokeAsync(HttpContext context, RequestDelegate next) + public async override Task InvokeAsync(HttpContext context, RequestDelegate next) { var middleware = new RequestLocalizationMiddleware( next, diff --git a/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Auditing/AbpAuditingMiddleware.cs b/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Auditing/AbpAuditingMiddleware.cs index 0987a8fd8f..86cc997ae7 100644 --- a/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Auditing/AbpAuditingMiddleware.cs +++ b/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Auditing/AbpAuditingMiddleware.cs @@ -4,6 +4,7 @@ using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Options; +using Volo.Abp.AspNetCore.Middleware; using Volo.Abp.Auditing; using Volo.Abp.DependencyInjection; using Volo.Abp.Uow; @@ -11,7 +12,7 @@ using Volo.Abp.Users; namespace Volo.Abp.AspNetCore.Auditing; -public class AbpAuditingMiddleware : IMiddleware, ITransientDependency +public class AbpAuditingMiddleware : AbpMiddlewareBase, ITransientDependency { private readonly IAuditingManager _auditingManager; protected AbpAuditingOptions AuditingOptions { get; } @@ -34,9 +35,9 @@ public class AbpAuditingMiddleware : IMiddleware, ITransientDependency AspNetCoreAuditingOptions = aspNetCoreAuditingOptions.Value; } - public async Task InvokeAsync(HttpContext context, RequestDelegate next) + public async override Task InvokeAsync(HttpContext context, RequestDelegate next) { - if (!AuditingOptions.IsEnabled || IsIgnoredUrl(context)) + if (await ShouldSkipAsync(context, next) || !AuditingOptions.IsEnabled || IsIgnoredUrl(context)) { await next(context); return; diff --git a/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/ExceptionHandling/AbpExceptionHandlingMiddleware.cs b/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/ExceptionHandling/AbpExceptionHandlingMiddleware.cs index b9d3b83068..7d5ef610e5 100644 --- a/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/ExceptionHandling/AbpExceptionHandlingMiddleware.cs +++ b/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/ExceptionHandling/AbpExceptionHandlingMiddleware.cs @@ -5,6 +5,7 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Microsoft.Net.Http.Headers; +using Volo.Abp.AspNetCore.Middleware; using Volo.Abp.AspNetCore.Mvc; using Volo.Abp.Authorization; using Volo.Abp.DependencyInjection; @@ -14,7 +15,7 @@ using Volo.Abp.Json; namespace Volo.Abp.AspNetCore.ExceptionHandling; -public class AbpExceptionHandlingMiddleware : IMiddleware, ITransientDependency +public class AbpExceptionHandlingMiddleware : AbpMiddlewareBase, ITransientDependency { private readonly ILogger _logger; @@ -27,7 +28,7 @@ public class AbpExceptionHandlingMiddleware : IMiddleware, ITransientDependency _clearCacheHeadersDelegate = ClearCacheHeaders; } - public async Task InvokeAsync(HttpContext context, RequestDelegate next) + public async override Task InvokeAsync(HttpContext context, RequestDelegate next) { try { diff --git a/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Filters/DisableAbpFilterAttribute.cs b/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Filters/DisableAbpFilterAttribute.cs new file mode 100644 index 0000000000..035c7b288f --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Filters/DisableAbpFilterAttribute.cs @@ -0,0 +1,19 @@ +using System; + +namespace Volo.Abp.AspNetCore.Filters; + +[AttributeUsage(AttributeTargets.Class)] +public class DisableAbpFilterAttribute : Attribute +{ + public bool SkipInMiddleware { get; set; } + + public DisableAbpFilterAttribute() + { + SkipInMiddleware = true; + } + + public DisableAbpFilterAttribute(bool skipInMiddleware) + { + SkipInMiddleware = skipInMiddleware; + } +} diff --git a/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Filters/IAbpFilter.cs b/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Filters/IAbpFilter.cs new file mode 100644 index 0000000000..dbd55a8ed4 --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Filters/IAbpFilter.cs @@ -0,0 +1,6 @@ +namespace Volo.Abp.AspNetCore.Filters; + +public interface IAbpFilter +{ + +} diff --git a/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Middleware/AbpMiddlewareBase.cs b/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Middleware/AbpMiddlewareBase.cs new file mode 100644 index 0000000000..bbf79ba22e --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Middleware/AbpMiddlewareBase.cs @@ -0,0 +1,20 @@ +using System.Reflection; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc.Controllers; +using Volo.Abp.AspNetCore.Filters; + +namespace Volo.Abp.AspNetCore.Middleware; + +public abstract class AbpMiddlewareBase : IMiddleware +{ + protected Task ShouldSkipAsync(HttpContext context, RequestDelegate next) + { + var endpoint = context.GetEndpoint(); + var controllerActionDescriptor = endpoint?.Metadata.GetMetadata(); + var disableAbpFilterAttribute = controllerActionDescriptor?.ControllerTypeInfo.GetCustomAttribute(); + return Task.FromResult(disableAbpFilterAttribute != null && disableAbpFilterAttribute.SkipInMiddleware); + } + + public abstract Task InvokeAsync(HttpContext context, RequestDelegate next); +} diff --git a/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Security/AbpSecurityHeadersMiddleware.cs b/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Security/AbpSecurityHeadersMiddleware.cs index ae2e3b173b..4542dd32e1 100644 --- a/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Security/AbpSecurityHeadersMiddleware.cs +++ b/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Security/AbpSecurityHeadersMiddleware.cs @@ -5,11 +5,12 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Options; using Microsoft.Extensions.Primitives; +using Volo.Abp.AspNetCore.Middleware; using Volo.Abp.DependencyInjection; namespace Volo.Abp.AspNetCore.Security; -public class AbpSecurityHeadersMiddleware : IMiddleware, ITransientDependency +public class AbpSecurityHeadersMiddleware : AbpMiddlewareBase, ITransientDependency { public IOptions Options { get; set; } protected const string ScriptSrcKey = "script-src"; @@ -20,7 +21,7 @@ public class AbpSecurityHeadersMiddleware : IMiddleware, ITransientDependency Options = options; } - public async Task InvokeAsync(HttpContext context, RequestDelegate next) + public async override 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.*/ AddHeader(context, "X-Content-Type-Options", "nosniff"); diff --git a/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Security/Claims/AbpClaimsMapMiddleware.cs b/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Security/Claims/AbpClaimsMapMiddleware.cs index ab23bdb944..bb2bedf901 100644 --- a/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Security/Claims/AbpClaimsMapMiddleware.cs +++ b/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Security/Claims/AbpClaimsMapMiddleware.cs @@ -4,14 +4,15 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; +using Volo.Abp.AspNetCore.Middleware; using Volo.Abp.DependencyInjection; using Volo.Abp.Security.Claims; namespace Volo.Abp.AspNetCore.Security.Claims; -public class AbpClaimsMapMiddleware : IMiddleware, ITransientDependency +public class AbpClaimsMapMiddleware : AbpMiddlewareBase, ITransientDependency { - public async Task InvokeAsync(HttpContext context, RequestDelegate next) + public async override Task InvokeAsync(HttpContext context, RequestDelegate next) { var currentPrincipalAccessor = context.RequestServices .GetRequiredService(); diff --git a/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Security/Claims/AbpDynamicClaimsMiddleware.cs b/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Security/Claims/AbpDynamicClaimsMiddleware.cs index 777ca7744a..9c62fa8b25 100644 --- a/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Security/Claims/AbpDynamicClaimsMiddleware.cs +++ b/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Security/Claims/AbpDynamicClaimsMiddleware.cs @@ -2,14 +2,15 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; +using Volo.Abp.AspNetCore.Middleware; using Volo.Abp.DependencyInjection; using Volo.Abp.Security.Claims; namespace Volo.Abp.AspNetCore.Security.Claims; -public class AbpDynamicClaimsMiddleware : IMiddleware, ITransientDependency +public class AbpDynamicClaimsMiddleware : AbpMiddlewareBase, ITransientDependency { - public async Task InvokeAsync(HttpContext context, RequestDelegate next) + public async override Task InvokeAsync(HttpContext context, RequestDelegate next) { if (context.User.Identity?.IsAuthenticated == true) { diff --git a/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Tracing/AbpCorrelationIdMiddleware.cs b/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Tracing/AbpCorrelationIdMiddleware.cs index a5f954c260..38356f8151 100644 --- a/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Tracing/AbpCorrelationIdMiddleware.cs +++ b/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Tracing/AbpCorrelationIdMiddleware.cs @@ -3,12 +3,13 @@ using System.Collections.Generic; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Options; using System.Threading.Tasks; +using Volo.Abp.AspNetCore.Middleware; using Volo.Abp.DependencyInjection; using Volo.Abp.Tracing; namespace Volo.Abp.AspNetCore.Tracing; -public class AbpCorrelationIdMiddleware : IMiddleware, ITransientDependency +public class AbpCorrelationIdMiddleware : AbpMiddlewareBase, ITransientDependency { private readonly AbpCorrelationIdOptions _options; private readonly ICorrelationIdProvider _correlationIdProvider; @@ -20,7 +21,7 @@ public class AbpCorrelationIdMiddleware : IMiddleware, ITransientDependency _correlationIdProvider = correlationIdProvider; } - public async Task InvokeAsync(HttpContext context, RequestDelegate next) + public async override Task InvokeAsync(HttpContext context, RequestDelegate next) { var correlationId = GetCorrelationIdFromRequest(context); using (_correlationIdProvider.Change(correlationId)) diff --git a/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Uow/AbpUnitOfWorkMiddleware.cs b/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Uow/AbpUnitOfWorkMiddleware.cs index 186501b4ac..013b3dad98 100644 --- a/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Uow/AbpUnitOfWorkMiddleware.cs +++ b/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Uow/AbpUnitOfWorkMiddleware.cs @@ -3,12 +3,13 @@ using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Options; +using Volo.Abp.AspNetCore.Middleware; using Volo.Abp.DependencyInjection; using Volo.Abp.Uow; namespace Volo.Abp.AspNetCore.Uow; -public class AbpUnitOfWorkMiddleware : IMiddleware, ITransientDependency +public class AbpUnitOfWorkMiddleware : AbpMiddlewareBase, ITransientDependency { private readonly IUnitOfWorkManager _unitOfWorkManager; private readonly AbpAspNetCoreUnitOfWorkOptions _options; @@ -21,9 +22,9 @@ public class AbpUnitOfWorkMiddleware : IMiddleware, ITransientDependency _options = options.Value; } - public async Task InvokeAsync(HttpContext context, RequestDelegate next) + public async override Task InvokeAsync(HttpContext context, RequestDelegate next) { - if (IsIgnoredUrl(context)) + if (await ShouldSkipAsync(context, next) || IsIgnoredUrl(context)) { await next(context); return; diff --git a/framework/src/Volo.Abp.Autofac/Autofac/Builder/AbpRegistrationBuilderExtensions.cs b/framework/src/Volo.Abp.Autofac/Autofac/Builder/AbpRegistrationBuilderExtensions.cs index 043f824b1a..9a2b1fa43a 100644 --- a/framework/src/Volo.Abp.Autofac/Autofac/Builder/AbpRegistrationBuilderExtensions.cs +++ b/framework/src/Volo.Abp.Autofac/Autofac/Builder/AbpRegistrationBuilderExtensions.cs @@ -7,6 +7,7 @@ using Microsoft.Extensions.DependencyInjection; using Volo.Abp.Autofac; using Volo.Abp.Castle.DynamicProxy; using Volo.Abp.DependencyInjection; +using Volo.Abp.DynamicProxy; using Volo.Abp.Modularity; namespace Autofac.Builder; @@ -73,7 +74,8 @@ public static class AbpRegistrationBuilderExtensions registrationAction.Invoke(serviceRegistredArgs); } - if (serviceRegistredArgs.Interceptors.Any()) + if (serviceRegistredArgs.Interceptors.Any() && + !serviceRegistredArgs.ImplementationType.IsDefined(typeof(DisableInterceptorAttribute), true)) { registrationBuilder = registrationBuilder.AddInterceptors( registrationActionList, diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/DynamicProxy/DisableInterceptorAttribute.cs b/framework/src/Volo.Abp.Core/Volo/Abp/DynamicProxy/DisableInterceptorAttribute.cs new file mode 100644 index 0000000000..7d3bf5bcc5 --- /dev/null +++ b/framework/src/Volo.Abp.Core/Volo/Abp/DynamicProxy/DisableInterceptorAttribute.cs @@ -0,0 +1,9 @@ +using System; + +namespace Volo.Abp.DynamicProxy; + +[AttributeUsage(AttributeTargets.Class)] +public class DisableInterceptorAttribute : Attribute +{ + +} diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/FakeAuthenticationMiddleware.cs b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/FakeAuthenticationMiddleware.cs index 41a9b56fe5..a3cd4a57e6 100644 --- a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/FakeAuthenticationMiddleware.cs +++ b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/FakeAuthenticationMiddleware.cs @@ -3,11 +3,12 @@ using System.Linq; using System.Security.Claims; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; +using Volo.Abp.AspNetCore.Middleware; using Volo.Abp.DependencyInjection; namespace Volo.Abp.AspNetCore.Mvc; -public class FakeAuthenticationMiddleware : IMiddleware, ITransientDependency +public class FakeAuthenticationMiddleware : AbpMiddlewareBase, ITransientDependency { private readonly FakeUserClaims _fakeUserClaims; @@ -16,7 +17,7 @@ public class FakeAuthenticationMiddleware : IMiddleware, ITransientDependency _fakeUserClaims = fakeUserClaims; } - public async Task InvokeAsync(HttpContext context, RequestDelegate next) + public async override Task InvokeAsync(HttpContext context, RequestDelegate next) { if (_fakeUserClaims.Claims.Any()) { From cb7e441a71e54a6bc03b65955a8cb266ca096dba Mon Sep 17 00:00:00 2001 From: maliming Date: Sat, 30 Dec 2023 17:57:32 +0800 Subject: [PATCH 06/98] Rename `DisableInterceptorAttribute` to `DisableAbpInterceptorAttribute`. --- .../Autofac/Builder/AbpRegistrationBuilderExtensions.cs | 2 +- ...nterceptorAttribute.cs => DisableAbpInterceptorAttribute.cs} | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename framework/src/Volo.Abp.Core/Volo/Abp/DynamicProxy/{DisableInterceptorAttribute.cs => DisableAbpInterceptorAttribute.cs} (62%) diff --git a/framework/src/Volo.Abp.Autofac/Autofac/Builder/AbpRegistrationBuilderExtensions.cs b/framework/src/Volo.Abp.Autofac/Autofac/Builder/AbpRegistrationBuilderExtensions.cs index 9a2b1fa43a..de5effd86c 100644 --- a/framework/src/Volo.Abp.Autofac/Autofac/Builder/AbpRegistrationBuilderExtensions.cs +++ b/framework/src/Volo.Abp.Autofac/Autofac/Builder/AbpRegistrationBuilderExtensions.cs @@ -75,7 +75,7 @@ public static class AbpRegistrationBuilderExtensions } if (serviceRegistredArgs.Interceptors.Any() && - !serviceRegistredArgs.ImplementationType.IsDefined(typeof(DisableInterceptorAttribute), true)) + !serviceRegistredArgs.ImplementationType.IsDefined(typeof(DisableAbpInterceptorAttribute), true)) { registrationBuilder = registrationBuilder.AddInterceptors( registrationActionList, diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/DynamicProxy/DisableInterceptorAttribute.cs b/framework/src/Volo.Abp.Core/Volo/Abp/DynamicProxy/DisableAbpInterceptorAttribute.cs similarity index 62% rename from framework/src/Volo.Abp.Core/Volo/Abp/DynamicProxy/DisableInterceptorAttribute.cs rename to framework/src/Volo.Abp.Core/Volo/Abp/DynamicProxy/DisableAbpInterceptorAttribute.cs index 7d3bf5bcc5..be7b773c87 100644 --- a/framework/src/Volo.Abp.Core/Volo/Abp/DynamicProxy/DisableInterceptorAttribute.cs +++ b/framework/src/Volo.Abp.Core/Volo/Abp/DynamicProxy/DisableAbpInterceptorAttribute.cs @@ -3,7 +3,7 @@ using System; namespace Volo.Abp.DynamicProxy; [AttributeUsage(AttributeTargets.Class)] -public class DisableInterceptorAttribute : Attribute +public class DisableAbpInterceptorAttribute : Attribute { } From b10761d99708e54246daba6c680c3ae044496dab Mon Sep 17 00:00:00 2001 From: maliming Date: Sat, 30 Dec 2023 20:23:29 +0800 Subject: [PATCH 07/98] Add `DisableAbpFeaturesAttribute`. --- .../Mvc/AbpMvcActionDescriptorProvider.cs | 7 +++--- .../Filters/DisableAbpFilterAttribute.cs | 19 -------------- .../Middleware/AbpMiddlewareBase.cs | 5 ++-- .../AbpRegistrationBuilderExtensions.cs | 19 ++++++++------ .../Volo/Abp/DisableAbpFeaturesAttribute.cs | 25 +++++++++++++++++++ .../DisableAbpInterceptorAttribute.cs | 9 ------- 6 files changed, 43 insertions(+), 41 deletions(-) delete mode 100644 framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Filters/DisableAbpFilterAttribute.cs create mode 100644 framework/src/Volo.Abp.Core/Volo/Abp/DisableAbpFeaturesAttribute.cs delete mode 100644 framework/src/Volo.Abp.Core/Volo/Abp/DynamicProxy/DisableAbpInterceptorAttribute.cs diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpMvcActionDescriptorProvider.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpMvcActionDescriptorProvider.cs index 9131cd44d6..1ae2180e47 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpMvcActionDescriptorProvider.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpMvcActionDescriptorProvider.cs @@ -20,10 +20,11 @@ public class AbpMvcActionDescriptorProvider : IActionDescriptorProvider { foreach (var action in context.Results.Where(x => x is ControllerActionDescriptor).Cast()) { - var disableFilterAttribute = action.ControllerTypeInfo.GetCustomAttribute(true); - if (disableFilterAttribute != null) + var disableAbpFeaturesAttribute = action.ControllerTypeInfo.GetCustomAttribute(true); + if (disableAbpFeaturesAttribute != null && disableAbpFeaturesAttribute.DisableMvcFilters) { - action.FilterDescriptors.RemoveAll(x => x.Filter is ServiceFilterAttribute serviceFilterAttribute && typeof(IAbpFilter).IsAssignableFrom(serviceFilterAttribute.ServiceType)); + action.FilterDescriptors.RemoveAll(x => x.Filter is ServiceFilterAttribute serviceFilterAttribute && + typeof(IAbpFilter).IsAssignableFrom(serviceFilterAttribute.ServiceType)); } } } diff --git a/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Filters/DisableAbpFilterAttribute.cs b/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Filters/DisableAbpFilterAttribute.cs deleted file mode 100644 index 035c7b288f..0000000000 --- a/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Filters/DisableAbpFilterAttribute.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System; - -namespace Volo.Abp.AspNetCore.Filters; - -[AttributeUsage(AttributeTargets.Class)] -public class DisableAbpFilterAttribute : Attribute -{ - public bool SkipInMiddleware { get; set; } - - public DisableAbpFilterAttribute() - { - SkipInMiddleware = true; - } - - public DisableAbpFilterAttribute(bool skipInMiddleware) - { - SkipInMiddleware = skipInMiddleware; - } -} diff --git a/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Middleware/AbpMiddlewareBase.cs b/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Middleware/AbpMiddlewareBase.cs index bbf79ba22e..f41578da33 100644 --- a/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Middleware/AbpMiddlewareBase.cs +++ b/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Middleware/AbpMiddlewareBase.cs @@ -2,7 +2,6 @@ using System.Reflection; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc.Controllers; -using Volo.Abp.AspNetCore.Filters; namespace Volo.Abp.AspNetCore.Middleware; @@ -12,8 +11,8 @@ public abstract class AbpMiddlewareBase : IMiddleware { var endpoint = context.GetEndpoint(); var controllerActionDescriptor = endpoint?.Metadata.GetMetadata(); - var disableAbpFilterAttribute = controllerActionDescriptor?.ControllerTypeInfo.GetCustomAttribute(); - return Task.FromResult(disableAbpFilterAttribute != null && disableAbpFilterAttribute.SkipInMiddleware); + var disableAbpFeaturesAttribute = controllerActionDescriptor?.ControllerTypeInfo.GetCustomAttribute(); + return Task.FromResult(disableAbpFeaturesAttribute != null && disableAbpFeaturesAttribute.DisableMiddlewares); } public abstract Task InvokeAsync(HttpContext context, RequestDelegate next); diff --git a/framework/src/Volo.Abp.Autofac/Autofac/Builder/AbpRegistrationBuilderExtensions.cs b/framework/src/Volo.Abp.Autofac/Autofac/Builder/AbpRegistrationBuilderExtensions.cs index de5effd86c..53216b03b9 100644 --- a/framework/src/Volo.Abp.Autofac/Autofac/Builder/AbpRegistrationBuilderExtensions.cs +++ b/framework/src/Volo.Abp.Autofac/Autofac/Builder/AbpRegistrationBuilderExtensions.cs @@ -1,9 +1,11 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Reflection; using Autofac.Core; using Autofac.Extras.DynamicProxy; using Microsoft.Extensions.DependencyInjection; +using Volo.Abp; using Volo.Abp.Autofac; using Volo.Abp.Castle.DynamicProxy; using Volo.Abp.DependencyInjection; @@ -74,14 +76,17 @@ public static class AbpRegistrationBuilderExtensions registrationAction.Invoke(serviceRegistredArgs); } - if (serviceRegistredArgs.Interceptors.Any() && - !serviceRegistredArgs.ImplementationType.IsDefined(typeof(DisableAbpInterceptorAttribute), true)) + if (serviceRegistredArgs.Interceptors.Any()) { - registrationBuilder = registrationBuilder.AddInterceptors( - registrationActionList, - serviceType, - serviceRegistredArgs.Interceptors - ); + var disableAbpFeaturesAttribute = serviceRegistredArgs.ImplementationType.GetCustomAttribute(true); + if (disableAbpFeaturesAttribute == null || !disableAbpFeaturesAttribute.DisableInterceptors) + { + registrationBuilder = registrationBuilder.AddInterceptors( + registrationActionList, + serviceType, + serviceRegistredArgs.Interceptors + ); + } } return registrationBuilder; diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/DisableAbpFeaturesAttribute.cs b/framework/src/Volo.Abp.Core/Volo/Abp/DisableAbpFeaturesAttribute.cs new file mode 100644 index 0000000000..69f80446a6 --- /dev/null +++ b/framework/src/Volo.Abp.Core/Volo/Abp/DisableAbpFeaturesAttribute.cs @@ -0,0 +1,25 @@ +using System; + +namespace Volo.Abp; + +[AttributeUsage(AttributeTargets.Class)] +public class DisableAbpFeaturesAttribute : Attribute +{ + /// + /// The framework will not register any interceptors for the class. + /// This will cause the all features that depend on interceptors to not work. + /// + public bool DisableInterceptors { get; set; } = true; + + /// + /// The framework middleware will skip the class. + /// This will cause the all features that depend on middleware to not work. + /// + public bool DisableMiddlewares { get; set; } = true; + + /// + /// The framework will not remove all built-in filters for the class. + /// This will cause the all features that depend on filters to not work. + /// + public bool DisableMvcFilters { get; set; } = true; +} diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/DynamicProxy/DisableAbpInterceptorAttribute.cs b/framework/src/Volo.Abp.Core/Volo/Abp/DynamicProxy/DisableAbpInterceptorAttribute.cs deleted file mode 100644 index be7b773c87..0000000000 --- a/framework/src/Volo.Abp.Core/Volo/Abp/DynamicProxy/DisableAbpInterceptorAttribute.cs +++ /dev/null @@ -1,9 +0,0 @@ -using System; - -namespace Volo.Abp.DynamicProxy; - -[AttributeUsage(AttributeTargets.Class)] -public class DisableAbpInterceptorAttribute : Attribute -{ - -} From 2823596497cecaa5c91ac2e568b5524607da7ff4 Mon Sep 17 00:00:00 2001 From: maliming Date: Sat, 30 Dec 2023 21:27:54 +0800 Subject: [PATCH 08/98] Add unit tests. --- .../Middleware/AbpMiddlewareBase.cs | 2 +- .../Volo/Abp/DisableAbpFeaturesAttribute.cs | 2 +- .../MvcDisableAbpFeaturesAttribute_Tests.cs | 74 +++++++++++++++++++ .../DynamicProxy/AbpInterceptionTestBase.cs | 31 ++++++++ .../AlwaysExceptionAsyncInterceptor.cs | 11 +++ .../DisableInterceptionTargetClass.cs | 41 ++++++++++ 6 files changed, 159 insertions(+), 2 deletions(-) create mode 100644 framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Filters/MvcDisableAbpFeaturesAttribute_Tests.cs create mode 100644 framework/test/Volo.Abp.Core.Tests/Volo/Abp/DynamicProxy/AlwaysExceptionAsyncInterceptor.cs create mode 100644 framework/test/Volo.Abp.Core.Tests/Volo/Abp/DynamicProxy/DisableInterceptionTargetClass.cs diff --git a/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Middleware/AbpMiddlewareBase.cs b/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Middleware/AbpMiddlewareBase.cs index f41578da33..52c9990a4f 100644 --- a/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Middleware/AbpMiddlewareBase.cs +++ b/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Middleware/AbpMiddlewareBase.cs @@ -12,7 +12,7 @@ public abstract class AbpMiddlewareBase : IMiddleware var endpoint = context.GetEndpoint(); var controllerActionDescriptor = endpoint?.Metadata.GetMetadata(); var disableAbpFeaturesAttribute = controllerActionDescriptor?.ControllerTypeInfo.GetCustomAttribute(); - return Task.FromResult(disableAbpFeaturesAttribute != null && disableAbpFeaturesAttribute.DisableMiddlewares); + return Task.FromResult(disableAbpFeaturesAttribute != null && disableAbpFeaturesAttribute.DisableMiddleware); } public abstract Task InvokeAsync(HttpContext context, RequestDelegate next); diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/DisableAbpFeaturesAttribute.cs b/framework/src/Volo.Abp.Core/Volo/Abp/DisableAbpFeaturesAttribute.cs index 69f80446a6..28c92b7463 100644 --- a/framework/src/Volo.Abp.Core/Volo/Abp/DisableAbpFeaturesAttribute.cs +++ b/framework/src/Volo.Abp.Core/Volo/Abp/DisableAbpFeaturesAttribute.cs @@ -15,7 +15,7 @@ public class DisableAbpFeaturesAttribute : Attribute /// The framework middleware will skip the class. /// This will cause the all features that depend on middleware to not work. /// - public bool DisableMiddlewares { get; set; } = true; + public bool DisableMiddleware { get; set; } = true; /// /// The framework will not remove all built-in filters for the class. diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Filters/MvcDisableAbpFeaturesAttribute_Tests.cs b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Filters/MvcDisableAbpFeaturesAttribute_Tests.cs new file mode 100644 index 0000000000..7ff181c645 --- /dev/null +++ b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Filters/MvcDisableAbpFeaturesAttribute_Tests.cs @@ -0,0 +1,74 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.Controllers; +using Microsoft.AspNetCore.Mvc.Filters; +using Shouldly; +using Volo.Abp.AspNetCore.Mvc.Auditing; +using Volo.Abp.AspNetCore.Mvc.ExceptionHandling; +using Volo.Abp.AspNetCore.Mvc.Features; +using Volo.Abp.AspNetCore.Mvc.GlobalFeatures; +using Volo.Abp.AspNetCore.Mvc.Response; +using Volo.Abp.AspNetCore.Mvc.Uow; +using Volo.Abp.AspNetCore.Mvc.Validation; +using Xunit; + +namespace Volo.Abp.AspNetCore.Mvc.Filters; + +[Route("api/enabled-features-test")] +public class EnabledAbpFeaturesController : AbpController, IRemoteService +{ + [HttpGet] + public Task> GetAsync() + { + var filters = HttpContext.GetEndpoint().Metadata.GetMetadata() + .FilterDescriptors.Where(x => x.Filter is ServiceFilterAttribute) + .Select(x => x.Filter.As().ServiceType.FullName).ToList(); + + return Task.FromResult(filters); + } +} + +[Route("api/disabled-features-test")] +[DisableAbpFeatures] +public class DisabledAbpFeaturesController : AbpController, IRemoteService +{ + [HttpGet] + public Task> GetAsync() + { + var filters = HttpContext.GetEndpoint().Metadata.GetMetadata() + .FilterDescriptors.Where(x => x.Filter is ServiceFilterAttribute) + .Select(x => x.Filter.As().ServiceType.FullName).ToList(); + + return Task.FromResult(filters); + } +} + +public class MvcDisableAbpFeaturesAttribute_Tests : AspNetCoreMvcTestBase +{ + [Fact] + public async Task Should_Disable_MVC_Filters() + { + var filters = await GetResponseAsObjectAsync>("/api/enabled-features-test"); + filters.ShouldContain(typeof(GlobalFeatureActionFilter).FullName); + filters.ShouldContain(typeof(AbpAuditActionFilter).FullName); + filters.ShouldContain(typeof(AbpNoContentActionFilter).FullName); + filters.ShouldContain(typeof(AbpFeatureActionFilter).FullName); + filters.ShouldContain(typeof(AbpValidationActionFilter).FullName); + filters.ShouldContain(typeof(AbpUowActionFilter).FullName); + filters.ShouldContain(typeof(AbpExceptionFilter).FullName); + + filters = await GetResponseAsObjectAsync>("/api/disabled-features-test"); + filters.ShouldNotContain(typeof(GlobalFeatureActionFilter).FullName); + filters.ShouldNotContain(typeof(AbpAuditActionFilter).FullName); + filters.ShouldNotContain(typeof(AbpNoContentActionFilter).FullName); + filters.ShouldNotContain(typeof(AbpFeatureActionFilter).FullName); + filters.ShouldNotContain(typeof(AbpValidationActionFilter).FullName); + filters.ShouldNotContain(typeof(AbpUowActionFilter).FullName); + filters.ShouldNotContain(typeof(AbpExceptionFilter).FullName); + } + +} diff --git a/framework/test/Volo.Abp.Core.Tests/Volo/Abp/DynamicProxy/AbpInterceptionTestBase.cs b/framework/test/Volo.Abp.Core.Tests/Volo/Abp/DynamicProxy/AbpInterceptionTestBase.cs index e244237598..4cce6a0c78 100644 --- a/framework/test/Volo.Abp.Core.Tests/Volo/Abp/DynamicProxy/AbpInterceptionTestBase.cs +++ b/framework/test/Volo.Abp.Core.Tests/Volo/Abp/DynamicProxy/AbpInterceptionTestBase.cs @@ -15,22 +15,34 @@ public abstract class AbpInterceptionTestBase : AbpAsyncIntegrat services.AddTransient(); services.AddTransient(); services.AddTransient(); + services.AddTransient(); services.AddTransient(); services.AddTransient(); + services.AddTransient(); + services.OnRegistered(registration => { if (typeof(SimpleInterceptionTargetClass) == registration.ImplementationType) { registration.Interceptors.Add(); registration.Interceptors.Add(); + registration.Interceptors.Add(); } if (typeof(CachedTestObject) == registration.ImplementationType) { registration.Interceptors.Add(); } + + if (typeof(DisableInterceptionTargetClass) == registration.ImplementationType) + { + registration.Interceptors.Add(); + registration.Interceptors.Add(); + registration.Interceptors.Add(); + registration.Interceptors.Add(); + } }); return Task.CompletedTask; @@ -96,4 +108,23 @@ public abstract class AbpInterceptionTestBase : AbpAsyncIntegrat (await target.GetValueAsync(43)).ShouldBe(42); //First run, cached previous value (await target.GetValueAsync(44)).ShouldBe(42); //First run, cached previous value } + + [Fact] + public async Task Should_Disable_Interceptors() + { + //Arrange + + var target = ServiceProvider.GetService(); + + //Act + + await target.DoItAsync(); + + //Assert + + target.Logs.Count.ShouldBe(3); + target.Logs[0].ShouldBe("EnterDoItAsync"); + target.Logs[1].ShouldBe("MiddleDoItAsync"); + target.Logs[2].ShouldBe("ExitDoItAsync"); + } } diff --git a/framework/test/Volo.Abp.Core.Tests/Volo/Abp/DynamicProxy/AlwaysExceptionAsyncInterceptor.cs b/framework/test/Volo.Abp.Core.Tests/Volo/Abp/DynamicProxy/AlwaysExceptionAsyncInterceptor.cs new file mode 100644 index 0000000000..2b9845a6ea --- /dev/null +++ b/framework/test/Volo.Abp.Core.Tests/Volo/Abp/DynamicProxy/AlwaysExceptionAsyncInterceptor.cs @@ -0,0 +1,11 @@ +using System.Threading.Tasks; + +namespace Volo.Abp.DynamicProxy; + +public class AlwaysExceptionAsyncInterceptor : AbpInterceptor +{ + public override Task InterceptAsync(IAbpMethodInvocation invocation) + { + throw new AbpException("This interceptor should not be executed!"); + } +} diff --git a/framework/test/Volo.Abp.Core.Tests/Volo/Abp/DynamicProxy/DisableInterceptionTargetClass.cs b/framework/test/Volo.Abp.Core.Tests/Volo/Abp/DynamicProxy/DisableInterceptionTargetClass.cs new file mode 100644 index 0000000000..caf17b5b9d --- /dev/null +++ b/framework/test/Volo.Abp.Core.Tests/Volo/Abp/DynamicProxy/DisableInterceptionTargetClass.cs @@ -0,0 +1,41 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using Volo.Abp.TestBase.Logging; + +namespace Volo.Abp.DynamicProxy; + +[DisableAbpFeatures] +public class DisableInterceptionTargetClass : ICanLogOnObject +{ + public List Logs { get; } = new List(); + + public virtual void DoIt() + { + Logs.Add("ExecutingDoIt"); + } + + public virtual int GetValue() + { + Logs.Add("ExecutingGetValue"); + return 42; + } + + public virtual async Task GetValueAsync() + { + Logs.Add("EnterGetValueAsync"); + await Task.Delay(5); + Logs.Add("MiddleGetValueAsync"); + await Task.Delay(5); + Logs.Add("ExitGetValueAsync"); + return 42; + } + + public virtual async Task DoItAsync() + { + Logs.Add("EnterDoItAsync"); + await Task.Delay(5); + Logs.Add("MiddleDoItAsync"); + await Task.Delay(5); + Logs.Add("ExitDoItAsync"); + } +} From a1570af6a7043dcc5e4b67762470b6dc598d1178 Mon Sep 17 00:00:00 2001 From: Salih Date: Tue, 2 Jan 2024 14:28:45 +0300 Subject: [PATCH 09/98] update localizations --- .../Commercial/Localization/Resources/ar.json | 4 ++-- .../Commercial/Localization/Resources/en.json | 4 ++-- .../Commercial/Localization/Resources/fi.json | 4 ++-- .../Commercial/Localization/Resources/hr.json | 4 ++-- .../Commercial/Localization/Resources/hu.json | 4 ++-- .../Commercial/Localization/Resources/ru.json | 4 ++-- .../Commercial/Localization/Resources/tr.json | 4 ++-- .../Commercial/Localization/Resources/zh-Hans.json | 4 ++-- .../Commercial/Localization/Resources/zh-Hant.json | 2 +- 9 files changed, 17 insertions(+), 17 deletions(-) diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/ar.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/ar.json index 2953d946a0..ec8b0a752d 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/ar.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/ar.json @@ -531,8 +531,8 @@ "MyOrganizations_Detail_LicenseStartAndExpiryDate": "تاريخ بدء الترخيص - تاريخ انتهاء الصلاحية", "MyOrganizations_Detail_OwnerRightInfo": "أنت تستخدم {0} من {1} حقوق المالك.", "MyOrganizations_Detail_CopyApiKey": "انسخ المفتاح", - "MyOrganizations_Detail_ApiKeyDescription": "مفتاح API هو الرمز المميز لحزم PRO المستضافة على {1}.", - "MyOrganizations_Detail_YourPrivateNugetSource": "مصدر NuGet الخاص بك هو {0}", + "MyOrganizations_Detail_ApiKeyDescription": "مفتاح API هو الرمز المميز لحزم PRO المستضافة على {1}.", + "MyOrganizations_Detail_YourPrivateNugetSource": "مصدر NuGet الخاص بك هو {0}", "MyOrganizations_Detail_PrivateNugetSourceWarning": "تتم إضافة هذا تلقائيًا كوجز إلى NuGet.Config في حل ABP الخاص بك. لا تشارك مفتاحك الخاص مع مستخدمين غير مصرح لهم!", "MyOrganizations_Detail_DeveloperSeatInfo": "أنت تستخدم {0} من {1} مقاعد مطوري البرامج.", "NeedMoreSeatsForYourTeam": "هل تحتاج إلى المزيد من المقاعد لفريقك؟", diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json index 95ffe6f855..b5ad4b58fb 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json @@ -556,8 +556,8 @@ "MyOrganizations_Detail_LicenseStartAndExpiryDate": "License Start Date - Expiry Date", "MyOrganizations_Detail_OwnerRightInfo": "You are using {0} of your {1} owners rights.", "MyOrganizations_Detail_CopyApiKey": "Copy the Key", - "MyOrganizations_Detail_ApiKeyDescription": "The API Key is the token of PRO packages hosted on {1}.", - "MyOrganizations_Detail_YourPrivateNugetSource": "Your private NuGet source is {0}", + "MyOrganizations_Detail_ApiKeyDescription": "The API Key is the token of PRO packages hosted on {1}.", + "MyOrganizations_Detail_YourPrivateNugetSource": "Your private NuGet source is {0}", "MyOrganizations_Detail_PrivateNugetSourceWarning": "This is automatically added as a feed to your NuGet.Config in your ABP solution. Do not share your private key with unauthorized users!", "MyOrganizations_Detail_DeveloperSeatInfo": "You are using {0} of your {1} developer seats.", "NeedMoreSeatsForYourTeam": "Need more seats for your team?", diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/fi.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/fi.json index 22226ba956..eebf13cc0d 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/fi.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/fi.json @@ -553,8 +553,8 @@ "MyOrganizations_Detail_LicenseStartAndExpiryDate": "Lisenssin alkamispäivä - viimeinen voimassaolopäivä", "MyOrganizations_Detail_OwnerRightInfo": "Käytät {0} {1} omistajan oikeuksistasi.", "MyOrganizations_Detail_CopyApiKey": "Kopioi avain", - "MyOrganizations_Detail_ApiKeyDescription": "API-avain on {1}-palvelussa isännöivien PRO-pakettien tunnus.", - "MyOrganizations_Detail_YourPrivateNugetSource": "Yksityinen NuGet-lähteesi on {0}", + "MyOrganizations_Detail_ApiKeyDescription": "API-avain on {1}-palvelussa isännöivien PRO-pakettien tunnus.", + "MyOrganizations_Detail_YourPrivateNugetSource": "Yksityinen NuGet-lähteesi on {0}", "MyOrganizations_Detail_PrivateNugetSourceWarning": "Tämä lisätään automaattisesti syötteeksi NuGet.Configiin ABP-ratkaisussasi. Älä jaa yksityistä avaintasi luvattomien käyttäjien kanssa!", "MyOrganizations_Detail_DeveloperSeatInfo": "Käytät {0} {1} kehittäjäpaikastasi.", "NeedMoreSeatsForYourTeam": "Tarvitsetko lisää paikkoja tiimillesi?", diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/hr.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/hr.json index 6cacd8f01d..a7fc0c4965 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/hr.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/hr.json @@ -556,8 +556,8 @@ "MyOrganizations_Detail_LicenseStartAndExpiryDate": "Datum početka licence - Datum isteka", "MyOrganizations_Detail_OwnerRightInfo": "Koristite {0} od svojih {1} vlasničkih prava.", "MyOrganizations_Detail_CopyApiKey": "Kopirajte ključ", - "MyOrganizations_Detail_ApiKeyDescription": "API ključ je token PRO paketa hostiranih na {1}.", - "MyOrganizations_Detail_YourPrivateNugetSource": "Vaš privatni NuGet izvor je {0}", + "MyOrganizations_Detail_ApiKeyDescription": "API ključ je token PRO paketa hostiranih na {1}.", + "MyOrganizations_Detail_YourPrivateNugetSource": "Vaš privatni NuGet izvor je {0}", "MyOrganizations_Detail_PrivateNugetSourceWarning": "Ovo se automatski dodaje kao feed u vaš NuGet.Config u vašem ABP rješenju. Ne dijelite svoj privatni ključ s neovlaštenim korisnicima!", "MyOrganizations_Detail_DeveloperSeatInfo": "Koristite {0} od svojih {1} razvojnih mjesta.", "NeedMoreSeatsForYourTeam": "Trebate više mjesta za svoj tim?", diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/hu.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/hu.json index 58169ed73c..514a1b3a9f 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/hu.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/hu.json @@ -554,8 +554,8 @@ "MyOrganizations_Detail_LicenseStartAndExpiryDate": "licensz kezdő dátuma – lejárati dátum", "MyOrganizations_Detail_OwnerRightInfo": "Ön {1} tulajdonosi jogának {0}-át használja.", "MyOrganizations_Detail_CopyApiKey": "Másolja ki a kulcsot", - "MyOrganizations_Detail_ApiKeyDescription": "Az API-kulcs a(z) {1} webhelyen tárolt PRO-csomagok tokenje.", - "MyOrganizations_Detail_YourPrivateNugetSource": "Az Ön privát NuGet-forrása {0}", + "MyOrganizations_Detail_ApiKeyDescription": "Az API-kulcs a(z) {1} webhelyen tárolt PRO-csomagok tokenje.", + "MyOrganizations_Detail_YourPrivateNugetSource": "Az Ön privát NuGet-forrása {0}", "MyOrganizations_Detail_PrivateNugetSourceWarning": "Ez automatikusan hozzáadódik feedként a NuGet.Config-hoz az ABP-megoldásban. Ne ossza meg privát kulcsát illetéktelen felhasználókkal!", "MyOrganizations_Detail_DeveloperSeatInfo": "Ön {1} fejlesztői helyéből {0}-ot használ.", "NeedMoreSeatsForYourTeam": "Több hozzáférésre van szüksége a csapatának?", diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/ru.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/ru.json index 9fc25da395..917b32033a 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/ru.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/ru.json @@ -557,8 +557,8 @@ "MyOrganizations_Detail_LicenseStartAndExpiryDate": "Дата начала действия лицензии – дата истечения срока действия", "MyOrganizations_Detail_OwnerRightInfo": "Вы используете {0} ваших прав владельца {1}.", "MyOrganizations_Detail_CopyApiKey": "Скопируйте ключ", - "MyOrganizations_Detail_ApiKeyDescription": "Ключ API — это токен PRO-пакетов, размещенных на {1}.", - "MyOrganizations_Detail_YourPrivateNugetSource": "Ваш личный источник NuGet: {0}", + "MyOrganizations_Detail_ApiKeyDescription": "Ключ API — это токен PRO-пакетов, размещенных на {1}.", + "MyOrganizations_Detail_YourPrivateNugetSource": "Ваш личный источник NuGet: {0}", "MyOrganizations_Detail_PrivateNugetSourceWarning": "Он автоматически добавляется в качестве канала в ваш NuGet.Config в вашем решении ABP. ", "MyOrganizations_Detail_DeveloperSeatInfo": "Вы используете {0} из {1} мест разработчика.", "NeedMoreSeatsForYourTeam": "Вам нужно больше мест для вашей команды?", diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/tr.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/tr.json index 0ea5c73e71..fa8fce1bcc 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/tr.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/tr.json @@ -563,8 +563,8 @@ "MyOrganizations_Detail_LicenseStartAndExpiryDate": "Lisans Başlangıç Tarihi - Sona Erme Tarihi", "MyOrganizations_Detail_OwnerRightInfo": "{1} sahiplik hakkınızın {0}'ını kullanıyorsunuz.", "MyOrganizations_Detail_CopyApiKey": "Anahtarı Kopyala", - "MyOrganizations_Detail_ApiKeyDescription": "API Anahtarı, {1} üzerinde barındırılan PRO paketlerinin belirtecidir.", - "MyOrganizations_Detail_YourPrivateNugetSource": "Özel NuGet kaynağınız {0}", + "MyOrganizations_Detail_ApiKeyDescription": "API Anahtarı, {1} üzerinde barındırılan PRO paketlerinin belirtecidir.", + "MyOrganizations_Detail_YourPrivateNugetSource": "Özel NuGet kaynağınız {0}", "MyOrganizations_Detail_PrivateNugetSourceWarning": "Bu, ABP çözümünüzdeki NuGet.Config'inize otomatik olarak bir besleme olarak eklenir. Özel anahtarınızı yetkisiz kullanıcılarla paylaşmayın!", "MyOrganizations_Detail_DeveloperSeatInfo": "{1} geliştirici koltuğunuzun {0} tanesini kullanıyorsunuz.", "NeedMoreSeatsForYourTeam": "Takımınız için daha fazla geliştirici koltuğu gerekiyor mu?", diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/zh-Hans.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/zh-Hans.json index db53fde072..5dd86061de 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/zh-Hans.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/zh-Hans.json @@ -556,8 +556,8 @@ "MyOrganizations_Detail_LicenseStartAndExpiryDate": "许可证开始日期 - 到期日期", "MyOrganizations_Detail_OwnerRightInfo": "您正在使用{1}所有者权利中的{0}项权利。", "MyOrganizations_Detail_CopyApiKey": "复制密钥", - "MyOrganizations_Detail_ApiKeyDescription": "API 密钥是 {1}. 上托管的 PRO 包的标记。", - "MyOrganizations_Detail_YourPrivateNugetSource": "您的 NuGet 私有源是 {0}", + "MyOrganizations_Detail_ApiKeyDescription": "API 密钥是 {1}. 上托管的 PRO 包的标记。", + "MyOrganizations_Detail_YourPrivateNugetSource": "您的 NuGet 私有源是 {0}", "MyOrganizations_Detail_PrivateNugetSourceWarning": "此密钥会自动添加到 ABP 解决方案中的 NuGet.Config 中。请勿与未经授权的用户共享您的私人密钥!", "MyOrganizations_Detail_DeveloperSeatInfo": "您正在使用{1}个开发人员席位中的{0}个。", "NeedMoreSeatsForYourTeam": "您的团队需要更多座位?", diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/zh-Hant.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/zh-Hant.json index ade3b387d5..613ff1e4e5 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/zh-Hant.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/zh-Hant.json @@ -545,7 +545,7 @@ "MyOrganizations_Detail_OwnerRightInfo": "您正在使用您的 {1} 項所有者權利中的 {0} 項。", "MyOrganizations_Detail_CopyApiKey": "複製密鑰", "MyOrganizations_Detail_ApiKeyDescription": "API 金鑰是{1} 上託管的 PRO 包的令牌。", - "MyOrganizations_Detail_YourPrivateNugetSource": "您的私有 NuGet 來源是{0}", + "MyOrganizations_Detail_YourPrivateNugetSource": "您的私有 NuGet 來源是{0}", "MyOrganizations_Detail_PrivateNugetSourceWarning": "這會作為 feed 自動添加到 ABP 解決方案中的 NuGet.Config 中。不要與未經授權的用戶分享您的私鑰!", "MyOrganizations_Detail_DeveloperSeatInfo": "您正在使用 {1} 個開發者席位中的 {0} 個。", "NeedMoreSeatsForYourTeam": "您的團隊需要更多座位嗎?", From 9402ea300933f41add1fcc8e304ae2f2a99f0d9f Mon Sep 17 00:00:00 2001 From: Salih Date: Wed, 3 Jan 2024 15:26:58 +0300 Subject: [PATCH 10/98] Update en.json --- .../Commercial/Localization/Resources/en.json | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json index b5ad4b58fb..3bb59e500f 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json @@ -838,7 +838,7 @@ "ModulesPageTitle": "ABP Pre-Built Application Modules", "Volo.AbpIo.Commercial:040001": "API Access Key is incorrect.", "GetLepton": "Get Lepton Now", - "MyOrganizations_Detail_LicenseStartDate": "License Start Date", + "MyOrganizations_Detail_LicenseStartDate": "Start Date", "MyOrganizations_Detail_LicenseExpiryDate": "Expiry Date", "BlazoriseSupport": "How do I get the Blazorise license key and support from the Blazorise team?", "BlazoriseSupportExplanation": "Follow the steps below to get support from the Blazorise team and get your Blazorise license key:", @@ -1106,6 +1106,15 @@ "AutoRenewalDisabled": "Auto Renewal Disabled", "PaymentRequestIdIsNotProvided": "Payment request id is not provided.", "PaymentFailedInfo": "Sorry, payment failed! This could be due to insufficient funds, invalid credit card numbers or invalid pin", - "UsedPayment": "This payment has been already used" + "UsedPayment": "This payment has been already used", + "ABPStudioBetaAccess": "ABP Studio Beta Access", + "VisitABPStudio": "Visit ABP Studio", + "EditBillingInformation": "Edit Billing Information", + "Organization": "Organization", + "E-Book": "E-Book", + "CreditCards": "Credit Cards", + "BillingInformation": "Billing Information", + "AddNewCreditCard": "Add New Credit Card", + "MyOrganizations_LearnMorePlan": "Learn more about plans on the pricing page" } } From 3cca9a13cfcf3b2c087b64989c88e7efda9ebb05 Mon Sep 17 00:00:00 2001 From: maliming Date: Thu, 4 Jan 2024 13:41:07 +0800 Subject: [PATCH 11/98] Use Deepl to translate localization files Resovle #18665 --- .../2024-01-04-CLI-Online-Translate/Post.md | 72 ++++++++++++++++++ .../2024-01-04-CLI-Online-Translate/deepl.jpg | Bin 0 -> 466794 bytes 2 files changed, 72 insertions(+) create mode 100644 docs/en/Community-Articles/2024-01-04-CLI-Online-Translate/Post.md create mode 100644 docs/en/Community-Articles/2024-01-04-CLI-Online-Translate/deepl.jpg diff --git a/docs/en/Community-Articles/2024-01-04-CLI-Online-Translate/Post.md b/docs/en/Community-Articles/2024-01-04-CLI-Online-Translate/Post.md new file mode 100644 index 0000000000..abddfd43fd --- /dev/null +++ b/docs/en/Community-Articles/2024-01-04-CLI-Online-Translate/Post.md @@ -0,0 +1,72 @@ +# Use Deepl to translate localization files + +Translating localized text during the development ABP modules is a boring work. For this reason we have added the `translate` command to the CLI tool to translate the localization files, but it still requires manual translate texts by the developer. + +Now, We introduce a new way to translate the target language, which is to use the [Deepl](https://www.deepl.com/translator) translation service to translate the target language. + +You can use the `translate --online` command to in your module directory to translate the target language. + +For example, You have added all `en` localization texts to your module, and you want to translate them to `zh-Hans`, you can run the following command: + +``` +abp translate -r en -c zh-Hans --online --deepl-auth-key your_auth_key +``` + +* `-r` parameter is used to specify the source language. It is usually a localized file that you have created. +* `-c` parameter is used to specify the target language. It is usually a language that you want to translate. +* `--online` parameter is used to indicate that the translation is performed from the Deepl service. +* `--deepl-auth-key` parameter is the API key of your Deepl account. You can get it from [here](https://support.deepl.com/hc/en-us/articles/360020695820-Authentication-Key). + + +The output of the above command is as follows: + +``` +ABP CLI 8.0.0 +Abp translate online... +Target culture: zh-Hans +Reference culture: en +Create translation: Settings => 设置 +Create translation: SuccessfullySaved => 成功保存 +Create translation: Permission:SettingManagement => 设置管理 +Create translation: Permission:Emailing => 发送电子邮件 +Create translation: Permission:EmailingTest => 电子邮件测试 +Create translation: Permission:TimeZone => 时区 +Create translation: SendTestEmail => 发送测试电子邮件 +Create translation: SenderEmailAddress => 发件人电子邮件地址 +Create translation: TargetEmailAddress => 目标电子邮件地址 +Create translation: Subject => 主题 +Create translation: Body => 正文 +Create translation: TestEmailSubject => 测试电子邮件 {0} +Create translation: TestEmailBody => 在此测试电子邮件正文信息 +Create translation: SuccessfullySent => 成功发送 +Create translation: Send => 发送 +Create translation: Menu:Emailing => 发送电子邮件 +Create translation: Menu:TimeZone => 时区 +Create translation: DisplayName:Timezone => 时区 +Create translation: TimezoneHelpText => 此设置用于应用程序范围或基于租户的设置。 +Create translation: SmtpHost => 主机 +Create translation: SmtpPort => 端口 +Create translation: SmtpUserName => 用户名 +Create translation: SmtpPassword => 密码 +Create translation: SmtpDomain => 域名 +Create translation: SmtpEnableSsl => 启用 ssl +Create translation: SmtpUseDefaultCredentials => 使用默认凭据 +Create translation: DefaultFromAddress => 默认地址 +Create translation: DefaultFromDisplayName => 显示名称的默认值 +Create translation: Feature:SettingManagementGroup => 设置管理 +Create translation: Feature:SettingManagementEnable => 启用设置管理 +Create translation: Feature:SettingManagementEnableDescription => 在应用程序中启用设置管理系统。 +Create translation: Feature:AllowChangingEmailSettings => 允许更改电子邮件设置。 +Create translation: Feature:AllowChangingEmailSettingsDescription => 允许更改电子邮件设置。 +Write translation json to setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/zh-Hans.json. +``` + +The generated `zh-Hans.json` as follow: + +![zh-Hans.json](deepl.jpg) + +In this example, It only translates one `en.json` to `zh-Hans.json`, but if there are multiple `en.json` files in the module, it will translate all `en.json` files to `zh-Hans.json`. + +Of course, the translation is not always correct, you can update the translation in the generated `zh-Hans.json` files. + +Enjoy it! diff --git a/docs/en/Community-Articles/2024-01-04-CLI-Online-Translate/deepl.jpg b/docs/en/Community-Articles/2024-01-04-CLI-Online-Translate/deepl.jpg new file mode 100644 index 0000000000000000000000000000000000000000..c54b9840f0df9a789e2058c1ba44f5b7d8448dee GIT binary patch literal 466794 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]Sx)$7a1cvinRZE#nl#|}%0UCcHc>Ee#Em_Ybw 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

bGI?k0;>0S>do&()f~AaxK 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

_*xSRiN(3feiuqpmgQ)j=f)eJw&X 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 WKbZ4#_Wv|z00K`}KbLh*2~7YxrIX+Q literal 0 HcmV?d00001 From 9595b64d404bc0b38d2b260902024f64f0d5de00 Mon Sep 17 00:00:00 2001 From: Salih Date: Thu, 4 Jan 2024 13:09:36 +0300 Subject: [PATCH 12/98] add text-white --- .../Commercial/Localization/Resources/ar.json | 2 +- .../Commercial/Localization/Resources/en.json | 6 ++++-- .../Commercial/Localization/Resources/fi.json | 2 +- .../Commercial/Localization/Resources/hr.json | 2 +- .../Commercial/Localization/Resources/hu.json | 2 +- .../Commercial/Localization/Resources/ru.json | 2 +- .../Commercial/Localization/Resources/tr.json | 2 +- .../Commercial/Localization/Resources/zh-Hans.json | 2 +- .../Commercial/Localization/Resources/zh-Hant.json | 2 +- 9 files changed, 12 insertions(+), 10 deletions(-) diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/ar.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/ar.json index ec8b0a752d..b5103b8b4f 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/ar.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/ar.json @@ -615,7 +615,7 @@ "Tools_Page_Description": "يوفر ABP التجاري أدوات تطوير سريعة للتطبيقات لزيادة إنتاجية المطورين. يتيح لك ABP Suite إنشاء صفحات CRUD بسهولة.", "DeveloperPrice": "سعر المطور", "AdditionalDeveloperPaymentInfoSection_AdditionalDevelopers": "{0} مطورين", - "LicenseRemainingDays": "لمدة {0} يوم", + "LicenseRemainingDays": "لمدة {0} يوم", "ExtendPaymentInfoSection_Description": "من خلال تمديد / تجديد رخصتك، ستستمر في الحصول على الدعم المتميز. ستتمكن أيضًا من الحصول على تحديثات رئيسية أو ثانوية للوحدات والسمات. ستتمكن من الاستمرار في إنشاء مشاريع جديدة. وستظل قادرًا على استخدام ABP Suite مما يسرع من تطويرك.", "LicenseRenewalPrice": "سعر تجديد الرخصة", "LicensePrice": "سعر الرخصة", diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json index 3bb59e500f..e8b8f4df76 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json @@ -641,7 +641,7 @@ "Tools_Page_Description": "ABP Commercial provides rapid application development tooling to increase developer productivity. ABP Suite allows you to create CRUD pages easily.", "DeveloperPrice": "Developer Price", "AdditionalDeveloperPaymentInfoSection_AdditionalDevelopers": "{0} developers", - "LicenseRemainingDays": "for {0} days", + "LicenseRemainingDays": "for {0} days", "ExtendPaymentInfoSection_Description": "By extending/renewing your license, you will continue to get premium support. You will also be able to get major or minor updates for modules and themes. You will be able to continue creating new projects. And you will still be able to use ABP Suite which speeds up your development.", "LicenseRenewalPrice": "License renewal price", "LicensePrice": "License Price", @@ -1115,6 +1115,8 @@ "CreditCards": "Credit Cards", "BillingInformation": "Billing Information", "AddNewCreditCard": "Add New Credit Card", - "MyOrganizations_LearnMorePlan": "Learn more about plans on the pricing page" + "MyOrganizations_LearnMorePlan": "Learn more about plans on the pricing page", + "AutoLicenseRenewalIsNotEnabled": "Auto license renewal is not enabled.", + "SetAsDefaultPaymentMethod": "Set as default payment method" } } diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/fi.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/fi.json index eebf13cc0d..5d5aa90c75 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/fi.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/fi.json @@ -639,7 +639,7 @@ "Tools_Page_Description": "ABP Commercial tarjoaa nopeat sovelluskehitystyökalut kehittäjien tuottavuuden lisäämiseksi. ABP Suiten avulla voit luoda CRUD-sivuja helposti.", "DeveloperPrice": "Kehittäjän hinta", "AdditionalDeveloperPaymentInfoSection_AdditionalDevelopers": "{0} kehittäjät", - "LicenseRemainingDays": " {0} päivän ajan", + "LicenseRemainingDays": " {0} päivän ajan", "ExtendPaymentInfoSection_Description": "Pidentämällä/uusimalla käyttölupaasi saat edelleen premium-tuen. Voit myös saada suurempia tai pieniä päivityksiä moduuleille ja teemoille. Voit jatkaa uusien projektien luomista. Voit silti käyttää ABP Suitea, joka nopeuttaa kehitystäsi.", "LicenseRenewalPrice": "Lisenssin uusimisen hinta", "LicensePrice": "Lisenssin hinta", diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/hr.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/hr.json index a7fc0c4965..d671367ec5 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/hr.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/hr.json @@ -641,7 +641,7 @@ "Tools_Page_Description": "ABP Commercial pruža alate za brzi razvoj aplikacija za povećanje produktivnosti programera. ABP Suite vam omogućuje jednostavno stvaranje CRUD stranica.", "DeveloperPrice": "Cijena programera", "AdditionalDeveloperPaymentInfoSection_AdditionalDevelopers": "{0} programeri", - "LicenseRemainingDays": "za {0} dana", + "LicenseRemainingDays": "za {0} dana", "ExtendPaymentInfoSection_Description": "Produljenjem/obnavljanjem licence i dalje ćete dobivati premium podršku . Također ćete moći dobiti veća ili manja ažuriranja za module i teme. Moći ćete nastaviti stvarati nove projekte. I dalje ćete moći koristiti ABP Suite koji ubrzava vaš razvoj.", "LicenseRenewalPrice": "Cijena obnove licence", "LicensePrice": "Cijena licence", diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/hu.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/hu.json index 514a1b3a9f..77eafe8df7 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/hu.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/hu.json @@ -639,7 +639,7 @@ "Tools_Page_Description": "Az ABP Commercial gyors alkalmazásfejlesztési eszközöket biztosít a fejlesztők termelékenységének növelése érdekében. Az ABP Suite segítségével könnyedén hozhat létre CRUD oldalakat.", "DeveloperPrice": "Fejlesztői ár", "AdditionalDeveloperPaymentInfoSection_AdditionalDevelopers": "{0} fejlesztő", - "LicenseRemainingDays": "{0} napig", + "LicenseRemainingDays": "{0} napig", "ExtendPaymentInfoSection_Description": "A licensz meghosszabbításával/megújításával továbbra is prémium támogatást kap. Emellett kisebb-nagyobb frissítéseket is kaphat a modulokhoz és témákhoz. Folytathatja új projektek létrehozását. És továbbra is használhatja az ABP Suite -ot, amely felgyorsítja a fejlesztést.", "LicenseRenewalPrice": "Licensz megújítási ára", "LicensePrice": "Licensz ára", diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/ru.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/ru.json index 917b32033a..43963ac972 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/ru.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/ru.json @@ -642,7 +642,7 @@ "Tools_Page_Description": "ABP Commercial предоставляет инструменты для быстрой разработки приложений, позволяющие повысить продуктивность разработчиков. ", "DeveloperPrice": "Цена застройщика", "AdditionalDeveloperPaymentInfoSection_AdditionalDevelopers": "{0} Разработчики", - "LicenseRemainingDays": "для {0} дни", + "LicenseRemainingDays": "для {0} дни", "ExtendPaymentInfoSection_Description": "Продлив/продлив лицензию, вы продолжите получать премиум-поддержка. ABP Люкс что ускоряет ваше развитие.", "LicenseRenewalPrice": "Стоимость продления лицензии", "LicensePrice": "Цена лицензии", diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/tr.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/tr.json index fa8fce1bcc..1a679ff5d1 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/tr.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/tr.json @@ -648,7 +648,7 @@ "Tools_Page_Description": "ABP Commercial, geliştirici verimliliğini artırmak için hızlı uygulama geliştirme araçları sağlar. ABP Suite, CRUD sayfalarını kolayca oluşturmanızı sağlar.", "DeveloperPrice": "Geliştirici Fiyatı", "AdditionalDeveloperPaymentInfoSection_AdditionalDevelopers": "{0} geliştiriciler", - "LicenseRemainingDays": " {0} gün boyunca", + "LicenseRemainingDays": " {0} gün boyunca", "ExtendPaymentInfoSection_Description": "Lisansınızı uzatarak/yenileyerek premium destek almaya devam edeceksiniz. You will also be able to get major or minor updates for modules and themes. You will be able to continue creating new projects. Ve gelişiminizi hızlandıran ABP Suite'i kullanmaya devam edebileceksiniz.", "LicenseRenewalPrice": "Lisans yenileme fiyatı", "LicensePrice": "Lisans fiyatı", diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/zh-Hans.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/zh-Hans.json index 5dd86061de..37d63cf826 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/zh-Hans.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/zh-Hans.json @@ -641,7 +641,7 @@ "Tools_Page_Description": "ABP 商业版提供快速应用程序开发工具,以提高开发人员的工作效率。ABP Suite 可让您轻松创建 CRUD 页面。", "DeveloperPrice": "开发者价格", "AdditionalDeveloperPaymentInfoSection_AdditionalDevelopers": "{0}<小>开发人员 {0} 天", + "LicenseRemainingDays": "为 {0} 天", "ExtendPaymentInfoSection_Description": "延长/续订许可证后,您将继续获得高级支持。您还可以获得模块和主题的主要或次要更新。您还可以继续创建新项目。您还可以使用 ABP Suite 来加快开发速度。", "LicenseRenewalPrice": "许可证续期价格", "LicensePrice": "许可证价格", diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/zh-Hant.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/zh-Hant.json index 613ff1e4e5..312a19994c 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/zh-Hant.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/zh-Hant.json @@ -628,7 +628,7 @@ "Tools_Page_Description": "ABP Commercial 提供快速應用程式開發工具來提高開發人員的工作效率。 ABP Suite 讓您輕鬆建立 CRUD 頁面。", "DeveloperPrice": "開發商價格", "AdditionalDeveloperPaymentInfoSection_AdditionalDevelopers": "{0}開發者", - "LicenseRemainingDays": "{0}天", + "LicenseRemainingDays": "{0}天", "ExtendPaymentInfoSection_Description": "透過延長/更新您的許可證,您將繼續獲得高級支援。您還可以獲得模組和主題的主要或次要更新。您將能夠繼續建立新專案。而且您仍然可以使用ABP Suite來加快您的開發速度。", "LicenseRenewalPrice": "許可證更新價格", "LicensePrice": "許可價格", From b7aeb4c7c7dad08998a0c2b548cbc164fee308b4 Mon Sep 17 00:00:00 2001 From: Salih Date: Thu, 4 Jan 2024 13:31:19 +0300 Subject: [PATCH 13/98] Update en.json --- .../Commercial/Localization/Resources/en.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json index e8b8f4df76..ebc989c12e 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json @@ -1117,6 +1117,7 @@ "AddNewCreditCard": "Add New Credit Card", "MyOrganizations_LearnMorePlan": "Learn more about plans on the pricing page", "AutoLicenseRenewalIsNotEnabled": "Auto license renewal is not enabled.", - "SetAsDefaultPaymentMethod": "Set as default payment method" + "SetAsDefaultPaymentMethod": "Set as default payment method", + "{0}PerAdditionalDeveloper": "{0} per additional developer" } } From 717053c28dc7282de0e71510ab626e706866e94b Mon Sep 17 00:00:00 2001 From: Salih Date: Thu, 4 Jan 2024 15:17:38 +0300 Subject: [PATCH 14/98] Update en.json --- .../Commercial/Localization/Resources/en.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json index ebc989c12e..de30a6f8b2 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json @@ -1118,6 +1118,7 @@ "MyOrganizations_LearnMorePlan": "Learn more about plans on the pricing page", "AutoLicenseRenewalIsNotEnabled": "Auto license renewal is not enabled.", "SetAsDefaultPaymentMethod": "Set as default payment method", - "{0}PerAdditionalDeveloper": "{0} per additional developer" + "{0}PerAdditionalDeveloper": "{0} per additional developer", + "CardAlias": "Card Alias" } } From b3f919a4cd3f114257aa965be754631d403e0ef6 Mon Sep 17 00:00:00 2001 From: Salih Date: Mon, 8 Jan 2024 09:49:21 +0300 Subject: [PATCH 15/98] commit --- .../AbpIoLocalization/Admin/Localization/Resources/en.json | 6 ++++-- .../Commercial/Localization/Resources/en.json | 4 ++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json index d428ff0480..eeb0c83547 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json @@ -571,7 +571,7 @@ "PaymentAlreadyTried": "Payment already tried!", "PaymentIsNotFailed": "Payment is not failed!", "OrganizationIdIsNull": "OrganizationId is null!", - "Menu:OrganizationAutoRenewalPayments": "Organization Auto Renewal Payments", + "Menu:AutoRenewals": "Auto Renewals", "OrganizationAutoRenewalPayments": "Organization Auto Renewal Payments", "PaymentDate": "Payment Date", "TryCount": "Try Count", @@ -587,6 +587,8 @@ "LastAutoRenewalPaymentTime": "Last Auto Renewal Payment Time", "OrganizationDoesNotHaveACreditCard": "Organization does not have a credit card!", "Permission:EditWinners": "Edit Winners", - "Permission:ChangeDrawingStatus": "Change Drawing Status" + "Permission:ChangeDrawingStatus": "Change Drawing Status", + "Menu:Licenses": "Licenses", + "OrganizationId": "Organization Id" } } diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json index de30a6f8b2..795434ad89 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json @@ -1094,12 +1094,12 @@ "YouAreNotAuthorizedToPayThisPaymentRequest": "You are not authorized to pay this payment request.", "YouAreNotAuthorizedToCreateBillingInfoForThisPaymentRequest": "You are not authorized to create billing info for this payment request.", "OrganizationNotFound": "Organization not found.", - "CannotDeleteDefaultCardBecauseAutoRenewalEnabled": "You cannot delete this card because it is your default card and you have auto renewal enabled. Please disable auto renewal first.", + "CannotDeleteDefaultCardBecauseAutoRenewalEnabled": "You cannot delete this card at the moment because the Auto-Renewal feature is enabled. To delete the card, first disable Auto-Renewal.", "AreYouSureWantToDeleteThisCard": "Are you sure you want to delete this card?", "AreYouSureWantToSetThisCardAsDefault": "Are you sure you want to set this card as default?", "OrganizationBillingInfoIsNotSuitableForIyzicoPayment": "Your organization's billing info is not suitable for iyzico payment.", "AutomaticRenewal": "Automatic Renewal", - "AutomaticRenewal_Description": "Renewing a license before it expires lets you get a discount of up to %40. The auto-renewal process lets you renew your license without losing this discount, and your development will never interrupt. Auto-renewal is only available for credit cards. You can disable auto-renewal at any time by accessing your Organization Management page. ABP.io does not save your credit card information, but our global payment gateways do secure savings.", + "AutomaticRenewal_Description": "Renewing a license before it expires lets you get a discount of up to %40. The auto-renewal process lets you renew your license without losing this discount, and your development will never interrupt. Auto-renewal is only available for credit card payment. You can disable auto-renewal at any time by accessing your Organization Management page. ABP does not save your credit card information, but our global payment gateways do secure savings.", "CardNotFoundMessage": "Do you want to add a new card?", "CardNotFoundTitle": "Card Not Found", "AutoRenewalEnabled": "Auto Renewal Enabled", From c79e401a66f9b9b6f19818cb0215ffd9883e3b76 Mon Sep 17 00:00:00 2001 From: Salih Date: Mon, 8 Jan 2024 18:17:51 +0300 Subject: [PATCH 16/98] Update en.json --- .../Commercial/Localization/Resources/en.json | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json index 9ce2577985..ce9db0d46e 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json @@ -1119,6 +1119,13 @@ "AutoLicenseRenewalIsNotEnabled": "Auto license renewal is not enabled.", "SetAsDefaultPaymentMethod": "Set as default payment method", "{0}PerAdditionalDeveloper": "{0} per additional developer", - "CardAlias": "Card Alias" + "CardAlias": "Card Alias", + "AbpDoesNotSaveYourPaymentDetails_Description": "The payment data will be saved in {2} security vaults and you can remove stored data anytime. Enabling auto-renewal ensures that your ABP subscription will automatically renew prior to expiration, providing a valid credit card. Disabling auto-renewal means you will have to renew your subscription manually. To continue your project development without interruption, we suggest you enable the Auto-Renewal option.", + "AddBillingInformation": "Add Billing Information", + "YouHaveNoCardsSaved": "You have no cards saved.", + "CreateCreditCardModal_BillingDetails_Description": "You must save your billing details to be able to add your credit card.", + "TaxNo": "Tax No", + "CardNumber": "Card Number", + "NameOnCard": "Name on Card", } } From 669721384b6fceca5dfd9225e106beffdd6148aa Mon Sep 17 00:00:00 2001 From: maliming Date: Tue, 9 Jan 2024 14:13:29 +0800 Subject: [PATCH 17/98] Update Multi-Tenancy.md --- docs/en/Multi-Tenancy.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/en/Multi-Tenancy.md b/docs/en/Multi-Tenancy.md index 661d99da16..392bea6809 100644 --- a/docs/en/Multi-Tenancy.md +++ b/docs/en/Multi-Tenancy.md @@ -394,6 +394,8 @@ app.UseMultiTenancy(); `ITenantStore` is used to get the tenant configuration from a data source. +> Tenant names are not case-sensitive. `ITenantStore` will use the `NormalizedName` parameter to get tenants, You need to use `ITenantNormalizer to normalize tenant names. + #### Tenant Management Module The [tenant management module](Modules/Tenant-Management) is **included in the startup templates** and implements the `ITenantStore` interface to get the tenants and their configuration from a database. It also provides the necessary functionality and UI to manage the tenants and their connection strings. @@ -408,11 +410,13 @@ The [tenant management module](Modules/Tenant-Management) is **included in the s "Tenants": [ { "Id": "446a5211-3d72-4339-9adc-845151f8ada0", - "Name": "tenant1" + "Name": "tenant1", + "NormalizedName": "TENANT1" }, { "Id": "25388015-ef1c-4355-9c18-f6b6ddbaf89d", "Name": "tenant2", + "NormalizedName": "TENANT2", "ConnectionStrings": { "Default": "...tenant2's db connection string here..." } From 0d1fcd91d335d2c81332e75fd08af0c2ed04090b Mon Sep 17 00:00:00 2001 From: Salih Date: Tue, 9 Jan 2024 14:32:45 +0300 Subject: [PATCH 18/98] Update en.json --- .../AbpIoLocalization/Commercial/Localization/Resources/en.json | 1 + 1 file changed, 1 insertion(+) diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json index ce9db0d46e..510c62ca7e 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json @@ -1127,5 +1127,6 @@ "TaxNo": "Tax No", "CardNumber": "Card Number", "NameOnCard": "Name on Card", + "BillingDetails": "Billing Details" } } From 1a3f35e085168cbd9ed565a8106b3981a485ea2a Mon Sep 17 00:00:00 2001 From: Salih Date: Wed, 10 Jan 2024 10:57:25 +0300 Subject: [PATCH 19/98] Update en.json --- .../Commercial/Localization/Resources/en.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json index 510c62ca7e..797756e54d 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json @@ -1127,6 +1127,7 @@ "TaxNo": "Tax No", "CardNumber": "Card Number", "NameOnCard": "Name on Card", - "BillingDetails": "Billing Details" + "BillingDetails": "Billing Details", + "ThereIsNoDeveloper": "There is no developer." } } From b2dae320054ac75a9aab70d8a144eaf524d4b10a Mon Sep 17 00:00:00 2001 From: Salih Date: Mon, 15 Jan 2024 16:20:11 +0300 Subject: [PATCH 20/98] Update en.json --- .../AbpIoLocalization/Admin/Localization/Resources/en.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json index 8e55766ff2..29211d4d8e 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json @@ -590,6 +590,7 @@ "Permission:ChangeDrawingStatus": "Change Drawing Status", "Menu:Licenses": "Licenses", "OrganizationId": "Organization Id", - "RemoveAllWinnersConfirmationMessage": "Are you sure you want to remove all winners?" + "RemoveAllWinnersConfirmationMessage": "Are you sure you want to remove all winners?", + "AutoRenewals": "Auto Renewals" } } From df87ea49c79da8696baa62b5636782f8f46a554a Mon Sep 17 00:00:00 2001 From: Salih Date: Tue, 16 Jan 2024 10:31:17 +0300 Subject: [PATCH 21/98] Update en.json --- .../Commercial/Localization/Resources/en.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json index 797756e54d..082438272d 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json @@ -1128,6 +1128,7 @@ "CardNumber": "Card Number", "NameOnCard": "Name on Card", "BillingDetails": "Billing Details", - "ThereIsNoDeveloper": "There is no developer." + "ThereIsNoDeveloper": "There is no developer.", + "CardDetails": "Card Details" } } From ed3ada88ba1b8fa813508e54ff3af1c2f368be0d Mon Sep 17 00:00:00 2001 From: Enis Necipoglu Date: Tue, 16 Jan 2024 16:22:54 +0300 Subject: [PATCH 22/98] Add an empty view for blog posts --- .../CmsKit/Localization/Resources/en.json | 5 +- .../Pages/Public/CmsKit/Blogs/Index.cshtml | 78 +++++++++++-------- 2 files changed, 47 insertions(+), 36 deletions(-) diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/en.json b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/en.json index 3bba4fc599..0a4a99fc30 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/en.json +++ b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/en.json @@ -1,5 +1,5 @@ { - "culture": "en", + "culture": "en", "texts": { "AddSubMenuItem": "Add Sub Menu Item", "AreYouSure": "Are You Sure?", @@ -227,6 +227,7 @@ "CssClass": "CSS Class", "TagsHelpText": "Tags should be comma-separated (e.g.: tag1, tag2, tag3)", "ThisPartOfContentCouldntBeLoaded": "This part of content couldn't be loaded.", - "DuplicateCommentAttemptMessage": "Duplicate comment post attempt detected. Your comment has already been submitted." + "DuplicateCommentAttemptMessage": "Duplicate comment post attempt detected. Your comment has already been submitted.", + "NoBlogPostYet": "No blog post yet!" } } \ No newline at end of file diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/Public/CmsKit/Blogs/Index.cshtml b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/Public/CmsKit/Blogs/Index.cshtml index 6f2a82e220..f935e734dc 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/Public/CmsKit/Blogs/Index.cshtml +++ b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/Public/CmsKit/Blogs/Index.cshtml @@ -59,38 +59,48 @@


} - - @foreach (var blog in Model.Blogs.Items) - { - - - @if (blog.CoverImageMediaId != null) - { - - } - else - { - - } - -
@blog.Title
-

- @@@blog.Author?.UserName - @blog.CreationTime -

-

@blog.ShortDescription

- -
-
+@if (Model.Blogs.TotalCount > 0) +{ + + @foreach (var blog in Model.Blogs.Items) + { + + + @if (blog.CoverImageMediaId != null) + { + + } + else + { + + } + +
@blog.Title
+

+ @@@blog.Author?.UserName + @blog.CreationTime +

+

@blog.ShortDescription

+ +
+
+
+ } +
+ + + - } - - - - - - +
+} +else +{ +
+

+

@L["NoBlogPostYet"]

+
+} From 0e4fccaee8ee8eac7c6fd81f849a24bdbbd402e2 Mon Sep 17 00:00:00 2001 From: Enis Necipoglu Date: Wed, 17 Jan 2024 11:22:29 +0300 Subject: [PATCH 23/98] Add FindTitleAsync to IPageRepository --- .../Volo.CmsKit.Domain/Volo/CmsKit/Pages/IPageRepository.cs | 2 ++ .../Volo/CmsKit/Pages/EfCorePageRepository.cs | 5 +++++ .../Volo/CmsKit/MongoDB/Pages/MongoPageRepository.cs | 6 ++++++ 3 files changed, 13 insertions(+) diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Pages/IPageRepository.cs b/modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Pages/IPageRepository.cs index 0b75c32d6b..2add03f1fd 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Pages/IPageRepository.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Pages/IPageRepository.cs @@ -24,4 +24,6 @@ public interface IPageRepository : IBasicRepository Task ExistsAsync(string slug, CancellationToken cancellationToken = default); Task> GetListOfHomePagesAsync(CancellationToken cancellationToken = default); + + Task FindTitleAsync(Guid pageId, CancellationToken cancellationToken = default); } diff --git a/modules/cms-kit/src/Volo.CmsKit.EntityFrameworkCore/Volo/CmsKit/Pages/EfCorePageRepository.cs b/modules/cms-kit/src/Volo.CmsKit.EntityFrameworkCore/Volo/CmsKit/Pages/EfCorePageRepository.cs index aefd834013..4af6bf18f3 100644 --- a/modules/cms-kit/src/Volo.CmsKit.EntityFrameworkCore/Volo/CmsKit/Pages/EfCorePageRepository.cs +++ b/modules/cms-kit/src/Volo.CmsKit.EntityFrameworkCore/Volo/CmsKit/Pages/EfCorePageRepository.cs @@ -68,4 +68,9 @@ public class EfCorePageRepository : EfCoreRepository x.IsHomePage, cancellationToken: GetCancellationToken(cancellationToken)); } + + public async Task FindTitleAsync(Guid pageId, CancellationToken cancellationToken = default) + { + return await (await GetDbSetAsync()).Where(x => x.Id == pageId).Select(x => x.Title).FirstOrDefaultAsync(cancellationToken); + } } diff --git a/modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Pages/MongoPageRepository.cs b/modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Pages/MongoPageRepository.cs index 601aad0570..565530fcb7 100644 --- a/modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Pages/MongoPageRepository.cs +++ b/modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Pages/MongoPageRepository.cs @@ -76,4 +76,10 @@ public class MongoPageRepository : MongoDbRepository x.IsHomePage, cancellationToken: GetCancellationToken(cancellationToken)); } + + public async Task FindTitleAsync(Guid pageId, CancellationToken cancellationToken = default) + { + return await (await GetMongoQueryableAsync(cancellationToken)).Where(x => x.Id == pageId).Select(x => x.Title) + .FirstOrDefaultAsync(cancellationToken); + } } From 673adf14921c04db72b6e42b3101fe3d431c3bcb Mon Sep 17 00:00:00 2001 From: Enis Necipoglu Date: Wed, 17 Jan 2024 11:22:45 +0300 Subject: [PATCH 24/98] Add tests for FindTitleAsync to IPageRepository --- .../Pages/PageRepository_Test.cs | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/modules/cms-kit/test/Volo.CmsKit.TestBase/Pages/PageRepository_Test.cs b/modules/cms-kit/test/Volo.CmsKit.TestBase/Pages/PageRepository_Test.cs index dcdcef5ad3..6c4c57cc47 100644 --- a/modules/cms-kit/test/Volo.CmsKit.TestBase/Pages/PageRepository_Test.cs +++ b/modules/cms-kit/test/Volo.CmsKit.TestBase/Pages/PageRepository_Test.cs @@ -1,4 +1,5 @@ -using System.Linq; +using System; +using System.Linq; using System.Threading.Tasks; using Shouldly; using Volo.Abp.Modularity; @@ -99,4 +100,20 @@ public abstract class PageRepository_Test : CmsKitTestBase Date: Wed, 17 Jan 2024 11:23:23 +0300 Subject: [PATCH 25/98] Add MenuItemWithDetailsDto to IMenuItemAdminAppService --- .../CmsKit/Admin/Menus/IMenuItemAdminAppService.cs | 2 +- .../CmsKit/Admin/Menus/MenuItemWithDetailsDto.cs | 10 ++++++++++ .../CmsKitAdminApplicationAutoMapperProfile.cs | 3 +++ .../CmsKit/Admin/Menus/MenuItemAdminAppService.cs | 13 ++++++++++--- .../CmsKit/Admin/Menus/MenuItemAdminController.cs | 2 +- 5 files changed, 25 insertions(+), 5 deletions(-) create mode 100644 modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Menus/MenuItemWithDetailsDto.cs diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Menus/IMenuItemAdminAppService.cs b/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Menus/IMenuItemAdminAppService.cs index 74aac7b814..a8908129d2 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Menus/IMenuItemAdminAppService.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Menus/IMenuItemAdminAppService.cs @@ -10,7 +10,7 @@ public interface IMenuItemAdminAppService : IApplicationService { Task> GetListAsync(); - Task GetAsync(Guid id); + Task GetAsync(Guid id); Task CreateAsync(MenuItemCreateInput input); diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Menus/MenuItemWithDetailsDto.cs b/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Menus/MenuItemWithDetailsDto.cs new file mode 100644 index 0000000000..a6d9906157 --- /dev/null +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Menus/MenuItemWithDetailsDto.cs @@ -0,0 +1,10 @@ +using System; +using Volo.CmsKit.Menus; + +namespace Volo.CmsKit.Admin.Menus; + +[Serializable] +public class MenuItemWithDetailsDto : MenuItemDto +{ + public string? PageTitle { get; set; } +} diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/CmsKitAdminApplicationAutoMapperProfile.cs b/modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/CmsKitAdminApplicationAutoMapperProfile.cs index 56f58f8078..1394b608c7 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/CmsKitAdminApplicationAutoMapperProfile.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/CmsKitAdminApplicationAutoMapperProfile.cs @@ -46,5 +46,8 @@ public class CmsKitAdminApplicationAutoMapperProfile : Profile CreateMap().MapExtraProperties(); CreateMap().MapExtraProperties(); + CreateMap() + .Ignore(x => x.PageTitle) + .MapExtraProperties(); } } diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/Menus/MenuItemAdminAppService.cs b/modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/Menus/MenuItemAdminAppService.cs index 8eac471a22..3a323efb13 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/Menus/MenuItemAdminAppService.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/Menus/MenuItemAdminAppService.cs @@ -43,10 +43,17 @@ public class MenuItemAdminAppService : CmsKitAdminAppServiceBase, IMenuItemAdmin ); } - public virtual async Task GetAsync(Guid id) + public virtual async Task GetAsync(Guid id) { - var menu = await MenuItemRepository.GetAsync(id); - return ObjectMapper.Map(menu); + var menuItem = await MenuItemRepository.GetAsync(id); + var dto = ObjectMapper.Map(menuItem); + + if (menuItem.PageId.HasValue) + { + dto.PageTitle = await PageRepository.FindTitleAsync(menuItem.PageId.Value); + } + + return dto; } [Authorize(CmsKitAdminPermissions.Menus.Create)] diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.HttpApi/Volo/CmsKit/Admin/Menus/MenuItemAdminController.cs b/modules/cms-kit/src/Volo.CmsKit.Admin.HttpApi/Volo/CmsKit/Admin/Menus/MenuItemAdminController.cs index a0325f4f27..8540e5306e 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.HttpApi/Volo/CmsKit/Admin/Menus/MenuItemAdminController.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.HttpApi/Volo/CmsKit/Admin/Menus/MenuItemAdminController.cs @@ -36,7 +36,7 @@ public class MenuItemAdminController : CmsKitAdminController, IMenuItemAdminAppS [HttpGet] [Route("{id}")] - public virtual Task GetAsync(Guid id) + public virtual Task GetAsync(Guid id) { return MenuItemAdminAppService.GetAsync(id); } From fe86d1a7ba5a6b3db26ef7d58575c787b48decf5 Mon Sep 17 00:00:00 2001 From: Enis Necipoglu Date: Wed, 17 Jan 2024 11:25:11 +0300 Subject: [PATCH 26/98] Update client-proxies --- .../MenuItemAdminClientProxy.Generated.cs | 4 +- .../cms-kit-admin-generate-proxy.json | 3104 ++++++++--------- 2 files changed, 1554 insertions(+), 1554 deletions(-) diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.HttpApi.Client/ClientProxies/Volo/CmsKit/Admin/Menus/MenuItemAdminClientProxy.Generated.cs b/modules/cms-kit/src/Volo.CmsKit.Admin.HttpApi.Client/ClientProxies/Volo/CmsKit/Admin/Menus/MenuItemAdminClientProxy.Generated.cs index 461ae877bd..70daab4da0 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.HttpApi.Client/ClientProxies/Volo/CmsKit/Admin/Menus/MenuItemAdminClientProxy.Generated.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.HttpApi.Client/ClientProxies/Volo/CmsKit/Admin/Menus/MenuItemAdminClientProxy.Generated.cs @@ -23,9 +23,9 @@ public partial class MenuItemAdminClientProxy : ClientProxyBase>(nameof(GetListAsync)); } - public virtual async Task GetAsync(Guid id) + public virtual async Task GetAsync(Guid id) { - return await RequestAsync(nameof(GetAsync), new ClientProxyRequestTypeValue + return await RequestAsync(nameof(GetAsync), new ClientProxyRequestTypeValue { { typeof(Guid), id } }); diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.HttpApi.Client/ClientProxies/cms-kit-admin-generate-proxy.json b/modules/cms-kit/src/Volo.CmsKit.Admin.HttpApi.Client/ClientProxies/cms-kit-admin-generate-proxy.json index cbb5992ebd..b8d0738fac 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.HttpApi.Client/ClientProxies/cms-kit-admin-generate-proxy.json +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.HttpApi.Client/ClientProxies/cms-kit-admin-generate-proxy.json @@ -4,60 +4,102 @@ "rootPath": "cms-kit-admin", "remoteServiceName": "CmsKitAdmin", "controllers": { - "Volo.CmsKit.Admin.Tags.EntityTagAdminController": { - "controllerName": "EntityTagAdmin", - "controllerGroupName": "EntityTagAdmin", + "Volo.CmsKit.Admin.Blogs.BlogAdminController": { + "controllerName": "BlogAdmin", + "controllerGroupName": "BlogAdmin", "isRemoteService": true, "isIntegrationService": false, "apiVersion": null, - "type": "Volo.CmsKit.Admin.Tags.EntityTagAdminController", + "type": "Volo.CmsKit.Admin.Blogs.BlogAdminController", "interfaces": [ { - "type": "Volo.CmsKit.Admin.Tags.IEntityTagAdminAppService", - "name": "IEntityTagAdminAppService", + "type": "Volo.CmsKit.Admin.Blogs.IBlogAdminAppService", + "name": "IBlogAdminAppService", "methods": [ { - "name": "AddTagToEntityAsync", + "name": "GetAsync", + "parametersOnMethod": [ + { + "name": "id", + "typeAsString": "System.Guid, System.Private.CoreLib", + "type": "System.Guid", + "typeSimple": "string", + "isOptional": false, + "defaultValue": null + } + ], + "returnValue": { + "type": "Volo.CmsKit.Admin.Blogs.BlogDto", + "typeSimple": "Volo.CmsKit.Admin.Blogs.BlogDto" + } + }, + { + "name": "GetListAsync", "parametersOnMethod": [ { "name": "input", - "typeAsString": "Volo.CmsKit.Admin.Tags.EntityTagCreateDto, Volo.CmsKit.Admin.Application.Contracts", - "type": "Volo.CmsKit.Admin.Tags.EntityTagCreateDto", - "typeSimple": "Volo.CmsKit.Admin.Tags.EntityTagCreateDto", + "typeAsString": "Volo.CmsKit.Admin.Blogs.BlogGetListInput, Volo.CmsKit.Admin.Application.Contracts", + "type": "Volo.CmsKit.Admin.Blogs.BlogGetListInput", + "typeSimple": "Volo.CmsKit.Admin.Blogs.BlogGetListInput", "isOptional": false, "defaultValue": null } ], "returnValue": { - "type": "System.Void", - "typeSimple": "System.Void" + "type": "Volo.Abp.Application.Dtos.PagedResultDto", + "typeSimple": "Volo.Abp.Application.Dtos.PagedResultDto" } }, { - "name": "RemoveTagFromEntityAsync", + "name": "CreateAsync", "parametersOnMethod": [ { "name": "input", - "typeAsString": "Volo.CmsKit.Admin.Tags.EntityTagRemoveDto, Volo.CmsKit.Admin.Application.Contracts", - "type": "Volo.CmsKit.Admin.Tags.EntityTagRemoveDto", - "typeSimple": "Volo.CmsKit.Admin.Tags.EntityTagRemoveDto", + "typeAsString": "Volo.CmsKit.Admin.Blogs.CreateBlogDto, Volo.CmsKit.Admin.Application.Contracts", + "type": "Volo.CmsKit.Admin.Blogs.CreateBlogDto", + "typeSimple": "Volo.CmsKit.Admin.Blogs.CreateBlogDto", "isOptional": false, "defaultValue": null } ], "returnValue": { - "type": "System.Void", - "typeSimple": "System.Void" + "type": "Volo.CmsKit.Admin.Blogs.BlogDto", + "typeSimple": "Volo.CmsKit.Admin.Blogs.BlogDto" } }, { - "name": "SetEntityTagsAsync", + "name": "UpdateAsync", "parametersOnMethod": [ + { + "name": "id", + "typeAsString": "System.Guid, System.Private.CoreLib", + "type": "System.Guid", + "typeSimple": "string", + "isOptional": false, + "defaultValue": null + }, { "name": "input", - "typeAsString": "Volo.CmsKit.Admin.Tags.EntityTagSetDto, Volo.CmsKit.Admin.Application.Contracts", - "type": "Volo.CmsKit.Admin.Tags.EntityTagSetDto", - "typeSimple": "Volo.CmsKit.Admin.Tags.EntityTagSetDto", + "typeAsString": "Volo.CmsKit.Admin.Blogs.UpdateBlogDto, Volo.CmsKit.Admin.Application.Contracts", + "type": "Volo.CmsKit.Admin.Blogs.UpdateBlogDto", + "typeSimple": "Volo.CmsKit.Admin.Blogs.UpdateBlogDto", + "isOptional": false, + "defaultValue": null + } + ], + "returnValue": { + "type": "Volo.CmsKit.Admin.Blogs.BlogDto", + "typeSimple": "Volo.CmsKit.Admin.Blogs.BlogDto" + } + }, + { + "name": "DeleteAsync", + "parametersOnMethod": [ + { + "name": "id", + "typeAsString": "System.Guid, System.Private.CoreLib", + "type": "System.Guid", + "typeSimple": "string", "isOptional": false, "defaultValue": null } @@ -71,55 +113,55 @@ } ], "actions": { - "AddTagToEntityAsyncByInput": { - "uniqueName": "AddTagToEntityAsyncByInput", - "name": "AddTagToEntityAsync", - "httpMethod": "POST", - "url": "api/cms-kit-admin/entity-tags", + "GetAsyncById": { + "uniqueName": "GetAsyncById", + "name": "GetAsync", + "httpMethod": "GET", + "url": "api/cms-kit-admin/blogs/{id}", "supportedVersions": [], "parametersOnMethod": [ { - "name": "input", - "typeAsString": "Volo.CmsKit.Admin.Tags.EntityTagCreateDto, Volo.CmsKit.Admin.Application.Contracts", - "type": "Volo.CmsKit.Admin.Tags.EntityTagCreateDto", - "typeSimple": "Volo.CmsKit.Admin.Tags.EntityTagCreateDto", + "name": "id", + "typeAsString": "System.Guid, System.Private.CoreLib", + "type": "System.Guid", + "typeSimple": "string", "isOptional": false, "defaultValue": null } ], "parameters": [ { - "nameOnMethod": "input", - "name": "input", + "nameOnMethod": "id", + "name": "id", "jsonName": null, - "type": "Volo.CmsKit.Admin.Tags.EntityTagCreateDto", - "typeSimple": "Volo.CmsKit.Admin.Tags.EntityTagCreateDto", + "type": "System.Guid", + "typeSimple": "string", "isOptional": false, "defaultValue": null, - "constraintTypes": null, - "bindingSourceId": "Body", + "constraintTypes": [], + "bindingSourceId": "Path", "descriptorName": "" } ], "returnValue": { - "type": "System.Void", - "typeSimple": "System.Void" + "type": "Volo.CmsKit.Admin.Blogs.BlogDto", + "typeSimple": "Volo.CmsKit.Admin.Blogs.BlogDto" }, - "allowAnonymous": null, - "implementFrom": "Volo.CmsKit.Admin.Tags.IEntityTagAdminAppService" + "allowAnonymous": false, + "implementFrom": "Volo.Abp.Application.Services.IReadOnlyAppService" }, - "RemoveTagFromEntityAsyncByInput": { - "uniqueName": "RemoveTagFromEntityAsyncByInput", - "name": "RemoveTagFromEntityAsync", - "httpMethod": "DELETE", - "url": "api/cms-kit-admin/entity-tags", + "GetListAsyncByInput": { + "uniqueName": "GetListAsyncByInput", + "name": "GetListAsync", + "httpMethod": "GET", + "url": "api/cms-kit-admin/blogs", "supportedVersions": [], "parametersOnMethod": [ { "name": "input", - "typeAsString": "Volo.CmsKit.Admin.Tags.EntityTagRemoveDto, Volo.CmsKit.Admin.Application.Contracts", - "type": "Volo.CmsKit.Admin.Tags.EntityTagRemoveDto", - "typeSimple": "Volo.CmsKit.Admin.Tags.EntityTagRemoveDto", + "typeAsString": "Volo.CmsKit.Admin.Blogs.BlogGetListInput, Volo.CmsKit.Admin.Application.Contracts", + "type": "Volo.CmsKit.Admin.Blogs.BlogGetListInput", + "typeSimple": "Volo.CmsKit.Admin.Blogs.BlogGetListInput", "isOptional": false, "defaultValue": null } @@ -127,9 +169,9 @@ "parameters": [ { "nameOnMethod": "input", - "name": "TagId", + "name": "Filter", "jsonName": null, - "type": "System.Guid", + "type": "System.String", "typeSimple": "string", "isOptional": false, "defaultValue": null, @@ -139,7 +181,7 @@ }, { "nameOnMethod": "input", - "name": "EntityType", + "name": "Sorting", "jsonName": null, "type": "System.String", "typeSimple": "string", @@ -151,10 +193,22 @@ }, { "nameOnMethod": "input", - "name": "EntityId", + "name": "SkipCount", "jsonName": null, - "type": "System.String", - "typeSimple": "string", + "type": "System.Int32", + "typeSimple": "number", + "isOptional": false, + "defaultValue": null, + "constraintTypes": null, + "bindingSourceId": "ModelBinding", + "descriptorName": "input" + }, + { + "nameOnMethod": "input", + "name": "MaxResultCount", + "jsonName": null, + "type": "System.Int32", + "typeSimple": "number", "isOptional": false, "defaultValue": null, "constraintTypes": null, @@ -163,24 +217,24 @@ } ], "returnValue": { - "type": "System.Void", - "typeSimple": "System.Void" + "type": "Volo.Abp.Application.Dtos.PagedResultDto", + "typeSimple": "Volo.Abp.Application.Dtos.PagedResultDto" }, - "allowAnonymous": null, - "implementFrom": "Volo.CmsKit.Admin.Tags.IEntityTagAdminAppService" + "allowAnonymous": false, + "implementFrom": "Volo.Abp.Application.Services.IReadOnlyAppService" }, - "SetEntityTagsAsyncByInput": { - "uniqueName": "SetEntityTagsAsyncByInput", - "name": "SetEntityTagsAsync", - "httpMethod": "PUT", - "url": "api/cms-kit-admin/entity-tags", + "CreateAsyncByInput": { + "uniqueName": "CreateAsyncByInput", + "name": "CreateAsync", + "httpMethod": "POST", + "url": "api/cms-kit-admin/blogs", "supportedVersions": [], "parametersOnMethod": [ { "name": "input", - "typeAsString": "Volo.CmsKit.Admin.Tags.EntityTagSetDto, Volo.CmsKit.Admin.Application.Contracts", - "type": "Volo.CmsKit.Admin.Tags.EntityTagSetDto", - "typeSimple": "Volo.CmsKit.Admin.Tags.EntityTagSetDto", + "typeAsString": "Volo.CmsKit.Admin.Blogs.CreateBlogDto, Volo.CmsKit.Admin.Application.Contracts", + "type": "Volo.CmsKit.Admin.Blogs.CreateBlogDto", + "typeSimple": "Volo.CmsKit.Admin.Blogs.CreateBlogDto", "isOptional": false, "defaultValue": null } @@ -190,8 +244,8 @@ "nameOnMethod": "input", "name": "input", "jsonName": null, - "type": "Volo.CmsKit.Admin.Tags.EntityTagSetDto", - "typeSimple": "Volo.CmsKit.Admin.Tags.EntityTagSetDto", + "type": "Volo.CmsKit.Admin.Blogs.CreateBlogDto", + "typeSimple": "Volo.CmsKit.Admin.Blogs.CreateBlogDto", "isOptional": false, "defaultValue": null, "constraintTypes": null, @@ -200,154 +254,55 @@ } ], "returnValue": { - "type": "System.Void", - "typeSimple": "System.Void" + "type": "Volo.CmsKit.Admin.Blogs.BlogDto", + "typeSimple": "Volo.CmsKit.Admin.Blogs.BlogDto" }, - "allowAnonymous": null, - "implementFrom": "Volo.CmsKit.Admin.Tags.IEntityTagAdminAppService" - } - } - }, - "Volo.CmsKit.Admin.Tags.TagAdminController": { - "controllerName": "TagAdmin", - "controllerGroupName": "TagAdmin", - "isRemoteService": true, - "isIntegrationService": false, - "apiVersion": null, - "type": "Volo.CmsKit.Admin.Tags.TagAdminController", - "interfaces": [ - { - "type": "Volo.CmsKit.Admin.Tags.ITagAdminAppService", - "name": "ITagAdminAppService", - "methods": [ - { - "name": "GetTagDefinitionsAsync", - "parametersOnMethod": [], - "returnValue": { - "type": "System.Collections.Generic.List", - "typeSimple": "[Volo.CmsKit.Admin.Tags.TagDefinitionDto]" - } - }, + "allowAnonymous": false, + "implementFrom": "Volo.Abp.Application.Services.ICreateAppService" + }, + "UpdateAsyncByIdAndInput": { + "uniqueName": "UpdateAsyncByIdAndInput", + "name": "UpdateAsync", + "httpMethod": "PUT", + "url": "api/cms-kit-admin/blogs/{id}", + "supportedVersions": [], + "parametersOnMethod": [ { - "name": "GetAsync", - "parametersOnMethod": [ - { - "name": "id", - "typeAsString": "System.Guid, System.Private.CoreLib", - "type": "System.Guid", - "typeSimple": "string", - "isOptional": false, - "defaultValue": null - } - ], - "returnValue": { - "type": "Volo.CmsKit.Tags.TagDto", - "typeSimple": "Volo.CmsKit.Tags.TagDto" - } + "name": "id", + "typeAsString": "System.Guid, System.Private.CoreLib", + "type": "System.Guid", + "typeSimple": "string", + "isOptional": false, + "defaultValue": null }, - { - "name": "GetListAsync", - "parametersOnMethod": [ - { - "name": "input", - "typeAsString": "Volo.CmsKit.Admin.Tags.TagGetListInput, Volo.CmsKit.Admin.Application.Contracts", - "type": "Volo.CmsKit.Admin.Tags.TagGetListInput", - "typeSimple": "Volo.CmsKit.Admin.Tags.TagGetListInput", - "isOptional": false, - "defaultValue": null - } - ], - "returnValue": { - "type": "Volo.Abp.Application.Dtos.PagedResultDto", - "typeSimple": "Volo.Abp.Application.Dtos.PagedResultDto" - } - }, - { - "name": "CreateAsync", - "parametersOnMethod": [ - { - "name": "input", - "typeAsString": "Volo.CmsKit.Admin.Tags.TagCreateDto, Volo.CmsKit.Admin.Application.Contracts", - "type": "Volo.CmsKit.Admin.Tags.TagCreateDto", - "typeSimple": "Volo.CmsKit.Admin.Tags.TagCreateDto", - "isOptional": false, - "defaultValue": null - } - ], - "returnValue": { - "type": "Volo.CmsKit.Tags.TagDto", - "typeSimple": "Volo.CmsKit.Tags.TagDto" - } - }, - { - "name": "UpdateAsync", - "parametersOnMethod": [ - { - "name": "id", - "typeAsString": "System.Guid, System.Private.CoreLib", - "type": "System.Guid", - "typeSimple": "string", - "isOptional": false, - "defaultValue": null - }, - { - "name": "input", - "typeAsString": "Volo.CmsKit.Admin.Tags.TagUpdateDto, Volo.CmsKit.Admin.Application.Contracts", - "type": "Volo.CmsKit.Admin.Tags.TagUpdateDto", - "typeSimple": "Volo.CmsKit.Admin.Tags.TagUpdateDto", - "isOptional": false, - "defaultValue": null - } - ], - "returnValue": { - "type": "Volo.CmsKit.Tags.TagDto", - "typeSimple": "Volo.CmsKit.Tags.TagDto" - } - }, - { - "name": "DeleteAsync", - "parametersOnMethod": [ - { - "name": "id", - "typeAsString": "System.Guid, System.Private.CoreLib", - "type": "System.Guid", - "typeSimple": "string", - "isOptional": false, - "defaultValue": null - } - ], - "returnValue": { - "type": "System.Void", - "typeSimple": "System.Void" - } - } - ] - } - ], - "actions": { - "CreateAsyncByInput": { - "uniqueName": "CreateAsyncByInput", - "name": "CreateAsync", - "httpMethod": "POST", - "url": "api/cms-kit-admin/tags", - "supportedVersions": [], - "parametersOnMethod": [ { "name": "input", - "typeAsString": "Volo.CmsKit.Admin.Tags.TagCreateDto, Volo.CmsKit.Admin.Application.Contracts", - "type": "Volo.CmsKit.Admin.Tags.TagCreateDto", - "typeSimple": "Volo.CmsKit.Admin.Tags.TagCreateDto", + "typeAsString": "Volo.CmsKit.Admin.Blogs.UpdateBlogDto, Volo.CmsKit.Admin.Application.Contracts", + "type": "Volo.CmsKit.Admin.Blogs.UpdateBlogDto", + "typeSimple": "Volo.CmsKit.Admin.Blogs.UpdateBlogDto", "isOptional": false, "defaultValue": null } ], "parameters": [ + { + "nameOnMethod": "id", + "name": "id", + "jsonName": null, + "type": "System.Guid", + "typeSimple": "string", + "isOptional": false, + "defaultValue": null, + "constraintTypes": [], + "bindingSourceId": "Path", + "descriptorName": "" + }, { "nameOnMethod": "input", "name": "input", "jsonName": null, - "type": "Volo.CmsKit.Admin.Tags.TagCreateDto", - "typeSimple": "Volo.CmsKit.Admin.Tags.TagCreateDto", + "type": "Volo.CmsKit.Admin.Blogs.UpdateBlogDto", + "typeSimple": "Volo.CmsKit.Admin.Blogs.UpdateBlogDto", "isOptional": false, "defaultValue": null, "constraintTypes": null, @@ -356,17 +311,17 @@ } ], "returnValue": { - "type": "Volo.CmsKit.Tags.TagDto", - "typeSimple": "Volo.CmsKit.Tags.TagDto" + "type": "Volo.CmsKit.Admin.Blogs.BlogDto", + "typeSimple": "Volo.CmsKit.Admin.Blogs.BlogDto" }, "allowAnonymous": false, - "implementFrom": "Volo.Abp.Application.Services.ICreateAppService" + "implementFrom": "Volo.Abp.Application.Services.IUpdateAppService" }, "DeleteAsyncById": { "uniqueName": "DeleteAsyncById", "name": "DeleteAsync", "httpMethod": "DELETE", - "url": "api/cms-kit-admin/tags/{id}", + "url": "api/cms-kit-admin/blogs/{id}", "supportedVersions": [], "parametersOnMethod": [ { @@ -398,16 +353,76 @@ }, "allowAnonymous": false, "implementFrom": "Volo.Abp.Application.Services.IDeleteAppService" - }, - "GetAsyncById": { - "uniqueName": "GetAsyncById", - "name": "GetAsync", + } + } + }, + "Volo.CmsKit.Admin.Blogs.BlogFeatureAdminController": { + "controllerName": "BlogFeatureAdmin", + "controllerGroupName": "BlogFeatureAdmin", + "isRemoteService": true, + "isIntegrationService": false, + "apiVersion": null, + "type": "Volo.CmsKit.Admin.Blogs.BlogFeatureAdminController", + "interfaces": [ + { + "type": "Volo.CmsKit.Admin.Blogs.IBlogFeatureAdminAppService", + "name": "IBlogFeatureAdminAppService", + "methods": [ + { + "name": "SetAsync", + "parametersOnMethod": [ + { + "name": "blogId", + "typeAsString": "System.Guid, System.Private.CoreLib", + "type": "System.Guid", + "typeSimple": "string", + "isOptional": false, + "defaultValue": null + }, + { + "name": "dto", + "typeAsString": "Volo.CmsKit.Admin.Blogs.BlogFeatureInputDto, Volo.CmsKit.Admin.Application.Contracts", + "type": "Volo.CmsKit.Admin.Blogs.BlogFeatureInputDto", + "typeSimple": "Volo.CmsKit.Admin.Blogs.BlogFeatureInputDto", + "isOptional": false, + "defaultValue": null + } + ], + "returnValue": { + "type": "System.Void", + "typeSimple": "System.Void" + } + }, + { + "name": "GetListAsync", + "parametersOnMethod": [ + { + "name": "blogId", + "typeAsString": "System.Guid, System.Private.CoreLib", + "type": "System.Guid", + "typeSimple": "string", + "isOptional": false, + "defaultValue": null + } + ], + "returnValue": { + "type": "System.Collections.Generic.List", + "typeSimple": "[Volo.CmsKit.Blogs.BlogFeatureDto]" + } + } + ] + } + ], + "actions": { + "GetListAsyncByBlogId": { + "uniqueName": "GetListAsyncByBlogId", + "name": "GetListAsync", "httpMethod": "GET", - "url": "api/cms-kit-admin/tags/{id}", + "url": "api/cms-kit-admin/blogs/{blogId}/features", "supportedVersions": [], "parametersOnMethod": [ { - "name": "id", + "name": "blogId", "typeAsString": "System.Guid, System.Private.CoreLib", "type": "System.Guid", "typeSimple": "string", @@ -417,8 +432,8 @@ ], "parameters": [ { - "nameOnMethod": "id", - "name": "id", + "nameOnMethod": "blogId", + "name": "blogId", "jsonName": null, "type": "System.Guid", "typeSimple": "string", @@ -430,128 +445,55 @@ } ], "returnValue": { - "type": "Volo.CmsKit.Tags.TagDto", - "typeSimple": "Volo.CmsKit.Tags.TagDto" + "type": "System.Collections.Generic.List", + "typeSimple": "[Volo.CmsKit.Blogs.BlogFeatureDto]" }, "allowAnonymous": false, - "implementFrom": "Volo.Abp.Application.Services.IReadOnlyAppService" + "implementFrom": "Volo.CmsKit.Admin.Blogs.IBlogFeatureAdminAppService" }, - "GetListAsyncByInput": { - "uniqueName": "GetListAsyncByInput", - "name": "GetListAsync", - "httpMethod": "GET", - "url": "api/cms-kit-admin/tags", + "SetAsyncByBlogIdAndDto": { + "uniqueName": "SetAsyncByBlogIdAndDto", + "name": "SetAsync", + "httpMethod": "PUT", + "url": "api/cms-kit-admin/blogs/{blogId}/features", "supportedVersions": [], "parametersOnMethod": [ { - "name": "input", - "typeAsString": "Volo.CmsKit.Admin.Tags.TagGetListInput, Volo.CmsKit.Admin.Application.Contracts", - "type": "Volo.CmsKit.Admin.Tags.TagGetListInput", - "typeSimple": "Volo.CmsKit.Admin.Tags.TagGetListInput", + "name": "blogId", + "typeAsString": "System.Guid, System.Private.CoreLib", + "type": "System.Guid", + "typeSimple": "string", + "isOptional": false, + "defaultValue": null + }, + { + "name": "dto", + "typeAsString": "Volo.CmsKit.Admin.Blogs.BlogFeatureInputDto, Volo.CmsKit.Admin.Application.Contracts", + "type": "Volo.CmsKit.Admin.Blogs.BlogFeatureInputDto", + "typeSimple": "Volo.CmsKit.Admin.Blogs.BlogFeatureInputDto", "isOptional": false, "defaultValue": null } ], "parameters": [ { - "nameOnMethod": "input", - "name": "Filter", - "jsonName": null, - "type": "System.String", - "typeSimple": "string", - "isOptional": false, - "defaultValue": null, - "constraintTypes": null, - "bindingSourceId": "ModelBinding", - "descriptorName": "input" - }, - { - "nameOnMethod": "input", - "name": "Sorting", + "nameOnMethod": "blogId", + "name": "blogId", "jsonName": null, - "type": "System.String", + "type": "System.Guid", "typeSimple": "string", "isOptional": false, "defaultValue": null, - "constraintTypes": null, - "bindingSourceId": "ModelBinding", - "descriptorName": "input" + "constraintTypes": [], + "bindingSourceId": "Path", + "descriptorName": "" }, { - "nameOnMethod": "input", - "name": "SkipCount", + "nameOnMethod": "dto", + "name": "dto", "jsonName": null, - "type": "System.Int32", - "typeSimple": "number", - "isOptional": false, - "defaultValue": null, - "constraintTypes": null, - "bindingSourceId": "ModelBinding", - "descriptorName": "input" - }, - { - "nameOnMethod": "input", - "name": "MaxResultCount", - "jsonName": null, - "type": "System.Int32", - "typeSimple": "number", - "isOptional": false, - "defaultValue": null, - "constraintTypes": null, - "bindingSourceId": "ModelBinding", - "descriptorName": "input" - } - ], - "returnValue": { - "type": "Volo.Abp.Application.Dtos.PagedResultDto", - "typeSimple": "Volo.Abp.Application.Dtos.PagedResultDto" - }, - "allowAnonymous": false, - "implementFrom": "Volo.Abp.Application.Services.IReadOnlyAppService" - }, - "UpdateAsyncByIdAndInput": { - "uniqueName": "UpdateAsyncByIdAndInput", - "name": "UpdateAsync", - "httpMethod": "PUT", - "url": "api/cms-kit-admin/tags/{id}", - "supportedVersions": [], - "parametersOnMethod": [ - { - "name": "id", - "typeAsString": "System.Guid, System.Private.CoreLib", - "type": "System.Guid", - "typeSimple": "string", - "isOptional": false, - "defaultValue": null - }, - { - "name": "input", - "typeAsString": "Volo.CmsKit.Admin.Tags.TagUpdateDto, Volo.CmsKit.Admin.Application.Contracts", - "type": "Volo.CmsKit.Admin.Tags.TagUpdateDto", - "typeSimple": "Volo.CmsKit.Admin.Tags.TagUpdateDto", - "isOptional": false, - "defaultValue": null - } - ], - "parameters": [ - { - "nameOnMethod": "id", - "name": "id", - "jsonName": null, - "type": "System.Guid", - "typeSimple": "string", - "isOptional": false, - "defaultValue": null, - "constraintTypes": [], - "bindingSourceId": "Path", - "descriptorName": "" - }, - { - "nameOnMethod": "input", - "name": "input", - "jsonName": null, - "type": "Volo.CmsKit.Admin.Tags.TagUpdateDto", - "typeSimple": "Volo.CmsKit.Admin.Tags.TagUpdateDto", + "type": "Volo.CmsKit.Admin.Blogs.BlogFeatureInputDto", + "typeSimple": "Volo.CmsKit.Admin.Blogs.BlogFeatureInputDto", "isOptional": false, "defaultValue": null, "constraintTypes": null, @@ -560,43 +502,79 @@ } ], "returnValue": { - "type": "Volo.CmsKit.Tags.TagDto", - "typeSimple": "Volo.CmsKit.Tags.TagDto" - }, - "allowAnonymous": false, - "implementFrom": "Volo.Abp.Application.Services.IUpdateAppService" - }, - "GetTagDefinitionsAsync": { - "uniqueName": "GetTagDefinitionsAsync", - "name": "GetTagDefinitionsAsync", - "httpMethod": "GET", - "url": "api/cms-kit-admin/tags/tag-definitions", - "supportedVersions": [], - "parametersOnMethod": [], - "parameters": [], - "returnValue": { - "type": "System.Collections.Generic.List", - "typeSimple": "[Volo.CmsKit.Admin.Tags.TagDefinitionDto]" + "type": "System.Void", + "typeSimple": "System.Void" }, "allowAnonymous": false, - "implementFrom": "Volo.CmsKit.Admin.Tags.ITagAdminAppService" + "implementFrom": "Volo.CmsKit.Admin.Blogs.IBlogFeatureAdminAppService" } } }, - "Volo.CmsKit.Admin.Pages.PageAdminController": { - "controllerName": "PageAdmin", - "controllerGroupName": "PageAdmin", + "Volo.CmsKit.Admin.Blogs.BlogPostAdminController": { + "controllerName": "BlogPostAdmin", + "controllerGroupName": "BlogPostAdmin", "isRemoteService": true, "isIntegrationService": false, "apiVersion": null, - "type": "Volo.CmsKit.Admin.Pages.PageAdminController", + "type": "Volo.CmsKit.Admin.Blogs.BlogPostAdminController", "interfaces": [ { - "type": "Volo.CmsKit.Admin.Pages.IPageAdminAppService", - "name": "IPageAdminAppService", + "type": "Volo.CmsKit.Admin.Blogs.IBlogPostAdminAppService", + "name": "IBlogPostAdminAppService", "methods": [ { - "name": "SetAsHomePageAsync", + "name": "PublishAsync", + "parametersOnMethod": [ + { + "name": "id", + "typeAsString": "System.Guid, System.Private.CoreLib", + "type": "System.Guid", + "typeSimple": "string", + "isOptional": false, + "defaultValue": null + } + ], + "returnValue": { + "type": "System.Void", + "typeSimple": "System.Void" + } + }, + { + "name": "DraftAsync", + "parametersOnMethod": [ + { + "name": "id", + "typeAsString": "System.Guid, System.Private.CoreLib", + "type": "System.Guid", + "typeSimple": "string", + "isOptional": false, + "defaultValue": null + } + ], + "returnValue": { + "type": "System.Void", + "typeSimple": "System.Void" + } + }, + { + "name": "CreateAndPublishAsync", + "parametersOnMethod": [ + { + "name": "input", + "typeAsString": "Volo.CmsKit.Admin.Blogs.CreateBlogPostDto, Volo.CmsKit.Admin.Application.Contracts", + "type": "Volo.CmsKit.Admin.Blogs.CreateBlogPostDto", + "typeSimple": "Volo.CmsKit.Admin.Blogs.CreateBlogPostDto", + "isOptional": false, + "defaultValue": null + } + ], + "returnValue": { + "type": "Volo.CmsKit.Admin.Blogs.BlogPostDto", + "typeSimple": "Volo.CmsKit.Admin.Blogs.BlogPostDto" + } + }, + { + "name": "SendToReviewAsync", "parametersOnMethod": [ { "name": "id", @@ -612,6 +590,31 @@ "typeSimple": "System.Void" } }, + { + "name": "CreateAndSendToReviewAsync", + "parametersOnMethod": [ + { + "name": "input", + "typeAsString": "Volo.CmsKit.Admin.Blogs.CreateBlogPostDto, Volo.CmsKit.Admin.Application.Contracts", + "type": "Volo.CmsKit.Admin.Blogs.CreateBlogPostDto", + "typeSimple": "Volo.CmsKit.Admin.Blogs.CreateBlogPostDto", + "isOptional": false, + "defaultValue": null + } + ], + "returnValue": { + "type": "Volo.CmsKit.Admin.Blogs.BlogPostDto", + "typeSimple": "Volo.CmsKit.Admin.Blogs.BlogPostDto" + } + }, + { + "name": "HasBlogPostWaitingForReviewAsync", + "parametersOnMethod": [], + "returnValue": { + "type": "System.Boolean", + "typeSimple": "boolean" + } + }, { "name": "GetAsync", "parametersOnMethod": [ @@ -625,8 +628,8 @@ } ], "returnValue": { - "type": "Volo.CmsKit.Admin.Pages.PageDto", - "typeSimple": "Volo.CmsKit.Admin.Pages.PageDto" + "type": "Volo.CmsKit.Admin.Blogs.BlogPostDto", + "typeSimple": "Volo.CmsKit.Admin.Blogs.BlogPostDto" } }, { @@ -634,16 +637,16 @@ "parametersOnMethod": [ { "name": "input", - "typeAsString": "Volo.CmsKit.Admin.Pages.GetPagesInputDto, Volo.CmsKit.Admin.Application.Contracts", - "type": "Volo.CmsKit.Admin.Pages.GetPagesInputDto", - "typeSimple": "Volo.CmsKit.Admin.Pages.GetPagesInputDto", + "typeAsString": "Volo.CmsKit.Admin.Blogs.BlogPostGetListInput, Volo.CmsKit.Admin.Application.Contracts", + "type": "Volo.CmsKit.Admin.Blogs.BlogPostGetListInput", + "typeSimple": "Volo.CmsKit.Admin.Blogs.BlogPostGetListInput", "isOptional": false, "defaultValue": null } ], "returnValue": { - "type": "Volo.Abp.Application.Dtos.PagedResultDto", - "typeSimple": "Volo.Abp.Application.Dtos.PagedResultDto" + "type": "Volo.Abp.Application.Dtos.PagedResultDto", + "typeSimple": "Volo.Abp.Application.Dtos.PagedResultDto" } }, { @@ -651,16 +654,16 @@ "parametersOnMethod": [ { "name": "input", - "typeAsString": "Volo.CmsKit.Admin.Pages.CreatePageInputDto, Volo.CmsKit.Admin.Application.Contracts", - "type": "Volo.CmsKit.Admin.Pages.CreatePageInputDto", - "typeSimple": "Volo.CmsKit.Admin.Pages.CreatePageInputDto", + "typeAsString": "Volo.CmsKit.Admin.Blogs.CreateBlogPostDto, Volo.CmsKit.Admin.Application.Contracts", + "type": "Volo.CmsKit.Admin.Blogs.CreateBlogPostDto", + "typeSimple": "Volo.CmsKit.Admin.Blogs.CreateBlogPostDto", "isOptional": false, "defaultValue": null } ], "returnValue": { - "type": "Volo.CmsKit.Admin.Pages.PageDto", - "typeSimple": "Volo.CmsKit.Admin.Pages.PageDto" + "type": "Volo.CmsKit.Admin.Blogs.BlogPostDto", + "typeSimple": "Volo.CmsKit.Admin.Blogs.BlogPostDto" } }, { @@ -676,16 +679,16 @@ }, { "name": "input", - "typeAsString": "Volo.CmsKit.Admin.Pages.UpdatePageInputDto, Volo.CmsKit.Admin.Application.Contracts", - "type": "Volo.CmsKit.Admin.Pages.UpdatePageInputDto", - "typeSimple": "Volo.CmsKit.Admin.Pages.UpdatePageInputDto", + "typeAsString": "Volo.CmsKit.Admin.Blogs.UpdateBlogPostDto, Volo.CmsKit.Admin.Application.Contracts", + "type": "Volo.CmsKit.Admin.Blogs.UpdateBlogPostDto", + "typeSimple": "Volo.CmsKit.Admin.Blogs.UpdateBlogPostDto", "isOptional": false, "defaultValue": null } ], "returnValue": { - "type": "Volo.CmsKit.Admin.Pages.PageDto", - "typeSimple": "Volo.CmsKit.Admin.Pages.PageDto" + "type": "Volo.CmsKit.Admin.Blogs.BlogPostDto", + "typeSimple": "Volo.CmsKit.Admin.Blogs.BlogPostDto" } }, { @@ -709,55 +712,131 @@ } ], "actions": { - "GetAsyncById": { - "uniqueName": "GetAsyncById", - "name": "GetAsync", - "httpMethod": "GET", - "url": "api/cms-kit-admin/pages/{id}", + "CreateAsyncByInput": { + "uniqueName": "CreateAsyncByInput", + "name": "CreateAsync", + "httpMethod": "POST", + "url": "api/cms-kit-admin/blogs/blog-posts", "supportedVersions": [], "parametersOnMethod": [ { - "name": "id", - "typeAsString": "System.Guid, System.Private.CoreLib", - "type": "System.Guid", - "typeSimple": "string", + "name": "input", + "typeAsString": "Volo.CmsKit.Admin.Blogs.CreateBlogPostDto, Volo.CmsKit.Admin.Application.Contracts", + "type": "Volo.CmsKit.Admin.Blogs.CreateBlogPostDto", + "typeSimple": "Volo.CmsKit.Admin.Blogs.CreateBlogPostDto", "isOptional": false, "defaultValue": null } ], "parameters": [ { - "nameOnMethod": "id", - "name": "id", + "nameOnMethod": "input", + "name": "input", "jsonName": null, - "type": "System.Guid", - "typeSimple": "string", + "type": "Volo.CmsKit.Admin.Blogs.CreateBlogPostDto", + "typeSimple": "Volo.CmsKit.Admin.Blogs.CreateBlogPostDto", "isOptional": false, "defaultValue": null, - "constraintTypes": [], - "bindingSourceId": "Path", + "constraintTypes": null, + "bindingSourceId": "Body", "descriptorName": "" } ], "returnValue": { - "type": "Volo.CmsKit.Admin.Pages.PageDto", - "typeSimple": "Volo.CmsKit.Admin.Pages.PageDto" + "type": "Volo.CmsKit.Admin.Blogs.BlogPostDto", + "typeSimple": "Volo.CmsKit.Admin.Blogs.BlogPostDto" }, "allowAnonymous": false, - "implementFrom": "Volo.Abp.Application.Services.IReadOnlyAppService" + "implementFrom": "Volo.Abp.Application.Services.ICreateAppService" }, - "GetListAsyncByInput": { - "uniqueName": "GetListAsyncByInput", - "name": "GetListAsync", - "httpMethod": "GET", - "url": "api/cms-kit-admin/pages", - "supportedVersions": [], - "parametersOnMethod": [ - { - "name": "input", - "typeAsString": "Volo.CmsKit.Admin.Pages.GetPagesInputDto, Volo.CmsKit.Admin.Application.Contracts", - "type": "Volo.CmsKit.Admin.Pages.GetPagesInputDto", - "typeSimple": "Volo.CmsKit.Admin.Pages.GetPagesInputDto", + "DeleteAsyncById": { + "uniqueName": "DeleteAsyncById", + "name": "DeleteAsync", + "httpMethod": "DELETE", + "url": "api/cms-kit-admin/blogs/blog-posts/{id}", + "supportedVersions": [], + "parametersOnMethod": [ + { + "name": "id", + "typeAsString": "System.Guid, System.Private.CoreLib", + "type": "System.Guid", + "typeSimple": "string", + "isOptional": false, + "defaultValue": null + } + ], + "parameters": [ + { + "nameOnMethod": "id", + "name": "id", + "jsonName": null, + "type": "System.Guid", + "typeSimple": "string", + "isOptional": false, + "defaultValue": null, + "constraintTypes": [], + "bindingSourceId": "Path", + "descriptorName": "" + } + ], + "returnValue": { + "type": "System.Void", + "typeSimple": "System.Void" + }, + "allowAnonymous": false, + "implementFrom": "Volo.Abp.Application.Services.IDeleteAppService" + }, + "GetAsyncById": { + "uniqueName": "GetAsyncById", + "name": "GetAsync", + "httpMethod": "GET", + "url": "api/cms-kit-admin/blogs/blog-posts/{id}", + "supportedVersions": [], + "parametersOnMethod": [ + { + "name": "id", + "typeAsString": "System.Guid, System.Private.CoreLib", + "type": "System.Guid", + "typeSimple": "string", + "isOptional": false, + "defaultValue": null + } + ], + "parameters": [ + { + "nameOnMethod": "id", + "name": "id", + "jsonName": null, + "type": "System.Guid", + "typeSimple": "string", + "isOptional": false, + "defaultValue": null, + "constraintTypes": [ + "GuidRouteConstraint" + ], + "bindingSourceId": "Path", + "descriptorName": "" + } + ], + "returnValue": { + "type": "Volo.CmsKit.Admin.Blogs.BlogPostDto", + "typeSimple": "Volo.CmsKit.Admin.Blogs.BlogPostDto" + }, + "allowAnonymous": false, + "implementFrom": "Volo.Abp.Application.Services.IReadOnlyAppService" + }, + "GetListAsyncByInput": { + "uniqueName": "GetListAsyncByInput", + "name": "GetListAsync", + "httpMethod": "GET", + "url": "api/cms-kit-admin/blogs/blog-posts", + "supportedVersions": [], + "parametersOnMethod": [ + { + "name": "input", + "typeAsString": "Volo.CmsKit.Admin.Blogs.BlogPostGetListInput, Volo.CmsKit.Admin.Application.Contracts", + "type": "Volo.CmsKit.Admin.Blogs.BlogPostGetListInput", + "typeSimple": "Volo.CmsKit.Admin.Blogs.BlogPostGetListInput", "isOptional": false, "defaultValue": null } @@ -777,7 +856,43 @@ }, { "nameOnMethod": "input", - "name": "Sorting", + "name": "BlogId", + "jsonName": null, + "type": "System.Guid?", + "typeSimple": "string?", + "isOptional": false, + "defaultValue": null, + "constraintTypes": null, + "bindingSourceId": "ModelBinding", + "descriptorName": "input" + }, + { + "nameOnMethod": "input", + "name": "AuthorId", + "jsonName": null, + "type": "System.Guid?", + "typeSimple": "string?", + "isOptional": false, + "defaultValue": null, + "constraintTypes": null, + "bindingSourceId": "ModelBinding", + "descriptorName": "input" + }, + { + "nameOnMethod": "input", + "name": "TagId", + "jsonName": null, + "type": "System.Guid?", + "typeSimple": "string?", + "isOptional": false, + "defaultValue": null, + "constraintTypes": null, + "bindingSourceId": "ModelBinding", + "descriptorName": "input" + }, + { + "nameOnMethod": "input", + "name": "Status", "jsonName": null, "type": "System.String", "typeSimple": "string", @@ -789,10 +904,10 @@ }, { "nameOnMethod": "input", - "name": "SkipCount", + "name": "Sorting", "jsonName": null, - "type": "System.Int32", - "typeSimple": "number", + "type": "System.String", + "typeSimple": "string", "isOptional": false, "defaultValue": null, "constraintTypes": null, @@ -801,7 +916,7 @@ }, { "nameOnMethod": "input", - "name": "MaxResultCount", + "name": "SkipCount", "jsonName": null, "type": "System.Int32", "typeSimple": "number", @@ -810,57 +925,32 @@ "constraintTypes": null, "bindingSourceId": "ModelBinding", "descriptorName": "input" - } - ], - "returnValue": { - "type": "Volo.Abp.Application.Dtos.PagedResultDto", - "typeSimple": "Volo.Abp.Application.Dtos.PagedResultDto" - }, - "allowAnonymous": false, - "implementFrom": "Volo.Abp.Application.Services.IReadOnlyAppService" - }, - "CreateAsyncByInput": { - "uniqueName": "CreateAsyncByInput", - "name": "CreateAsync", - "httpMethod": "POST", - "url": "api/cms-kit-admin/pages", - "supportedVersions": [], - "parametersOnMethod": [ - { - "name": "input", - "typeAsString": "Volo.CmsKit.Admin.Pages.CreatePageInputDto, Volo.CmsKit.Admin.Application.Contracts", - "type": "Volo.CmsKit.Admin.Pages.CreatePageInputDto", - "typeSimple": "Volo.CmsKit.Admin.Pages.CreatePageInputDto", - "isOptional": false, - "defaultValue": null - } - ], - "parameters": [ + }, { "nameOnMethod": "input", - "name": "input", + "name": "MaxResultCount", "jsonName": null, - "type": "Volo.CmsKit.Admin.Pages.CreatePageInputDto", - "typeSimple": "Volo.CmsKit.Admin.Pages.CreatePageInputDto", + "type": "System.Int32", + "typeSimple": "number", "isOptional": false, "defaultValue": null, "constraintTypes": null, - "bindingSourceId": "Body", - "descriptorName": "" + "bindingSourceId": "ModelBinding", + "descriptorName": "input" } ], "returnValue": { - "type": "Volo.CmsKit.Admin.Pages.PageDto", - "typeSimple": "Volo.CmsKit.Admin.Pages.PageDto" + "type": "Volo.Abp.Application.Dtos.PagedResultDto", + "typeSimple": "Volo.Abp.Application.Dtos.PagedResultDto" }, "allowAnonymous": false, - "implementFrom": "Volo.Abp.Application.Services.ICreateAppService" + "implementFrom": "Volo.Abp.Application.Services.IReadOnlyAppService" }, "UpdateAsyncByIdAndInput": { "uniqueName": "UpdateAsyncByIdAndInput", "name": "UpdateAsync", "httpMethod": "PUT", - "url": "api/cms-kit-admin/pages/{id}", + "url": "api/cms-kit-admin/blogs/blog-posts/{id}", "supportedVersions": [], "parametersOnMethod": [ { @@ -873,9 +963,9 @@ }, { "name": "input", - "typeAsString": "Volo.CmsKit.Admin.Pages.UpdatePageInputDto, Volo.CmsKit.Admin.Application.Contracts", - "type": "Volo.CmsKit.Admin.Pages.UpdatePageInputDto", - "typeSimple": "Volo.CmsKit.Admin.Pages.UpdatePageInputDto", + "typeAsString": "Volo.CmsKit.Admin.Blogs.UpdateBlogPostDto, Volo.CmsKit.Admin.Application.Contracts", + "type": "Volo.CmsKit.Admin.Blogs.UpdateBlogPostDto", + "typeSimple": "Volo.CmsKit.Admin.Blogs.UpdateBlogPostDto", "isOptional": false, "defaultValue": null } @@ -897,8 +987,8 @@ "nameOnMethod": "input", "name": "input", "jsonName": null, - "type": "Volo.CmsKit.Admin.Pages.UpdatePageInputDto", - "typeSimple": "Volo.CmsKit.Admin.Pages.UpdatePageInputDto", + "type": "Volo.CmsKit.Admin.Blogs.UpdateBlogPostDto", + "typeSimple": "Volo.CmsKit.Admin.Blogs.UpdateBlogPostDto", "isOptional": false, "defaultValue": null, "constraintTypes": null, @@ -907,17 +997,17 @@ } ], "returnValue": { - "type": "Volo.CmsKit.Admin.Pages.PageDto", - "typeSimple": "Volo.CmsKit.Admin.Pages.PageDto" + "type": "Volo.CmsKit.Admin.Blogs.BlogPostDto", + "typeSimple": "Volo.CmsKit.Admin.Blogs.BlogPostDto" }, "allowAnonymous": false, - "implementFrom": "Volo.Abp.Application.Services.IUpdateAppService" + "implementFrom": "Volo.Abp.Application.Services.IUpdateAppService" }, - "DeleteAsyncById": { - "uniqueName": "DeleteAsyncById", - "name": "DeleteAsync", - "httpMethod": "DELETE", - "url": "api/cms-kit-admin/pages/{id}", + "PublishAsyncById": { + "uniqueName": "PublishAsyncById", + "name": "PublishAsync", + "httpMethod": "POST", + "url": "api/cms-kit-admin/blogs/blog-posts/{id}/publish", "supportedVersions": [], "parametersOnMethod": [ { @@ -948,13 +1038,13 @@ "typeSimple": "System.Void" }, "allowAnonymous": false, - "implementFrom": "Volo.Abp.Application.Services.IDeleteAppService" + "implementFrom": "Volo.CmsKit.Admin.Blogs.IBlogPostAdminAppService" }, - "SetAsHomePageAsyncById": { - "uniqueName": "SetAsHomePageAsyncById", - "name": "SetAsHomePageAsync", - "httpMethod": "PUT", - "url": "api/cms-kit-admin/pages/setashomepage/{id}", + "DraftAsyncById": { + "uniqueName": "DraftAsyncById", + "name": "DraftAsync", + "httpMethod": "POST", + "url": "api/cms-kit-admin/blogs/blog-posts/{id}/draft", "supportedVersions": [], "parametersOnMethod": [ { @@ -985,91 +1075,167 @@ "typeSimple": "System.Void" }, "allowAnonymous": false, - "implementFrom": "Volo.CmsKit.Admin.Pages.IPageAdminAppService" - } - } - }, - "Volo.CmsKit.Admin.Menus.MenuItemAdminController": { - "controllerName": "MenuItemAdmin", - "controllerGroupName": "MenuItemAdmin", - "isRemoteService": true, - "isIntegrationService": false, - "apiVersion": null, - "type": "Volo.CmsKit.Admin.Menus.MenuItemAdminController", - "interfaces": [ - { - "type": "Volo.CmsKit.Admin.Menus.IMenuItemAdminAppService", - "name": "IMenuItemAdminAppService", - "methods": [ - { - "name": "GetListAsync", - "parametersOnMethod": [], - "returnValue": { - "type": "Volo.Abp.Application.Dtos.ListResultDto", - "typeSimple": "Volo.Abp.Application.Dtos.ListResultDto" - } - }, + "implementFrom": "Volo.CmsKit.Admin.Blogs.IBlogPostAdminAppService" + }, + "CreateAndPublishAsyncByInput": { + "uniqueName": "CreateAndPublishAsyncByInput", + "name": "CreateAndPublishAsync", + "httpMethod": "POST", + "url": "api/cms-kit-admin/blogs/blog-posts/create-and-publish", + "supportedVersions": [], + "parametersOnMethod": [ { - "name": "GetAsync", - "parametersOnMethod": [ - { - "name": "id", - "typeAsString": "System.Guid, System.Private.CoreLib", - "type": "System.Guid", - "typeSimple": "string", - "isOptional": false, - "defaultValue": null - } - ], - "returnValue": { - "type": "Volo.CmsKit.Menus.MenuItemDto", - "typeSimple": "Volo.CmsKit.Menus.MenuItemDto" - } - }, + "name": "input", + "typeAsString": "Volo.CmsKit.Admin.Blogs.CreateBlogPostDto, Volo.CmsKit.Admin.Application.Contracts", + "type": "Volo.CmsKit.Admin.Blogs.CreateBlogPostDto", + "typeSimple": "Volo.CmsKit.Admin.Blogs.CreateBlogPostDto", + "isOptional": false, + "defaultValue": null + } + ], + "parameters": [ { - "name": "CreateAsync", - "parametersOnMethod": [ - { - "name": "input", - "typeAsString": "Volo.CmsKit.Admin.Menus.MenuItemCreateInput, Volo.CmsKit.Admin.Application.Contracts", - "type": "Volo.CmsKit.Admin.Menus.MenuItemCreateInput", - "typeSimple": "Volo.CmsKit.Admin.Menus.MenuItemCreateInput", - "isOptional": false, - "defaultValue": null - } - ], - "returnValue": { - "type": "Volo.CmsKit.Menus.MenuItemDto", - "typeSimple": "Volo.CmsKit.Menus.MenuItemDto" - } - }, + "nameOnMethod": "input", + "name": "input", + "jsonName": null, + "type": "Volo.CmsKit.Admin.Blogs.CreateBlogPostDto", + "typeSimple": "Volo.CmsKit.Admin.Blogs.CreateBlogPostDto", + "isOptional": false, + "defaultValue": null, + "constraintTypes": null, + "bindingSourceId": "Body", + "descriptorName": "" + } + ], + "returnValue": { + "type": "Volo.CmsKit.Admin.Blogs.BlogPostDto", + "typeSimple": "Volo.CmsKit.Admin.Blogs.BlogPostDto" + }, + "allowAnonymous": false, + "implementFrom": "Volo.CmsKit.Admin.Blogs.IBlogPostAdminAppService" + }, + "SendToReviewAsyncById": { + "uniqueName": "SendToReviewAsyncById", + "name": "SendToReviewAsync", + "httpMethod": "POST", + "url": "api/cms-kit-admin/blogs/blog-posts/{id}/send-to-review", + "supportedVersions": [], + "parametersOnMethod": [ { - "name": "UpdateAsync", + "name": "id", + "typeAsString": "System.Guid, System.Private.CoreLib", + "type": "System.Guid", + "typeSimple": "string", + "isOptional": false, + "defaultValue": null + } + ], + "parameters": [ + { + "nameOnMethod": "id", + "name": "id", + "jsonName": null, + "type": "System.Guid", + "typeSimple": "string", + "isOptional": false, + "defaultValue": null, + "constraintTypes": [], + "bindingSourceId": "Path", + "descriptorName": "" + } + ], + "returnValue": { + "type": "System.Void", + "typeSimple": "System.Void" + }, + "allowAnonymous": false, + "implementFrom": "Volo.CmsKit.Admin.Blogs.IBlogPostAdminAppService" + }, + "CreateAndSendToReviewAsyncByInput": { + "uniqueName": "CreateAndSendToReviewAsyncByInput", + "name": "CreateAndSendToReviewAsync", + "httpMethod": "POST", + "url": "api/cms-kit-admin/blogs/blog-posts/create-and-send-to-review", + "supportedVersions": [], + "parametersOnMethod": [ + { + "name": "input", + "typeAsString": "Volo.CmsKit.Admin.Blogs.CreateBlogPostDto, Volo.CmsKit.Admin.Application.Contracts", + "type": "Volo.CmsKit.Admin.Blogs.CreateBlogPostDto", + "typeSimple": "Volo.CmsKit.Admin.Blogs.CreateBlogPostDto", + "isOptional": false, + "defaultValue": null + } + ], + "parameters": [ + { + "nameOnMethod": "input", + "name": "input", + "jsonName": null, + "type": "Volo.CmsKit.Admin.Blogs.CreateBlogPostDto", + "typeSimple": "Volo.CmsKit.Admin.Blogs.CreateBlogPostDto", + "isOptional": false, + "defaultValue": null, + "constraintTypes": null, + "bindingSourceId": "Body", + "descriptorName": "" + } + ], + "returnValue": { + "type": "Volo.CmsKit.Admin.Blogs.BlogPostDto", + "typeSimple": "Volo.CmsKit.Admin.Blogs.BlogPostDto" + }, + "allowAnonymous": false, + "implementFrom": "Volo.CmsKit.Admin.Blogs.IBlogPostAdminAppService" + }, + "HasBlogPostWaitingForReviewAsync": { + "uniqueName": "HasBlogPostWaitingForReviewAsync", + "name": "HasBlogPostWaitingForReviewAsync", + "httpMethod": "GET", + "url": "api/cms-kit-admin/blogs/blog-posts/has-blogpost-waiting-for-review", + "supportedVersions": [], + "parametersOnMethod": [], + "parameters": [], + "returnValue": { + "type": "System.Boolean", + "typeSimple": "boolean" + }, + "allowAnonymous": false, + "implementFrom": "Volo.CmsKit.Admin.Blogs.IBlogPostAdminAppService" + } + } + }, + "Volo.CmsKit.Admin.Comments.CommentAdminController": { + "controllerName": "CommentAdmin", + "controllerGroupName": "CommentAdmin", + "isRemoteService": true, + "isIntegrationService": false, + "apiVersion": null, + "type": "Volo.CmsKit.Admin.Comments.CommentAdminController", + "interfaces": [ + { + "type": "Volo.CmsKit.Admin.Comments.ICommentAdminAppService", + "name": "ICommentAdminAppService", + "methods": [ + { + "name": "GetListAsync", "parametersOnMethod": [ - { - "name": "id", - "typeAsString": "System.Guid, System.Private.CoreLib", - "type": "System.Guid", - "typeSimple": "string", - "isOptional": false, - "defaultValue": null - }, { "name": "input", - "typeAsString": "Volo.CmsKit.Admin.Menus.MenuItemUpdateInput, Volo.CmsKit.Admin.Application.Contracts", - "type": "Volo.CmsKit.Admin.Menus.MenuItemUpdateInput", - "typeSimple": "Volo.CmsKit.Admin.Menus.MenuItemUpdateInput", + "typeAsString": "Volo.CmsKit.Admin.Comments.CommentGetListInput, Volo.CmsKit.Admin.Application.Contracts", + "type": "Volo.CmsKit.Admin.Comments.CommentGetListInput", + "typeSimple": "Volo.CmsKit.Admin.Comments.CommentGetListInput", "isOptional": false, "defaultValue": null } ], "returnValue": { - "type": "Volo.CmsKit.Menus.MenuItemDto", - "typeSimple": "Volo.CmsKit.Menus.MenuItemDto" + "type": "Volo.Abp.Application.Dtos.PagedResultDto", + "typeSimple": "Volo.Abp.Application.Dtos.PagedResultDto" } }, { - "name": "DeleteAsync", + "name": "GetAsync", "parametersOnMethod": [ { "name": "id", @@ -1081,12 +1247,12 @@ } ], "returnValue": { - "type": "System.Void", - "typeSimple": "System.Void" + "type": "Volo.CmsKit.Admin.Comments.CommentWithAuthorDto", + "typeSimple": "Volo.CmsKit.Admin.Comments.CommentWithAuthorDto" } }, { - "name": "MoveMenuItemAsync", + "name": "DeleteAsync", "parametersOnMethod": [ { "name": "id", @@ -1095,193 +1261,155 @@ "typeSimple": "string", "isOptional": false, "defaultValue": null - }, - { - "name": "input", - "typeAsString": "Volo.CmsKit.Admin.Menus.MenuItemMoveInput, Volo.CmsKit.Admin.Application.Contracts", - "type": "Volo.CmsKit.Admin.Menus.MenuItemMoveInput", - "typeSimple": "Volo.CmsKit.Admin.Menus.MenuItemMoveInput", - "isOptional": false, - "defaultValue": null } ], "returnValue": { "type": "System.Void", "typeSimple": "System.Void" } - }, - { - "name": "GetPageLookupAsync", - "parametersOnMethod": [ - { - "name": "input", - "typeAsString": "Volo.CmsKit.Admin.Menus.PageLookupInputDto, Volo.CmsKit.Admin.Application.Contracts", - "type": "Volo.CmsKit.Admin.Menus.PageLookupInputDto", - "typeSimple": "Volo.CmsKit.Admin.Menus.PageLookupInputDto", - "isOptional": false, - "defaultValue": null - } - ], - "returnValue": { - "type": "Volo.Abp.Application.Dtos.PagedResultDto", - "typeSimple": "Volo.Abp.Application.Dtos.PagedResultDto" - } } ] } ], "actions": { - "GetListAsync": { - "uniqueName": "GetListAsync", + "GetListAsyncByInput": { + "uniqueName": "GetListAsyncByInput", "name": "GetListAsync", "httpMethod": "GET", - "url": "api/cms-kit-admin/menu-items", - "supportedVersions": [], - "parametersOnMethod": [], - "parameters": [], - "returnValue": { - "type": "Volo.Abp.Application.Dtos.ListResultDto", - "typeSimple": "Volo.Abp.Application.Dtos.ListResultDto" - }, - "allowAnonymous": false, - "implementFrom": "Volo.CmsKit.Admin.Menus.IMenuItemAdminAppService" - }, - "GetAsyncById": { - "uniqueName": "GetAsyncById", - "name": "GetAsync", - "httpMethod": "GET", - "url": "api/cms-kit-admin/menu-items/{id}", + "url": "api/cms-kit-admin/comments", "supportedVersions": [], "parametersOnMethod": [ { - "name": "id", - "typeAsString": "System.Guid, System.Private.CoreLib", - "type": "System.Guid", - "typeSimple": "string", + "name": "input", + "typeAsString": "Volo.CmsKit.Admin.Comments.CommentGetListInput, Volo.CmsKit.Admin.Application.Contracts", + "type": "Volo.CmsKit.Admin.Comments.CommentGetListInput", + "typeSimple": "Volo.CmsKit.Admin.Comments.CommentGetListInput", "isOptional": false, "defaultValue": null } ], "parameters": [ { - "nameOnMethod": "id", - "name": "id", + "nameOnMethod": "input", + "name": "EntityType", "jsonName": null, - "type": "System.Guid", + "type": "System.String", "typeSimple": "string", "isOptional": false, "defaultValue": null, - "constraintTypes": [], - "bindingSourceId": "Path", - "descriptorName": "" - } - ], - "returnValue": { - "type": "Volo.CmsKit.Menus.MenuItemDto", - "typeSimple": "Volo.CmsKit.Menus.MenuItemDto" - }, - "allowAnonymous": false, - "implementFrom": "Volo.CmsKit.Admin.Menus.IMenuItemAdminAppService" - }, - "CreateAsyncByInput": { - "uniqueName": "CreateAsyncByInput", - "name": "CreateAsync", - "httpMethod": "POST", - "url": "api/cms-kit-admin/menu-items", - "supportedVersions": [], - "parametersOnMethod": [ + "constraintTypes": null, + "bindingSourceId": "ModelBinding", + "descriptorName": "input" + }, { - "name": "input", - "typeAsString": "Volo.CmsKit.Admin.Menus.MenuItemCreateInput, Volo.CmsKit.Admin.Application.Contracts", - "type": "Volo.CmsKit.Admin.Menus.MenuItemCreateInput", - "typeSimple": "Volo.CmsKit.Admin.Menus.MenuItemCreateInput", - "isOptional": false, - "defaultValue": null - } - ], - "parameters": [ + "nameOnMethod": "input", + "name": "Text", + "jsonName": null, + "type": "System.String", + "typeSimple": "string", + "isOptional": false, + "defaultValue": null, + "constraintTypes": null, + "bindingSourceId": "ModelBinding", + "descriptorName": "input" + }, { "nameOnMethod": "input", - "name": "input", + "name": "RepliedCommentId", "jsonName": null, - "type": "Volo.CmsKit.Admin.Menus.MenuItemCreateInput", - "typeSimple": "Volo.CmsKit.Admin.Menus.MenuItemCreateInput", + "type": "System.Guid?", + "typeSimple": "string?", "isOptional": false, "defaultValue": null, "constraintTypes": null, - "bindingSourceId": "Body", - "descriptorName": "" - } - ], - "returnValue": { - "type": "Volo.CmsKit.Menus.MenuItemDto", - "typeSimple": "Volo.CmsKit.Menus.MenuItemDto" - }, - "allowAnonymous": false, - "implementFrom": "Volo.CmsKit.Admin.Menus.IMenuItemAdminAppService" - }, - "UpdateAsyncByIdAndInput": { - "uniqueName": "UpdateAsyncByIdAndInput", - "name": "UpdateAsync", - "httpMethod": "PUT", - "url": "api/cms-kit-admin/menu-items/{id}", - "supportedVersions": [], - "parametersOnMethod": [ + "bindingSourceId": "ModelBinding", + "descriptorName": "input" + }, { - "name": "id", - "typeAsString": "System.Guid, System.Private.CoreLib", - "type": "System.Guid", + "nameOnMethod": "input", + "name": "Author", + "jsonName": null, + "type": "System.String", "typeSimple": "string", "isOptional": false, - "defaultValue": null + "defaultValue": null, + "constraintTypes": null, + "bindingSourceId": "ModelBinding", + "descriptorName": "input" }, { - "name": "input", - "typeAsString": "Volo.CmsKit.Admin.Menus.MenuItemUpdateInput, Volo.CmsKit.Admin.Application.Contracts", - "type": "Volo.CmsKit.Admin.Menus.MenuItemUpdateInput", - "typeSimple": "Volo.CmsKit.Admin.Menus.MenuItemUpdateInput", + "nameOnMethod": "input", + "name": "CreationStartDate", + "jsonName": null, + "type": "System.DateTime?", + "typeSimple": "string?", "isOptional": false, - "defaultValue": null - } - ], - "parameters": [ + "defaultValue": null, + "constraintTypes": null, + "bindingSourceId": "ModelBinding", + "descriptorName": "input" + }, { - "nameOnMethod": "id", - "name": "id", + "nameOnMethod": "input", + "name": "CreationEndDate", "jsonName": null, - "type": "System.Guid", + "type": "System.DateTime?", + "typeSimple": "string?", + "isOptional": false, + "defaultValue": null, + "constraintTypes": null, + "bindingSourceId": "ModelBinding", + "descriptorName": "input" + }, + { + "nameOnMethod": "input", + "name": "Sorting", + "jsonName": null, + "type": "System.String", "typeSimple": "string", "isOptional": false, "defaultValue": null, - "constraintTypes": [], - "bindingSourceId": "Path", - "descriptorName": "" + "constraintTypes": null, + "bindingSourceId": "ModelBinding", + "descriptorName": "input" }, { "nameOnMethod": "input", - "name": "input", + "name": "SkipCount", "jsonName": null, - "type": "Volo.CmsKit.Admin.Menus.MenuItemUpdateInput", - "typeSimple": "Volo.CmsKit.Admin.Menus.MenuItemUpdateInput", + "type": "System.Int32", + "typeSimple": "number", "isOptional": false, "defaultValue": null, "constraintTypes": null, - "bindingSourceId": "Body", - "descriptorName": "" + "bindingSourceId": "ModelBinding", + "descriptorName": "input" + }, + { + "nameOnMethod": "input", + "name": "MaxResultCount", + "jsonName": null, + "type": "System.Int32", + "typeSimple": "number", + "isOptional": false, + "defaultValue": null, + "constraintTypes": null, + "bindingSourceId": "ModelBinding", + "descriptorName": "input" } ], "returnValue": { - "type": "Volo.CmsKit.Menus.MenuItemDto", - "typeSimple": "Volo.CmsKit.Menus.MenuItemDto" + "type": "Volo.Abp.Application.Dtos.PagedResultDto", + "typeSimple": "Volo.Abp.Application.Dtos.PagedResultDto" }, "allowAnonymous": false, - "implementFrom": "Volo.CmsKit.Admin.Menus.IMenuItemAdminAppService" + "implementFrom": "Volo.CmsKit.Admin.Comments.ICommentAdminAppService" }, - "DeleteAsyncById": { - "uniqueName": "DeleteAsyncById", - "name": "DeleteAsync", - "httpMethod": "DELETE", - "url": "api/cms-kit-admin/menu-items/{id}", + "GetAsyncById": { + "uniqueName": "GetAsyncById", + "name": "GetAsync", + "httpMethod": "GET", + "url": "api/cms-kit-admin/comments/{id}", "supportedVersions": [], "parametersOnMethod": [ { @@ -1308,17 +1436,17 @@ } ], "returnValue": { - "type": "System.Void", - "typeSimple": "System.Void" + "type": "Volo.CmsKit.Admin.Comments.CommentWithAuthorDto", + "typeSimple": "Volo.CmsKit.Admin.Comments.CommentWithAuthorDto" }, "allowAnonymous": false, - "implementFrom": "Volo.CmsKit.Admin.Menus.IMenuItemAdminAppService" + "implementFrom": "Volo.CmsKit.Admin.Comments.ICommentAdminAppService" }, - "MoveMenuItemAsyncByIdAndInput": { - "uniqueName": "MoveMenuItemAsyncByIdAndInput", - "name": "MoveMenuItemAsync", - "httpMethod": "PUT", - "url": "api/cms-kit-admin/menu-items/{id}/move", + "DeleteAsyncById": { + "uniqueName": "DeleteAsyncById", + "name": "DeleteAsync", + "httpMethod": "DELETE", + "url": "api/cms-kit-admin/comments/{id}", "supportedVersions": [], "parametersOnMethod": [ { @@ -1328,14 +1456,6 @@ "typeSimple": "string", "isOptional": false, "defaultValue": null - }, - { - "name": "input", - "typeAsString": "Volo.CmsKit.Admin.Menus.MenuItemMoveInput, Volo.CmsKit.Admin.Application.Contracts", - "type": "Volo.CmsKit.Admin.Menus.MenuItemMoveInput", - "typeSimple": "Volo.CmsKit.Admin.Menus.MenuItemMoveInput", - "isOptional": false, - "defaultValue": null } ], "parameters": [ @@ -1350,18 +1470,6 @@ "constraintTypes": [], "bindingSourceId": "Path", "descriptorName": "" - }, - { - "nameOnMethod": "input", - "name": "input", - "jsonName": null, - "type": "Volo.CmsKit.Admin.Menus.MenuItemMoveInput", - "typeSimple": "Volo.CmsKit.Admin.Menus.MenuItemMoveInput", - "isOptional": false, - "defaultValue": null, - "constraintTypes": null, - "bindingSourceId": "Body", - "descriptorName": "" } ], "returnValue": { @@ -1369,80 +1477,102 @@ "typeSimple": "System.Void" }, "allowAnonymous": false, - "implementFrom": "Volo.CmsKit.Admin.Menus.IMenuItemAdminAppService" - }, - "GetPageLookupAsyncByInput": { - "uniqueName": "GetPageLookupAsyncByInput", - "name": "GetPageLookupAsync", - "httpMethod": "GET", - "url": "api/cms-kit-admin/menu-items/lookup/pages", - "supportedVersions": [], - "parametersOnMethod": [ - { - "name": "input", - "typeAsString": "Volo.CmsKit.Admin.Menus.PageLookupInputDto, Volo.CmsKit.Admin.Application.Contracts", - "type": "Volo.CmsKit.Admin.Menus.PageLookupInputDto", - "typeSimple": "Volo.CmsKit.Admin.Menus.PageLookupInputDto", - "isOptional": false, - "defaultValue": null - } - ], - "parameters": [ + "implementFrom": "Volo.CmsKit.Admin.Comments.ICommentAdminAppService" + } + } + }, + "Volo.CmsKit.Admin.GlobalResources.GlobalResourceAdminController": { + "controllerName": "GlobalResourceAdmin", + "controllerGroupName": "GlobalResourceAdmin", + "isRemoteService": true, + "isIntegrationService": false, + "apiVersion": null, + "type": "Volo.CmsKit.Admin.GlobalResources.GlobalResourceAdminController", + "interfaces": [ + { + "type": "Volo.CmsKit.Admin.GlobalResources.IGlobalResourceAdminAppService", + "name": "IGlobalResourceAdminAppService", + "methods": [ { - "nameOnMethod": "input", - "name": "Filter", - "jsonName": null, - "type": "System.String", - "typeSimple": "string", - "isOptional": false, - "defaultValue": null, - "constraintTypes": null, - "bindingSourceId": "ModelBinding", - "descriptorName": "input" + "name": "GetAsync", + "parametersOnMethod": [], + "returnValue": { + "type": "Volo.CmsKit.Admin.GlobalResources.GlobalResourcesDto", + "typeSimple": "Volo.CmsKit.Admin.GlobalResources.GlobalResourcesDto" + } }, { - "nameOnMethod": "input", - "name": "Sorting", - "jsonName": null, - "type": "System.String", - "typeSimple": "string", - "isOptional": false, - "defaultValue": null, - "constraintTypes": null, - "bindingSourceId": "ModelBinding", - "descriptorName": "input" - }, + "name": "SetGlobalResourcesAsync", + "parametersOnMethod": [ + { + "name": "input", + "typeAsString": "Volo.CmsKit.Admin.GlobalResources.GlobalResourcesUpdateDto, Volo.CmsKit.Admin.Application.Contracts", + "type": "Volo.CmsKit.Admin.GlobalResources.GlobalResourcesUpdateDto", + "typeSimple": "Volo.CmsKit.Admin.GlobalResources.GlobalResourcesUpdateDto", + "isOptional": false, + "defaultValue": null + } + ], + "returnValue": { + "type": "System.Void", + "typeSimple": "System.Void" + } + } + ] + } + ], + "actions": { + "GetAsync": { + "uniqueName": "GetAsync", + "name": "GetAsync", + "httpMethod": "GET", + "url": "api/cms-kit-admin/global-resources", + "supportedVersions": [], + "parametersOnMethod": [], + "parameters": [], + "returnValue": { + "type": "Volo.CmsKit.Admin.GlobalResources.GlobalResourcesDto", + "typeSimple": "Volo.CmsKit.Admin.GlobalResources.GlobalResourcesDto" + }, + "allowAnonymous": false, + "implementFrom": "Volo.CmsKit.Admin.GlobalResources.IGlobalResourceAdminAppService" + }, + "SetGlobalResourcesAsyncByInput": { + "uniqueName": "SetGlobalResourcesAsyncByInput", + "name": "SetGlobalResourcesAsync", + "httpMethod": "POST", + "url": "api/cms-kit-admin/global-resources", + "supportedVersions": [], + "parametersOnMethod": [ { - "nameOnMethod": "input", - "name": "SkipCount", - "jsonName": null, - "type": "System.Int32", - "typeSimple": "number", + "name": "input", + "typeAsString": "Volo.CmsKit.Admin.GlobalResources.GlobalResourcesUpdateDto, Volo.CmsKit.Admin.Application.Contracts", + "type": "Volo.CmsKit.Admin.GlobalResources.GlobalResourcesUpdateDto", + "typeSimple": "Volo.CmsKit.Admin.GlobalResources.GlobalResourcesUpdateDto", "isOptional": false, - "defaultValue": null, - "constraintTypes": null, - "bindingSourceId": "ModelBinding", - "descriptorName": "input" - }, + "defaultValue": null + } + ], + "parameters": [ { "nameOnMethod": "input", - "name": "MaxResultCount", + "name": "input", "jsonName": null, - "type": "System.Int32", - "typeSimple": "number", + "type": "Volo.CmsKit.Admin.GlobalResources.GlobalResourcesUpdateDto", + "typeSimple": "Volo.CmsKit.Admin.GlobalResources.GlobalResourcesUpdateDto", "isOptional": false, "defaultValue": null, "constraintTypes": null, - "bindingSourceId": "ModelBinding", - "descriptorName": "input" + "bindingSourceId": "Body", + "descriptorName": "" } ], "returnValue": { - "type": "Volo.Abp.Application.Dtos.PagedResultDto", - "typeSimple": "Volo.Abp.Application.Dtos.PagedResultDto" + "type": "System.Void", + "typeSimple": "System.Void" }, "allowAnonymous": false, - "implementFrom": "Volo.CmsKit.Admin.Menus.IMenuItemAdminAppService" + "implementFrom": "Volo.CmsKit.Admin.GlobalResources.IGlobalResourceAdminAppService" } } }, @@ -1612,132 +1742,62 @@ } } }, - "Volo.CmsKit.Admin.GlobalResources.GlobalResourceAdminController": { - "controllerName": "GlobalResourceAdmin", - "controllerGroupName": "GlobalResourceAdmin", + "Volo.CmsKit.Admin.Menus.MenuItemAdminController": { + "controllerName": "MenuItemAdmin", + "controllerGroupName": "MenuItemAdmin", "isRemoteService": true, "isIntegrationService": false, "apiVersion": null, - "type": "Volo.CmsKit.Admin.GlobalResources.GlobalResourceAdminController", + "type": "Volo.CmsKit.Admin.Menus.MenuItemAdminController", "interfaces": [ { - "type": "Volo.CmsKit.Admin.GlobalResources.IGlobalResourceAdminAppService", - "name": "IGlobalResourceAdminAppService", + "type": "Volo.CmsKit.Admin.Menus.IMenuItemAdminAppService", + "name": "IMenuItemAdminAppService", "methods": [ { - "name": "GetAsync", + "name": "GetListAsync", "parametersOnMethod": [], "returnValue": { - "type": "Volo.CmsKit.Admin.GlobalResources.GlobalResourcesDto", - "typeSimple": "Volo.CmsKit.Admin.GlobalResources.GlobalResourcesDto" + "type": "Volo.Abp.Application.Dtos.ListResultDto", + "typeSimple": "Volo.Abp.Application.Dtos.ListResultDto" } }, { - "name": "SetGlobalResourcesAsync", + "name": "GetAsync", "parametersOnMethod": [ { - "name": "input", - "typeAsString": "Volo.CmsKit.Admin.GlobalResources.GlobalResourcesUpdateDto, Volo.CmsKit.Admin.Application.Contracts", - "type": "Volo.CmsKit.Admin.GlobalResources.GlobalResourcesUpdateDto", - "typeSimple": "Volo.CmsKit.Admin.GlobalResources.GlobalResourcesUpdateDto", + "name": "id", + "typeAsString": "System.Guid, System.Private.CoreLib", + "type": "System.Guid", + "typeSimple": "string", "isOptional": false, "defaultValue": null } ], "returnValue": { - "type": "System.Void", - "typeSimple": "System.Void" + "type": "Volo.CmsKit.Admin.Menus.MenuItemWithDetailsDto", + "typeSimple": "Volo.CmsKit.Admin.Menus.MenuItemWithDetailsDto" } - } - ] - } - ], - "actions": { - "GetAsync": { - "uniqueName": "GetAsync", - "name": "GetAsync", - "httpMethod": "GET", - "url": "api/cms-kit-admin/global-resources", - "supportedVersions": [], - "parametersOnMethod": [], - "parameters": [], - "returnValue": { - "type": "Volo.CmsKit.Admin.GlobalResources.GlobalResourcesDto", - "typeSimple": "Volo.CmsKit.Admin.GlobalResources.GlobalResourcesDto" - }, - "allowAnonymous": false, - "implementFrom": "Volo.CmsKit.Admin.GlobalResources.IGlobalResourceAdminAppService" - }, - "SetGlobalResourcesAsyncByInput": { - "uniqueName": "SetGlobalResourcesAsyncByInput", - "name": "SetGlobalResourcesAsync", - "httpMethod": "POST", - "url": "api/cms-kit-admin/global-resources", - "supportedVersions": [], - "parametersOnMethod": [ - { - "name": "input", - "typeAsString": "Volo.CmsKit.Admin.GlobalResources.GlobalResourcesUpdateDto, Volo.CmsKit.Admin.Application.Contracts", - "type": "Volo.CmsKit.Admin.GlobalResources.GlobalResourcesUpdateDto", - "typeSimple": "Volo.CmsKit.Admin.GlobalResources.GlobalResourcesUpdateDto", - "isOptional": false, - "defaultValue": null - } - ], - "parameters": [ - { - "nameOnMethod": "input", - "name": "input", - "jsonName": null, - "type": "Volo.CmsKit.Admin.GlobalResources.GlobalResourcesUpdateDto", - "typeSimple": "Volo.CmsKit.Admin.GlobalResources.GlobalResourcesUpdateDto", - "isOptional": false, - "defaultValue": null, - "constraintTypes": null, - "bindingSourceId": "Body", - "descriptorName": "" - } - ], - "returnValue": { - "type": "System.Void", - "typeSimple": "System.Void" - }, - "allowAnonymous": false, - "implementFrom": "Volo.CmsKit.Admin.GlobalResources.IGlobalResourceAdminAppService" - } - } - }, - "Volo.CmsKit.Admin.Comments.CommentAdminController": { - "controllerName": "CommentAdmin", - "controllerGroupName": "CommentAdmin", - "isRemoteService": true, - "isIntegrationService": false, - "apiVersion": null, - "type": "Volo.CmsKit.Admin.Comments.CommentAdminController", - "interfaces": [ - { - "type": "Volo.CmsKit.Admin.Comments.ICommentAdminAppService", - "name": "ICommentAdminAppService", - "methods": [ + }, { - "name": "GetListAsync", + "name": "CreateAsync", "parametersOnMethod": [ { "name": "input", - "typeAsString": "Volo.CmsKit.Admin.Comments.CommentGetListInput, Volo.CmsKit.Admin.Application.Contracts", - "type": "Volo.CmsKit.Admin.Comments.CommentGetListInput", - "typeSimple": "Volo.CmsKit.Admin.Comments.CommentGetListInput", + "typeAsString": "Volo.CmsKit.Admin.Menus.MenuItemCreateInput, Volo.CmsKit.Admin.Application.Contracts", + "type": "Volo.CmsKit.Admin.Menus.MenuItemCreateInput", + "typeSimple": "Volo.CmsKit.Admin.Menus.MenuItemCreateInput", "isOptional": false, "defaultValue": null } ], "returnValue": { - "type": "Volo.Abp.Application.Dtos.PagedResultDto", - "typeSimple": "Volo.Abp.Application.Dtos.PagedResultDto" + "type": "Volo.CmsKit.Menus.MenuItemDto", + "typeSimple": "Volo.CmsKit.Menus.MenuItemDto" } }, { - "name": "GetAsync", + "name": "UpdateAsync", "parametersOnMethod": [ { "name": "id", @@ -1746,11 +1806,19 @@ "typeSimple": "string", "isOptional": false, "defaultValue": null + }, + { + "name": "input", + "typeAsString": "Volo.CmsKit.Admin.Menus.MenuItemUpdateInput, Volo.CmsKit.Admin.Application.Contracts", + "type": "Volo.CmsKit.Admin.Menus.MenuItemUpdateInput", + "typeSimple": "Volo.CmsKit.Admin.Menus.MenuItemUpdateInput", + "isOptional": false, + "defaultValue": null } ], "returnValue": { - "type": "Volo.CmsKit.Admin.Comments.CommentWithAuthorDto", - "typeSimple": "Volo.CmsKit.Admin.Comments.CommentWithAuthorDto" + "type": "Volo.CmsKit.Menus.MenuItemDto", + "typeSimple": "Volo.CmsKit.Menus.MenuItemDto" } }, { @@ -1769,23 +1837,117 @@ "type": "System.Void", "typeSimple": "System.Void" } + }, + { + "name": "MoveMenuItemAsync", + "parametersOnMethod": [ + { + "name": "id", + "typeAsString": "System.Guid, System.Private.CoreLib", + "type": "System.Guid", + "typeSimple": "string", + "isOptional": false, + "defaultValue": null + }, + { + "name": "input", + "typeAsString": "Volo.CmsKit.Admin.Menus.MenuItemMoveInput, Volo.CmsKit.Admin.Application.Contracts", + "type": "Volo.CmsKit.Admin.Menus.MenuItemMoveInput", + "typeSimple": "Volo.CmsKit.Admin.Menus.MenuItemMoveInput", + "isOptional": false, + "defaultValue": null + } + ], + "returnValue": { + "type": "System.Void", + "typeSimple": "System.Void" + } + }, + { + "name": "GetPageLookupAsync", + "parametersOnMethod": [ + { + "name": "input", + "typeAsString": "Volo.CmsKit.Admin.Menus.PageLookupInputDto, Volo.CmsKit.Admin.Application.Contracts", + "type": "Volo.CmsKit.Admin.Menus.PageLookupInputDto", + "typeSimple": "Volo.CmsKit.Admin.Menus.PageLookupInputDto", + "isOptional": false, + "defaultValue": null + } + ], + "returnValue": { + "type": "Volo.Abp.Application.Dtos.PagedResultDto", + "typeSimple": "Volo.Abp.Application.Dtos.PagedResultDto" + } } ] } ], "actions": { - "GetListAsyncByInput": { - "uniqueName": "GetListAsyncByInput", + "GetListAsync": { + "uniqueName": "GetListAsync", "name": "GetListAsync", "httpMethod": "GET", - "url": "api/cms-kit-admin/comments", + "url": "api/cms-kit-admin/menu-items", + "supportedVersions": [], + "parametersOnMethod": [], + "parameters": [], + "returnValue": { + "type": "Volo.Abp.Application.Dtos.ListResultDto", + "typeSimple": "Volo.Abp.Application.Dtos.ListResultDto" + }, + "allowAnonymous": false, + "implementFrom": "Volo.CmsKit.Admin.Menus.IMenuItemAdminAppService" + }, + "GetAsyncById": { + "uniqueName": "GetAsyncById", + "name": "GetAsync", + "httpMethod": "GET", + "url": "api/cms-kit-admin/menu-items/{id}", + "supportedVersions": [], + "parametersOnMethod": [ + { + "name": "id", + "typeAsString": "System.Guid, System.Private.CoreLib", + "type": "System.Guid", + "typeSimple": "string", + "isOptional": false, + "defaultValue": null + } + ], + "parameters": [ + { + "nameOnMethod": "id", + "name": "id", + "jsonName": null, + "type": "System.Guid", + "typeSimple": "string", + "isOptional": false, + "defaultValue": null, + "constraintTypes": [], + "bindingSourceId": "Path", + "descriptorName": "" + } + ], + "returnValue": { + "type": "Volo.CmsKit.Admin.Menus.MenuItemWithDetailsDto", + "typeSimple": "Volo.CmsKit.Admin.Menus.MenuItemWithDetailsDto" + }, + "allowAnonymous": false, + "implementFrom": "Volo.CmsKit.Admin.Menus.IMenuItemAdminAppService" + }, + "CreateAsyncByInput": { + "uniqueName": "CreateAsyncByInput", + "name": "CreateAsync", + "httpMethod": "POST", + "url": "api/cms-kit-admin/menu-items", "supportedVersions": [], "parametersOnMethod": [ { "name": "input", - "typeAsString": "Volo.CmsKit.Admin.Comments.CommentGetListInput, Volo.CmsKit.Admin.Application.Contracts", - "type": "Volo.CmsKit.Admin.Comments.CommentGetListInput", - "typeSimple": "Volo.CmsKit.Admin.Comments.CommentGetListInput", + "typeAsString": "Volo.CmsKit.Admin.Menus.MenuItemCreateInput, Volo.CmsKit.Admin.Application.Contracts", + "type": "Volo.CmsKit.Admin.Menus.MenuItemCreateInput", + "typeSimple": "Volo.CmsKit.Admin.Menus.MenuItemCreateInput", "isOptional": false, "defaultValue": null } @@ -1793,125 +1955,123 @@ "parameters": [ { "nameOnMethod": "input", - "name": "EntityType", + "name": "input", "jsonName": null, - "type": "System.String", - "typeSimple": "string", + "type": "Volo.CmsKit.Admin.Menus.MenuItemCreateInput", + "typeSimple": "Volo.CmsKit.Admin.Menus.MenuItemCreateInput", "isOptional": false, "defaultValue": null, "constraintTypes": null, - "bindingSourceId": "ModelBinding", - "descriptorName": "input" - }, + "bindingSourceId": "Body", + "descriptorName": "" + } + ], + "returnValue": { + "type": "Volo.CmsKit.Menus.MenuItemDto", + "typeSimple": "Volo.CmsKit.Menus.MenuItemDto" + }, + "allowAnonymous": false, + "implementFrom": "Volo.CmsKit.Admin.Menus.IMenuItemAdminAppService" + }, + "UpdateAsyncByIdAndInput": { + "uniqueName": "UpdateAsyncByIdAndInput", + "name": "UpdateAsync", + "httpMethod": "PUT", + "url": "api/cms-kit-admin/menu-items/{id}", + "supportedVersions": [], + "parametersOnMethod": [ { - "nameOnMethod": "input", - "name": "Text", - "jsonName": null, - "type": "System.String", + "name": "id", + "typeAsString": "System.Guid, System.Private.CoreLib", + "type": "System.Guid", "typeSimple": "string", "isOptional": false, - "defaultValue": null, - "constraintTypes": null, - "bindingSourceId": "ModelBinding", - "descriptorName": "input" + "defaultValue": null }, { - "nameOnMethod": "input", - "name": "RepliedCommentId", - "jsonName": null, - "type": "System.Guid?", - "typeSimple": "string?", + "name": "input", + "typeAsString": "Volo.CmsKit.Admin.Menus.MenuItemUpdateInput, Volo.CmsKit.Admin.Application.Contracts", + "type": "Volo.CmsKit.Admin.Menus.MenuItemUpdateInput", + "typeSimple": "Volo.CmsKit.Admin.Menus.MenuItemUpdateInput", "isOptional": false, - "defaultValue": null, - "constraintTypes": null, - "bindingSourceId": "ModelBinding", - "descriptorName": "input" - }, + "defaultValue": null + } + ], + "parameters": [ { - "nameOnMethod": "input", - "name": "Author", + "nameOnMethod": "id", + "name": "id", "jsonName": null, - "type": "System.String", + "type": "System.Guid", "typeSimple": "string", "isOptional": false, "defaultValue": null, - "constraintTypes": null, - "bindingSourceId": "ModelBinding", - "descriptorName": "input" - }, - { - "nameOnMethod": "input", - "name": "CreationStartDate", - "jsonName": null, - "type": "System.DateTime?", - "typeSimple": "string?", - "isOptional": false, - "defaultValue": null, - "constraintTypes": null, - "bindingSourceId": "ModelBinding", - "descriptorName": "input" + "constraintTypes": [], + "bindingSourceId": "Path", + "descriptorName": "" }, { "nameOnMethod": "input", - "name": "CreationEndDate", + "name": "input", "jsonName": null, - "type": "System.DateTime?", - "typeSimple": "string?", + "type": "Volo.CmsKit.Admin.Menus.MenuItemUpdateInput", + "typeSimple": "Volo.CmsKit.Admin.Menus.MenuItemUpdateInput", "isOptional": false, "defaultValue": null, "constraintTypes": null, - "bindingSourceId": "ModelBinding", - "descriptorName": "input" - }, + "bindingSourceId": "Body", + "descriptorName": "" + } + ], + "returnValue": { + "type": "Volo.CmsKit.Menus.MenuItemDto", + "typeSimple": "Volo.CmsKit.Menus.MenuItemDto" + }, + "allowAnonymous": false, + "implementFrom": "Volo.CmsKit.Admin.Menus.IMenuItemAdminAppService" + }, + "DeleteAsyncById": { + "uniqueName": "DeleteAsyncById", + "name": "DeleteAsync", + "httpMethod": "DELETE", + "url": "api/cms-kit-admin/menu-items/{id}", + "supportedVersions": [], + "parametersOnMethod": [ { - "nameOnMethod": "input", - "name": "Sorting", - "jsonName": null, - "type": "System.String", + "name": "id", + "typeAsString": "System.Guid, System.Private.CoreLib", + "type": "System.Guid", "typeSimple": "string", "isOptional": false, - "defaultValue": null, - "constraintTypes": null, - "bindingSourceId": "ModelBinding", - "descriptorName": "input" - }, - { - "nameOnMethod": "input", - "name": "SkipCount", - "jsonName": null, - "type": "System.Int32", - "typeSimple": "number", - "isOptional": false, - "defaultValue": null, - "constraintTypes": null, - "bindingSourceId": "ModelBinding", - "descriptorName": "input" - }, + "defaultValue": null + } + ], + "parameters": [ { - "nameOnMethod": "input", - "name": "MaxResultCount", + "nameOnMethod": "id", + "name": "id", "jsonName": null, - "type": "System.Int32", - "typeSimple": "number", + "type": "System.Guid", + "typeSimple": "string", "isOptional": false, "defaultValue": null, - "constraintTypes": null, - "bindingSourceId": "ModelBinding", - "descriptorName": "input" + "constraintTypes": [], + "bindingSourceId": "Path", + "descriptorName": "" } ], "returnValue": { - "type": "Volo.Abp.Application.Dtos.PagedResultDto", - "typeSimple": "Volo.Abp.Application.Dtos.PagedResultDto" + "type": "System.Void", + "typeSimple": "System.Void" }, "allowAnonymous": false, - "implementFrom": "Volo.CmsKit.Admin.Comments.ICommentAdminAppService" + "implementFrom": "Volo.CmsKit.Admin.Menus.IMenuItemAdminAppService" }, - "GetAsyncById": { - "uniqueName": "GetAsyncById", - "name": "GetAsync", - "httpMethod": "GET", - "url": "api/cms-kit-admin/comments/{id}", + "MoveMenuItemAsyncByIdAndInput": { + "uniqueName": "MoveMenuItemAsyncByIdAndInput", + "name": "MoveMenuItemAsync", + "httpMethod": "PUT", + "url": "api/cms-kit-admin/menu-items/{id}/move", "supportedVersions": [], "parametersOnMethod": [ { @@ -1921,6 +2081,14 @@ "typeSimple": "string", "isOptional": false, "defaultValue": null + }, + { + "name": "input", + "typeAsString": "Volo.CmsKit.Admin.Menus.MenuItemMoveInput, Volo.CmsKit.Admin.Application.Contracts", + "type": "Volo.CmsKit.Admin.Menus.MenuItemMoveInput", + "typeSimple": "Volo.CmsKit.Admin.Menus.MenuItemMoveInput", + "isOptional": false, + "defaultValue": null } ], "parameters": [ @@ -1935,66 +2103,131 @@ "constraintTypes": [], "bindingSourceId": "Path", "descriptorName": "" + }, + { + "nameOnMethod": "input", + "name": "input", + "jsonName": null, + "type": "Volo.CmsKit.Admin.Menus.MenuItemMoveInput", + "typeSimple": "Volo.CmsKit.Admin.Menus.MenuItemMoveInput", + "isOptional": false, + "defaultValue": null, + "constraintTypes": null, + "bindingSourceId": "Body", + "descriptorName": "" } ], "returnValue": { - "type": "Volo.CmsKit.Admin.Comments.CommentWithAuthorDto", - "typeSimple": "Volo.CmsKit.Admin.Comments.CommentWithAuthorDto" + "type": "System.Void", + "typeSimple": "System.Void" }, "allowAnonymous": false, - "implementFrom": "Volo.CmsKit.Admin.Comments.ICommentAdminAppService" + "implementFrom": "Volo.CmsKit.Admin.Menus.IMenuItemAdminAppService" }, - "DeleteAsyncById": { - "uniqueName": "DeleteAsyncById", - "name": "DeleteAsync", - "httpMethod": "DELETE", - "url": "api/cms-kit-admin/comments/{id}", + "GetPageLookupAsyncByInput": { + "uniqueName": "GetPageLookupAsyncByInput", + "name": "GetPageLookupAsync", + "httpMethod": "GET", + "url": "api/cms-kit-admin/menu-items/lookup/pages", "supportedVersions": [], "parametersOnMethod": [ { - "name": "id", - "typeAsString": "System.Guid, System.Private.CoreLib", - "type": "System.Guid", + "name": "input", + "typeAsString": "Volo.CmsKit.Admin.Menus.PageLookupInputDto, Volo.CmsKit.Admin.Application.Contracts", + "type": "Volo.CmsKit.Admin.Menus.PageLookupInputDto", + "typeSimple": "Volo.CmsKit.Admin.Menus.PageLookupInputDto", + "isOptional": false, + "defaultValue": null + } + ], + "parameters": [ + { + "nameOnMethod": "input", + "name": "Filter", + "jsonName": null, + "type": "System.String", + "typeSimple": "string", + "isOptional": false, + "defaultValue": null, + "constraintTypes": null, + "bindingSourceId": "ModelBinding", + "descriptorName": "input" + }, + { + "nameOnMethod": "input", + "name": "Sorting", + "jsonName": null, + "type": "System.String", "typeSimple": "string", "isOptional": false, - "defaultValue": null - } - ], - "parameters": [ + "defaultValue": null, + "constraintTypes": null, + "bindingSourceId": "ModelBinding", + "descriptorName": "input" + }, + { + "nameOnMethod": "input", + "name": "SkipCount", + "jsonName": null, + "type": "System.Int32", + "typeSimple": "number", + "isOptional": false, + "defaultValue": null, + "constraintTypes": null, + "bindingSourceId": "ModelBinding", + "descriptorName": "input" + }, { - "nameOnMethod": "id", - "name": "id", + "nameOnMethod": "input", + "name": "MaxResultCount", "jsonName": null, - "type": "System.Guid", - "typeSimple": "string", + "type": "System.Int32", + "typeSimple": "number", "isOptional": false, "defaultValue": null, - "constraintTypes": [], - "bindingSourceId": "Path", - "descriptorName": "" + "constraintTypes": null, + "bindingSourceId": "ModelBinding", + "descriptorName": "input" } ], "returnValue": { - "type": "System.Void", - "typeSimple": "System.Void" + "type": "Volo.Abp.Application.Dtos.PagedResultDto", + "typeSimple": "Volo.Abp.Application.Dtos.PagedResultDto" }, "allowAnonymous": false, - "implementFrom": "Volo.CmsKit.Admin.Comments.ICommentAdminAppService" + "implementFrom": "Volo.CmsKit.Admin.Menus.IMenuItemAdminAppService" } } }, - "Volo.CmsKit.Admin.Blogs.BlogAdminController": { - "controllerName": "BlogAdmin", - "controllerGroupName": "BlogAdmin", + "Volo.CmsKit.Admin.Pages.PageAdminController": { + "controllerName": "PageAdmin", + "controllerGroupName": "PageAdmin", "isRemoteService": true, "isIntegrationService": false, "apiVersion": null, - "type": "Volo.CmsKit.Admin.Blogs.BlogAdminController", + "type": "Volo.CmsKit.Admin.Pages.PageAdminController", "interfaces": [ { - "type": "Volo.CmsKit.Admin.Blogs.IBlogAdminAppService", - "name": "IBlogAdminAppService", + "type": "Volo.CmsKit.Admin.Pages.IPageAdminAppService", + "name": "IPageAdminAppService", "methods": [ + { + "name": "SetAsHomePageAsync", + "parametersOnMethod": [ + { + "name": "id", + "typeAsString": "System.Guid, System.Private.CoreLib", + "type": "System.Guid", + "typeSimple": "string", + "isOptional": false, + "defaultValue": null + } + ], + "returnValue": { + "type": "System.Void", + "typeSimple": "System.Void" + } + }, { "name": "GetAsync", "parametersOnMethod": [ @@ -2008,8 +2241,8 @@ } ], "returnValue": { - "type": "Volo.CmsKit.Admin.Blogs.BlogDto", - "typeSimple": "Volo.CmsKit.Admin.Blogs.BlogDto" + "type": "Volo.CmsKit.Admin.Pages.PageDto", + "typeSimple": "Volo.CmsKit.Admin.Pages.PageDto" } }, { @@ -2017,16 +2250,16 @@ "parametersOnMethod": [ { "name": "input", - "typeAsString": "Volo.CmsKit.Admin.Blogs.BlogGetListInput, Volo.CmsKit.Admin.Application.Contracts", - "type": "Volo.CmsKit.Admin.Blogs.BlogGetListInput", - "typeSimple": "Volo.CmsKit.Admin.Blogs.BlogGetListInput", + "typeAsString": "Volo.CmsKit.Admin.Pages.GetPagesInputDto, Volo.CmsKit.Admin.Application.Contracts", + "type": "Volo.CmsKit.Admin.Pages.GetPagesInputDto", + "typeSimple": "Volo.CmsKit.Admin.Pages.GetPagesInputDto", "isOptional": false, "defaultValue": null } ], "returnValue": { - "type": "Volo.Abp.Application.Dtos.PagedResultDto", - "typeSimple": "Volo.Abp.Application.Dtos.PagedResultDto" + "type": "Volo.Abp.Application.Dtos.PagedResultDto", + "typeSimple": "Volo.Abp.Application.Dtos.PagedResultDto" } }, { @@ -2034,16 +2267,16 @@ "parametersOnMethod": [ { "name": "input", - "typeAsString": "Volo.CmsKit.Admin.Blogs.CreateBlogDto, Volo.CmsKit.Admin.Application.Contracts", - "type": "Volo.CmsKit.Admin.Blogs.CreateBlogDto", - "typeSimple": "Volo.CmsKit.Admin.Blogs.CreateBlogDto", + "typeAsString": "Volo.CmsKit.Admin.Pages.CreatePageInputDto, Volo.CmsKit.Admin.Application.Contracts", + "type": "Volo.CmsKit.Admin.Pages.CreatePageInputDto", + "typeSimple": "Volo.CmsKit.Admin.Pages.CreatePageInputDto", "isOptional": false, "defaultValue": null } ], "returnValue": { - "type": "Volo.CmsKit.Admin.Blogs.BlogDto", - "typeSimple": "Volo.CmsKit.Admin.Blogs.BlogDto" + "type": "Volo.CmsKit.Admin.Pages.PageDto", + "typeSimple": "Volo.CmsKit.Admin.Pages.PageDto" } }, { @@ -2059,16 +2292,16 @@ }, { "name": "input", - "typeAsString": "Volo.CmsKit.Admin.Blogs.UpdateBlogDto, Volo.CmsKit.Admin.Application.Contracts", - "type": "Volo.CmsKit.Admin.Blogs.UpdateBlogDto", - "typeSimple": "Volo.CmsKit.Admin.Blogs.UpdateBlogDto", + "typeAsString": "Volo.CmsKit.Admin.Pages.UpdatePageInputDto, Volo.CmsKit.Admin.Application.Contracts", + "type": "Volo.CmsKit.Admin.Pages.UpdatePageInputDto", + "typeSimple": "Volo.CmsKit.Admin.Pages.UpdatePageInputDto", "isOptional": false, "defaultValue": null } ], "returnValue": { - "type": "Volo.CmsKit.Admin.Blogs.BlogDto", - "typeSimple": "Volo.CmsKit.Admin.Blogs.BlogDto" + "type": "Volo.CmsKit.Admin.Pages.PageDto", + "typeSimple": "Volo.CmsKit.Admin.Pages.PageDto" } }, { @@ -2096,7 +2329,7 @@ "uniqueName": "GetAsyncById", "name": "GetAsync", "httpMethod": "GET", - "url": "api/cms-kit-admin/blogs/{id}", + "url": "api/cms-kit-admin/pages/{id}", "supportedVersions": [], "parametersOnMethod": [ { @@ -2123,24 +2356,24 @@ } ], "returnValue": { - "type": "Volo.CmsKit.Admin.Blogs.BlogDto", - "typeSimple": "Volo.CmsKit.Admin.Blogs.BlogDto" + "type": "Volo.CmsKit.Admin.Pages.PageDto", + "typeSimple": "Volo.CmsKit.Admin.Pages.PageDto" }, "allowAnonymous": false, - "implementFrom": "Volo.Abp.Application.Services.IReadOnlyAppService" + "implementFrom": "Volo.Abp.Application.Services.IReadOnlyAppService" }, "GetListAsyncByInput": { "uniqueName": "GetListAsyncByInput", "name": "GetListAsync", "httpMethod": "GET", - "url": "api/cms-kit-admin/blogs", + "url": "api/cms-kit-admin/pages", "supportedVersions": [], "parametersOnMethod": [ { "name": "input", - "typeAsString": "Volo.CmsKit.Admin.Blogs.BlogGetListInput, Volo.CmsKit.Admin.Application.Contracts", - "type": "Volo.CmsKit.Admin.Blogs.BlogGetListInput", - "typeSimple": "Volo.CmsKit.Admin.Blogs.BlogGetListInput", + "typeAsString": "Volo.CmsKit.Admin.Pages.GetPagesInputDto, Volo.CmsKit.Admin.Application.Contracts", + "type": "Volo.CmsKit.Admin.Pages.GetPagesInputDto", + "typeSimple": "Volo.CmsKit.Admin.Pages.GetPagesInputDto", "isOptional": false, "defaultValue": null } @@ -2196,24 +2429,24 @@ } ], "returnValue": { - "type": "Volo.Abp.Application.Dtos.PagedResultDto", - "typeSimple": "Volo.Abp.Application.Dtos.PagedResultDto" + "type": "Volo.Abp.Application.Dtos.PagedResultDto", + "typeSimple": "Volo.Abp.Application.Dtos.PagedResultDto" }, "allowAnonymous": false, - "implementFrom": "Volo.Abp.Application.Services.IReadOnlyAppService" + "implementFrom": "Volo.Abp.Application.Services.IReadOnlyAppService" }, "CreateAsyncByInput": { "uniqueName": "CreateAsyncByInput", "name": "CreateAsync", "httpMethod": "POST", - "url": "api/cms-kit-admin/blogs", + "url": "api/cms-kit-admin/pages", "supportedVersions": [], "parametersOnMethod": [ { "name": "input", - "typeAsString": "Volo.CmsKit.Admin.Blogs.CreateBlogDto, Volo.CmsKit.Admin.Application.Contracts", - "type": "Volo.CmsKit.Admin.Blogs.CreateBlogDto", - "typeSimple": "Volo.CmsKit.Admin.Blogs.CreateBlogDto", + "typeAsString": "Volo.CmsKit.Admin.Pages.CreatePageInputDto, Volo.CmsKit.Admin.Application.Contracts", + "type": "Volo.CmsKit.Admin.Pages.CreatePageInputDto", + "typeSimple": "Volo.CmsKit.Admin.Pages.CreatePageInputDto", "isOptional": false, "defaultValue": null } @@ -2223,8 +2456,8 @@ "nameOnMethod": "input", "name": "input", "jsonName": null, - "type": "Volo.CmsKit.Admin.Blogs.CreateBlogDto", - "typeSimple": "Volo.CmsKit.Admin.Blogs.CreateBlogDto", + "type": "Volo.CmsKit.Admin.Pages.CreatePageInputDto", + "typeSimple": "Volo.CmsKit.Admin.Pages.CreatePageInputDto", "isOptional": false, "defaultValue": null, "constraintTypes": null, @@ -2233,17 +2466,17 @@ } ], "returnValue": { - "type": "Volo.CmsKit.Admin.Blogs.BlogDto", - "typeSimple": "Volo.CmsKit.Admin.Blogs.BlogDto" + "type": "Volo.CmsKit.Admin.Pages.PageDto", + "typeSimple": "Volo.CmsKit.Admin.Pages.PageDto" }, "allowAnonymous": false, - "implementFrom": "Volo.Abp.Application.Services.ICreateAppService" + "implementFrom": "Volo.Abp.Application.Services.ICreateAppService" }, "UpdateAsyncByIdAndInput": { "uniqueName": "UpdateAsyncByIdAndInput", "name": "UpdateAsync", "httpMethod": "PUT", - "url": "api/cms-kit-admin/blogs/{id}", + "url": "api/cms-kit-admin/pages/{id}", "supportedVersions": [], "parametersOnMethod": [ { @@ -2256,9 +2489,9 @@ }, { "name": "input", - "typeAsString": "Volo.CmsKit.Admin.Blogs.UpdateBlogDto, Volo.CmsKit.Admin.Application.Contracts", - "type": "Volo.CmsKit.Admin.Blogs.UpdateBlogDto", - "typeSimple": "Volo.CmsKit.Admin.Blogs.UpdateBlogDto", + "typeAsString": "Volo.CmsKit.Admin.Pages.UpdatePageInputDto, Volo.CmsKit.Admin.Application.Contracts", + "type": "Volo.CmsKit.Admin.Pages.UpdatePageInputDto", + "typeSimple": "Volo.CmsKit.Admin.Pages.UpdatePageInputDto", "isOptional": false, "defaultValue": null } @@ -2280,8 +2513,8 @@ "nameOnMethod": "input", "name": "input", "jsonName": null, - "type": "Volo.CmsKit.Admin.Blogs.UpdateBlogDto", - "typeSimple": "Volo.CmsKit.Admin.Blogs.UpdateBlogDto", + "type": "Volo.CmsKit.Admin.Pages.UpdatePageInputDto", + "typeSimple": "Volo.CmsKit.Admin.Pages.UpdatePageInputDto", "isOptional": false, "defaultValue": null, "constraintTypes": null, @@ -2290,17 +2523,17 @@ } ], "returnValue": { - "type": "Volo.CmsKit.Admin.Blogs.BlogDto", - "typeSimple": "Volo.CmsKit.Admin.Blogs.BlogDto" + "type": "Volo.CmsKit.Admin.Pages.PageDto", + "typeSimple": "Volo.CmsKit.Admin.Pages.PageDto" }, "allowAnonymous": false, - "implementFrom": "Volo.Abp.Application.Services.IUpdateAppService" + "implementFrom": "Volo.Abp.Application.Services.IUpdateAppService" }, "DeleteAsyncById": { "uniqueName": "DeleteAsyncById", "name": "DeleteAsync", "httpMethod": "DELETE", - "url": "api/cms-kit-admin/blogs/{id}", + "url": "api/cms-kit-admin/pages/{id}", "supportedVersions": [], "parametersOnMethod": [ { @@ -2331,133 +2564,28 @@ "typeSimple": "System.Void" }, "allowAnonymous": false, - "implementFrom": "Volo.Abp.Application.Services.IDeleteAppService" - } - } - }, - "Volo.CmsKit.Admin.Blogs.BlogFeatureAdminController": { - "controllerName": "BlogFeatureAdmin", - "controllerGroupName": "BlogFeatureAdmin", - "isRemoteService": true, - "isIntegrationService": false, - "apiVersion": null, - "type": "Volo.CmsKit.Admin.Blogs.BlogFeatureAdminController", - "interfaces": [ - { - "type": "Volo.CmsKit.Admin.Blogs.IBlogFeatureAdminAppService", - "name": "IBlogFeatureAdminAppService", - "methods": [ - { - "name": "SetAsync", - "parametersOnMethod": [ - { - "name": "blogId", - "typeAsString": "System.Guid, System.Private.CoreLib", - "type": "System.Guid", - "typeSimple": "string", - "isOptional": false, - "defaultValue": null - }, - { - "name": "dto", - "typeAsString": "Volo.CmsKit.Admin.Blogs.BlogFeatureInputDto, Volo.CmsKit.Admin.Application.Contracts", - "type": "Volo.CmsKit.Admin.Blogs.BlogFeatureInputDto", - "typeSimple": "Volo.CmsKit.Admin.Blogs.BlogFeatureInputDto", - "isOptional": false, - "defaultValue": null - } - ], - "returnValue": { - "type": "System.Void", - "typeSimple": "System.Void" - } - }, - { - "name": "GetListAsync", - "parametersOnMethod": [ - { - "name": "blogId", - "typeAsString": "System.Guid, System.Private.CoreLib", - "type": "System.Guid", - "typeSimple": "string", - "isOptional": false, - "defaultValue": null - } - ], - "returnValue": { - "type": "System.Collections.Generic.List", - "typeSimple": "[Volo.CmsKit.Blogs.BlogFeatureDto]" - } - } - ] - } - ], - "actions": { - "GetListAsyncByBlogId": { - "uniqueName": "GetListAsyncByBlogId", - "name": "GetListAsync", - "httpMethod": "GET", - "url": "api/cms-kit-admin/blogs/{blogId}/features", - "supportedVersions": [], - "parametersOnMethod": [ - { - "name": "blogId", - "typeAsString": "System.Guid, System.Private.CoreLib", - "type": "System.Guid", - "typeSimple": "string", - "isOptional": false, - "defaultValue": null - } - ], - "parameters": [ - { - "nameOnMethod": "blogId", - "name": "blogId", - "jsonName": null, - "type": "System.Guid", - "typeSimple": "string", - "isOptional": false, - "defaultValue": null, - "constraintTypes": [], - "bindingSourceId": "Path", - "descriptorName": "" - } - ], - "returnValue": { - "type": "System.Collections.Generic.List", - "typeSimple": "[Volo.CmsKit.Blogs.BlogFeatureDto]" - }, - "allowAnonymous": false, - "implementFrom": "Volo.CmsKit.Admin.Blogs.IBlogFeatureAdminAppService" + "implementFrom": "Volo.Abp.Application.Services.IDeleteAppService" }, - "SetAsyncByBlogIdAndDto": { - "uniqueName": "SetAsyncByBlogIdAndDto", - "name": "SetAsync", + "SetAsHomePageAsyncById": { + "uniqueName": "SetAsHomePageAsyncById", + "name": "SetAsHomePageAsync", "httpMethod": "PUT", - "url": "api/cms-kit-admin/blogs/{blogId}/features", + "url": "api/cms-kit-admin/pages/setashomepage/{id}", "supportedVersions": [], "parametersOnMethod": [ { - "name": "blogId", + "name": "id", "typeAsString": "System.Guid, System.Private.CoreLib", "type": "System.Guid", "typeSimple": "string", "isOptional": false, "defaultValue": null - }, - { - "name": "dto", - "typeAsString": "Volo.CmsKit.Admin.Blogs.BlogFeatureInputDto, Volo.CmsKit.Admin.Application.Contracts", - "type": "Volo.CmsKit.Admin.Blogs.BlogFeatureInputDto", - "typeSimple": "Volo.CmsKit.Admin.Blogs.BlogFeatureInputDto", - "isOptional": false, - "defaultValue": null } ], "parameters": [ { - "nameOnMethod": "blogId", - "name": "blogId", + "nameOnMethod": "id", + "name": "id", "jsonName": null, "type": "System.Guid", "typeSimple": "string", @@ -2466,18 +2594,6 @@ "constraintTypes": [], "bindingSourceId": "Path", "descriptorName": "" - }, - { - "nameOnMethod": "dto", - "name": "dto", - "jsonName": null, - "type": "Volo.CmsKit.Admin.Blogs.BlogFeatureInputDto", - "typeSimple": "Volo.CmsKit.Admin.Blogs.BlogFeatureInputDto", - "isOptional": false, - "defaultValue": null, - "constraintTypes": null, - "bindingSourceId": "Body", - "descriptorName": "" } ], "returnValue": { @@ -2485,47 +2601,30 @@ "typeSimple": "System.Void" }, "allowAnonymous": false, - "implementFrom": "Volo.CmsKit.Admin.Blogs.IBlogFeatureAdminAppService" + "implementFrom": "Volo.CmsKit.Admin.Pages.IPageAdminAppService" } } }, - "Volo.CmsKit.Admin.Blogs.BlogPostAdminController": { - "controllerName": "BlogPostAdmin", - "controllerGroupName": "BlogPostAdmin", + "Volo.CmsKit.Admin.Tags.EntityTagAdminController": { + "controllerName": "EntityTagAdmin", + "controllerGroupName": "EntityTagAdmin", "isRemoteService": true, "isIntegrationService": false, "apiVersion": null, - "type": "Volo.CmsKit.Admin.Blogs.BlogPostAdminController", + "type": "Volo.CmsKit.Admin.Tags.EntityTagAdminController", "interfaces": [ { - "type": "Volo.CmsKit.Admin.Blogs.IBlogPostAdminAppService", - "name": "IBlogPostAdminAppService", + "type": "Volo.CmsKit.Admin.Tags.IEntityTagAdminAppService", + "name": "IEntityTagAdminAppService", "methods": [ { - "name": "PublishAsync", - "parametersOnMethod": [ - { - "name": "id", - "typeAsString": "System.Guid, System.Private.CoreLib", - "type": "System.Guid", - "typeSimple": "string", - "isOptional": false, - "defaultValue": null - } - ], - "returnValue": { - "type": "System.Void", - "typeSimple": "System.Void" - } - }, - { - "name": "DraftAsync", + "name": "AddTagToEntityAsync", "parametersOnMethod": [ { - "name": "id", - "typeAsString": "System.Guid, System.Private.CoreLib", - "type": "System.Guid", - "typeSimple": "string", + "name": "input", + "typeAsString": "Volo.CmsKit.Admin.Tags.EntityTagCreateDto, Volo.CmsKit.Admin.Application.Contracts", + "type": "Volo.CmsKit.Admin.Tags.EntityTagCreateDto", + "typeSimple": "Volo.CmsKit.Admin.Tags.EntityTagCreateDto", "isOptional": false, "defaultValue": null } @@ -2536,30 +2635,13 @@ } }, { - "name": "CreateAndPublishAsync", + "name": "RemoveTagFromEntityAsync", "parametersOnMethod": [ { "name": "input", - "typeAsString": "Volo.CmsKit.Admin.Blogs.CreateBlogPostDto, Volo.CmsKit.Admin.Application.Contracts", - "type": "Volo.CmsKit.Admin.Blogs.CreateBlogPostDto", - "typeSimple": "Volo.CmsKit.Admin.Blogs.CreateBlogPostDto", - "isOptional": false, - "defaultValue": null - } - ], - "returnValue": { - "type": "Volo.CmsKit.Admin.Blogs.BlogPostDto", - "typeSimple": "Volo.CmsKit.Admin.Blogs.BlogPostDto" - } - }, - { - "name": "SendToReviewAsync", - "parametersOnMethod": [ - { - "name": "id", - "typeAsString": "System.Guid, System.Private.CoreLib", - "type": "System.Guid", - "typeSimple": "string", + "typeAsString": "Volo.CmsKit.Admin.Tags.EntityTagRemoveDto, Volo.CmsKit.Admin.Application.Contracts", + "type": "Volo.CmsKit.Admin.Tags.EntityTagRemoveDto", + "typeSimple": "Volo.CmsKit.Admin.Tags.EntityTagRemoveDto", "isOptional": false, "defaultValue": null } @@ -2570,114 +2652,13 @@ } }, { - "name": "CreateAndSendToReviewAsync", - "parametersOnMethod": [ - { - "name": "input", - "typeAsString": "Volo.CmsKit.Admin.Blogs.CreateBlogPostDto, Volo.CmsKit.Admin.Application.Contracts", - "type": "Volo.CmsKit.Admin.Blogs.CreateBlogPostDto", - "typeSimple": "Volo.CmsKit.Admin.Blogs.CreateBlogPostDto", - "isOptional": false, - "defaultValue": null - } - ], - "returnValue": { - "type": "Volo.CmsKit.Admin.Blogs.BlogPostDto", - "typeSimple": "Volo.CmsKit.Admin.Blogs.BlogPostDto" - } - }, - { - "name": "HasBlogPostWaitingForReviewAsync", - "parametersOnMethod": [], - "returnValue": { - "type": "System.Boolean", - "typeSimple": "boolean" - } - }, - { - "name": "GetAsync", - "parametersOnMethod": [ - { - "name": "id", - "typeAsString": "System.Guid, System.Private.CoreLib", - "type": "System.Guid", - "typeSimple": "string", - "isOptional": false, - "defaultValue": null - } - ], - "returnValue": { - "type": "Volo.CmsKit.Admin.Blogs.BlogPostDto", - "typeSimple": "Volo.CmsKit.Admin.Blogs.BlogPostDto" - } - }, - { - "name": "GetListAsync", - "parametersOnMethod": [ - { - "name": "input", - "typeAsString": "Volo.CmsKit.Admin.Blogs.BlogPostGetListInput, Volo.CmsKit.Admin.Application.Contracts", - "type": "Volo.CmsKit.Admin.Blogs.BlogPostGetListInput", - "typeSimple": "Volo.CmsKit.Admin.Blogs.BlogPostGetListInput", - "isOptional": false, - "defaultValue": null - } - ], - "returnValue": { - "type": "Volo.Abp.Application.Dtos.PagedResultDto", - "typeSimple": "Volo.Abp.Application.Dtos.PagedResultDto" - } - }, - { - "name": "CreateAsync", - "parametersOnMethod": [ - { - "name": "input", - "typeAsString": "Volo.CmsKit.Admin.Blogs.CreateBlogPostDto, Volo.CmsKit.Admin.Application.Contracts", - "type": "Volo.CmsKit.Admin.Blogs.CreateBlogPostDto", - "typeSimple": "Volo.CmsKit.Admin.Blogs.CreateBlogPostDto", - "isOptional": false, - "defaultValue": null - } - ], - "returnValue": { - "type": "Volo.CmsKit.Admin.Blogs.BlogPostDto", - "typeSimple": "Volo.CmsKit.Admin.Blogs.BlogPostDto" - } - }, - { - "name": "UpdateAsync", + "name": "SetEntityTagsAsync", "parametersOnMethod": [ - { - "name": "id", - "typeAsString": "System.Guid, System.Private.CoreLib", - "type": "System.Guid", - "typeSimple": "string", - "isOptional": false, - "defaultValue": null - }, { "name": "input", - "typeAsString": "Volo.CmsKit.Admin.Blogs.UpdateBlogPostDto, Volo.CmsKit.Admin.Application.Contracts", - "type": "Volo.CmsKit.Admin.Blogs.UpdateBlogPostDto", - "typeSimple": "Volo.CmsKit.Admin.Blogs.UpdateBlogPostDto", - "isOptional": false, - "defaultValue": null - } - ], - "returnValue": { - "type": "Volo.CmsKit.Admin.Blogs.BlogPostDto", - "typeSimple": "Volo.CmsKit.Admin.Blogs.BlogPostDto" - } - }, - { - "name": "DeleteAsync", - "parametersOnMethod": [ - { - "name": "id", - "typeAsString": "System.Guid, System.Private.CoreLib", - "type": "System.Guid", - "typeSimple": "string", + "typeAsString": "Volo.CmsKit.Admin.Tags.EntityTagSetDto, Volo.CmsKit.Admin.Application.Contracts", + "type": "Volo.CmsKit.Admin.Tags.EntityTagSetDto", + "typeSimple": "Volo.CmsKit.Admin.Tags.EntityTagSetDto", "isOptional": false, "defaultValue": null } @@ -2691,70 +2672,33 @@ } ], "actions": { - "CreateAsyncByInput": { - "uniqueName": "CreateAsyncByInput", - "name": "CreateAsync", - "httpMethod": "POST", - "url": "api/cms-kit-admin/blogs/blog-posts", - "supportedVersions": [], - "parametersOnMethod": [ - { - "name": "input", - "typeAsString": "Volo.CmsKit.Admin.Blogs.CreateBlogPostDto, Volo.CmsKit.Admin.Application.Contracts", - "type": "Volo.CmsKit.Admin.Blogs.CreateBlogPostDto", - "typeSimple": "Volo.CmsKit.Admin.Blogs.CreateBlogPostDto", - "isOptional": false, - "defaultValue": null - } - ], - "parameters": [ - { - "nameOnMethod": "input", - "name": "input", - "jsonName": null, - "type": "Volo.CmsKit.Admin.Blogs.CreateBlogPostDto", - "typeSimple": "Volo.CmsKit.Admin.Blogs.CreateBlogPostDto", - "isOptional": false, - "defaultValue": null, - "constraintTypes": null, - "bindingSourceId": "Body", - "descriptorName": "" - } - ], - "returnValue": { - "type": "Volo.CmsKit.Admin.Blogs.BlogPostDto", - "typeSimple": "Volo.CmsKit.Admin.Blogs.BlogPostDto" - }, - "allowAnonymous": false, - "implementFrom": "Volo.Abp.Application.Services.ICreateAppService" - }, - "DeleteAsyncById": { - "uniqueName": "DeleteAsyncById", - "name": "DeleteAsync", - "httpMethod": "DELETE", - "url": "api/cms-kit-admin/blogs/blog-posts/{id}", + "AddTagToEntityAsyncByInput": { + "uniqueName": "AddTagToEntityAsyncByInput", + "name": "AddTagToEntityAsync", + "httpMethod": "POST", + "url": "api/cms-kit-admin/entity-tags", "supportedVersions": [], "parametersOnMethod": [ { - "name": "id", - "typeAsString": "System.Guid, System.Private.CoreLib", - "type": "System.Guid", - "typeSimple": "string", + "name": "input", + "typeAsString": "Volo.CmsKit.Admin.Tags.EntityTagCreateDto, Volo.CmsKit.Admin.Application.Contracts", + "type": "Volo.CmsKit.Admin.Tags.EntityTagCreateDto", + "typeSimple": "Volo.CmsKit.Admin.Tags.EntityTagCreateDto", "isOptional": false, "defaultValue": null } ], "parameters": [ { - "nameOnMethod": "id", - "name": "id", + "nameOnMethod": "input", + "name": "input", "jsonName": null, - "type": "System.Guid", - "typeSimple": "string", + "type": "Volo.CmsKit.Admin.Tags.EntityTagCreateDto", + "typeSimple": "Volo.CmsKit.Admin.Tags.EntityTagCreateDto", "isOptional": false, "defaultValue": null, - "constraintTypes": [], - "bindingSourceId": "Path", + "constraintTypes": null, + "bindingSourceId": "Body", "descriptorName": "" } ], @@ -2762,60 +2706,21 @@ "type": "System.Void", "typeSimple": "System.Void" }, - "allowAnonymous": false, - "implementFrom": "Volo.Abp.Application.Services.IDeleteAppService" - }, - "GetAsyncById": { - "uniqueName": "GetAsyncById", - "name": "GetAsync", - "httpMethod": "GET", - "url": "api/cms-kit-admin/blogs/blog-posts/{id}", - "supportedVersions": [], - "parametersOnMethod": [ - { - "name": "id", - "typeAsString": "System.Guid, System.Private.CoreLib", - "type": "System.Guid", - "typeSimple": "string", - "isOptional": false, - "defaultValue": null - } - ], - "parameters": [ - { - "nameOnMethod": "id", - "name": "id", - "jsonName": null, - "type": "System.Guid", - "typeSimple": "string", - "isOptional": false, - "defaultValue": null, - "constraintTypes": [ - "GuidRouteConstraint" - ], - "bindingSourceId": "Path", - "descriptorName": "" - } - ], - "returnValue": { - "type": "Volo.CmsKit.Admin.Blogs.BlogPostDto", - "typeSimple": "Volo.CmsKit.Admin.Blogs.BlogPostDto" - }, - "allowAnonymous": false, - "implementFrom": "Volo.Abp.Application.Services.IReadOnlyAppService" + "allowAnonymous": null, + "implementFrom": "Volo.CmsKit.Admin.Tags.IEntityTagAdminAppService" }, - "GetListAsyncByInput": { - "uniqueName": "GetListAsyncByInput", - "name": "GetListAsync", - "httpMethod": "GET", - "url": "api/cms-kit-admin/blogs/blog-posts", + "RemoveTagFromEntityAsyncByInput": { + "uniqueName": "RemoveTagFromEntityAsyncByInput", + "name": "RemoveTagFromEntityAsync", + "httpMethod": "DELETE", + "url": "api/cms-kit-admin/entity-tags", "supportedVersions": [], "parametersOnMethod": [ { "name": "input", - "typeAsString": "Volo.CmsKit.Admin.Blogs.BlogPostGetListInput, Volo.CmsKit.Admin.Application.Contracts", - "type": "Volo.CmsKit.Admin.Blogs.BlogPostGetListInput", - "typeSimple": "Volo.CmsKit.Admin.Blogs.BlogPostGetListInput", + "typeAsString": "Volo.CmsKit.Admin.Tags.EntityTagRemoveDto, Volo.CmsKit.Admin.Application.Contracts", + "type": "Volo.CmsKit.Admin.Tags.EntityTagRemoveDto", + "typeSimple": "Volo.CmsKit.Admin.Tags.EntityTagRemoveDto", "isOptional": false, "defaultValue": null } @@ -2823,9 +2728,9 @@ "parameters": [ { "nameOnMethod": "input", - "name": "Filter", + "name": "TagId", "jsonName": null, - "type": "System.String", + "type": "System.Guid", "typeSimple": "string", "isOptional": false, "defaultValue": null, @@ -2835,10 +2740,10 @@ }, { "nameOnMethod": "input", - "name": "BlogId", + "name": "EntityType", "jsonName": null, - "type": "System.Guid?", - "typeSimple": "string?", + "type": "System.String", + "typeSimple": "string", "isOptional": false, "defaultValue": null, "constraintTypes": null, @@ -2847,127 +2752,203 @@ }, { "nameOnMethod": "input", - "name": "AuthorId", + "name": "EntityId", "jsonName": null, - "type": "System.Guid?", - "typeSimple": "string?", + "type": "System.String", + "typeSimple": "string", "isOptional": false, "defaultValue": null, "constraintTypes": null, "bindingSourceId": "ModelBinding", "descriptorName": "input" - }, + } + ], + "returnValue": { + "type": "System.Void", + "typeSimple": "System.Void" + }, + "allowAnonymous": null, + "implementFrom": "Volo.CmsKit.Admin.Tags.IEntityTagAdminAppService" + }, + "SetEntityTagsAsyncByInput": { + "uniqueName": "SetEntityTagsAsyncByInput", + "name": "SetEntityTagsAsync", + "httpMethod": "PUT", + "url": "api/cms-kit-admin/entity-tags", + "supportedVersions": [], + "parametersOnMethod": [ { - "nameOnMethod": "input", - "name": "TagId", - "jsonName": null, - "type": "System.Guid?", - "typeSimple": "string?", + "name": "input", + "typeAsString": "Volo.CmsKit.Admin.Tags.EntityTagSetDto, Volo.CmsKit.Admin.Application.Contracts", + "type": "Volo.CmsKit.Admin.Tags.EntityTagSetDto", + "typeSimple": "Volo.CmsKit.Admin.Tags.EntityTagSetDto", "isOptional": false, - "defaultValue": null, - "constraintTypes": null, - "bindingSourceId": "ModelBinding", - "descriptorName": "input" - }, + "defaultValue": null + } + ], + "parameters": [ { "nameOnMethod": "input", - "name": "Status", + "name": "input", "jsonName": null, - "type": "System.String", - "typeSimple": "string", + "type": "Volo.CmsKit.Admin.Tags.EntityTagSetDto", + "typeSimple": "Volo.CmsKit.Admin.Tags.EntityTagSetDto", "isOptional": false, "defaultValue": null, "constraintTypes": null, - "bindingSourceId": "ModelBinding", - "descriptorName": "input" + "bindingSourceId": "Body", + "descriptorName": "" + } + ], + "returnValue": { + "type": "System.Void", + "typeSimple": "System.Void" + }, + "allowAnonymous": null, + "implementFrom": "Volo.CmsKit.Admin.Tags.IEntityTagAdminAppService" + } + } + }, + "Volo.CmsKit.Admin.Tags.TagAdminController": { + "controllerName": "TagAdmin", + "controllerGroupName": "TagAdmin", + "isRemoteService": true, + "isIntegrationService": false, + "apiVersion": null, + "type": "Volo.CmsKit.Admin.Tags.TagAdminController", + "interfaces": [ + { + "type": "Volo.CmsKit.Admin.Tags.ITagAdminAppService", + "name": "ITagAdminAppService", + "methods": [ + { + "name": "GetTagDefinitionsAsync", + "parametersOnMethod": [], + "returnValue": { + "type": "System.Collections.Generic.List", + "typeSimple": "[Volo.CmsKit.Admin.Tags.TagDefinitionDto]" + } }, { - "nameOnMethod": "input", - "name": "Sorting", - "jsonName": null, - "type": "System.String", - "typeSimple": "string", - "isOptional": false, - "defaultValue": null, - "constraintTypes": null, - "bindingSourceId": "ModelBinding", - "descriptorName": "input" + "name": "GetAsync", + "parametersOnMethod": [ + { + "name": "id", + "typeAsString": "System.Guid, System.Private.CoreLib", + "type": "System.Guid", + "typeSimple": "string", + "isOptional": false, + "defaultValue": null + } + ], + "returnValue": { + "type": "Volo.CmsKit.Tags.TagDto", + "typeSimple": "Volo.CmsKit.Tags.TagDto" + } }, { - "nameOnMethod": "input", - "name": "SkipCount", - "jsonName": null, - "type": "System.Int32", - "typeSimple": "number", - "isOptional": false, - "defaultValue": null, - "constraintTypes": null, - "bindingSourceId": "ModelBinding", - "descriptorName": "input" + "name": "GetListAsync", + "parametersOnMethod": [ + { + "name": "input", + "typeAsString": "Volo.CmsKit.Admin.Tags.TagGetListInput, Volo.CmsKit.Admin.Application.Contracts", + "type": "Volo.CmsKit.Admin.Tags.TagGetListInput", + "typeSimple": "Volo.CmsKit.Admin.Tags.TagGetListInput", + "isOptional": false, + "defaultValue": null + } + ], + "returnValue": { + "type": "Volo.Abp.Application.Dtos.PagedResultDto", + "typeSimple": "Volo.Abp.Application.Dtos.PagedResultDto" + } + }, + { + "name": "CreateAsync", + "parametersOnMethod": [ + { + "name": "input", + "typeAsString": "Volo.CmsKit.Admin.Tags.TagCreateDto, Volo.CmsKit.Admin.Application.Contracts", + "type": "Volo.CmsKit.Admin.Tags.TagCreateDto", + "typeSimple": "Volo.CmsKit.Admin.Tags.TagCreateDto", + "isOptional": false, + "defaultValue": null + } + ], + "returnValue": { + "type": "Volo.CmsKit.Tags.TagDto", + "typeSimple": "Volo.CmsKit.Tags.TagDto" + } + }, + { + "name": "UpdateAsync", + "parametersOnMethod": [ + { + "name": "id", + "typeAsString": "System.Guid, System.Private.CoreLib", + "type": "System.Guid", + "typeSimple": "string", + "isOptional": false, + "defaultValue": null + }, + { + "name": "input", + "typeAsString": "Volo.CmsKit.Admin.Tags.TagUpdateDto, Volo.CmsKit.Admin.Application.Contracts", + "type": "Volo.CmsKit.Admin.Tags.TagUpdateDto", + "typeSimple": "Volo.CmsKit.Admin.Tags.TagUpdateDto", + "isOptional": false, + "defaultValue": null + } + ], + "returnValue": { + "type": "Volo.CmsKit.Tags.TagDto", + "typeSimple": "Volo.CmsKit.Tags.TagDto" + } }, { - "nameOnMethod": "input", - "name": "MaxResultCount", - "jsonName": null, - "type": "System.Int32", - "typeSimple": "number", - "isOptional": false, - "defaultValue": null, - "constraintTypes": null, - "bindingSourceId": "ModelBinding", - "descriptorName": "input" + "name": "DeleteAsync", + "parametersOnMethod": [ + { + "name": "id", + "typeAsString": "System.Guid, System.Private.CoreLib", + "type": "System.Guid", + "typeSimple": "string", + "isOptional": false, + "defaultValue": null + } + ], + "returnValue": { + "type": "System.Void", + "typeSimple": "System.Void" + } } - ], - "returnValue": { - "type": "Volo.Abp.Application.Dtos.PagedResultDto", - "typeSimple": "Volo.Abp.Application.Dtos.PagedResultDto" - }, - "allowAnonymous": false, - "implementFrom": "Volo.Abp.Application.Services.IReadOnlyAppService" - }, - "UpdateAsyncByIdAndInput": { - "uniqueName": "UpdateAsyncByIdAndInput", - "name": "UpdateAsync", - "httpMethod": "PUT", - "url": "api/cms-kit-admin/blogs/blog-posts/{id}", + ] + } + ], + "actions": { + "CreateAsyncByInput": { + "uniqueName": "CreateAsyncByInput", + "name": "CreateAsync", + "httpMethod": "POST", + "url": "api/cms-kit-admin/tags", "supportedVersions": [], "parametersOnMethod": [ - { - "name": "id", - "typeAsString": "System.Guid, System.Private.CoreLib", - "type": "System.Guid", - "typeSimple": "string", - "isOptional": false, - "defaultValue": null - }, { "name": "input", - "typeAsString": "Volo.CmsKit.Admin.Blogs.UpdateBlogPostDto, Volo.CmsKit.Admin.Application.Contracts", - "type": "Volo.CmsKit.Admin.Blogs.UpdateBlogPostDto", - "typeSimple": "Volo.CmsKit.Admin.Blogs.UpdateBlogPostDto", + "typeAsString": "Volo.CmsKit.Admin.Tags.TagCreateDto, Volo.CmsKit.Admin.Application.Contracts", + "type": "Volo.CmsKit.Admin.Tags.TagCreateDto", + "typeSimple": "Volo.CmsKit.Admin.Tags.TagCreateDto", "isOptional": false, "defaultValue": null } ], "parameters": [ - { - "nameOnMethod": "id", - "name": "id", - "jsonName": null, - "type": "System.Guid", - "typeSimple": "string", - "isOptional": false, - "defaultValue": null, - "constraintTypes": [], - "bindingSourceId": "Path", - "descriptorName": "" - }, { "nameOnMethod": "input", "name": "input", "jsonName": null, - "type": "Volo.CmsKit.Admin.Blogs.UpdateBlogPostDto", - "typeSimple": "Volo.CmsKit.Admin.Blogs.UpdateBlogPostDto", + "type": "Volo.CmsKit.Admin.Tags.TagCreateDto", + "typeSimple": "Volo.CmsKit.Admin.Tags.TagCreateDto", "isOptional": false, "defaultValue": null, "constraintTypes": null, @@ -2976,17 +2957,17 @@ } ], "returnValue": { - "type": "Volo.CmsKit.Admin.Blogs.BlogPostDto", - "typeSimple": "Volo.CmsKit.Admin.Blogs.BlogPostDto" + "type": "Volo.CmsKit.Tags.TagDto", + "typeSimple": "Volo.CmsKit.Tags.TagDto" }, "allowAnonymous": false, - "implementFrom": "Volo.Abp.Application.Services.IUpdateAppService" + "implementFrom": "Volo.Abp.Application.Services.ICreateAppService" }, - "PublishAsyncById": { - "uniqueName": "PublishAsyncById", - "name": "PublishAsync", - "httpMethod": "POST", - "url": "api/cms-kit-admin/blogs/blog-posts/{id}/publish", + "DeleteAsyncById": { + "uniqueName": "DeleteAsyncById", + "name": "DeleteAsync", + "httpMethod": "DELETE", + "url": "api/cms-kit-admin/tags/{id}", "supportedVersions": [], "parametersOnMethod": [ { @@ -3017,13 +2998,13 @@ "typeSimple": "System.Void" }, "allowAnonymous": false, - "implementFrom": "Volo.CmsKit.Admin.Blogs.IBlogPostAdminAppService" + "implementFrom": "Volo.Abp.Application.Services.IDeleteAppService" }, - "DraftAsyncById": { - "uniqueName": "DraftAsyncById", - "name": "DraftAsync", - "httpMethod": "POST", - "url": "api/cms-kit-admin/blogs/blog-posts/{id}/draft", + "GetAsyncById": { + "uniqueName": "GetAsyncById", + "name": "GetAsync", + "httpMethod": "GET", + "url": "api/cms-kit-admin/tags/{id}", "supportedVersions": [], "parametersOnMethod": [ { @@ -3050,24 +3031,24 @@ } ], "returnValue": { - "type": "System.Void", - "typeSimple": "System.Void" + "type": "Volo.CmsKit.Tags.TagDto", + "typeSimple": "Volo.CmsKit.Tags.TagDto" }, "allowAnonymous": false, - "implementFrom": "Volo.CmsKit.Admin.Blogs.IBlogPostAdminAppService" + "implementFrom": "Volo.Abp.Application.Services.IReadOnlyAppService" }, - "CreateAndPublishAsyncByInput": { - "uniqueName": "CreateAndPublishAsyncByInput", - "name": "CreateAndPublishAsync", - "httpMethod": "POST", - "url": "api/cms-kit-admin/blogs/blog-posts/create-and-publish", + "GetListAsyncByInput": { + "uniqueName": "GetListAsyncByInput", + "name": "GetListAsync", + "httpMethod": "GET", + "url": "api/cms-kit-admin/tags", "supportedVersions": [], "parametersOnMethod": [ { "name": "input", - "typeAsString": "Volo.CmsKit.Admin.Blogs.CreateBlogPostDto, Volo.CmsKit.Admin.Application.Contracts", - "type": "Volo.CmsKit.Admin.Blogs.CreateBlogPostDto", - "typeSimple": "Volo.CmsKit.Admin.Blogs.CreateBlogPostDto", + "typeAsString": "Volo.CmsKit.Admin.Tags.TagGetListInput, Volo.CmsKit.Admin.Application.Contracts", + "type": "Volo.CmsKit.Admin.Tags.TagGetListInput", + "typeSimple": "Volo.CmsKit.Admin.Tags.TagGetListInput", "isOptional": false, "defaultValue": null } @@ -3075,29 +3056,65 @@ "parameters": [ { "nameOnMethod": "input", - "name": "input", + "name": "Filter", "jsonName": null, - "type": "Volo.CmsKit.Admin.Blogs.CreateBlogPostDto", - "typeSimple": "Volo.CmsKit.Admin.Blogs.CreateBlogPostDto", + "type": "System.String", + "typeSimple": "string", "isOptional": false, "defaultValue": null, "constraintTypes": null, - "bindingSourceId": "Body", - "descriptorName": "" + "bindingSourceId": "ModelBinding", + "descriptorName": "input" + }, + { + "nameOnMethod": "input", + "name": "Sorting", + "jsonName": null, + "type": "System.String", + "typeSimple": "string", + "isOptional": false, + "defaultValue": null, + "constraintTypes": null, + "bindingSourceId": "ModelBinding", + "descriptorName": "input" + }, + { + "nameOnMethod": "input", + "name": "SkipCount", + "jsonName": null, + "type": "System.Int32", + "typeSimple": "number", + "isOptional": false, + "defaultValue": null, + "constraintTypes": null, + "bindingSourceId": "ModelBinding", + "descriptorName": "input" + }, + { + "nameOnMethod": "input", + "name": "MaxResultCount", + "jsonName": null, + "type": "System.Int32", + "typeSimple": "number", + "isOptional": false, + "defaultValue": null, + "constraintTypes": null, + "bindingSourceId": "ModelBinding", + "descriptorName": "input" } ], "returnValue": { - "type": "Volo.CmsKit.Admin.Blogs.BlogPostDto", - "typeSimple": "Volo.CmsKit.Admin.Blogs.BlogPostDto" + "type": "Volo.Abp.Application.Dtos.PagedResultDto", + "typeSimple": "Volo.Abp.Application.Dtos.PagedResultDto" }, "allowAnonymous": false, - "implementFrom": "Volo.CmsKit.Admin.Blogs.IBlogPostAdminAppService" + "implementFrom": "Volo.Abp.Application.Services.IReadOnlyAppService" }, - "SendToReviewAsyncById": { - "uniqueName": "SendToReviewAsyncById", - "name": "SendToReviewAsync", - "httpMethod": "POST", - "url": "api/cms-kit-admin/blogs/blog-posts/{id}/send-to-review", + "UpdateAsyncByIdAndInput": { + "uniqueName": "UpdateAsyncByIdAndInput", + "name": "UpdateAsync", + "httpMethod": "PUT", + "url": "api/cms-kit-admin/tags/{id}", "supportedVersions": [], "parametersOnMethod": [ { @@ -3107,6 +3124,14 @@ "typeSimple": "string", "isOptional": false, "defaultValue": null + }, + { + "name": "input", + "typeAsString": "Volo.CmsKit.Admin.Tags.TagUpdateDto, Volo.CmsKit.Admin.Application.Contracts", + "type": "Volo.CmsKit.Admin.Tags.TagUpdateDto", + "typeSimple": "Volo.CmsKit.Admin.Tags.TagUpdateDto", + "isOptional": false, + "defaultValue": null } ], "parameters": [ @@ -3121,38 +3146,13 @@ "constraintTypes": [], "bindingSourceId": "Path", "descriptorName": "" - } - ], - "returnValue": { - "type": "System.Void", - "typeSimple": "System.Void" - }, - "allowAnonymous": false, - "implementFrom": "Volo.CmsKit.Admin.Blogs.IBlogPostAdminAppService" - }, - "CreateAndSendToReviewAsyncByInput": { - "uniqueName": "CreateAndSendToReviewAsyncByInput", - "name": "CreateAndSendToReviewAsync", - "httpMethod": "POST", - "url": "api/cms-kit-admin/blogs/blog-posts/create-and-send-to-review", - "supportedVersions": [], - "parametersOnMethod": [ - { - "name": "input", - "typeAsString": "Volo.CmsKit.Admin.Blogs.CreateBlogPostDto, Volo.CmsKit.Admin.Application.Contracts", - "type": "Volo.CmsKit.Admin.Blogs.CreateBlogPostDto", - "typeSimple": "Volo.CmsKit.Admin.Blogs.CreateBlogPostDto", - "isOptional": false, - "defaultValue": null - } - ], - "parameters": [ + }, { "nameOnMethod": "input", "name": "input", "jsonName": null, - "type": "Volo.CmsKit.Admin.Blogs.CreateBlogPostDto", - "typeSimple": "Volo.CmsKit.Admin.Blogs.CreateBlogPostDto", + "type": "Volo.CmsKit.Admin.Tags.TagUpdateDto", + "typeSimple": "Volo.CmsKit.Admin.Tags.TagUpdateDto", "isOptional": false, "defaultValue": null, "constraintTypes": null, @@ -3161,26 +3161,26 @@ } ], "returnValue": { - "type": "Volo.CmsKit.Admin.Blogs.BlogPostDto", - "typeSimple": "Volo.CmsKit.Admin.Blogs.BlogPostDto" + "type": "Volo.CmsKit.Tags.TagDto", + "typeSimple": "Volo.CmsKit.Tags.TagDto" }, "allowAnonymous": false, - "implementFrom": "Volo.CmsKit.Admin.Blogs.IBlogPostAdminAppService" + "implementFrom": "Volo.Abp.Application.Services.IUpdateAppService" }, - "HasBlogPostWaitingForReviewAsync": { - "uniqueName": "HasBlogPostWaitingForReviewAsync", - "name": "HasBlogPostWaitingForReviewAsync", + "GetTagDefinitionsAsync": { + "uniqueName": "GetTagDefinitionsAsync", + "name": "GetTagDefinitionsAsync", "httpMethod": "GET", - "url": "api/cms-kit-admin/blogs/blog-posts/has-blogpost-waiting-for-review", + "url": "api/cms-kit-admin/tags/tag-definitions", "supportedVersions": [], "parametersOnMethod": [], "parameters": [], "returnValue": { - "type": "System.Boolean", - "typeSimple": "boolean" + "type": "System.Collections.Generic.List", + "typeSimple": "[Volo.CmsKit.Admin.Tags.TagDefinitionDto]" }, "allowAnonymous": false, - "implementFrom": "Volo.CmsKit.Admin.Blogs.IBlogPostAdminAppService" + "implementFrom": "Volo.CmsKit.Admin.Tags.ITagAdminAppService" } } } From 1e9d537f13d4be66afd4f4cdad751ae40bcada85 Mon Sep 17 00:00:00 2001 From: Enis Necipoglu Date: Wed, 17 Jan 2024 11:26:02 +0300 Subject: [PATCH 27/98] Update CreateModal for MenuItem --- .../Pages/CmsKit/Menus/MenuItems/CreateModal.cshtml | 10 +++++++++- .../Pages/CmsKit/Menus/MenuItems/createModal.js | 2 +- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Menus/MenuItems/CreateModal.cshtml b/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Menus/MenuItems/CreateModal.cshtml index 52f9392d3d..594565539c 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Menus/MenuItems/CreateModal.cshtml +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Menus/MenuItems/CreateModal.cshtml @@ -34,7 +34,15 @@ - + diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Menus/MenuItems/createModal.js b/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Menus/MenuItems/createModal.js index 2818f48523..cbba0ea235 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Menus/MenuItems/createModal.js +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Menus/MenuItems/createModal.js @@ -9,7 +9,7 @@ $(function () { var $displayName = $('#ViewModel_DisplayName'); var $pageIdClearButton = $('#url-tab'); - initSelectPageId(); + //initSelectPageId(); $pageId.on('change', function (params) { $url.prop('disabled', $pageId.val()); From 425333c308fd641b96e791a15f77e0a5bf85d8c1 Mon Sep 17 00:00:00 2001 From: Enis Necipoglu Date: Wed, 17 Jan 2024 11:42:53 +0300 Subject: [PATCH 28/98] Update mappings for MenuItem UpdateModal --- .../CmsKitAdminWebAutoMapperProfile.cs | 3 ++- .../Pages/CmsKit/Menus/MenuItems/UpdateModal.cshtml.cs | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.Web/CmsKitAdminWebAutoMapperProfile.cs b/modules/cms-kit/src/Volo.CmsKit.Admin.Web/CmsKitAdminWebAutoMapperProfile.cs index b61b1842b5..655399109d 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.Web/CmsKitAdminWebAutoMapperProfile.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.Web/CmsKitAdminWebAutoMapperProfile.cs @@ -1,4 +1,5 @@ using AutoMapper; +using Volo.Abp.AutoMapper; using Volo.CmsKit.Admin.Blogs; using Volo.CmsKit.Admin.Menus; using Volo.CmsKit.Admin.Pages; @@ -37,7 +38,7 @@ public class CmsKitAdminWebAutoMapperProfile : Profile { CreateMap().MapExtraProperties(); CreateMap().MapExtraProperties(); - CreateMap().MapExtraProperties(); + CreateMap().MapExtraProperties(); } protected virtual void CreatePageMappings() diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Menus/MenuItems/UpdateModal.cshtml.cs b/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Menus/MenuItems/UpdateModal.cshtml.cs index 9da2e135d9..aa52134a97 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Menus/MenuItems/UpdateModal.cshtml.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Menus/MenuItems/UpdateModal.cshtml.cs @@ -31,7 +31,7 @@ public class UpdateModalModel : CmsKitAdminPageModel { var menuItemDto = await MenuAdminAppService.GetAsync(Id); - ViewModel = ObjectMapper.Map(menuItemDto); + ViewModel = ObjectMapper.Map(menuItemDto); } public async Task OnPostAsync() @@ -43,8 +43,6 @@ public class UpdateModalModel : CmsKitAdminPageModel return new OkObjectResult(result); } - [AutoMap(typeof(MenuItemDto))] - [AutoMap(typeof(MenuItemUpdateInput), ReverseMap = true)] public class MenuItemUpdateViewModel : ExtensibleObject, IHasConcurrencyStamp { [Required] @@ -64,6 +62,8 @@ public class UpdateModalModel : CmsKitAdminPageModel public Guid? PageId { get; set; } + public string? PageTitle { get; set; } + [HiddenInput] public string ConcurrencyStamp { get; set; } } From f268bbf424904f256244d5d2d58c8ea0ca0379c2 Mon Sep 17 00:00:00 2001 From: Enis Necipoglu Date: Wed, 17 Jan 2024 11:43:08 +0300 Subject: [PATCH 29/98] Fix bug for unrelating menuitem with a page --- .../Volo/CmsKit/Admin/Menus/MenuItemAdminAppService.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/Menus/MenuItemAdminAppService.cs b/modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/Menus/MenuItemAdminAppService.cs index 3a323efb13..2436f92d95 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/Menus/MenuItemAdminAppService.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/Menus/MenuItemAdminAppService.cs @@ -94,6 +94,7 @@ public class MenuItemAdminAppService : CmsKitAdminAppServiceBase, IMenuItemAdmin } else { + input.PageId = null; menuItem.SetUrl(input.Url); } From 3a7998f2bd231f6f11b61ae5e07c8f77543d43e7 Mon Sep 17 00:00:00 2001 From: Enis Necipoglu Date: Wed, 17 Jan 2024 11:43:28 +0300 Subject: [PATCH 30/98] Update logic in MenuItem UpdateModal --- .../CmsKit/Menus/MenuItems/UpdateModal.cshtml | 16 +++++++++++++++- .../CmsKit/Menus/MenuItems/updateModal.js | 19 ------------------- 2 files changed, 15 insertions(+), 20 deletions(-) diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Menus/MenuItems/UpdateModal.cshtml b/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Menus/MenuItems/UpdateModal.cshtml index 72780b33d8..47278209f1 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Menus/MenuItems/UpdateModal.cshtml +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Menus/MenuItems/UpdateModal.cshtml @@ -35,7 +35,21 @@ - + diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Menus/MenuItems/updateModal.js b/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Menus/MenuItems/updateModal.js index d8ded357bb..6ece96b41a 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Menus/MenuItems/updateModal.js +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Menus/MenuItems/updateModal.js @@ -7,9 +7,6 @@ $(function () { var $pageId = $('#ViewModel_PageId'); var $url = $('#ViewModel_Url'); var $displayName = $('#ViewModel_DisplayName'); - var $pageIdClearButton = $('#url-tab'); - - initSelectPageId(); $pageId.on('change', function (params) { $url.prop('disabled', $pageId.val()); @@ -22,22 +19,6 @@ $(function () { }) $pageId.trigger('change'); - - $pageIdClearButton.click(function () { - $pageId.val(''); - $pageId.trigger('change'); - }); - - function initSelectPageId() { - $pageId.data('autocompleteApiUrl', '/api/cms-kit-admin/menu-items/lookup/pages'); - $pageId.data('autocompleteDisplayProperty', 'title'); - $pageId.data('autocompleteValueProperty', 'id'); - $pageId.data('autocompleteItemsProperty', 'items'); - $pageId.data('autocompleteFilterParamName', 'filter'); - $pageId.data('autocompleteParentSelector', '#menu-update-modal'); - - abp.dom.initializers.initializeAutocompleteSelects($pageId); - } }; return { From 6c54e01267e12335aaaa9431aa83bd79f901041e Mon Sep 17 00:00:00 2001 From: Enis Necipoglu Date: Wed, 17 Jan 2024 11:59:03 +0300 Subject: [PATCH 31/98] Add validation for MenuItem URL --- .../CmsKit/Menus/MenuItems/CreateModal.cshtml | 4 +-- .../Menus/MenuItems/CreateModal.cshtml.cs | 1 + .../CmsKit/Menus/MenuItems/UpdateModal.cshtml | 2 +- .../Menus/MenuItems/UpdateModal.cshtml.cs | 1 + .../CmsKit/Menus/MenuItems/createModal.js | 26 +++++-------------- .../CmsKit/Menus/MenuItems/updateModal.js | 5 ++++ 6 files changed, 16 insertions(+), 23 deletions(-) diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Menus/MenuItems/CreateModal.cshtml b/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Menus/MenuItems/CreateModal.cshtml index 594565539c..b73ac8b2d5 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Menus/MenuItems/CreateModal.cshtml +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Menus/MenuItems/CreateModal.cshtml @@ -19,7 +19,7 @@ Layout = null; } -
+ @@ -27,7 +27,7 @@ - + diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Menus/MenuItems/CreateModal.cshtml.cs b/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Menus/MenuItems/CreateModal.cshtml.cs index 21d4390bfc..03ca715d2a 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Menus/MenuItems/CreateModal.cshtml.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Menus/MenuItems/CreateModal.cshtml.cs @@ -52,6 +52,7 @@ public class CreateModalModel : CmsKitAdminPageModel public bool IsActive { get; set; } = true; + [Required] public string Url { get; set; } public Guid? PageId { get; set; } diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Menus/MenuItems/UpdateModal.cshtml b/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Menus/MenuItems/UpdateModal.cshtml index 47278209f1..e440b3176a 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Menus/MenuItems/UpdateModal.cshtml +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Menus/MenuItems/UpdateModal.cshtml @@ -19,7 +19,7 @@ Layout = null; } - + diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Menus/MenuItems/UpdateModal.cshtml.cs b/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Menus/MenuItems/UpdateModal.cshtml.cs index aa52134a97..e071dc0230 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Menus/MenuItems/UpdateModal.cshtml.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Menus/MenuItems/UpdateModal.cshtml.cs @@ -50,6 +50,7 @@ public class UpdateModalModel : CmsKitAdminPageModel public bool IsActive { get; set; } + [Required] public string Url { get; set; } public string Icon { get; set; } diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Menus/MenuItems/createModal.js b/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Menus/MenuItems/createModal.js index cbba0ea235..0c4103c6f8 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Menus/MenuItems/createModal.js +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Menus/MenuItems/createModal.js @@ -7,36 +7,22 @@ $(function () { var $pageId = $('#ViewModel_PageId'); var $url = $('#ViewModel_Url'); var $displayName = $('#ViewModel_DisplayName'); - var $pageIdClearButton = $('#url-tab'); - - //initSelectPageId(); - + var $menuItemForm = $('#menu-item-form'); + $pageId.on('change', function (params) { $url.prop('disabled', $pageId.val()); if ($pageId.val()) { if (!$displayName.val()){ - $displayName.val($pageId.text()); + $displayName.val($pageId.text().trim()); } } }) - - $pageIdClearButton.click(function (){ - $pageId.val(''); - $pageId.trigger('change'); - }) - - function initSelectPageId() { - $pageId.data('autocompleteApiUrl', '/api/cms-kit-admin/menu-items/lookup/pages'); - $pageId.data('autocompleteDisplayProperty', 'title'); - $pageId.data('autocompleteValueProperty', 'id'); - $pageId.data('autocompleteItemsProperty', 'items'); - $pageId.data('autocompleteFilterParamName', 'filter'); - $pageId.data('autocompleteParentSelector', '#menu-create-modal'); - abp.dom.initializers.initializeAutocompleteSelects($pageId); - } + $menuItemForm.on('submit', function (e) { + $('[href="#url"]').tab('show'); + }); }; return { diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Menus/MenuItems/updateModal.js b/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Menus/MenuItems/updateModal.js index 6ece96b41a..173c6459e5 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Menus/MenuItems/updateModal.js +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Menus/MenuItems/updateModal.js @@ -7,6 +7,7 @@ $(function () { var $pageId = $('#ViewModel_PageId'); var $url = $('#ViewModel_Url'); var $displayName = $('#ViewModel_DisplayName'); + var $menuItemForm = $('#menu-item-form'); $pageId.on('change', function (params) { $url.prop('disabled', $pageId.val()); @@ -19,6 +20,10 @@ $(function () { }) $pageId.trigger('change'); + + $menuItemForm.on('submit', function (e) { + $('[href="#url"]').tab('show'); + }); }; return { From 9115fb1e1d2a1586301d2cac39fd515e0a72120c Mon Sep 17 00:00:00 2001 From: Enis Necipoglu Date: Wed, 17 Jan 2024 12:06:57 +0300 Subject: [PATCH 32/98] Handle CmsKit Page feature in Menu Items --- .../CmsKit/Menus/MenuItems/CreateModal.cshtml | 50 +++++++++-------- .../Menus/MenuItems/CreateModal.cshtml.cs | 25 +++++---- .../CmsKit/Menus/MenuItems/UpdateModal.cshtml | 54 ++++++++++--------- .../Menus/MenuItems/UpdateModal.cshtml.cs | 14 ++++- 4 files changed, 87 insertions(+), 56 deletions(-) diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Menus/MenuItems/CreateModal.cshtml b/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Menus/MenuItems/CreateModal.cshtml index b73ac8b2d5..c4c2a1476a 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Menus/MenuItems/CreateModal.cshtml +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Menus/MenuItems/CreateModal.cshtml @@ -24,31 +24,39 @@ - - - - + @if (Model.IsPageFeatureEnabled) + { + + + + + + + + + - - + - + + - - - - + +
+ } + else + { + + } -
-
diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Menus/MenuItems/CreateModal.cshtml.cs b/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Menus/MenuItems/CreateModal.cshtml.cs index 03ca715d2a..eaab7e8903 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Menus/MenuItems/CreateModal.cshtml.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Menus/MenuItems/CreateModal.cshtml.cs @@ -1,35 +1,40 @@ -using AutoMapper; -using Microsoft.AspNetCore.Mvc; -using System; -using System.Collections.Generic; +using System; using System.ComponentModel.DataAnnotations; -using System.Linq; -using System.Text; using System.Threading.Tasks; -using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form; +using AutoMapper; +using Microsoft.AspNetCore.Mvc; +using Volo.Abp.Features; +using Volo.Abp.GlobalFeatures; using Volo.Abp.ObjectExtending; using Volo.CmsKit.Admin.Menus; +using Volo.CmsKit.Features; +using Volo.CmsKit.GlobalFeatures; namespace Volo.CmsKit.Admin.Web.Pages.CmsKit.Menus.MenuItems; public class CreateModalModel : CmsKitAdminPageModel { protected IMenuItemAdminAppService MenuAdminAppService { get; } + protected IFeatureChecker FeatureChecker { get; } [BindProperty] public MenuItemCreateViewModel ViewModel { get; set; } - public CreateModalModel(IMenuItemAdminAppService menuAdminAppService) + public bool IsPageFeatureEnabled { get; set; } + + public CreateModalModel(IMenuItemAdminAppService menuAdminAppService, IFeatureChecker featureChecker) { MenuAdminAppService = menuAdminAppService; + FeatureChecker = featureChecker; ViewModel = new MenuItemCreateViewModel(); } - public virtual Task OnGetAsync(Guid? parentId) + public virtual async Task OnGetAsync(Guid? parentId) { ViewModel.ParentId = parentId; - return Task.CompletedTask; + IsPageFeatureEnabled = GlobalFeatureManager.Instance.IsEnabled() + && await FeatureChecker.IsEnabledAsync(CmsKitFeatures.PageEnable); } public virtual async Task OnPostAsync() diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Menus/MenuItems/UpdateModal.cshtml b/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Menus/MenuItems/UpdateModal.cshtml index e440b3176a..4659dbfe3b 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Menus/MenuItems/UpdateModal.cshtml +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Menus/MenuItems/UpdateModal.cshtml @@ -26,35 +26,41 @@ - - - - - - + @if (Model.IsPageFeatureEnabled) + { + + + + + - + - - - @if (Model.ViewModel.PageId.HasValue) - { - - } - - + + @if (Model.ViewModel.PageId.HasValue) + { + + } + + - + -
+
+ } + else + { + + } diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Menus/MenuItems/UpdateModal.cshtml.cs b/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Menus/MenuItems/UpdateModal.cshtml.cs index e071dc0230..b64427e516 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Menus/MenuItems/UpdateModal.cshtml.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Menus/MenuItems/UpdateModal.cshtml.cs @@ -5,8 +5,12 @@ using AutoMapper; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; using Volo.Abp.Domain.Entities; +using Volo.Abp.Features; +using Volo.Abp.GlobalFeatures; using Volo.Abp.ObjectExtending; using Volo.CmsKit.Admin.Menus; +using Volo.CmsKit.Features; +using Volo.CmsKit.GlobalFeatures; using Volo.CmsKit.Menus; namespace Volo.CmsKit.Admin.Web.Pages.CmsKit.Menus.MenuItems; @@ -14,6 +18,7 @@ namespace Volo.CmsKit.Admin.Web.Pages.CmsKit.Menus.MenuItems; public class UpdateModalModel : CmsKitAdminPageModel { protected IMenuItemAdminAppService MenuAdminAppService { get; } + protected IFeatureChecker FeatureChecker { get; } [BindProperty] public MenuItemUpdateViewModel ViewModel { get; set; } @@ -22,15 +27,22 @@ public class UpdateModalModel : CmsKitAdminPageModel [BindProperty(SupportsGet = true)] public Guid Id { get; set; } - public UpdateModalModel(IMenuItemAdminAppService menuAdminAppService) + public bool IsPageFeatureEnabled { get; set; } + + public UpdateModalModel(IMenuItemAdminAppService menuAdminAppService, IFeatureChecker featureChecker) { MenuAdminAppService = menuAdminAppService; + FeatureChecker = featureChecker; + IsPageFeatureEnabled = GlobalFeatureManager.Instance.IsEnabled(); } public async Task OnGetAsync() { var menuItemDto = await MenuAdminAppService.GetAsync(Id); + IsPageFeatureEnabled = GlobalFeatureManager.Instance.IsEnabled() + && await FeatureChecker.IsEnabledAsync(CmsKitFeatures.PageEnable); + ViewModel = ObjectMapper.Map(menuItemDto); } From 47c64064938b3b5c4faeb6d4459d4322ca416e56 Mon Sep 17 00:00:00 2001 From: Enis Necipoglu Date: Wed, 17 Jan 2024 12:12:54 +0300 Subject: [PATCH 33/98] Update localization on update modal --- .../Pages/CmsKit/Menus/MenuItems/UpdateModal.cshtml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Menus/MenuItems/UpdateModal.cshtml b/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Menus/MenuItems/UpdateModal.cshtml index 4659dbfe3b..d9871aa749 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Menus/MenuItems/UpdateModal.cshtml +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Menus/MenuItems/UpdateModal.cshtml @@ -21,7 +21,7 @@ - + From 73cac92edb08186502216a1620504b420d1d461b Mon Sep 17 00:00:00 2001 From: Enis Necipoglu Date: Wed, 17 Jan 2024 12:16:01 +0300 Subject: [PATCH 34/98] Add parent selector for select2 --- .../Pages/CmsKit/Menus/MenuItems/CreateModal.cshtml | 3 ++- .../Pages/CmsKit/Menus/MenuItems/UpdateModal.cshtml | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Menus/MenuItems/CreateModal.cshtml b/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Menus/MenuItems/CreateModal.cshtml index c4c2a1476a..57d0dca5f1 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Menus/MenuItems/CreateModal.cshtml +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Menus/MenuItems/CreateModal.cshtml @@ -43,7 +43,8 @@ data-autocomplete-value-property="id" data-autocomplete-items-property="items" data-autocomplete-filter-param-name="filter" - data-autocomplete-allow-clear="true"> + data-autocomplete-allow-clear="true" + data-autocomplete-parent-selector="#menu-create-modal'"> diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Menus/MenuItems/UpdateModal.cshtml b/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Menus/MenuItems/UpdateModal.cshtml index d9871aa749..a190808560 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Menus/MenuItems/UpdateModal.cshtml +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Menus/MenuItems/UpdateModal.cshtml @@ -43,7 +43,8 @@ data-autocomplete-value-property="id" data-autocomplete-items-property="items" data-autocomplete-filter-param-name="filter" - data-autocomplete-allow-clear="true"> + data-autocomplete-allow-clear="true" + data-autocomplete-parent-selector="#menu-update-modal"> @if (Model.ViewModel.PageId.HasValue) From 0989098a25401c31833eeb3b9057e43ac38c0e8b Mon Sep 17 00:00:00 2001 From: Enis Necipoglu Date: Wed, 17 Jan 2024 13:08:45 +0300 Subject: [PATCH 35/98] Add test for unrelating Page from MenuItem --- .../Menus/MenuItemAdminAppService_Tests.cs | 23 +++++++++++++++++++ .../CmsKitDataSeedContributor.cs | 17 ++++++++++---- .../Volo.CmsKit.TestBase/CmsKitTestData.cs | 4 ++++ 3 files changed, 40 insertions(+), 4 deletions(-) diff --git a/modules/cms-kit/test/Volo.CmsKit.Application.Tests/Menus/MenuItemAdminAppService_Tests.cs b/modules/cms-kit/test/Volo.CmsKit.Application.Tests/Menus/MenuItemAdminAppService_Tests.cs index 509070fd7d..9812fe9597 100644 --- a/modules/cms-kit/test/Volo.CmsKit.Application.Tests/Menus/MenuItemAdminAppService_Tests.cs +++ b/modules/cms-kit/test/Volo.CmsKit.Application.Tests/Menus/MenuItemAdminAppService_Tests.cs @@ -77,6 +77,29 @@ public class MenuItemAdminAppService_Tests : CmsKitApplicationTestBase menu.Url.ShouldBe(newUrl); } + [Fact] + public async Task UpdateAsync_ShouldRemoveRelation_WithoutPageId() + { + var newUrl = "/my-new-url"; + await WithUnitOfWorkAsync(async () => + { + await MenuAdminAppService.UpdateAsync( + TestData.MenuItem_4_With_Page_1_Id, + new MenuItemUpdateInput + { + DisplayName = TestData.MenuItem_4_With_Page_1_Name, + Url = newUrl, + PageId = null + }); + }); + + var menu = await MenuRepository.FindAsync(TestData.MenuItem_4_With_Page_1_Id); + + menu.ShouldNotBeNull(); + menu.Url.ShouldBe(newUrl); + menu.PageId.ShouldBeNull(); + } + [Fact] public async Task DeleteAsync_ShouldWorkProperly_WithExistingId() { diff --git a/modules/cms-kit/test/Volo.CmsKit.TestBase/CmsKitDataSeedContributor.cs b/modules/cms-kit/test/Volo.CmsKit.TestBase/CmsKitDataSeedContributor.cs index f17a95ddba..a51741bdeb 100644 --- a/modules/cms-kit/test/Volo.CmsKit.TestBase/CmsKitDataSeedContributor.cs +++ b/modules/cms-kit/test/Volo.CmsKit.TestBase/CmsKitDataSeedContributor.cs @@ -1,8 +1,9 @@ -using Microsoft.Extensions.Options; +using System; using System.Collections.Generic; using System.IO; using System.Text; using System.Threading.Tasks; +using Microsoft.Extensions.Options; using Volo.Abp.BlobStoring; using Volo.Abp.Data; using Volo.Abp.DependencyInjection; @@ -194,7 +195,8 @@ public class CmsKitDataSeedContributor : IDataSeedContributor, ITransientDepende "comment", null, _cmsKitTestData.User1Id - ){ IdempotencyToken = _cmsKitTestData.IdempotencyToken_1 }); + ) + { IdempotencyToken = _cmsKitTestData.IdempotencyToken_1 }); await _commentRepository.InsertAsync(new Comment(_guidGenerator.Create(), _cmsKitTestData.EntityType1, @@ -416,6 +418,13 @@ public class CmsKitDataSeedContributor : IDataSeedContributor, ITransientDepende private async Task SeedMenusAsync() { + var menuItem4 = await _menuItemRepository.InsertAsync(new MenuItem( + _cmsKitTestData.MenuItem_4_With_Page_1_Id, + _cmsKitTestData.MenuItem_4_With_Page_1_Name, + _cmsKitTestData.Page_1_Slug.EnsureStartsWith('/'))); + + menuItem4.SetPageId(_cmsKitTestData.Page_1_Id); + await _menuItemRepository.InsertManyAsync(new[] { new MenuItem( @@ -429,8 +438,8 @@ public class CmsKitDataSeedContributor : IDataSeedContributor, ITransientDepende new MenuItem( _cmsKitTestData.MenuItem_3_Id, _cmsKitTestData.MenuItem_3_Name, - _cmsKitTestData.MenuItem_3_Url) - + _cmsKitTestData.MenuItem_3_Url), + menuItem4 }); } } diff --git a/modules/cms-kit/test/Volo.CmsKit.TestBase/CmsKitTestData.cs b/modules/cms-kit/test/Volo.CmsKit.TestBase/CmsKitTestData.cs index 8c4c07e283..b21e7aab08 100644 --- a/modules/cms-kit/test/Volo.CmsKit.TestBase/CmsKitTestData.cs +++ b/modules/cms-kit/test/Volo.CmsKit.TestBase/CmsKitTestData.cs @@ -128,6 +128,10 @@ public class CmsKitTestData : ISingletonDependency public string MenuItem_3_Url { get; } = "/products"; + public Guid MenuItem_4_With_Page_1_Id { get; } = Guid.NewGuid(); + + public string MenuItem_4_With_Page_1_Name { get; } = "Products"; + public string PollName { get; } = "Poll"; public string WidgetName { get; } = "CmsPollByCode"; From dccf2988ccd41a8b4f289c1da239098c78b249b5 Mon Sep 17 00:00:00 2001 From: Enis Necipoglu Date: Wed, 17 Jan 2024 13:13:47 +0300 Subject: [PATCH 36/98] Fix the broken test --- .../Volo/CmsKit/Menus/MenuItem.cs | 2 +- .../Volo/CmsKit/Menus/MenuItemManager.cs | 6 ++++++ .../Menus/MenuManager_Test.cs | 14 ++++++++++++++ 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Menus/MenuItem.cs b/modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Menus/MenuItem.cs index fa2505eecc..56cef52826 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Menus/MenuItem.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Menus/MenuItem.cs @@ -80,7 +80,7 @@ public class MenuItem : AuditedAggregateRoot, IMultiTenant Url = Check.NotNullOrEmpty(url, nameof(url), MenuItemConsts.MaxUrlLength); } - internal void SetPageId(Guid pageId) + internal void SetPageId(Guid? pageId) { PageId = pageId; } diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Menus/MenuItemManager.cs b/modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Menus/MenuItemManager.cs index 76d95f175f..be83b455d2 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Menus/MenuItemManager.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Menus/MenuItemManager.cs @@ -25,6 +25,12 @@ public class MenuItemManager : CmsKitDomainServiceBase menuItem.SetUrl(page.Slug.EnsureStartsWith('/')); } + public virtual void SetPageUrl(MenuItem menuItem, string url) + { + menuItem.SetPageId(null); + menuItem.SetUrl(url); + } + [UnitOfWork] public virtual async Task MoveAsync(Guid menuItemId, Guid? newParentMenuItemId, int position = 0) { diff --git a/modules/cms-kit/test/Volo.CmsKit.Domain.Tests/Menus/MenuManager_Test.cs b/modules/cms-kit/test/Volo.CmsKit.Domain.Tests/Menus/MenuManager_Test.cs index bcc1612d41..36900219d4 100644 --- a/modules/cms-kit/test/Volo.CmsKit.Domain.Tests/Menus/MenuManager_Test.cs +++ b/modules/cms-kit/test/Volo.CmsKit.Domain.Tests/Menus/MenuManager_Test.cs @@ -35,6 +35,20 @@ public class MenuManager_Test : CmsKitDomainTestBase menuItem.Url.ShouldBe(page.Slug.EnsureStartsWith('/')); } + [Fact] + public async Task SetPageUrl_ShouldSetUrlSameWithPage_WithStringUrl() + { + var newUrl = "/my-new-url"; + + var menuItem = await menuItemRepository.GetAsync(testData.MenuItem_4_With_Page_1_Id); + + menuManager.SetPageUrl(menuItem, newUrl); + + menuItem.Url.ShouldNotBeNullOrEmpty(); + menuItem.Url.ShouldBe(newUrl); + menuItem.PageId.ShouldBeNull(); + } + [Fact] public async Task MoveAsync_ShouldMoveCorrectly_UnderAnotherMenu() { From 84bae26b79224ada679102f4d189962a1005f77b Mon Sep 17 00:00:00 2001 From: Enis Necipoglu Date: Wed, 17 Jan 2024 13:13:52 +0300 Subject: [PATCH 37/98] Update MenuItemAdminAppService.cs --- .../Volo/CmsKit/Admin/Menus/MenuItemAdminAppService.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/Menus/MenuItemAdminAppService.cs b/modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/Menus/MenuItemAdminAppService.cs index 2436f92d95..65952c1a15 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/Menus/MenuItemAdminAppService.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/Menus/MenuItemAdminAppService.cs @@ -94,8 +94,7 @@ public class MenuItemAdminAppService : CmsKitAdminAppServiceBase, IMenuItemAdmin } else { - input.PageId = null; - menuItem.SetUrl(input.Url); + MenuManager.SetPageUrl(menuItem, input.Url); } menuItem.SetDisplayName(input.DisplayName); From 899910e9adb55eddbe3692be975fa8963b0b5909 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sinan=20=C3=96zt=C3=BCrk?= Date: Wed, 17 Jan 2024 15:26:05 +0300 Subject: [PATCH 38/98] fix error handling, update documentation --- docs/en/UI/Angular/HTTP-Requests.md | 24 +++++++------- .../core/src/lib/services/rest.service.ts | 6 ++-- .../src/lib/handlers/error.handler.ts | 33 +++++++++---------- .../theme-shared/src/lib/models/common.ts | 4 +-- .../lib/providers/error-handlers.provider.ts | 2 +- .../src/lib/theme-shared.module.ts | 4 +-- 6 files changed, 36 insertions(+), 37 deletions(-) diff --git a/docs/en/UI/Angular/HTTP-Requests.md b/docs/en/UI/Angular/HTTP-Requests.md index a0e53df9c9..b524b4a8ee 100644 --- a/docs/en/UI/Angular/HTTP-Requests.md +++ b/docs/en/UI/Angular/HTTP-Requests.md @@ -219,23 +219,23 @@ import { ContentProjectionService, PROJECTION_STRATEGY } from '@abp/ng.core'; import { ToasterService } from '@abp/ng.theme.shared'; import { HttpErrorResponse } from '@angular/common/http'; import { Injector } from '@angular/core'; -import { throwError } from 'rxjs'; +import { of, EMPTY } from 'rxjs'; import { Error404Component } from './error404/error404.component'; export function handleHttpErrors(injector: Injector, httpError: HttpErrorResponse) { if (httpError.status === 400) { const toaster = injector.get(ToasterService); toaster.error(httpError.error?.error?.message || 'Bad request!', '400'); - return; + return EMPTY; } if (httpError.status === 404) { const contentProjection = injector.get(ContentProjectionService); contentProjection.projectContent(PROJECTION_STRATEGY.AppendComponentToBody(Error404Component)); - return; + return EMPTY; } - return throwError(httpError); + return of(httpError); } // app.module.ts @@ -267,22 +267,22 @@ In the example above: ![custom-error-handler-404-component](images/custom-error-handler-404-component.jpg) - - Since `throwError(httpError)` is returned at bottom of the `handleHttpErrors`, the `ErrorHandler` will handle the HTTP errors except 400 and 404 errors. + - Since `of(httpError)` is returned at bottom of the `handleHttpErrors`, the `ErrorHandler` will handle the HTTP errors except 400 and 404 errors. -**Note 1:** If you put `return` to next line of handling an error, default error handling will not work for that error. +**Note 1:** If you put `return EMPTY` to next line of handling an error, default error handling will not work for that error. `EMPTY` can be imported from `rxjs` ```js export function handleHttpErrors(injector: Injector, httpError: HttpErrorResponse) { if (httpError.status === 403) { // handle 403 errors here - return; // put return to skip default error handling + return EMPTY; // put return to skip default error handling } } ``` -**Note 2:** If you put `return throwError(httpError)`, default error handling will work. - - `throwError` is a function. It can be imported from `rxjs`. +**Note 2:** If you put `return of(httpError)`, default error handling will work. + - `of` is a function. It can be imported from `rxjs`. - `httpError` is the second parameter of the error handler function which is registered to the `HTTP_ERROR_HANDLER` provider. Type of the `httpError` is `HttpErrorResponse`. ```js @@ -291,11 +291,11 @@ import { throwError } from 'rxjs'; export function handleHttpErrors(injector: Injector, httpError: HttpErrorResponse) { if (httpError.status === 500) { // handle 500 errors here - return; + return EMPTY; } - // you can return the throwError(httpError) at bottom of the function to run the default handler of ABP for HTTP errors that you didn't handle above. - return throwError(httpError) + // you can return the of(httpError) at bottom of the function to run the default handler of ABP for HTTP errors that you didn't handle above. + return of(httpError) } ``` diff --git a/npm/ng-packs/packages/core/src/lib/services/rest.service.ts b/npm/ng-packs/packages/core/src/lib/services/rest.service.ts index a7ee7a491b..83f91777ca 100644 --- a/npm/ng-packs/packages/core/src/lib/services/rest.service.ts +++ b/npm/ng-packs/packages/core/src/lib/services/rest.service.ts @@ -20,7 +20,7 @@ export class RestService { protected externalHttp: ExternalHttpClient, protected environment: EnvironmentService, protected httpErrorReporter: HttpErrorReporterService, - ) {} + ) { } protected getApiFromStore(apiName: string | undefined): string { return this.environment.getApiUrl(apiName); @@ -28,7 +28,7 @@ export class RestService { handleError(err: any): Observable { this.httpErrorReporter.reportError(err); - return throwError(err); + return throwError(() => err); } request( @@ -51,7 +51,7 @@ export class RestService { }), ...options, } as any) - .pipe(catchError(err => (skipHandleError ? throwError(err) : this.handleError(err)))); + .pipe(catchError(err => (skipHandleError ? throwError(() => err) : this.handleError(err)))); } private getHttpClient(isExternal: boolean) { return isExternal ? this.externalHttp : this.http; diff --git a/npm/ng-packs/packages/theme-shared/src/lib/handlers/error.handler.ts b/npm/ng-packs/packages/theme-shared/src/lib/handlers/error.handler.ts index 480a647bbe..a3417900a2 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/handlers/error.handler.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/handlers/error.handler.ts @@ -1,11 +1,11 @@ import { inject, Injectable, Injector } from '@angular/core'; import { HttpErrorResponse } from '@angular/common/http'; -import { Observable, of, throwError } from 'rxjs'; -import { catchError, filter, switchMap } from 'rxjs/operators'; +import { Observable, of } from 'rxjs'; +import { filter, switchMap } from 'rxjs/operators'; import { HttpErrorReporterService } from '@abp/ng.core'; -import { CustomHttpErrorHandlerService } from '../models/common'; +import { CustomHttpErrorHandlerService, HttpErrorHandler } from '../models/common'; import { Confirmation } from '../models/confirmation'; import { CUSTOM_ERROR_HANDLERS, HTTP_ERROR_HANDLER } from '../tokens/http-error.token'; @@ -21,10 +21,8 @@ export class ErrorHandler { protected readonly confirmationService = inject(ConfirmationService); protected readonly routerErrorHandlerService = inject(RouterErrorHandlerService); protected readonly httpErrorConfig = inject(HTTP_ERROR_CONFIG); - protected readonly customErrorHandlers = inject(CUSTOM_ERROR_HANDLERS); - protected readonly defaultHttpErrorHandler = (_, err: HttpErrorResponse) => throwError(() => err); - protected readonly httpErrorHandler = - inject(HTTP_ERROR_HANDLER, { optional: true }) || this.defaultHttpErrorHandler; + protected readonly defaultErrorHandlers = inject(CUSTOM_ERROR_HANDLERS); + protected readonly httpErrorHandler = inject(HTTP_ERROR_HANDLER, { optional: true }); constructor(protected injector: Injector) { this.listenToRestError(); @@ -42,10 +40,11 @@ export class ErrorHandler { } protected executeErrorHandler = (error: HttpErrorResponse) => { - const errHandler = this.httpErrorHandler(this.injector, error); - const isObservable = errHandler instanceof Observable; - - return (isObservable ? errHandler : of(null)).pipe(catchError(err => of(err))); + if (this.httpErrorHandler) { + return this.httpErrorHandler(this.injector, error); + } + + return of(error); }; protected sortHttpErrorHandlers( @@ -56,17 +55,17 @@ export class ErrorHandler { } protected handleError(err: unknown) { - if (this.customErrorHandlers && this.customErrorHandlers.length) { - const canHandleService = this.customErrorHandlers + if (this.defaultErrorHandlers && this.defaultErrorHandlers.length) { + const errorHandlerService = this.defaultErrorHandlers .sort(this.sortHttpErrorHandlers) .find(service => service.canHandle(err)); - - if (canHandleService) { - canHandleService.execute(); + + if (errorHandlerService) { + errorHandlerService.execute(); return; } } - + this.showError().subscribe(); } diff --git a/npm/ng-packs/packages/theme-shared/src/lib/models/common.ts b/npm/ng-packs/packages/theme-shared/src/lib/models/common.ts index 82a14641ad..ac0e9ac120 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/models/common.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/models/common.ts @@ -1,5 +1,5 @@ import { HttpErrorResponse } from '@angular/common/http'; -import { Type } from '@angular/core'; +import { Injector, Type } from '@angular/core'; import { Validation } from '@ngx-validate/core'; import { Observable } from 'rxjs'; import { ConfirmationIcons } from '../tokens/confirmation-icons.token'; @@ -20,7 +20,7 @@ export interface HttpErrorConfig { hideCloseIcon?: boolean; }; } -export type HttpErrorHandler = (httpError: HttpErrorResponse) => Observable; +export type HttpErrorHandler = (injector: Injector, httpError: HttpErrorResponse) => Observable; export type LocaleDirection = 'ltr' | 'rtl'; export interface CustomHttpErrorHandlerService { diff --git a/npm/ng-packs/packages/theme-shared/src/lib/providers/error-handlers.provider.ts b/npm/ng-packs/packages/theme-shared/src/lib/providers/error-handlers.provider.ts index 0d177ec510..61a2a25fcd 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/providers/error-handlers.provider.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/providers/error-handlers.provider.ts @@ -5,7 +5,7 @@ import { AbpFormatErrorHandlerService } from '../services/abp-format-error-handl import { StatusCodeErrorHandlerService } from '../services/status-code-error-handler.service'; import { UnknownStatusCodeErrorHandlerService } from '../services/unknown-status-code-error-handler.service'; -export const ERROR_HANDLERS_PROVIDERS: Provider[] = [ +export const DEFAULT_HANDLERS_PROVIDERS: Provider[] = [ { provide: CUSTOM_ERROR_HANDLERS, multi: true, diff --git a/npm/ng-packs/packages/theme-shared/src/lib/theme-shared.module.ts b/npm/ng-packs/packages/theme-shared/src/lib/theme-shared.module.ts index 53c2498f60..d2d294bfc5 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/theme-shared.module.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/theme-shared.module.ts @@ -29,7 +29,7 @@ import { NgxDatatableListDirective } from './directives/ngx-datatable-list.direc import { DocumentDirHandlerService } from './handlers/document-dir.handler'; import { ErrorHandler } from './handlers/error.handler'; import { RootParams } from './models/common'; -import { ERROR_HANDLERS_PROVIDERS, NG_BOOTSTRAP_CONFIG_PROVIDERS } from './providers'; +import { DEFAULT_HANDLERS_PROVIDERS, NG_BOOTSTRAP_CONFIG_PROVIDERS } from './providers'; import { THEME_SHARED_ROUTE_PROVIDERS } from './providers/route.provider'; import { THEME_SHARED_APPEND_CONTENT } from './tokens/append-content.token'; import { HTTP_ERROR_CONFIG, httpErrorConfigFactory } from './tokens/http-error.token'; @@ -149,7 +149,7 @@ export class ThemeSharedModule { }, }, tenantNotFoundProvider, - ERROR_HANDLERS_PROVIDERS, + DEFAULT_HANDLERS_PROVIDERS, ], }; } From f9c1342f6661f503c813f0396e2ecf95d815e693 Mon Sep 17 00:00:00 2001 From: Salih Date: Wed, 17 Jan 2024 17:57:09 +0300 Subject: [PATCH 39/98] Update en.json --- .../AbpIoLocalization/Base/Localization/Resources/en.json | 1 + 1 file changed, 1 insertion(+) diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/en.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/en.json index 0dae45eee8..46bd84d0df 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/en.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/en.json @@ -29,6 +29,7 @@ "Volo.AbpIo.Domain:030012": "A user is entitled to have only 1 free trial period. You already used your trial license.", "Volo.AbpIo.Domain:030013": "A user with an active license cannot start a trial license.", "Volo.AbpIo.Domain:040000": "Telemetry already exists!.", + "Volo.AbpIo.Domain:050000": "Organization has credit card. You can not delete it!", "Volo.AbpIo.Domain:070000": "The organization name can only contain latin letters, numbers, dots and hyphens!", "Volo.AbpIo.Domain:070001": "The company name can only contain latin letters, numbers, dots, space and hyphens!", "WantToLearn?": "Want to learn?", From d8ba109ee13a2cb031bd95dac851cfd37c17c33f Mon Sep 17 00:00:00 2001 From: Salih Date: Wed, 17 Jan 2024 17:57:13 +0300 Subject: [PATCH 40/98] Update en.json --- .../AbpIoLocalization/Admin/Localization/Resources/en.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json index 29211d4d8e..aa16e3931c 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json @@ -591,6 +591,7 @@ "Menu:Licenses": "Licenses", "OrganizationId": "Organization Id", "RemoveAllWinnersConfirmationMessage": "Are you sure you want to remove all winners?", - "AutoRenewals": "Auto Renewals" + "AutoRenewals": "Auto Renewals", + "OrganizationHasCreditCard": "Organization has credit card. Please remove credit card first!" } } From bf8c6cd9721eb8523bd70ec583980c156714f560 Mon Sep 17 00:00:00 2001 From: Enis Necipoglu Date: Thu, 18 Jan 2024 11:14:42 +0300 Subject: [PATCH 41/98] Fix broken test --- .../Menus/MenuItemAdminAppService_Tests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/cms-kit/test/Volo.CmsKit.Application.Tests/Menus/MenuItemAdminAppService_Tests.cs b/modules/cms-kit/test/Volo.CmsKit.Application.Tests/Menus/MenuItemAdminAppService_Tests.cs index 9812fe9597..5ff1e85161 100644 --- a/modules/cms-kit/test/Volo.CmsKit.Application.Tests/Menus/MenuItemAdminAppService_Tests.cs +++ b/modules/cms-kit/test/Volo.CmsKit.Application.Tests/Menus/MenuItemAdminAppService_Tests.cs @@ -39,7 +39,7 @@ public class MenuItemAdminAppService_Tests : CmsKitApplicationTestBase result.ShouldNotBeNull(); result.Items.ShouldNotBeEmpty(); - result.Items.Count.ShouldBe(3); + result.Items.Count.ShouldBe(4); } [Fact] From 3e47be48f8baad3dbe40f0b2f1ab7babedf9f2a0 Mon Sep 17 00:00:00 2001 From: Enis Necipoglu Date: Thu, 18 Jan 2024 12:51:38 +0300 Subject: [PATCH 42/98] Fix MongoDB tests --- .../test/Volo.CmsKit.TestBase/CmsKitDataSeedContributor.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/cms-kit/test/Volo.CmsKit.TestBase/CmsKitDataSeedContributor.cs b/modules/cms-kit/test/Volo.CmsKit.TestBase/CmsKitDataSeedContributor.cs index a51741bdeb..19b51ccf7c 100644 --- a/modules/cms-kit/test/Volo.CmsKit.TestBase/CmsKitDataSeedContributor.cs +++ b/modules/cms-kit/test/Volo.CmsKit.TestBase/CmsKitDataSeedContributor.cs @@ -418,10 +418,10 @@ public class CmsKitDataSeedContributor : IDataSeedContributor, ITransientDepende private async Task SeedMenusAsync() { - var menuItem4 = await _menuItemRepository.InsertAsync(new MenuItem( + var menuItem4 = new MenuItem( _cmsKitTestData.MenuItem_4_With_Page_1_Id, _cmsKitTestData.MenuItem_4_With_Page_1_Name, - _cmsKitTestData.Page_1_Slug.EnsureStartsWith('/'))); + _cmsKitTestData.Page_1_Slug.EnsureStartsWith('/')); menuItem4.SetPageId(_cmsKitTestData.Page_1_Id); From 1c98a3bc3105ba96d427876eae5fd5113137f0a4 Mon Sep 17 00:00:00 2001 From: Enis Necipoglu Date: Fri, 19 Jan 2024 16:09:31 +0300 Subject: [PATCH 43/98] Make Url of MenuItem as Required in DTOs --- .../Volo/CmsKit/Admin/Menus/MenuItemCreateInput.cs | 1 + .../Volo/CmsKit/Admin/Menus/MenuItemUpdateInput.cs | 1 + 2 files changed, 2 insertions(+) diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Menus/MenuItemCreateInput.cs b/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Menus/MenuItemCreateInput.cs index f5ec9c6444..ebb312699a 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Menus/MenuItemCreateInput.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Menus/MenuItemCreateInput.cs @@ -14,6 +14,7 @@ public class MenuItemCreateInput : ExtensibleObject public bool IsActive { get; set; } + [Required] public string Url { get; set; } public string Icon { get; set; } diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Menus/MenuItemUpdateInput.cs b/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Menus/MenuItemUpdateInput.cs index 8767a6192a..b51903359c 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Menus/MenuItemUpdateInput.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Menus/MenuItemUpdateInput.cs @@ -13,6 +13,7 @@ public class MenuItemUpdateInput : ExtensibleObject, IHasConcurrencyStamp public bool IsActive { get; set; } + [Required] public string Url { get; set; } public string Icon { get; set; } From 2c37566528661e66fd814c837b47915cda4633ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sinan=20=C3=96zt=C3=BCrk?= Date: Fri, 19 Jan 2024 18:36:59 +0300 Subject: [PATCH 44/98] update documentation, deprecate HTTP_ERROR_HANDLER injection token --- docs/en/UI/Angular/HTTP-Error-Handling.md | 100 +++++++++++++ docs/en/UI/Angular/HTTP-Requests.md | 140 +----------------- docs/en/docs-nav.json | 15 +- .../src/lib/handlers/error.handler.ts | 12 +- .../lib/providers/error-handlers.provider.ts | 8 +- .../src/lib/tokens/http-error.token.ts | 3 + 6 files changed, 132 insertions(+), 146 deletions(-) create mode 100644 docs/en/UI/Angular/HTTP-Error-Handling.md diff --git a/docs/en/UI/Angular/HTTP-Error-Handling.md b/docs/en/UI/Angular/HTTP-Error-Handling.md new file mode 100644 index 0000000000..8bf2589204 --- /dev/null +++ b/docs/en/UI/Angular/HTTP-Error-Handling.md @@ -0,0 +1,100 @@ +# HTTP Error Handling + +When the `RestService` is used, all HTTP errors are reported to the [`HttpErrorReporterService`](./HTTP-Error-Reporter-Service), and then `ErrorHandler`, a service exposed by the `@abp/ng.theme.shared` package automatically handles the errors. + +## Custom HTTP Error Handler + +A custom HTTP error handler service can be registered to an injection token named **`CUSTOM_ERROR_HANDLERS`**. ABP has some default error handlers, you can see them [here](https://github.com/abpframework/abp/blob/dev/npm/ng-packs/packages/theme-shared/src/lib/providers/error-handlers.provider.ts). + +### How ABP handles errors and How to add new one? + +- First of all it will be better to understand how ABP handles errors. +- ABP error handler services are implements the interface of **CustomHttpErrorHandlerService**. + +**Interface of `CUSTOM_ERROR_HANDLERS`** + +```ts +interface CustomHttpErrorHandlerService { + readonly priority: number; + canHandle(error: unknown): boolean; + execute(): void; +} +``` + +- **`priority`** ABP sorts the services according to the number of the priority variable. Higher priority will be checked first. You can think this as a z-index property in CSS. +- **`canHandle(error: unknown): boolean :`** Check if the service can handle the error. Returns boolean. +- **`execute(): void :`** If the service can handle the error, then run the execute method. + +**In Summarry** + +- Services are sorted by their priority number. +- Start from highest priority service and run canHandle() method. Pick the service if can handle the error, if not check next service. +- If the service found, run the execute method of a service. Done. + +See an example: + +```ts +// custom-error-handler.service.ts +import { inject, Injectable } from "@angular/core"; +import { HttpErrorResponse } from "@angular/common/http"; +import { CustomHttpErrorHandlerService } from "@abp/ng.theme.shared"; +import { CUSTOM_HTTP_ERROR_HANDLER_PRIORITY } from "@abp/ng.theme.shared"; +import { ToasterService } from "@abp/ng.theme.shared"; + +@Injectable({ providedIn: "root" }) +export class MyCustomErrorHandlerService + implements CustomHttpErrorHandlerService +{ + + // You can write any number here, ex: 9999 + readonly priority = CUSTOM_HTTP_ERROR_HANDLER_PRIORITY.veryHigh; + private toaster = inject(ToasterService); + private error: HttpErrorResponse | undefined = undefined; + + // What kind of error should be handled by this service? You can decide it in this method. If error is suitable to your case then return true; otherwise return false. + canHandle(error: unknown): boolean { + if (error instanceof HttpErrorResponse && error.status === 400) { + this.error = error; + return true; + } + return false; + } + + // If this service is picked from ErrorHandler, this execute method will be called. + execute() { + this.toaster.error( + this.error.error?.error?.message || "Bad request!", + "400" + ); + } +} +``` + +```ts + +// app.module.ts +import { CUSTOM_ERROR_HANDLERS, ... } from '@abp/ng.theme.shared'; +import { MyCustomErrorHandlerService } from './custom-error-handler.service'; + +@NgModule({ + // ... + providers: [ + // ... + { provide: CUSTOM_ERROR_HANDLERS, useExisting: MyCustomErrorHandlerService, multi: true } + ] +}) +export class AppModule {} +``` + +In the example above: + +- Created a service named `MyCustomErrorHandlerService`, and provided via `useExisting` key because we dont want another instance of it. And set `multi` key to true because ABP default error handlers are also provided with **CUSTOM_ERROR_HANDLERS** injection token. + +- 400 errors are handled from custom `MyCustomErrorHandlerService`. When a 400 error occurs, backend error message will be displayed as shown below: + +![custom-error-handler-toaster-message](images/custom-error-handler-toaster-message.jpg) + +**Note 1:** If your service cannot handle the error. Then ABP will check the next Error Service. +**Note 2:** If none of the service handle the error. Then basic confirmation message about the error will be shown to the user. +**Note 3:** You can provide more than one service, with CUSTOM_ERROR_HANDLER injection token. +**Note 4:** If you want your custom service to be evaluated (checked) earlier, set the priority variable high. diff --git a/docs/en/UI/Angular/HTTP-Requests.md b/docs/en/UI/Angular/HTTP-Requests.md index b524b4a8ee..c58e35fc51 100644 --- a/docs/en/UI/Angular/HTTP-Requests.md +++ b/docs/en/UI/Angular/HTTP-Requests.md @@ -1,7 +1,5 @@ # How to Make HTTP Requests - - ## About HttpClient Angular has the amazing [HttpClient](https://angular.io/guide/http) for communication with backend services. It is a layer on top and a simplified representation of [XMLHttpRequest Web API](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest). It also is the recommended agent by Angular for any HTTP request. There is nothing wrong with using the `HttpClient` in your ABP project. @@ -23,14 +21,10 @@ Although clear and flexible, handling errors this way is repetitive work, even w An `HttpInterceptor` is able to catch `HttpErrorResponse` and can be used for a centralized error handling. Nevertheless, cases where default error handler, therefore the interceptor, must be disabled require additional work and comprehension of Angular internals. Check [this issue](https://github.com/angular/angular/issues/20203) for details. - - ## RestService ABP core module has a utility service for HTTP requests: `RestService`. Unless explicitly configured otherwise, it catches HTTP errors and dispatches a `RestOccurError` action. This action is then captured by the `ErrorHandler` introduced by the `ThemeSharedModule`. Since you should already import this module in your app, when the `RestService` is used, all HTTP errors get automatically handled by default. - - ### Getting Started with RestService In order to use the `RestService`, you must inject it in your class as a dependency. @@ -48,11 +42,9 @@ class DemoService { You do not have to provide the `RestService` at module or component/directive level, because it is already **provided in root**. - - ### How to Make a Request with RestService -You can use the `request` method of the `RestService` is for HTTP requests. Here is an example: +You can use the `request` method of the `RestService` is for HTTP requests. Here is an example: ```js getFoo(id: number) { @@ -65,8 +57,6 @@ getFoo(id: number) { } ``` - - The `request` method always returns an `Observable`. Therefore you can do the following wherever you use `getFoo` method: ```js @@ -79,12 +69,8 @@ doSomethingWithFoo(id: number) { } ``` - - **You do not have to worry about unsubscription.** The `RestService` uses `HttpClient` behind the scenes, so every observable it returns is a finite observable, i.e. it closes subscriptions automatically upon success or error. - - As you see, `request` method gets a request options object with `Rest.Request` type. This generic type expects the interface of the request body. You may pass `null` when there is no body, like in a `GET` or a `DELETE` request. Here is an example where there is one: ```js @@ -99,11 +85,7 @@ postFoo(body: Foo) { } ``` - - -You may [check here](https://github.com/abpframework/abp/blob/dev/npm/ng-packs/packages/core/src/lib/models/rest.ts#L23) for complete `Rest.Request` type, which has only a few changes compared to [HttpRequest](https://angular.io/api/common/http/HttpRequest) class in Angular. - - +You may [check here](https://github.com/abpframework/abp/blob/dev/npm/ng-packs/packages/core/src/lib/models/rest.ts#L23) for complete `Rest.Request` type, which has only a few changes compared to [HttpRequest](https://angular.io/api/common/http/HttpRequest) class in Angular. ### How to Disable Default Error Handler of RestService @@ -120,8 +102,6 @@ deleteFoo(id: number) { } ``` - - `skipHandleError` config option, when set to `true`, disables the error handler and the returned observable starts throwing an error that you can catch in your subscription. ```js @@ -137,14 +117,10 @@ removeFooFromList(id: number) { } ``` - - ### How to Get a Specific API Endpoint From Application Config Another nice config option that `request` method receives is `apiName` (available as of v2.4), which can be used to get a specific module endpoint from application configuration. - - ```js putFoo(body: Foo, id: string) { const request: Rest.Request = { @@ -157,8 +133,6 @@ putFoo(body: Foo, id: string) { } ``` - - `putFoo` above will request `https://localhost:44305/api/some/path/to/foo/{id}` as long as the environment variables are as follows: ```js @@ -167,19 +141,17 @@ putFoo(body: Foo, id: string) { export const environment = { apis: { default: { - url: 'https://localhost:44305', + url: "https://localhost:44305", }, foo: { - url: 'https://localhost:44305/api/some/path/to/foo', + url: "https://localhost:44305/api/some/path/to/foo", }, }, - + /* rest of the environment variables here */ -} +}; ``` - - ### How to Observe Response Object or HTTP Events Instead of Body `RestService` assumes you are generally interested in the body of a response and, by default, sets `observe` property as `'body'`. However, there may be times you are rather interested in something else, such as a custom proprietary header. For that, the `request` method receives `observe` property in its config object. @@ -202,104 +174,6 @@ getSomeCustomHeaderValue() { You may find `Rest.Observe` enum [here](https://github.com/abpframework/abp/blob/dev/npm/ng-packs/packages/core/src/lib/models/rest.ts#L10). - -## HTTP Error Handling - -When the `RestService` is used, all HTTP errors are reported to the [`HttpErrorReporterService`](./HTTP-Error-Reporter-Service), and then `ErrorHandler`, a service exposed by the `@abp/ng.theme.shared` package automatically handles the errors. - -### Custom HTTP Error Handler - -A custom HTTP error handler can be registered to an injection token named `HTTP_ERROR_HANDLER`. If a custom handler function is registered, the `ErrorHandler` executes that function. - -See an example: - -```js -// http-error-handler.ts -import { ContentProjectionService, PROJECTION_STRATEGY } from '@abp/ng.core'; -import { ToasterService } from '@abp/ng.theme.shared'; -import { HttpErrorResponse } from '@angular/common/http'; -import { Injector } from '@angular/core'; -import { of, EMPTY } from 'rxjs'; -import { Error404Component } from './error404/error404.component'; - -export function handleHttpErrors(injector: Injector, httpError: HttpErrorResponse) { - if (httpError.status === 400) { - const toaster = injector.get(ToasterService); - toaster.error(httpError.error?.error?.message || 'Bad request!', '400'); - return EMPTY; - } - - if (httpError.status === 404) { - const contentProjection = injector.get(ContentProjectionService); - contentProjection.projectContent(PROJECTION_STRATEGY.AppendComponentToBody(Error404Component)); - return EMPTY; - } - - return of(httpError); -} - -// app.module.ts -import { Error404Component } from './error404/error404.component'; -import { handleHttpErrors } from './http-error-handling'; -import { HTTP_ERROR_HANDLER, ... } from '@abp/ng.theme.shared'; - -@NgModule({ - // ... - providers: [ - // ... - { provide: HTTP_ERROR_HANDLER, useValue: handleHttpErrors } - ], - declarations: [ - //... - Error404Component], -}) -export class AppModule {} -``` - -In the example above: - - - Created a function named `handleHttpErrors` and defined as value of the `HTTP_ERROR_HANDLER` provider in app.module. After this, the function executes when an HTTP error occurs. - - 400 bad request errors is handled. When a 400 error occurs, backend error message will be displayed as shown below: - - ![custom-error-handler-toaster-message](images/custom-error-handler-toaster-message.jpg) - - - 404 not found errors is handled. When a 404 error occurs, `Error404Component` will be appended to the `` as shown below: - -![custom-error-handler-404-component](images/custom-error-handler-404-component.jpg) - - - Since `of(httpError)` is returned at bottom of the `handleHttpErrors`, the `ErrorHandler` will handle the HTTP errors except 400 and 404 errors. - - -**Note 1:** If you put `return EMPTY` to next line of handling an error, default error handling will not work for that error. `EMPTY` can be imported from `rxjs` - -```js -export function handleHttpErrors(injector: Injector, httpError: HttpErrorResponse) { - if (httpError.status === 403) { - // handle 403 errors here - return EMPTY; // put return to skip default error handling - } -} -``` - -**Note 2:** If you put `return of(httpError)`, default error handling will work. - - `of` is a function. It can be imported from `rxjs`. - - `httpError` is the second parameter of the error handler function which is registered to the `HTTP_ERROR_HANDLER` provider. Type of the `httpError` is `HttpErrorResponse`. - -```js -import { throwError } from 'rxjs'; - -export function handleHttpErrors(injector: Injector, httpError: HttpErrorResponse) { - if (httpError.status === 500) { - // handle 500 errors here - return EMPTY; - } - - // you can return the of(httpError) at bottom of the function to run the default handler of ABP for HTTP errors that you didn't handle above. - return of(httpError) -} -``` - - ### How to Skip HTTP interceptors and ABP headers The ABP Framework adds several HTTP headers to the HttpClient, such as the "Auth token" or "tenant Id". @@ -309,4 +183,4 @@ The ABP Http interceptors check the value of the `IS_EXTERNAL_REQUEST` token. If The `ExternalHttpClient` extends from `HTTPClient` and sets the `IS_EXTERNAL_REQUEST` context token to true. When you are using `ExternalHttpClient` as HttpClient in your components, it does not add ABP-specific headers. -Note: With `IS_EXTERNAL_REQUEST` or without it, ABP loading service works. +Note: With `IS_EXTERNAL_REQUEST` or without it, ABP loading service works. diff --git a/docs/en/docs-nav.json b/docs/en/docs-nav.json index 8e766c7430..be988b795c 100644 --- a/docs/en/docs-nav.json +++ b/docs/en/docs-nav.json @@ -1053,7 +1053,16 @@ }, { "text": "HTTP Requests", - "path": "UI/Angular/HTTP-Requests.md" + "items": [ + { + "text": "How to Make HTTP Requests", + "path": "UI/Angular/HTTP-Requests.md" + }, + { + "text": "HTTP Error Handling / Customization", + "path": "UI/Angular/HTTP-Error-Handling.md" + } + ] }, { "text": "Localization", @@ -1173,8 +1182,8 @@ "path": "UI/Angular/Content-Security-Strategy.md" }, { - "text":"Abp Window Service", - "path":"UI/Angular/Abp-Window-Service.md" + "text": "Abp Window Service", + "path": "UI/Angular/Abp-Window-Service.md" } ] }, diff --git a/npm/ng-packs/packages/theme-shared/src/lib/handlers/error.handler.ts b/npm/ng-packs/packages/theme-shared/src/lib/handlers/error.handler.ts index a3417900a2..168fef1f53 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/handlers/error.handler.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/handlers/error.handler.ts @@ -21,7 +21,7 @@ export class ErrorHandler { protected readonly confirmationService = inject(ConfirmationService); protected readonly routerErrorHandlerService = inject(RouterErrorHandlerService); protected readonly httpErrorConfig = inject(HTTP_ERROR_CONFIG); - protected readonly defaultErrorHandlers = inject(CUSTOM_ERROR_HANDLERS); + protected readonly customErrorHandlers = inject(CUSTOM_ERROR_HANDLERS); protected readonly httpErrorHandler = inject(HTTP_ERROR_HANDLER, { optional: true }); constructor(protected injector: Injector) { @@ -43,7 +43,7 @@ export class ErrorHandler { if (this.httpErrorHandler) { return this.httpErrorHandler(this.injector, error); } - + return of(error); }; @@ -55,17 +55,17 @@ export class ErrorHandler { } protected handleError(err: unknown) { - if (this.defaultErrorHandlers && this.defaultErrorHandlers.length) { - const errorHandlerService = this.defaultErrorHandlers + if (this.customErrorHandlers && this.customErrorHandlers.length) { + const errorHandlerService = this.customErrorHandlers .sort(this.sortHttpErrorHandlers) .find(service => service.canHandle(err)); - + if (errorHandlerService) { errorHandlerService.execute(); return; } } - + this.showError().subscribe(); } diff --git a/npm/ng-packs/packages/theme-shared/src/lib/providers/error-handlers.provider.ts b/npm/ng-packs/packages/theme-shared/src/lib/providers/error-handlers.provider.ts index 61a2a25fcd..d456c82912 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/providers/error-handlers.provider.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/providers/error-handlers.provider.ts @@ -9,21 +9,21 @@ export const DEFAULT_HANDLERS_PROVIDERS: Provider[] = [ { provide: CUSTOM_ERROR_HANDLERS, multi: true, - useClass: TenantResolveErrorHandlerService, + useExisting: TenantResolveErrorHandlerService, }, { provide: CUSTOM_ERROR_HANDLERS, multi: true, - useClass: AbpFormatErrorHandlerService, + useExisting: AbpFormatErrorHandlerService, }, { provide: CUSTOM_ERROR_HANDLERS, multi: true, - useClass: StatusCodeErrorHandlerService, + useExisting: StatusCodeErrorHandlerService, }, { provide: CUSTOM_ERROR_HANDLERS, multi: true, - useClass: UnknownStatusCodeErrorHandlerService, + useExisting: UnknownStatusCodeErrorHandlerService, }, ]; diff --git a/npm/ng-packs/packages/theme-shared/src/lib/tokens/http-error.token.ts b/npm/ng-packs/packages/theme-shared/src/lib/tokens/http-error.token.ts index a2784f4332..64245680db 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/tokens/http-error.token.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/tokens/http-error.token.ts @@ -15,6 +15,9 @@ export function httpErrorConfigFactory(config = {} as HttpErrorConfig) { export const HTTP_ERROR_CONFIG = new InjectionToken('HTTP_ERROR_CONFIG'); +/** + @deprecated use **`CUSTOM_ERROR_HANDLERS`** injection token instead of this, see more info https://docs.abp.io/en/abp/latest/UI/Angular/HTTP-Requests +*/ export const HTTP_ERROR_HANDLER = new InjectionToken('HTTP_ERROR_HANDLER'); export const CUSTOM_ERROR_HANDLERS = new InjectionToken( From 037c013427cf0b4518f8f012e0dd3909bd9024cf Mon Sep 17 00:00:00 2001 From: maliming Date: Mon, 22 Jan 2024 11:25:34 +0800 Subject: [PATCH 45/98] Return `NotFoundFileInfo` or `NotFoundDirectoryContents` when `subpach` is `null`. --- .../VirtualFileSystem/WebContentFileProvider.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/VirtualFileSystem/WebContentFileProvider.cs b/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/VirtualFileSystem/WebContentFileProvider.cs index ba9240d48b..fffc35792a 100644 --- a/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/VirtualFileSystem/WebContentFileProvider.cs +++ b/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/VirtualFileSystem/WebContentFileProvider.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Linq; -using JetBrains.Annotations; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.FileProviders; using Microsoft.Extensions.Options; @@ -34,7 +33,10 @@ public class WebContentFileProvider : IWebContentFileProvider, ISingletonDepende public virtual IFileInfo GetFileInfo(string subpath) { - Check.NotNullOrEmpty(subpath, nameof(subpath)); + if (string.IsNullOrEmpty(subpath)) + { + return new NotFoundFileInfo(subpath); + } if (PathUtils.PathNavigatesAboveRoot(subpath)) { @@ -53,11 +55,9 @@ public class WebContentFileProvider : IWebContentFileProvider, ISingletonDepende return _fileProvider.GetFileInfo(_rootPath + subpath); } - public virtual IDirectoryContents GetDirectoryContents([NotNull] string subpath) + public virtual IDirectoryContents GetDirectoryContents(string subpath) { - Check.NotNullOrEmpty(subpath, nameof(subpath)); - - if (PathUtils.PathNavigatesAboveRoot(subpath)) + if (subpath == null || PathUtils.PathNavigatesAboveRoot(subpath)) { return NotFoundDirectoryContents.Singleton; } From 2d69007ea314348729ff6c422cddab1e6642d8f7 Mon Sep 17 00:00:00 2001 From: Enis Necipoglu Date: Mon, 22 Jan 2024 09:48:57 +0300 Subject: [PATCH 46/98] Update MenuItemAdminAppService_Tests.cs --- .../Menus/MenuItemAdminAppService_Tests.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/cms-kit/test/Volo.CmsKit.Application.Tests/Menus/MenuItemAdminAppService_Tests.cs b/modules/cms-kit/test/Volo.CmsKit.Application.Tests/Menus/MenuItemAdminAppService_Tests.cs index 5ff1e85161..7dd89ba9d0 100644 --- a/modules/cms-kit/test/Volo.CmsKit.Application.Tests/Menus/MenuItemAdminAppService_Tests.cs +++ b/modules/cms-kit/test/Volo.CmsKit.Application.Tests/Menus/MenuItemAdminAppService_Tests.cs @@ -48,7 +48,8 @@ public class MenuItemAdminAppService_Tests : CmsKitApplicationTestBase var name = "My Awesome Menu"; var menu = await MenuAdminAppService.CreateAsync(new MenuItemCreateInput { - DisplayName = name + DisplayName = name, + Url = "#" }); menu.ShouldNotBeNull(); From b34c01616418a8012ab7307ac87844d770885c10 Mon Sep 17 00:00:00 2001 From: liangshiwei Date: Mon, 22 Jan 2024 17:02:04 +0800 Subject: [PATCH 47/98] Throw exception if provder was not found --- .../Volo/Abp/SettingManagement/SettingManager.cs | 2 +- .../SettingManagement/SettingManager_Basic_Tests.cs | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain/Volo/Abp/SettingManagement/SettingManager.cs b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain/Volo/Abp/SettingManagement/SettingManager.cs index 5439c1213a..68d66ee4b0 100644 --- a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain/Volo/Abp/SettingManagement/SettingManager.cs +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain/Volo/Abp/SettingManagement/SettingManager.cs @@ -125,7 +125,7 @@ public class SettingManager : ISettingManager, ISingletonDependency if (!providers.Any()) { - return; + throw new AbpException($"Could not find a setting provider named '{providerName}'."); } if (setting.IsEncrypted) diff --git a/modules/setting-management/test/Volo.Abp.SettingManagement.Tests/Volo/Abp/SettingManagement/SettingManager_Basic_Tests.cs b/modules/setting-management/test/Volo.Abp.SettingManagement.Tests/Volo/Abp/SettingManagement/SettingManager_Basic_Tests.cs index 44655c8cb0..00dc337c0f 100644 --- a/modules/setting-management/test/Volo.Abp.SettingManagement.Tests/Volo/Abp/SettingManagement/SettingManager_Basic_Tests.cs +++ b/modules/setting-management/test/Volo.Abp.SettingManagement.Tests/Volo/Abp/SettingManagement/SettingManager_Basic_Tests.cs @@ -63,4 +63,15 @@ public class SettingManager_Basic_Tests : SettingsTestBase (await _settingManager.GetOrNullGlobalAsync("MySetting1")).ShouldBe("43"); (await _settingProvider.GetOrNullAsync("MySetting1")).ShouldBe("43"); } + + [Fact] + public async Task Should_Throw_Exception_If_Provider_Not_Found() + { + var exception = await Assert.ThrowsAsync(async () => + { + await _settingManager.SetAsync("MySetting1", "43", "UndefinedProvider", "UndefinedProviderKey"); + }); + + exception.Message.ShouldBe("Could not find a setting provider named 'UndefinedProvider'."); + } } \ No newline at end of file From dc33781ed7addfcde378ebc2b3370921b4e5d6f3 Mon Sep 17 00:00:00 2001 From: liangshiwei Date: Mon, 22 Jan 2024 17:39:09 +0800 Subject: [PATCH 48/98] SettingValueProvider with duplicate names is not allowed --- .../Settings/SettingValueProviderManager.cs | 16 ++++- .../SettingValueProviderManager_Tests.cs | 64 +++++++++++++++++++ 2 files changed, 79 insertions(+), 1 deletion(-) create mode 100644 framework/test/Volo.Abp.Settings.Tests/Volo/Abp/Settings/SettingValueProviderManager_Tests.cs diff --git a/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingValueProviderManager.cs b/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingValueProviderManager.cs index d0300357dc..c13f884e98 100644 --- a/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingValueProviderManager.cs +++ b/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingValueProviderManager.cs @@ -9,7 +9,8 @@ namespace Volo.Abp.Settings; public class SettingValueProviderManager : ISettingValueProviderManager, ISingletonDependency { - public List Providers => _lazyProviders.Value; + public List Providers => GetProviders(); + protected AbpSettingOptions Options { get; } private readonly Lazy> _lazyProviders; @@ -28,4 +29,17 @@ public class SettingValueProviderManager : ISettingValueProviderManager, ISingle true ); } + + protected virtual List GetProviders() + { + var providers = _lazyProviders.Value; + + var multipleProviders = providers.GroupBy(p => p.Name).FirstOrDefault(x => x.Count() > 1); + if(multipleProviders != null) + { + throw new AbpException($"Duplicate setting value provider name detected: {multipleProviders.Key}. Providers:{Environment.NewLine}{multipleProviders.Select(p => p.GetType().FullName!).JoinAsString(Environment.NewLine)}"); + } + + return providers; + } } diff --git a/framework/test/Volo.Abp.Settings.Tests/Volo/Abp/Settings/SettingValueProviderManager_Tests.cs b/framework/test/Volo.Abp.Settings.Tests/Volo/Abp/Settings/SettingValueProviderManager_Tests.cs new file mode 100644 index 0000000000..93bf26431a --- /dev/null +++ b/framework/test/Volo.Abp.Settings.Tests/Volo/Abp/Settings/SettingValueProviderManager_Tests.cs @@ -0,0 +1,64 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; +using NSubstitute.Extensions; +using Shouldly; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Testing; +using Xunit; + +namespace Volo.Abp.Settings; + +public class SettingValueProviderManager_Tests: AbpIntegratedTest +{ + private readonly ISettingValueProviderManager _settingValueProviderManager; + + public SettingValueProviderManager_Tests() + { + _settingValueProviderManager = GetRequiredService(); + } + + protected override void SetAbpApplicationCreationOptions(AbpApplicationCreationOptions options) + { + options.UseAutofac(); + options.Services.Configure(settingOptions => + { + settingOptions.ValueProviders.Add(); + }); + } + + [Fact] + public void Should_Throw_Exception_If_Duplicate_Provider_Name_Detected() + { + var exception = Assert.Throws(() => + { + var providers = _settingValueProviderManager.Providers; + }); + + exception.Message.ShouldBe($"Duplicate setting value provider name detected: Test. Providers:{Environment.NewLine}Volo.Abp.Settings.Test2SettingValueProvider{Environment.NewLine}Volo.Abp.Settings.TestSettingValueProvider"); + } +} + +public class Test2SettingValueProvider : ISettingValueProvider, ITransientDependency +{ + public const string ProviderName = "Test"; + + + public string Name => ProviderName; + + public Test2SettingValueProvider() + { + } + + public Task GetOrNullAsync(SettingDefinition setting) + { + throw new NotImplementedException(); + } + + public Task> GetAllAsync(SettingDefinition[] settings) + { + throw new NotImplementedException(); + } +} \ No newline at end of file From 64e19acd89ee090f5ae7aedf157e6cad5588143c Mon Sep 17 00:00:00 2001 From: Enis Necipoglu Date: Mon, 22 Jan 2024 13:49:04 +0300 Subject: [PATCH 49/98] Fix parent-selector in create modal --- .../Pages/CmsKit/Menus/MenuItems/CreateModal.cshtml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Menus/MenuItems/CreateModal.cshtml b/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Menus/MenuItems/CreateModal.cshtml index 57d0dca5f1..a79912e51c 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Menus/MenuItems/CreateModal.cshtml +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Menus/MenuItems/CreateModal.cshtml @@ -44,7 +44,7 @@ data-autocomplete-items-property="items" data-autocomplete-filter-param-name="filter" data-autocomplete-allow-clear="true" - data-autocomplete-parent-selector="#menu-create-modal'"> + data-autocomplete-parent-selector="#menu-create-modal"> From 594b644089c07cc51c2807e603652f16f085bf03 Mon Sep 17 00:00:00 2001 From: Enis Necipoglu Date: Mon, 22 Jan 2024 14:16:57 +0300 Subject: [PATCH 50/98] Remove [Required] attribute from MenuItem DTOs --- .../Volo/CmsKit/Admin/Menus/MenuItemCreateInput.cs | 1 - .../Volo/CmsKit/Admin/Menus/MenuItemUpdateInput.cs | 1 - .../Menus/MenuItemAdminAppService_Tests.cs | 1 - 3 files changed, 3 deletions(-) diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Menus/MenuItemCreateInput.cs b/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Menus/MenuItemCreateInput.cs index ebb312699a..f5ec9c6444 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Menus/MenuItemCreateInput.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Menus/MenuItemCreateInput.cs @@ -14,7 +14,6 @@ public class MenuItemCreateInput : ExtensibleObject public bool IsActive { get; set; } - [Required] public string Url { get; set; } public string Icon { get; set; } diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Menus/MenuItemUpdateInput.cs b/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Menus/MenuItemUpdateInput.cs index b51903359c..8767a6192a 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Menus/MenuItemUpdateInput.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Menus/MenuItemUpdateInput.cs @@ -13,7 +13,6 @@ public class MenuItemUpdateInput : ExtensibleObject, IHasConcurrencyStamp public bool IsActive { get; set; } - [Required] public string Url { get; set; } public string Icon { get; set; } diff --git a/modules/cms-kit/test/Volo.CmsKit.Application.Tests/Menus/MenuItemAdminAppService_Tests.cs b/modules/cms-kit/test/Volo.CmsKit.Application.Tests/Menus/MenuItemAdminAppService_Tests.cs index 7dd89ba9d0..d349623c2d 100644 --- a/modules/cms-kit/test/Volo.CmsKit.Application.Tests/Menus/MenuItemAdminAppService_Tests.cs +++ b/modules/cms-kit/test/Volo.CmsKit.Application.Tests/Menus/MenuItemAdminAppService_Tests.cs @@ -49,7 +49,6 @@ public class MenuItemAdminAppService_Tests : CmsKitApplicationTestBase var menu = await MenuAdminAppService.CreateAsync(new MenuItemCreateInput { DisplayName = name, - Url = "#" }); menu.ShouldNotBeNull(); From 9546cdf0d02a0308835d9def1b76a8bfb0de4d99 Mon Sep 17 00:00:00 2001 From: masumulu28 Date: Tue, 23 Jan 2024 11:26:35 +0300 Subject: [PATCH 51/98] remove unused import --- .../packages/theme-shared/src/lib/handlers/error.handler.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/npm/ng-packs/packages/theme-shared/src/lib/handlers/error.handler.ts b/npm/ng-packs/packages/theme-shared/src/lib/handlers/error.handler.ts index 168fef1f53..30f9f7b3cb 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/handlers/error.handler.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/handlers/error.handler.ts @@ -5,7 +5,7 @@ import { filter, switchMap } from 'rxjs/operators'; import { HttpErrorReporterService } from '@abp/ng.core'; -import { CustomHttpErrorHandlerService, HttpErrorHandler } from '../models/common'; +import { CustomHttpErrorHandlerService } from '../models/common'; import { Confirmation } from '../models/confirmation'; import { CUSTOM_ERROR_HANDLERS, HTTP_ERROR_HANDLER } from '../tokens/http-error.token'; From e9b0932bb112b9c8c7151fb070b5a09f866da285 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sinan=20=C3=96zt=C3=BCrk?= Date: Tue, 23 Jan 2024 13:21:43 +0300 Subject: [PATCH 52/98] update localizations --- .../Volo/Abp/FeatureManagement/Localization/Domain/cs.json | 2 +- .../Volo/Abp/FeatureManagement/Localization/Domain/de-DE.json | 2 +- .../Volo/Abp/FeatureManagement/Localization/Domain/de.json | 2 +- .../Volo/Abp/FeatureManagement/Localization/Domain/en-GB.json | 2 +- .../Volo/Abp/FeatureManagement/Localization/Domain/en.json | 2 +- .../Volo/Abp/FeatureManagement/Localization/Domain/es.json | 2 +- .../Volo/Abp/FeatureManagement/Localization/Domain/fi.json | 2 +- .../Volo/Abp/FeatureManagement/Localization/Domain/fr.json | 2 +- .../Volo/Abp/FeatureManagement/Localization/Domain/hr.json | 2 +- .../Volo/Abp/FeatureManagement/Localization/Domain/hu.json | 2 +- .../Volo/Abp/FeatureManagement/Localization/Domain/it.json | 2 +- .../Volo/Abp/FeatureManagement/Localization/Domain/nl.json | 2 +- .../Volo/Abp/FeatureManagement/Localization/Domain/pl-PL.json | 2 +- .../Volo/Abp/FeatureManagement/Localization/Domain/pt-BR.json | 2 +- .../Volo/Abp/FeatureManagement/Localization/Domain/ro-RO.json | 2 +- .../Volo/Abp/FeatureManagement/Localization/Domain/sk.json | 2 +- .../Volo/Abp/FeatureManagement/Localization/Domain/sl.json | 2 +- .../Volo/Abp/FeatureManagement/Localization/Domain/tr.json | 2 +- 18 files changed, 18 insertions(+), 18 deletions(-) diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/cs.json b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/cs.json index ffe5744826..480a67e42a 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/cs.json +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/cs.json @@ -3,7 +3,7 @@ "texts": { "Features": "Funkce", "NoFeatureFoundMessage": "Nejsou zde dostupné žádné funkce.", - "ManageHostFeatures": "Správa funkcí hostitele", + "ManageHostFeatures": "Správa Funkcí Hostitele", "ManageHostFeaturesText": "Funkce na straně hostitele můžete spravovat kliknutím na následující tlačítko.", "Permission:FeatureManagement": "Správa Funkcí", "Permission:FeatureManagement.ManageHostFeatures": "Správa funkcí hostitele", diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/de-DE.json b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/de-DE.json index 0b6d85af5f..5938622c4a 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/de-DE.json +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/de-DE.json @@ -3,7 +3,7 @@ "texts": { "Features": "Features", "NoFeatureFoundMessage": "Es ist kein Feature verfügbar.", - "ManageHostFeatures": "Host-Features verwalten", + "ManageHostFeatures": "Host-Features Verwalten", "Permission:FeatureManagement": "Feature-Verwaltung", "Permission:FeatureManagement.ManageHostFeatures": "Host-Features verwalten", "Volo.Abp.FeatureManagement:InvalidFeatureValue": "{0} Feature-Wert ist ungültig!", diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/de.json b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/de.json index 9a9a5b2338..87d31ff00b 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/de.json +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/de.json @@ -3,7 +3,7 @@ "texts": { "Features": "Funktionen", "NoFeatureFoundMessage": "Es ist keine Funktion verfügbar.", - "ManageHostFeatures": "Hostfunktionen verwalten", + "ManageHostFeatures": "Hostfunktionen Verwalten", "ManageHostFeaturesText": "Sie können die hostseitigen Funktionen verwalten, indem Sie auf die folgende Schaltfläche klicken.", "Permission:FeatureManagement": "Funktionsverwaltung", "Permission:FeatureManagement.ManageHostFeatures": "Hostfunktionen verwalten", diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/en-GB.json b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/en-GB.json index 7888423261..5259b2ef2d 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/en-GB.json +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/en-GB.json @@ -3,8 +3,8 @@ "texts": { "Features": "Features", "NoFeatureFoundMessage": "There isn't any available feature.", - "ManageHostFeatures": "Manage Host features", "Permission:FeatureManagement": "Feature Management", + "ManageHostFeatures": "Manage Host Features", "Permission:FeatureManagement.ManageHostFeatures": "Manage Host features", "Volo.Abp.FeatureManagement:InvalidFeatureValue": "{0} feature value is not valid!", "Menu:FeatureManagement": "Feature Management", diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/en.json b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/en.json index 29e6ec85a1..e222db62b8 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/en.json +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/en.json @@ -3,7 +3,7 @@ "texts": { "Features": "Features", "NoFeatureFoundMessage": "There isn't any available feature.", - "ManageHostFeatures": "Manage Host features", + "ManageHostFeatures": "Manage Host Features", "ManageHostFeaturesText": "You can manage the host side features by clicking the following button.", "Permission:FeatureManagement": "Feature Management", "Permission:FeatureManagement.ManageHostFeatures": "Manage Host features", diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/es.json b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/es.json index 618bd8b128..92e0ca98a7 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/es.json +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/es.json @@ -3,7 +3,7 @@ "texts": { "Features": "Características", "NoFeatureFoundMessage": "No hay ninguna característica disponible.", - "ManageHostFeatures": "Administrar funciones de host", + "ManageHostFeatures": "Administrar Funciones de Host", "ManageHostFeaturesText": "Puede administrar las funciones del lado del host haciendo clic en el siguiente botón.", "Permission:FeatureManagement": "Gestión de Características", "Permission:FeatureManagement.ManageHostFeatures": "Gestionar características del Host", diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/fi.json b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/fi.json index ecf4da045a..c76042de73 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/fi.json +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/fi.json @@ -3,7 +3,7 @@ "texts": { "Features": "Ominaisuudet", "NoFeatureFoundMessage": "Käytettävissä olevia ominaisuuksia ei löydy.", - "ManageHostFeatures": "Hallinnoi isäntäominaisuuksia", + "ManageHostFeatures": "Hallinnoi Isäntä Ominaisuuksia", "ManageHostFeaturesText": "Voit hallita isäntäpuolen ominaisuuksia napsauttamalla seuraavaa painiketta.", "Permission:FeatureManagement": "Ominaisuuden Hallinta", "Permission:FeatureManagement.ManageHostFeatures": "Hallinnoi isäntäominaisuuksia", diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/fr.json b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/fr.json index 9cf4e60352..d381820f3e 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/fr.json +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/fr.json @@ -3,7 +3,7 @@ "texts": { "Features": "Fonctionnalités", "NoFeatureFoundMessage": "Il n'y a aucune fonctionnalité disponible.", - "ManageHostFeatures": "Gérer les fonctionnalités de l’hôte", + "ManageHostFeatures": "Gérer les Fonctionnalités de l’hôte", "ManageHostFeaturesText": "Vous pouvez gérer les fonctionnalités côté hôte en cliquant sur le bouton suivant.", "Permission:FeatureManagement": "Gestion des Fonctionnalités", "Permission:FeatureManagement.ManageHostFeatures": "Gérer les fonctionnalités de l'hôte", diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/hr.json b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/hr.json index 5252d5dbd5..7fad950146 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/hr.json +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/hr.json @@ -3,7 +3,7 @@ "texts": { "Features": "Značajke", "NoFeatureFoundMessage": "Ne postoji nijedna dostupna značajka.", - "ManageHostFeatures": "Upravljanje značajkama domaćina", + "ManageHostFeatures": "Upravljanje Značajkama Domaćina", "ManageHostFeaturesText": "Možete upravljati značajkama strane domaćina klikom na sljedeći gumb.", "Permission:FeatureManagement": "Upravljanje Značajkama", "Permission:FeatureManagement.ManageHostFeatures": "Upravljanje značajkama domaćina", diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/hu.json b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/hu.json index 1a3ceb5fed..e787cf7ec4 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/hu.json +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/hu.json @@ -3,7 +3,7 @@ "texts": { "Features": "Funkciók", "NoFeatureFoundMessage": "Nincs elérhető funkció.", - "ManageHostFeatures": "Host funkciók kezelése", + "ManageHostFeatures": "Host Funkciók Kezelése", "ManageHostFeaturesText": "A gazdaoldali funkciókat a következő gombra kattintva kezelheti.", "Permission:FeatureManagement": "Funkciókezelés", "Permission:FeatureManagement.ManageHostFeatures": "Host funkciók kezelése", diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/it.json b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/it.json index 6ce7b79ec0..669c4d64e9 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/it.json +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/it.json @@ -3,7 +3,7 @@ "texts": { "Features": "Funzionalità", "NoFeatureFoundMessage": "Non ci sono funzioni disponibili.", - "ManageHostFeatures": "Gestisci le funzionalità dell'host", + "ManageHostFeatures": "Gestisci le Funzionalità Dell'host", "ManageHostFeaturesText": "È possibile gestire le funzionalità lato host facendo clic sul pulsante seguente.", "Permission:FeatureManagement": "Gestione Funzionalità", "Permission:FeatureManagement.ManageHostFeatures": "Gestisci le funzionalità dell'host", diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/nl.json b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/nl.json index cb7643ca78..0db4130a7b 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/nl.json +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/nl.json @@ -3,7 +3,7 @@ "texts": { "Features": "Functies", "NoFeatureFoundMessage": "Er is geen functie beschikbaar.", - "ManageHostFeatures": "Beheer host functies", + "ManageHostFeatures": "Beheer Host Functies", "ManageHostFeaturesText": "U kunt de functies aan de hostzijde beheren door op de volgende knop te klikken.", "Permission:FeatureManagement": "Functiebeheer", "Permission:FeatureManagement.ManageHostFeatures": "Beheer host functies", diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/pl-PL.json b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/pl-PL.json index 84b546cc4e..2073ba01c1 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/pl-PL.json +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/pl-PL.json @@ -3,7 +3,7 @@ "texts": { "Features": "Funkcje", "NoFeatureFoundMessage": "Brak dostępnej funkcji.", - "ManageHostFeatures": "Zarządzaj funkcjami hosta", + "ManageHostFeatures": "Zarządzaj Funkcjami Hosta", "ManageHostFeaturesText": "Możesz zarządzać funkcjami po stronie hosta, klikając poniższy przycisk.", "Permission:FeatureManagement": "Zarządzanie Funkcjami", "Permission:FeatureManagement.ManageHostFeatures": "Zarządzaj funkcjami hosta", diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/pt-BR.json b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/pt-BR.json index f9094d19f6..c2e90f0172 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/pt-BR.json +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/pt-BR.json @@ -3,7 +3,7 @@ "texts": { "Features": "Funcionalidades", "NoFeatureFoundMessage": "Não há nenhuma funcionalidade disponivel.", - "ManageHostFeatures": "Gerenciar recursos do Host", + "ManageHostFeatures": "Gerenciar Recursos do Host", "ManageHostFeaturesText": "Você pode gerenciar os recursos do host clicando no botão a seguir.", "Permission:FeatureManagement": "Gerenciamento de Recursos", "Permission:FeatureManagement.ManageHostFeatures": "Gerenciar recursos do Host", diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/ro-RO.json b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/ro-RO.json index b4adea69db..41f9221fbf 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/ro-RO.json +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/ro-RO.json @@ -3,7 +3,7 @@ "texts": { "Features": "Caracteristici", "NoFeatureFoundMessage": "Nu există nicio caracteristică disponibilă.", - "ManageHostFeatures": "Administraţi caracteristicile de host", + "ManageHostFeatures": "Administraţi Caracteristicile de Host", "ManageHostFeaturesText": "Puteți gestiona funcțiile din partea gazdă făcând clic pe următorul buton.", "Permission:FeatureManagement": "Administrare Caracteristici", "Permission:FeatureManagement.ManageHostFeatures": "Gestionare caracteristici gazdă", diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/sk.json b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/sk.json index e384bcba35..d5cc33428f 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/sk.json +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/sk.json @@ -3,7 +3,7 @@ "texts": { "Features": "Funkcie", "NoFeatureFoundMessage": "Nie je k dispozícii žiadna funkcia.", - "ManageHostFeatures": "Spravovať funkcie poskytovateľa", + "ManageHostFeatures": "Spravovať Funkcie Poskytovateľa", "ManageHostFeaturesText": "Funkcie na strane hostiteľa môžete spravovať kliknutím na nasledujúce tlačidlo.", "Permission:FeatureManagement": "Správa Funkcií", "Permission:FeatureManagement.ManageHostFeatures": "Správa funkcií poskytovateľa", diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/sl.json b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/sl.json index 4d6d037b2b..684a1f065c 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/sl.json +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/sl.json @@ -3,7 +3,7 @@ "texts": { "Features": "Funkcionalnosti", "NoFeatureFoundMessage": "Na voljo ni nobene funkcionalnosti.", - "ManageHostFeatures": "Upravljajte funkcije gostitelja", + "ManageHostFeatures": "Upravljajte Funkcije Gostitelja", "ManageHostFeaturesText": "Funkcije gostiteljske strani lahko upravljate s klikom na naslednji gumb.", "Permission:FeatureManagement": "Upravljanje Funkcij", "Permission:FeatureManagement.ManageHostFeatures": "Upravljajte funkcije gostitelja", diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/tr.json b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/tr.json index 936e999af4..44adad1dc3 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/tr.json +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/tr.json @@ -3,7 +3,7 @@ "texts": { "Features": "Özellikler", "NoFeatureFoundMessage": "Hiç özellik yok.", - "ManageHostFeatures": "Host özelliklerini yönetin", + "ManageHostFeatures": "Host Özelliklerini Yönetin", "ManageHostFeaturesText": "Aşağıdaki butona tıklayarak host özelliklerini yönetebilirsiniz.", "Permission:FeatureManagement": "Özellik Yönetimi", "Permission:FeatureManagement.ManageHostFeatures": "Host özelliklerini düzenle", From af1cc0ffbae1a435c409bec1fe9259b39b02f5e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sinan=20=C3=96zt=C3=BCrk?= Date: Tue, 23 Jan 2024 14:39:54 +0300 Subject: [PATCH 53/98] update documentation --- docs/en/UI/Angular/HTTP-Error-Handling.md | 107 ++++++++++++++++++++-- docs/en/UI/Angular/HTTP-Requests.md | 4 + 2 files changed, 105 insertions(+), 6 deletions(-) diff --git a/docs/en/UI/Angular/HTTP-Error-Handling.md b/docs/en/UI/Angular/HTTP-Error-Handling.md index 8bf2589204..1b4de9c38a 100644 --- a/docs/en/UI/Angular/HTTP-Error-Handling.md +++ b/docs/en/UI/Angular/HTTP-Error-Handling.md @@ -4,11 +4,107 @@ When the `RestService` is used, all HTTP errors are reported to the [`HttpErrorR ## Custom HTTP Error Handler -A custom HTTP error handler service can be registered to an injection token named **`CUSTOM_ERROR_HANDLERS`**. ABP has some default error handlers, you can see them [here](https://github.com/abpframework/abp/blob/dev/npm/ng-packs/packages/theme-shared/src/lib/providers/error-handlers.provider.ts). +### (Deprecated!) Function Method; -### How ABP handles errors and How to add new one? +A custom HTTP error handler can be registered to an injection token named `HTTP_ERROR_HANDLER`. If a custom handler function is registered, the `ErrorHandler` executes that function. + +See an example: + +```ts +// http-error-handler.ts +import { ContentProjectionService, PROJECTION_STRATEGY } from '@abp/ng.core'; +import { ToasterService } from '@abp/ng.theme.shared'; +import { HttpErrorResponse } from '@angular/common/http'; +import { Injector } from '@angular/core'; +import { of, EMPTY } from 'rxjs'; +import { Error404Component } from './error404/error404.component'; + +export function handleHttpErrors(injector: Injector, httpError: HttpErrorResponse) { + if (httpError.status === 400) { + const toaster = injector.get(ToasterService); + toaster.error(httpError.error?.error?.message || 'Bad request!', '400'); + return EMPTY; + } + + if (httpError.status === 404) { + const contentProjection = injector.get(ContentProjectionService); + contentProjection.projectContent(PROJECTION_STRATEGY.AppendComponentToBody(Error404Component)); + return EMPTY; + } + + return of(httpError); +} + +// app.module.ts +import { Error404Component } from './error404/error404.component'; +import { handleHttpErrors } from './http-error-handling'; +import { HTTP_ERROR_HANDLER, ... } from '@abp/ng.theme.shared'; + +@NgModule({ + // ... + providers: [ + // ... + { provide: HTTP_ERROR_HANDLER, useValue: handleHttpErrors } + ], + declarations: [ + //... + Error404Component], +}) +export class AppModule {} +``` + +In the example above: + +- Created a function named `handleHttpErrors` and defined as value of the `HTTP_ERROR_HANDLER` provider in app.module. After this, the function executes when an HTTP error occurs. +- 400 bad request errors is handled. When a 400 error occurs. + +- Since `of(httpError)` is returned at bottom of the `handleHttpErrors`, the `ErrorHandler` will handle the HTTP errors except 400 and 404 errors. + +**Note 1:** If you put `return EMPTY` to next line of handling an error, default error handling will not work for that error. [EMPTY](https://rxjs.dev/api/index/const/EMPTY) can be imported from `rxjs`. + +```ts +export function handleHttpErrors( + injector: Injector, + httpError: HttpErrorResponse +) { + if (httpError.status === 403) { + // handle 403 errors here + return EMPTY; // put return EMPTY to skip default error handling + } +} +``` + +**Note 2:** If you put `return of(httpError)`, default error handling will work. + +- `of` is a function. It can be imported from `rxjs`. +- `httpError` is the second parameter of the error handler function which is registered to the `HTTP_ERROR_HANDLER` provider. Type of the `httpError` is `HttpErrorResponse`. + +```ts +import { of } from "rxjs"; + +export function handleHttpErrors( + injector: Injector, + httpError: HttpErrorResponse +) { + if (httpError.status === 500) { + // handle 500 errors here + } + + // you can return the of(httpError) at bottom of the function to run the default handler of ABP for HTTP errors that you didn't handle above. + return of(httpError); +} +``` + +### Service Method; + +With Services you can provide **more than one handler**. + +A custom HTTP error handler service can be registered to an injection token named **`CUSTOM_ERROR_HANDLERS`**. + +ABP has some default error handlers, you can see them [here](https://github.com/abpframework/abp/blob/dev/npm/ng-packs/packages/theme-shared/src/lib/providers/error-handlers.provider.ts). + +### How To Add New Handler Service? -- First of all it will be better to understand how ABP handles errors. - ABP error handler services are implements the interface of **CustomHttpErrorHandlerService**. **Interface of `CUSTOM_ERROR_HANDLERS`** @@ -25,7 +121,7 @@ interface CustomHttpErrorHandlerService { - **`canHandle(error: unknown): boolean :`** Check if the service can handle the error. Returns boolean. - **`execute(): void :`** If the service can handle the error, then run the execute method. -**In Summarry** +**In Summary** - Services are sorted by their priority number. - Start from highest priority service and run canHandle() method. Pick the service if can handle the error, if not check next service. @@ -45,9 +141,8 @@ import { ToasterService } from "@abp/ng.theme.shared"; export class MyCustomErrorHandlerService implements CustomHttpErrorHandlerService { - // You can write any number here, ex: 9999 - readonly priority = CUSTOM_HTTP_ERROR_HANDLER_PRIORITY.veryHigh; + readonly priority = CUSTOM_HTTP_ERROR_HANDLER_PRIORITY.veryHigh; private toaster = inject(ToasterService); private error: HttpErrorResponse | undefined = undefined; diff --git a/docs/en/UI/Angular/HTTP-Requests.md b/docs/en/UI/Angular/HTTP-Requests.md index c58e35fc51..9bef5cb8f2 100644 --- a/docs/en/UI/Angular/HTTP-Requests.md +++ b/docs/en/UI/Angular/HTTP-Requests.md @@ -184,3 +184,7 @@ The `ExternalHttpClient` extends from `HTTPClient` and sets the `IS_EXTERNAL_REQ When you are using `ExternalHttpClient` as HttpClient in your components, it does not add ABP-specific headers. Note: With `IS_EXTERNAL_REQUEST` or without it, ABP loading service works. + +## See Also + +- [HTTP Error Handling / Customization](./HTTP-Error-Handling) From 8b2c5693dedf06ec14822ed27656910ed7a248c3 Mon Sep 17 00:00:00 2001 From: Mark Cilia Vincenti Date: Tue, 23 Jan 2024 13:02:58 +0100 Subject: [PATCH 54/98] Bump AsyncKeyedLock to 6.3.4; performance improvement --- Directory.Packages.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index 6842c542ce..3a2a7b5aaa 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -6,7 +6,7 @@ - + From d3d7e1bd761ebad3f2bae35108a45ef35669c321 Mon Sep 17 00:00:00 2001 From: Enis Necipoglu Date: Tue, 23 Jan 2024 15:03:08 +0300 Subject: [PATCH 55/98] Add test-case for related page title --- .../Menus/MenuItemAdminAppService_Tests.cs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/modules/cms-kit/test/Volo.CmsKit.Application.Tests/Menus/MenuItemAdminAppService_Tests.cs b/modules/cms-kit/test/Volo.CmsKit.Application.Tests/Menus/MenuItemAdminAppService_Tests.cs index d349623c2d..28e2c8b087 100644 --- a/modules/cms-kit/test/Volo.CmsKit.Application.Tests/Menus/MenuItemAdminAppService_Tests.cs +++ b/modules/cms-kit/test/Volo.CmsKit.Application.Tests/Menus/MenuItemAdminAppService_Tests.cs @@ -32,6 +32,15 @@ public class MenuItemAdminAppService_Tests : CmsKitApplicationTestBase menu.ShouldNotBeNull(); } + [Fact] + public async Task GetAsync_PageTitleShouldBeCorrect_WithRelatedPage() + { + var menu = await MenuAdminAppService.GetAsync(TestData.MenuItem_4_With_Page_1_Id); + + menu.ShouldNotBeNull(); + menu.PageTitle.ShouldBe(TestData.Page_1_Title); + } + [Fact] public async Task GetListAsync_ShouldWorkProperly() { From 2184b532c5881c48fd756a574d7f9aa29b8f8c73 Mon Sep 17 00:00:00 2001 From: Enis Necipoglu Date: Tue, 23 Jan 2024 15:03:29 +0300 Subject: [PATCH 56/98] Fix FindTitleAsync return type --- .../Volo/CmsKit/MongoDB/Pages/MongoPageRepository.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Pages/MongoPageRepository.cs b/modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Pages/MongoPageRepository.cs index 565530fcb7..1b49ac48bb 100644 --- a/modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Pages/MongoPageRepository.cs +++ b/modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Pages/MongoPageRepository.cs @@ -77,7 +77,7 @@ public class MongoPageRepository : MongoDbRepository x.IsHomePage, cancellationToken: GetCancellationToken(cancellationToken)); } - public async Task FindTitleAsync(Guid pageId, CancellationToken cancellationToken = default) + public async Task FindTitleAsync(Guid pageId, CancellationToken cancellationToken = default) { return await (await GetMongoQueryableAsync(cancellationToken)).Where(x => x.Id == pageId).Select(x => x.Title) .FirstOrDefaultAsync(cancellationToken); From 39eeba55e588a8594e53c6db4c587f50cbf0bd45 Mon Sep 17 00:00:00 2001 From: Enis Necipoglu Date: Tue, 23 Jan 2024 15:26:55 +0300 Subject: [PATCH 57/98] Use outline variation for Cancel in Modals --- .../TagHelpers/Modal/AbpModalFooterTagHelperService.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Modal/AbpModalFooterTagHelperService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Modal/AbpModalFooterTagHelperService.cs index 671b00e094..8b46f6e78c 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Modal/AbpModalFooterTagHelperService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Modal/AbpModalFooterTagHelperService.cs @@ -90,13 +90,13 @@ public class AbpModalFooterTagHelperService : AbpTagHelperService Date: Tue, 23 Jan 2024 16:00:12 +0300 Subject: [PATCH 58/98] use outline variation for sweetalert modals --- .../sweetalert2/abp-sweetalert2.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/sweetalert2/abp-sweetalert2.js b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/sweetalert2/abp-sweetalert2.js index 51c7db5cd9..44ef812995 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/sweetalert2/abp-sweetalert2.js +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/sweetalert2/abp-sweetalert2.js @@ -103,6 +103,13 @@ var abp = abp || {}; abp.libs.sweetAlert.config.default.confirmButtonText = l('Ok'); abp.libs.sweetAlert.config.default.denyButtonText = l('No'); abp.libs.sweetAlert.config.default.cancelButtonText = l('Cancel'); + abp.libs.sweetAlert.config.default.buttonsStyling = false; + abp.libs.sweetAlert.config.default.customClass = { + confirmButton: "btn btn-primary", + cancelButton: "btn btn-outline-primary me-1", + denyButton: "btn btn-outline-primary me-1" + }; + abp.libs.sweetAlert.config.confirm.title = l('AreYouSure'); abp.libs.sweetAlert.config.confirm.confirmButtonText = l('Yes'); abp.libs.sweetAlert.config.confirm.showCancelButton = true; From a240717e4c1f74bb0ed7f66ec73b09068b678514 Mon Sep 17 00:00:00 2001 From: Enis Necipoglu Date: Tue, 23 Jan 2024 16:10:51 +0300 Subject: [PATCH 59/98] Update Default.cshtml --- .../Components/EmailSettingGroup/Default.cshtml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.Web/Pages/SettingManagement/Components/EmailSettingGroup/Default.cshtml b/modules/setting-management/src/Volo.Abp.SettingManagement.Web/Pages/SettingManagement/Components/EmailSettingGroup/Default.cshtml index f653ec54a0..61d4dbe996 100644 --- a/modules/setting-management/src/Volo.Abp.SettingManagement.Web/Pages/SettingManagement/Components/EmailSettingGroup/Default.cshtml +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.Web/Pages/SettingManagement/Components/EmailSettingGroup/Default.cshtml @@ -31,7 +31,7 @@ @if (await PermissionChecker.IsGrantedAsync(SettingManagementPermissions.EmailingTest)) { - + @L["SendTestEmail"] } From c95dbaac17bbf6e8b6a7daed85f8ead66b09e922 Mon Sep 17 00:00:00 2001 From: Enis Necipoglu Date: Tue, 23 Jan 2024 16:30:49 +0300 Subject: [PATCH 60/98] Update abp-sweetalert2.js --- .../sweetalert2/abp-sweetalert2.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/sweetalert2/abp-sweetalert2.js b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/sweetalert2/abp-sweetalert2.js index 44ef812995..4a11feeda2 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/sweetalert2/abp-sweetalert2.js +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/sweetalert2/abp-sweetalert2.js @@ -106,8 +106,8 @@ var abp = abp || {}; abp.libs.sweetAlert.config.default.buttonsStyling = false; abp.libs.sweetAlert.config.default.customClass = { confirmButton: "btn btn-primary", - cancelButton: "btn btn-outline-primary me-1", - denyButton: "btn btn-outline-primary me-1" + cancelButton: "btn btn-outline-primary mx-2", + denyButton: "btn btn-outline-primary mx-2" }; abp.libs.sweetAlert.config.confirm.title = l('AreYouSure'); From 6d33639fec8f3540997142837afa5471992c3ace Mon Sep 17 00:00:00 2001 From: denizdemirkan Date: Tue, 23 Jan 2024 17:16:26 +0300 Subject: [PATCH 61/98] Update Getting-Started-Running-Solution.md --- docs/en/Getting-Started-Running-Solution.md | 33 +++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/docs/en/Getting-Started-Running-Solution.md b/docs/en/Getting-Started-Running-Solution.md index 921fb2b247..d71c0a64da 100644 --- a/docs/en/Getting-Started-Running-Solution.md +++ b/docs/en/Getting-Started-Running-Solution.md @@ -127,6 +127,29 @@ abp bundle > **Note**: Before starting the application, run `abp install-libs` command in your Web directory to restore the client-side libraries. This will populate the `libs` folder. +{{ if UI == "BlazorServer" }} + +> **Important:** The `.AuthServer` application serves as the **Authentication Server** for the `.Blazor` application. It is essential to have the `.AuthServer` application running in the background to ensure the proper functioning of the `.Blazor` application. + +To do this, open terminal in `.AuthServer` project folder and run the following command. + +````bash +dotnet run +```` + +Once the `.AuthServer`application has started, it is time to run `.HttpApi.Host` application. + +> **Important:** Prior to launching the `.Blazor` project, it is essential to execute the `.HttpApi.Host` application as well. + +To do this, open terminal in `.HttpApi.Host` project folder and run the following command. + +````bash +dotnet run +```` +Once the `.AuthServer` and `.HttpApi.Host` applications has started, you can proceed to run the `.Blazor` project. + +{{ end # UI }} + {{ if Tiered == "Yes" }} > Tiered solutions use **Redis** as the distributed cache. Ensure that it is installed and running in your local computer. If you are using a remote Redis Server, set the configuration in the `appsettings.json` files of the projects below. @@ -195,6 +218,16 @@ You can see the application APIs and test them here. Get [more info](https://swa ### Running the Blazor Application (Client Side) +> **Important:** The `.HttpApi.Host` application serves as the **Authentication Server** for the `.Blazor` application. It is essential to have the `.HttpApi.Host` application running in the background to ensure the proper functioning of the `.Blazor` application. + +To do this, you can open terminal in `.HttpApi.Host` project folder and run the following command. + +````bash +dotnet run +```` + +Once the `.HttpApi.Host` application has started, you can proceed to run the `.Blazor` application. + Ensure that the `.Blazor` project is the startup project and run the application. > Use Ctrl+F5 in Visual Studio (instead of F5) to run the application without debugging. If you don't have a debug purpose, this will be faster. From 45e9a0da2df2a0bbf5dc7564fc08fa02782d0175 Mon Sep 17 00:00:00 2001 From: liangshiwei Date: Wed, 24 Jan 2024 11:20:45 +0800 Subject: [PATCH 62/98] FeatureValueProvider and PermissionValueProvider with duplicate names is not allowed --- .../PermissionValueProviderManager.cs | 15 ++++- .../Volo/Abp/Features/FeatureChecker.cs | 20 ++----- .../Features/FeatureValueProviderManager.cs | 44 ++++++++++++++ .../Features/IFeatureValueProviderManager.cs | 8 +++ .../PermissionValueProviderManager_Tests.cs | 59 +++++++++++++++++++ .../FeatureValueProviderManager_Tests.cs | 54 +++++++++++++++++ .../SettingValueProviderManager_Tests.cs | 10 ++-- 7 files changed, 189 insertions(+), 21 deletions(-) create mode 100644 framework/src/Volo.Abp.Features/Volo/Abp/Features/FeatureValueProviderManager.cs create mode 100644 framework/src/Volo.Abp.Features/Volo/Abp/Features/IFeatureValueProviderManager.cs create mode 100644 framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/PermissionValueProviderManager_Tests.cs create mode 100644 framework/test/Volo.Abp.Features.Tests/Volo/Abp/Features/FeatureValueProviderManager_Tests.cs diff --git a/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/PermissionValueProviderManager.cs b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/PermissionValueProviderManager.cs index 84d0ad0b2c..09b2da2acb 100644 --- a/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/PermissionValueProviderManager.cs +++ b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/PermissionValueProviderManager.cs @@ -9,7 +9,7 @@ namespace Volo.Abp.Authorization.Permissions; public class PermissionValueProviderManager : IPermissionValueProviderManager, ISingletonDependency { - public IReadOnlyList ValueProviders => _lazyProviders.Value; + public IReadOnlyList ValueProviders => GetProviders(); private readonly Lazy> _lazyProviders; protected AbpPermissionOptions Options { get; } @@ -28,4 +28,17 @@ public class PermissionValueProviderManager : IPermissionValueProviderManager, I true ); } + + protected virtual List GetProviders() + { + var providers = _lazyProviders.Value; + + var multipleProviders = providers.GroupBy(p => p.Name).FirstOrDefault(x => x.Count() > 1); + if(multipleProviders != null) + { + throw new AbpException($"Duplicate permission value provider name detected: {multipleProviders.Key}. Providers:{Environment.NewLine}{multipleProviders.Select(p => p.GetType().FullName!).JoinAsString(Environment.NewLine)}"); + } + + return providers; + } } diff --git a/framework/src/Volo.Abp.Features/Volo/Abp/Features/FeatureChecker.cs b/framework/src/Volo.Abp.Features/Volo/Abp/Features/FeatureChecker.cs index c2a4a71ab3..66e145563d 100644 --- a/framework/src/Volo.Abp.Features/Volo/Abp/Features/FeatureChecker.cs +++ b/framework/src/Volo.Abp.Features/Volo/Abp/Features/FeatureChecker.cs @@ -12,34 +12,26 @@ public class FeatureChecker : FeatureCheckerBase protected AbpFeatureOptions Options { get; } protected IServiceProvider ServiceProvider { get; } protected IFeatureDefinitionManager FeatureDefinitionManager { get; } - protected List Providers => _providers.Value; - - private readonly Lazy> _providers; + protected IFeatureValueProviderManager FeatureValueProviderManager { get; } public FeatureChecker( IOptions options, IServiceProvider serviceProvider, - IFeatureDefinitionManager featureDefinitionManager) + IFeatureDefinitionManager featureDefinitionManager, + IFeatureValueProviderManager featureValueProviderManager) { ServiceProvider = serviceProvider; FeatureDefinitionManager = featureDefinitionManager; + FeatureValueProviderManager = featureValueProviderManager; Options = options.Value; - - _providers = new Lazy>( - () => Options - .ValueProviders - .Select(type => (ServiceProvider.GetRequiredService(type) as IFeatureValueProvider)!) - .ToList(), - true - ); } public override async Task GetOrNullAsync(string name) { var featureDefinition = await FeatureDefinitionManager.GetAsync(name); - var providers = Enumerable - .Reverse(Providers); + var providers = FeatureValueProviderManager.ValueProviders + .Reverse(); if (featureDefinition.AllowedProviders.Any()) { diff --git a/framework/src/Volo.Abp.Features/Volo/Abp/Features/FeatureValueProviderManager.cs b/framework/src/Volo.Abp.Features/Volo/Abp/Features/FeatureValueProviderManager.cs new file mode 100644 index 0000000000..98d73dd4e4 --- /dev/null +++ b/framework/src/Volo.Abp.Features/Volo/Abp/Features/FeatureValueProviderManager.cs @@ -0,0 +1,44 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.Features; + +public class FeatureValueProviderManager : IFeatureValueProviderManager, ISingletonDependency +{ + public IReadOnlyList ValueProviders => GetProviders(); + private readonly Lazy> _lazyProviders; + + protected AbpFeatureOptions Options { get; } + + public FeatureValueProviderManager( + IServiceProvider serviceProvider, + IOptions options) + { + Options = options.Value; + + _lazyProviders = new Lazy>( + () => Options + .ValueProviders + .Select(c => serviceProvider.GetRequiredService(c) as IFeatureValueProvider) + .ToList()!, + true + ); + } + + protected virtual List GetProviders() + { + var providers = _lazyProviders.Value; + + var multipleProviders = providers.GroupBy(p => p.Name).FirstOrDefault(x => x.Count() > 1); + if(multipleProviders != null) + { + throw new AbpException($"Duplicate feature value provider name detected: {multipleProviders.Key}. Providers:{Environment.NewLine}{multipleProviders.Select(p => p.GetType().FullName!).JoinAsString(Environment.NewLine)}"); + } + + return providers; + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.Features/Volo/Abp/Features/IFeatureValueProviderManager.cs b/framework/src/Volo.Abp.Features/Volo/Abp/Features/IFeatureValueProviderManager.cs new file mode 100644 index 0000000000..56de662a99 --- /dev/null +++ b/framework/src/Volo.Abp.Features/Volo/Abp/Features/IFeatureValueProviderManager.cs @@ -0,0 +1,8 @@ +using System.Collections.Generic; + +namespace Volo.Abp.Features; + +public interface IFeatureValueProviderManager +{ + IReadOnlyList ValueProviders { get; } +} \ No newline at end of file diff --git a/framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/PermissionValueProviderManager_Tests.cs b/framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/PermissionValueProviderManager_Tests.cs new file mode 100644 index 0000000000..d4af25ad3a --- /dev/null +++ b/framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/PermissionValueProviderManager_Tests.cs @@ -0,0 +1,59 @@ +using System; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; +using Shouldly; +using Volo.Abp.Authorization; +using Volo.Abp.Authorization.Permissions; +using Volo.Abp.Authorization.TestServices; +using Xunit; + +namespace Volo.Abp; + +public class PermissionValueProviderManager_Tests: AuthorizationTestBase +{ + private readonly IPermissionValueProviderManager _permissionValueProviderManager; + + public PermissionValueProviderManager_Tests() + { + _permissionValueProviderManager = GetRequiredService(); + } + + protected override void SetAbpApplicationCreationOptions(AbpApplicationCreationOptions options) + { + options.Services.Configure(permissionOptions => + { + permissionOptions.ValueProviders.Add(); + }); + } + + [Fact] + public void Should_Throw_Exception_If_Duplicate_Provider_Name_Detected() + { + var exception = Assert.Throws(() => + { + var providers = _permissionValueProviderManager.ValueProviders; + }); + + exception.Message.ShouldBe($"Duplicate permission value provider name detected: TestPermissionValueProvider1. Providers:{Environment.NewLine}{typeof(TestDuplicatePermissionValueProvider).FullName}{Environment.NewLine}{typeof(TestPermissionValueProvider1).FullName}"); + } +} + +public class TestDuplicatePermissionValueProvider : PermissionValueProvider +{ + public TestDuplicatePermissionValueProvider(IPermissionStore permissionStore) : base(permissionStore) + { + } + + public override string Name => "TestPermissionValueProvider1"; + + public override Task CheckAsync(PermissionValueCheckContext context) + { + throw new NotImplementedException(); + } + + public override Task CheckAsync(PermissionValuesCheckContext context) + { + throw new NotImplementedException(); + } +} \ No newline at end of file diff --git a/framework/test/Volo.Abp.Features.Tests/Volo/Abp/Features/FeatureValueProviderManager_Tests.cs b/framework/test/Volo.Abp.Features.Tests/Volo/Abp/Features/FeatureValueProviderManager_Tests.cs new file mode 100644 index 0000000000..7e73ef65fc --- /dev/null +++ b/framework/test/Volo.Abp.Features.Tests/Volo/Abp/Features/FeatureValueProviderManager_Tests.cs @@ -0,0 +1,54 @@ +using System; +using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; +using Shouldly; +using Xunit; + +namespace Volo.Abp.Features; + +public class FeatureValueProviderManager_Tests : FeatureTestBase +{ + private readonly IFeatureValueProviderManager _featureValueProviderManager; + + public FeatureValueProviderManager_Tests() + { + _featureValueProviderManager = GetRequiredService(); + } + + protected override void SetAbpApplicationCreationOptions(AbpApplicationCreationOptions options) + { + options.Services.Configure(permissionOptions => + { + permissionOptions.ValueProviders.Add(); + }); + } + + [Fact] + public void Should_Throw_Exception_If_Duplicate_Provider_Name_Detected() + { + var exception = Assert.Throws(() => + { + var providers = _featureValueProviderManager.ValueProviders; + }); + + exception.Message.ShouldBe($"Duplicate feature value provider name detected: {TestDuplicateFeatureValueProvider.ProviderName}. Providers:{Environment.NewLine}{typeof(TestDuplicateFeatureValueProvider).FullName}{Environment.NewLine}{typeof(DefaultValueFeatureValueProvider).FullName}"); + } +} + +public class TestDuplicateFeatureValueProvider : FeatureValueProvider +{ + public const string ProviderName = "D"; + + public override string Name => ProviderName; + + public TestDuplicateFeatureValueProvider(IFeatureStore settingStore) + : base(settingStore) + { + + } + + public override Task GetOrNullAsync(FeatureDefinition setting) + { + throw new NotImplementedException(); + } +} \ No newline at end of file diff --git a/framework/test/Volo.Abp.Settings.Tests/Volo/Abp/Settings/SettingValueProviderManager_Tests.cs b/framework/test/Volo.Abp.Settings.Tests/Volo/Abp/Settings/SettingValueProviderManager_Tests.cs index 93bf26431a..f85e465d8e 100644 --- a/framework/test/Volo.Abp.Settings.Tests/Volo/Abp/Settings/SettingValueProviderManager_Tests.cs +++ b/framework/test/Volo.Abp.Settings.Tests/Volo/Abp/Settings/SettingValueProviderManager_Tests.cs @@ -1,9 +1,7 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Threading.Tasks; using Microsoft.Extensions.DependencyInjection; -using NSubstitute.Extensions; using Shouldly; using Volo.Abp.DependencyInjection; using Volo.Abp.Testing; @@ -25,7 +23,7 @@ public class SettingValueProviderManager_Tests: AbpIntegratedTest(settingOptions => { - settingOptions.ValueProviders.Add(); + settingOptions.ValueProviders.Add(); }); } @@ -37,18 +35,18 @@ public class SettingValueProviderManager_Tests: AbpIntegratedTest ProviderName; - public Test2SettingValueProvider() + public TestDuplicateSettingValueProvider() { } From 08adcc5c8c441e3896c9d04caacbf64e819b7920 Mon Sep 17 00:00:00 2001 From: Masum ULU <49063256+masumulu28@users.noreply.github.com> Date: Wed, 24 Jan 2024 08:58:40 +0300 Subject: [PATCH 63/98] Update HTTP-Error-Handling.md --- docs/en/UI/Angular/HTTP-Error-Handling.md | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/docs/en/UI/Angular/HTTP-Error-Handling.md b/docs/en/UI/Angular/HTTP-Error-Handling.md index 1b4de9c38a..e657f5c773 100644 --- a/docs/en/UI/Angular/HTTP-Error-Handling.md +++ b/docs/en/UI/Angular/HTTP-Error-Handling.md @@ -138,12 +138,11 @@ import { CUSTOM_HTTP_ERROR_HANDLER_PRIORITY } from "@abp/ng.theme.shared"; import { ToasterService } from "@abp/ng.theme.shared"; @Injectable({ providedIn: "root" }) -export class MyCustomErrorHandlerService - implements CustomHttpErrorHandlerService +export class MyCustomErrorHandlerService implements CustomHttpErrorHandlerService { // You can write any number here, ex: 9999 readonly priority = CUSTOM_HTTP_ERROR_HANDLER_PRIORITY.veryHigh; - private toaster = inject(ToasterService); + protected readonly toaster = inject(ToasterService); private error: HttpErrorResponse | undefined = undefined; // What kind of error should be handled by this service? You can decide it in this method. If error is suitable to your case then return true; otherwise return false. @@ -175,7 +174,11 @@ import { MyCustomErrorHandlerService } from './custom-error-handler.service'; // ... providers: [ // ... - { provide: CUSTOM_ERROR_HANDLERS, useExisting: MyCustomErrorHandlerService, multi: true } + { + provide: CUSTOM_ERROR_HANDLERS, + useExisting: MyCustomErrorHandlerService, + multi: true, + } ] }) export class AppModule {} From 9851f671b29da7fdbb7548e20f603c93a33a061b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sinan=20=C3=96zt=C3=BCrk?= Date: Wed, 24 Jan 2024 10:13:19 +0300 Subject: [PATCH 64/98] update document according to reviever comments --- docs/en/UI/Angular/HTTP-Error-Handling.md | 31 ++++++++++++----------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/docs/en/UI/Angular/HTTP-Error-Handling.md b/docs/en/UI/Angular/HTTP-Error-Handling.md index e657f5c773..d2e873aa63 100644 --- a/docs/en/UI/Angular/HTTP-Error-Handling.md +++ b/docs/en/UI/Angular/HTTP-Error-Handling.md @@ -4,7 +4,7 @@ When the `RestService` is used, all HTTP errors are reported to the [`HttpErrorR ## Custom HTTP Error Handler -### (Deprecated!) Function Method; +### Function Method `Deprecated` A custom HTTP error handler can be registered to an injection token named `HTTP_ERROR_HANDLER`. If a custom handler function is registered, the `ErrorHandler` executes that function. @@ -95,17 +95,15 @@ export function handleHttpErrors( } ``` -### Service Method; +### Service Method With Services you can provide **more than one handler**. -A custom HTTP error handler service can be registered to an injection token named **`CUSTOM_ERROR_HANDLERS`**. +A custom HTTP error handler service can be registered to an injection token named **`CUSTOM_ERROR_HANDLERS`**. ABP has some default [error handlers](https://github.com/abpframework/abp/blob/dev/npm/ng-packs/packages/theme-shared/src/lib/providers/error-handlers.provider.ts). -ABP has some default error handlers, you can see them [here](https://github.com/abpframework/abp/blob/dev/npm/ng-packs/packages/theme-shared/src/lib/providers/error-handlers.provider.ts). +### How To Add New Handler Service -### How To Add New Handler Service? - -- ABP error handler services are implements the interface of **CustomHttpErrorHandlerService**. +ABP error handler services are implements the interface of **CustomHttpErrorHandlerService**. **Interface of `CUSTOM_ERROR_HANDLERS`** @@ -117,9 +115,9 @@ interface CustomHttpErrorHandlerService { } ``` -- **`priority`** ABP sorts the services according to the number of the priority variable. Higher priority will be checked first. You can think this as a z-index property in CSS. -- **`canHandle(error: unknown): boolean :`** Check if the service can handle the error. Returns boolean. -- **`execute(): void :`** If the service can handle the error, then run the execute method. +- **`priority`** ABP sorts the services according to the number of the priority variable. Higher priority will be checked first. +- **`canHandle`** Check if the service can handle the error. Returns boolean. +- **`execute`** If the service can handle the error, then run the execute method. **In Summary** @@ -138,7 +136,8 @@ import { CUSTOM_HTTP_ERROR_HANDLER_PRIORITY } from "@abp/ng.theme.shared"; import { ToasterService } from "@abp/ng.theme.shared"; @Injectable({ providedIn: "root" }) -export class MyCustomErrorHandlerService implements CustomHttpErrorHandlerService +export class MyCustomErrorHandlerService + implements CustomHttpErrorHandlerService { // You can write any number here, ex: 9999 readonly priority = CUSTOM_HTTP_ERROR_HANDLER_PRIORITY.veryHigh; @@ -192,7 +191,9 @@ In the example above: ![custom-error-handler-toaster-message](images/custom-error-handler-toaster-message.jpg) -**Note 1:** If your service cannot handle the error. Then ABP will check the next Error Service. -**Note 2:** If none of the service handle the error. Then basic confirmation message about the error will be shown to the user. -**Note 3:** You can provide more than one service, with CUSTOM_ERROR_HANDLER injection token. -**Note 4:** If you want your custom service to be evaluated (checked) earlier, set the priority variable high. +### Notes + +- If your service cannot handle the error. Then ABP will check the next Error Service. +- If none of the service handle the error. Then basic confirmation message about the error will be shown to the user. +- You can provide more than one service, with CUSTOM_ERROR_HANDLER injection token. +- If you want your custom service to be evaluated (checked) earlier, set the priority variable high. From 20b7151d447e69aaa5944bddbc0842c5207fbd52 Mon Sep 17 00:00:00 2001 From: Masum ULU <49063256+masumulu28@users.noreply.github.com> Date: Wed, 24 Jan 2024 10:45:37 +0300 Subject: [PATCH 65/98] Minor changes applied --- docs/en/UI/Angular/HTTP-Error-Handling.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/docs/en/UI/Angular/HTTP-Error-Handling.md b/docs/en/UI/Angular/HTTP-Error-Handling.md index d2e873aa63..606211bfeb 100644 --- a/docs/en/UI/Angular/HTTP-Error-Handling.md +++ b/docs/en/UI/Angular/HTTP-Error-Handling.md @@ -97,9 +97,7 @@ export function handleHttpErrors( ### Service Method -With Services you can provide **more than one handler**. - -A custom HTTP error handler service can be registered to an injection token named **`CUSTOM_ERROR_HANDLERS`**. ABP has some default [error handlers](https://github.com/abpframework/abp/blob/dev/npm/ng-packs/packages/theme-shared/src/lib/providers/error-handlers.provider.ts). +You can provide **more than one handler** with services, a custom HTTP error handler service can be registered with injection token named **`CUSTOM_ERROR_HANDLERS`**. ABP has some default [error handlers](https://github.com/abpframework/abp/blob/dev/npm/ng-packs/packages/theme-shared/src/lib/providers/error-handlers.provider.ts). ### How To Add New Handler Service From c43adeadfc148952cb08a609daeb2510a2c6b3c5 Mon Sep 17 00:00:00 2001 From: liangshiwei Date: Wed, 24 Jan 2024 15:46:10 +0800 Subject: [PATCH 66/98] Update Devart.Data.Oracle.EFCore to 10.3.10.8 --- Directory.Packages.props | 2 +- docs/en/Migration-Guides/Abp-8_0.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index 4b265264c4..6a76d2d8c7 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -26,7 +26,7 @@ - + diff --git a/docs/en/Migration-Guides/Abp-8_0.md b/docs/en/Migration-Guides/Abp-8_0.md index 8214dfef1a..09e44b7ec8 100644 --- a/docs/en/Migration-Guides/Abp-8_0.md +++ b/docs/en/Migration-Guides/Abp-8_0.md @@ -181,7 +181,7 @@ You can see the following list of NuGet libraries that have been upgraded with . | Dapper | 2.0.123 | 2.1.21 | | Dapr.AspNetCore | 1.9.0 | 1.12.0 | | Dapr.Client | 1.9.0 | 1.12.0 | -| Devart.Data.Oracle.EFCore | 10.1.134.7 | 10.1.151.7 | +| Devart.Data.Oracle.EFCore | 10.1.134.7 | 10.3.10.8 | | DistributedLock.Core | 1.0.4 | 1.0.5 | | DistributedLock.Redis | 1.0.1 | 1.0.2 | | EphemeralMongo.Core | 1.1.0 | 1.1.3 | From da59ccbeebc8022c2334283de59272fe4dbfb9df Mon Sep 17 00:00:00 2001 From: liangshiwei Date: Wed, 24 Jan 2024 15:53:20 +0800 Subject: [PATCH 67/98] Update Volo.Abp.EntityFrameworkCore.Oracle.Devart.csproj --- .../Volo.Abp.EntityFrameworkCore.Oracle.Devart.csproj | 1 - 1 file changed, 1 deletion(-) diff --git a/framework/src/Volo.Abp.EntityFrameworkCore.Oracle.Devart/Volo.Abp.EntityFrameworkCore.Oracle.Devart.csproj b/framework/src/Volo.Abp.EntityFrameworkCore.Oracle.Devart/Volo.Abp.EntityFrameworkCore.Oracle.Devart.csproj index 70d234cd20..bb46006ac9 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore.Oracle.Devart/Volo.Abp.EntityFrameworkCore.Oracle.Devart.csproj +++ b/framework/src/Volo.Abp.EntityFrameworkCore.Oracle.Devart/Volo.Abp.EntityFrameworkCore.Oracle.Devart.csproj @@ -21,7 +21,6 @@ - From 46f3338e8fac2a4a1e3f933065fbad748e4ec738 Mon Sep 17 00:00:00 2001 From: Enis Necipoglu Date: Wed, 24 Jan 2024 10:55:11 +0300 Subject: [PATCH 68/98] Use Outline button variation for blazor alert --- .../src/Volo.Abp.BlazoriseUI/Components/UiMessageAlert.razor | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/src/Volo.Abp.BlazoriseUI/Components/UiMessageAlert.razor b/framework/src/Volo.Abp.BlazoriseUI/Components/UiMessageAlert.razor index 82fc576b7e..9951e616e2 100644 --- a/framework/src/Volo.Abp.BlazoriseUI/Components/UiMessageAlert.razor +++ b/framework/src/Volo.Abp.BlazoriseUI/Components/UiMessageAlert.razor @@ -22,7 +22,7 @@ @if ( IsConfirmation ) { - + @@ -119,7 +119,7 @@ - + From 44d51d06bd7642594828f6c7bd6f898816d48231 Mon Sep 17 00:00:00 2001 From: Enis Necipoglu Date: Wed, 24 Jan 2024 15:19:55 +0300 Subject: [PATCH 72/98] Update FeatureManagementModal buttons --- .../Components/FeatureManagementModal.razor | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Blazor/Components/FeatureManagementModal.razor b/modules/feature-management/src/Volo.Abp.FeatureManagement.Blazor/Components/FeatureManagementModal.razor index 719cea562a..6b5a16fbb0 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.Blazor/Components/FeatureManagementModal.razor +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Blazor/Components/FeatureManagementModal.razor @@ -95,8 +95,8 @@ - - + + } From 46fcdb21e5f32d1680abee23c0307d93d96e5e5e Mon Sep 17 00:00:00 2001 From: Enis Necipoglu Date: Wed, 24 Jan 2024 15:28:03 +0300 Subject: [PATCH 73/98] Use outline variation of buttons for Identity module on blazor --- .../Pages/Identity/RoleManagement.razor | 4 ++-- .../Pages/Identity/UserManagement.razor | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/modules/identity/src/Volo.Abp.Identity.Blazor/Pages/Identity/RoleManagement.razor b/modules/identity/src/Volo.Abp.Identity.Blazor/Pages/Identity/RoleManagement.razor index b5b8b15d47..d65325abae 100644 --- a/modules/identity/src/Volo.Abp.Identity.Blazor/Pages/Identity/RoleManagement.razor +++ b/modules/identity/src/Volo.Abp.Identity.Blazor/Pages/Identity/RoleManagement.razor @@ -63,7 +63,7 @@ - + @@ -101,7 +101,7 @@ - + diff --git a/modules/identity/src/Volo.Abp.Identity.Blazor/Pages/Identity/UserManagement.razor b/modules/identity/src/Volo.Abp.Identity.Blazor/Pages/Identity/UserManagement.razor index 57ab80dc5e..349da3d9da 100644 --- a/modules/identity/src/Volo.Abp.Identity.Blazor/Pages/Identity/UserManagement.razor +++ b/modules/identity/src/Volo.Abp.Identity.Blazor/Pages/Identity/UserManagement.razor @@ -154,7 +154,7 @@ - + @@ -275,7 +275,7 @@ - + From 4384eb683e18690ea23ab888bff5f2df4efbb424 Mon Sep 17 00:00:00 2001 From: Enis Necipoglu Date: Wed, 24 Jan 2024 16:52:09 +0300 Subject: [PATCH 74/98] Update PermissionManagementModal.razor --- .../Components/PermissionManagementModal.razor | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/permission-management/src/Volo.Abp.PermissionManagement.Blazor/Components/PermissionManagementModal.razor b/modules/permission-management/src/Volo.Abp.PermissionManagement.Blazor/Components/PermissionManagementModal.razor index 8c1f5871db..88d023a906 100644 --- a/modules/permission-management/src/Volo.Abp.PermissionManagement.Blazor/Components/PermissionManagementModal.razor +++ b/modules/permission-management/src/Volo.Abp.PermissionManagement.Blazor/Components/PermissionManagementModal.razor @@ -81,7 +81,7 @@ } - + From 4df046dae234e6c6a64f2b22824567a8f6fcc3eb Mon Sep 17 00:00:00 2001 From: denizdemirkan Date: Wed, 24 Jan 2024 19:29:10 +0300 Subject: [PATCH 75/98] MarkdownSupported Localization for Community --- .../AbpIoLocalization/Community/Localization/Resources/ar.json | 3 ++- .../AbpIoLocalization/Community/Localization/Resources/cs.json | 3 ++- .../AbpIoLocalization/Community/Localization/Resources/de.json | 3 ++- .../Community/Localization/Resources/en-GB.json | 3 ++- .../AbpIoLocalization/Community/Localization/Resources/en.json | 3 ++- .../AbpIoLocalization/Community/Localization/Resources/es.json | 3 ++- .../AbpIoLocalization/Community/Localization/Resources/fi.json | 3 ++- .../AbpIoLocalization/Community/Localization/Resources/fr.json | 3 ++- .../AbpIoLocalization/Community/Localization/Resources/hi.json | 3 ++- .../AbpIoLocalization/Community/Localization/Resources/hr.json | 3 ++- .../AbpIoLocalization/Community/Localization/Resources/hu.json | 3 ++- .../AbpIoLocalization/Community/Localization/Resources/is.json | 3 ++- .../AbpIoLocalization/Community/Localization/Resources/it.json | 3 ++- .../AbpIoLocalization/Community/Localization/Resources/nl.json | 3 ++- .../Community/Localization/Resources/pl-PL.json | 3 ++- .../Community/Localization/Resources/pt-BR.json | 3 ++- .../Community/Localization/Resources/ro-RO.json | 3 ++- .../AbpIoLocalization/Community/Localization/Resources/ru.json | 3 ++- .../AbpIoLocalization/Community/Localization/Resources/sk.json | 3 ++- .../AbpIoLocalization/Community/Localization/Resources/sl.json | 3 ++- .../AbpIoLocalization/Community/Localization/Resources/tr.json | 3 ++- .../AbpIoLocalization/Community/Localization/Resources/vi.json | 3 ++- .../Community/Localization/Resources/zh-Hans.json | 3 ++- .../Community/Localization/Resources/zh-Hant.json | 3 ++- 24 files changed, 48 insertions(+), 24 deletions(-) diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/ar.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/ar.json index 963546d9a3..df39dea75d 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/ar.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/ar.json @@ -255,6 +255,7 @@ "LatestArticles": "أحدث المقالات", "RaffleHeader": "مرحبًا عضو مجتمع برنامج الجسر الأكاديمي!", "RafflesInfo": "
هذه هي صفحة السحب المخصصة لإظهار تقديرنا لك لكونك عضوًا نشطًا في المجتمع. نحن نقوم بإجراء محادثات مجتمعية لبرنامج ABP ، ومؤتمر ABP .NET ، ونحضر أو نرعى الأحداث المتعلقة بـ .NET والتي نقدم فيها بعض الهدايا.

يمكنك متابعة هذه الصفحة لرؤية السحوبات القادمة أو حضورها أو الاطلاع على السحوبات السابقة التي قمنا بسحبها بما في ذلك الفائزين.

شكرا لكونك عضوا نشطا! نراكم في السحوبات القادمة.", - "RafflesInfoTitle": "سحوبات مجتمع ABP" + "RafflesInfoTitle": "سحوبات مجتمع ABP", + "MarkdownSupported": "Markdown أيد." } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/cs.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/cs.json index 418cf5aef1..4c6a229861 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/cs.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/cs.json @@ -255,6 +255,7 @@ "LatestArticles": "poslední články", "RaffleHeader": "Dobrý den, člen komunity ABP!", "RafflesInfo": "
Toto je stránka s losováním věnovaná tomu, abychom vám ukázali naše uznání za to, že jste aktivním členem komunity. Pořádáme ABP Community Talks , ABP .NET Conference , účastníme se nebo sponzorujeme akce související s .NET, ve kterých rozdáváme nějaké dárky.

Na této stránce můžete sledovat nadcházející tomboly, zúčastnit se jich nebo si prohlédnout předchozí tomboly, které losujeme, včetně výherců.

Děkujeme, že jste aktivním členem! Uvidíme se v nadcházejícím slosování.", - "RafflesInfoTitle": "Komunitní tomboly ABP" + "RafflesInfoTitle": "Komunitní tomboly ABP", + "MarkdownSupported": "Markdown podporováno." } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/de.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/de.json index 021c19b3ff..146985eb49 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/de.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/de.json @@ -255,6 +255,7 @@ "LatestArticles": "Neueste Artikel", "RaffleHeader": "Hallo ABP-Community-Mitglied!", "RafflesInfo": "
Auf dieser Verlosungsseite möchten wir Ihnen unsere Wertschätzung dafür zeigen, dass Sie ein aktives Community-Mitglied sind. Wir veranstalten ABP Community Talks und ABP .NET Conferences , nehmen an .NET-bezogenen Veranstaltungen teil oder sponsern diese, bei denen wir einige Geschenke verschenken.

Sie können dieser Seite folgen, um die bevorstehenden Verlosungen zu sehen, daran teilzunehmen oder frühere Verlosungen, die wir verlosen, einschließlich der Gewinner, anzusehen.

Vielen Dank, dass Sie ein aktives Mitglied sind! Wir sehen uns bei den kommenden Gewinnspielen.", - "RafflesInfoTitle": "ABP-Community- Verlosungen" + "RafflesInfoTitle": "ABP-Community- Verlosungen", + "MarkdownSupported": "Markdown unterstützt." } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/en-GB.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/en-GB.json index 0283b963bc..fc21345c05 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/en-GB.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/en-GB.json @@ -103,6 +103,7 @@ "Language": "Language", "CreatePostLanguageInfo": "Language of the post", "SeeMore": "See More", - "MemberNotPublishedPostYet": "This member hasn't published any posts yet." + "MemberNotPublishedPostYet": "This member hasn't published any posts yet.", + "MarkdownSupported": "Markdown supported." } } diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/en.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/en.json index fa10d9c408..4bcd1bd525 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/en.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/en.json @@ -256,6 +256,7 @@ "RaffleHeader": "Hello ABP Community Member!", "RafflesInfo": "
This is the raffle page dedicated to show our appreciation towards you for being an active Community Member. We do ABP Community Talks ,ABP .NET Conference, attend or sponsor to the .NET-related events in which we give away some gifts.

You can follow this page to see the upcoming raffles, attend them, or see previous raffles we draw including the winners.

Thank you for being an active member! See you in the upcoming raffles.", "RafflesInfoTitle": "ABP Community Raffles", - "ToLuckyWinner": "to 1 lucky winner" + "ToLuckyWinner": "to 1 lucky winner", + "MarkdownSupported": "Markdown supported." } } diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/es.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/es.json index c4e178bbd9..f24cb1d511 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/es.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/es.json @@ -255,6 +255,7 @@ "LatestArticles": "últimos artículos", "RaffleHeader": "¡Hola miembro de la comunidad ABP!", "RafflesInfo": "
Esta es la página del sorteo dedicada a mostrarle nuestro agradecimiento por ser un miembro activo de la comunidad. Realizamos charlas comunitarias de ABP , conferencias ABP .NET , asistimos o patrocinamos eventos relacionados con .NET en los que regalamos algunos obsequios.

Puedes seguir esta página para ver los próximos sorteos, asistir a ellos o ver sorteos anteriores que sorteamos incluyendo a los ganadores.

¡Gracias por ser un miembro activo! Nos vemos en los próximos sorteos.", - "RafflesInfoTitle": "Rifas de la Comunidad ABP" + "RafflesInfoTitle": "Rifas de la Comunidad ABP", + "MarkdownSupported": "Markdown soportado." } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/fi.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/fi.json index ac509875d6..a42a7d693f 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/fi.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/fi.json @@ -255,6 +255,7 @@ "LatestArticles": "Viimeisimmät artikkelit", "RaffleHeader": "Hei ABP-yhteisön jäsen!", "RafflesInfo": "
Tämä on arvontasivu, joka on omistettu osoittamaan kiitollisuuttamme sinua kohtaan, että olet aktiivinen yhteisön jäsen. Teemme ABP Community Talksia , ABP .NET -konferenssia , osallistumme tai sponsoroimme .NET-tapahtumia, joissa annamme lahjoja.

Voit seurata tätä sivua nähdäksesi tulevat arvonnat, osallistua niihin tai nähdäksesi aiemmat arvonnamme, mukaan lukien voittajat.

Kiitos aktiivisesta jäsenyydestäsi! Nähdään tulevissa arvonnassa.", - "RafflesInfoTitle": "ABP-yhteisön arpajaiset" + "RafflesInfoTitle": "ABP-yhteisön arpajaiset", + "MarkdownSupported": "Markdown tuettu." } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/fr.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/fr.json index c98a48d93e..2ed85aaa95 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/fr.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/fr.json @@ -255,6 +255,7 @@ "LatestArticles": "Derniers articles", "RaffleHeader": "Bonjour membre de la communauté ABP !", "RafflesInfo": "
Ceci est la page de tirage au sort dédiée à vous montrer notre gratitude pour votre participation active à la communauté. Nous organisons des discussions communautaires ABP , des conférences ABP .NET , assistons ou sponsorisons des événements liés à .NET au cours desquels nous offrons des cadeaux.

Vous pouvez suivre cette page pour voir les tirages au sort à venir, y assister ou voir les tirages au sort précédents que nous tirons, y compris les gagnants.

Merci d'être un membre actif ! Rendez-vous lors des prochains tirages au sort.", - "RafflesInfoTitle": "Tirages au sort communautaires ABP" + "RafflesInfoTitle": "Tirages au sort communautaires ABP", + "MarkdownSupported": "Markdown prise en charge." } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/hi.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/hi.json index f3d300e8a2..6a969b99f3 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/hi.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/hi.json @@ -255,6 +255,7 @@ "LatestArticles": "नवीनतम लेख", "RaffleHeader": "नमस्ते एबीपी समुदाय सदस्य!", "RafflesInfo": "
यह रैफ़ल पेज है जो एक सक्रिय समुदाय सदस्य होने के लिए आपके प्रति हमारी सराहना दिखाने के लिए समर्पित है। हम एबीपी सामुदायिक वार्ता , एबीपी .NET सम्मेलन करते हैं, .NET से संबंधित कार्यक्रमों में भाग लेते हैं या प्रायोजित करते हैं जिसमें हम कुछ उपहार देते हैं।

आप आगामी रैफ़ल देखने, उनमें भाग लेने, या विजेताओं सहित हमारे द्वारा निकाले गए पिछले रैफ़ल देखने के लिए इस पृष्ठ का अनुसरण कर सकते हैं।

सक्रिय सदस्य बनने के लिए धन्यवाद! आगामी रैफ़ल में मिलते हैं।", - "RafflesInfoTitle": "एबीपी कम्युनिटी रैफल्स" + "RafflesInfoTitle": "एबीपी कम्युनिटी रैफल्स", + "MarkdownSupported": "Markdown का समर्थन किया।" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/hr.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/hr.json index 5b3546a78b..4e213a9c66 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/hr.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/hr.json @@ -255,6 +255,7 @@ "LatestArticles": "Najnoviji članci", "RaffleHeader": "Pozdrav članu ABP zajednice!", "RafflesInfo": "
Ovo je stranica za nagradnu igru namijenjena da vam pokažemo našu zahvalnost što ste aktivni član zajednice. Vodimo razgovore o ABP zajednici , ABP .NET konferenciji , prisustvujemo ili sponzoriramo događaje vezane uz .NET na kojima dijelimo neke darove.

Možete pratiti ovu stranicu kako biste vidjeli nadolazeće nagradne igre, prisustvovali im ili vidjeli prethodne nagradne igre koje izvlačimo uključujući dobitnike.

Hvala vam što ste aktivan član! Vidimo se u nadolazećim nagradnim igrama.", - "RafflesInfoTitle": "Izvlačenje nagradne igre zajednice ABP" + "RafflesInfoTitle": "Izvlačenje nagradne igre zajednice ABP", + "MarkdownSupported": "Markdown podržan." } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/hu.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/hu.json index 1f74f9e7a9..f489cdc571 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/hu.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/hu.json @@ -255,6 +255,7 @@ "LatestArticles": "Legfrissebb cikkek", "RaffleHeader": "Kedves ABP közösségi tag!", "RafflesInfo": "
Ez az a sorsolási oldal, amelynek célja, hogy kifejezzük hálánkat feléd, amiért aktív közösségi tag vagy. Az ABP Community Talks-okat , az ABP .NET konferenciákat szervezzük, részt veszünk vagy szponzorálunk olyan .NET-hez kapcsolódó eseményeket, amelyeken ajándékokat adunk.

Ezt az oldalt követheti, hogy megtekinthesse a közelgő sorsolásokat, részt vegyen azokon, vagy megtekinthesse korábbi sorsolásainkat, beleértve a nyerteseket is.

Köszönjük, hogy aktív tag vagy! Találkozunk a sorsoláson.", - "RafflesInfoTitle": "ABP közösségi tombola" + "RafflesInfoTitle": "ABP közösségi tombola", + "MarkdownSupported": "Markdown támogatott." } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/is.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/is.json index a991c387d4..32284f5f37 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/is.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/is.json @@ -255,6 +255,7 @@ "LatestArticles": "Nýjustu greinar", "RaffleHeader": "Halló ABP samfélagsmeðlimur!", "RafflesInfo": "
Þetta er happdrættisíðan sem er tileinkuð þér að þakka þér fyrir að vera virkur samfélagsmeðlimur. Við gerum ABP Community Talks , ABP .NET ráðstefnu , sækjum eða styrkjum .NET tengda viðburði þar sem við gefum nokkrar gjafir.

Þú getur fylgst með þessari síðu til að sjá komandi happdrætti, mæta á þær eða sjá fyrri happdrætti sem við drögum út, þar á meðal vinningshafa.

Þakka þér fyrir að vera virkur meðlimur! Sjáumst í komandi happdrætti.", - "RafflesInfoTitle": "ABP samfélagshappdrætti" + "RafflesInfoTitle": "ABP samfélagshappdrætti", + "MarkdownSupported": "Markdown stutt." } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/it.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/it.json index 901c356c9a..301c1e84e7 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/it.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/it.json @@ -255,6 +255,7 @@ "LatestArticles": "Articoli Recenti", "RaffleHeader": "Ciao membro della comunità ABP!", "RafflesInfo": "
Questa è la pagina della lotteria dedicata a mostrare il nostro apprezzamento nei tuoi confronti per essere un membro attivo della comunità. Organizziamo ABP Community Talks , ABP .NET Conference , partecipiamo o sponsorizziamo eventi relativi a .NET in cui regaliamo alcuni regali.

Puoi seguire questa pagina per vedere le prossime lotterie, parteciparvi o vedere le lotterie precedenti che estraiamo, compresi i vincitori.

Grazie per essere un membro attivo! Ci vediamo alle prossime lotterie.", - "RafflesInfoTitle": "Lotterie comunitarie ABP" + "RafflesInfoTitle": "Lotterie comunitarie ABP", + "MarkdownSupported": "Markdown supportato." } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/nl.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/nl.json index 4ee8e44a09..8beba46650 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/nl.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/nl.json @@ -255,6 +255,7 @@ "LatestArticles": "Laatste artikels", "RaffleHeader": "Hallo ABP Community-lid!", "RafflesInfo": "
Dit is de loterijpagina die bedoeld is om onze waardering voor u te tonen omdat u een actief lid van de community bent. We houden ABP Community Talks , ABP .NET Conference , wonen of sponsoren de .NET-gerelateerde evenementen bij waarin we een aantal geschenken weggeven.

U kunt deze pagina volgen om de komende loterijen te zien, deze bij te wonen of eerdere loterijen te zien die we trekken, inclusief de winnaars.

Bedankt dat u een actief lid bent! Tot ziens bij de komende loterijen.", - "RafflesInfoTitle": "ABP- gemeenschaploterijen" + "RafflesInfoTitle": "ABP- gemeenschaploterijen", + "MarkdownSupported": "Markdown ondersteund." } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/pl-PL.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/pl-PL.json index 2df6780f03..e47be75ccc 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/pl-PL.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/pl-PL.json @@ -255,6 +255,7 @@ "LatestArticles": "ostatnie artykuły", "RaffleHeader": "Witaj, członku społeczności ABP!", "RafflesInfo": "
To jest strona loterii, której celem jest wyrażenie naszego uznania dla Ciebie za bycie aktywnym członkiem społeczności. Prowadzimy rozmowy społecznościowe ABP , konferencje ABP .NET , uczestniczymy lub sponsorujemy wydarzenia związane z .NET, podczas których rozdajemy prezenty.

Możesz śledzić tę stronę, aby zobaczyć nadchodzące loterie, wziąć w nich udział lub zobaczyć poprzednie loterie, które losowaliśmy, w tym zwycięzców.

Dziękujemy za bycie aktywnym członkiem! Do zobaczenia w nadchodzących loteriach.", - "RafflesInfoTitle": "Loterie społecznościowe ABP" + "RafflesInfoTitle": "Loterie społecznościowe ABP", + "MarkdownSupported": "Markdown utrzymany." } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/pt-BR.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/pt-BR.json index 9f2ce433d9..d987c03211 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/pt-BR.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/pt-BR.json @@ -255,6 +255,7 @@ "LatestArticles": "Artigos Mais Recentes", "RaffleHeader": "Olá, membro da comunidade ABP!", "RafflesInfo": "
Esta é a página do sorteio dedicada a mostrar nosso agradecimento por você ser um membro ativo da comunidade. Fazemos ABP Community Talks , ABP .NET Conference , participamos ou patrocinamos eventos relacionados ao .NET nos quais distribuímos alguns presentes.

Você pode seguir esta página para ver os próximos sorteios, participar deles ou ver os sorteios anteriores que sorteamos, incluindo os vencedores.

Obrigado por ser um membro ativo! Nos vemos nos próximos sorteios.", - "RafflesInfoTitle": "Sorteios da Comunidade ABP" + "RafflesInfoTitle": "Sorteios da Comunidade ABP", + "MarkdownSupported": "Markdown suportado." } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/ro-RO.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/ro-RO.json index c2862d1fd7..06ecc4dea8 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/ro-RO.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/ro-RO.json @@ -255,6 +255,7 @@ "LatestArticles": "ultimele articole", "RaffleHeader": "Bună ziua, membru al comunității ABP!", "RafflesInfo": "
Aceasta este pagina de tombolă dedicată pentru a arăta aprecierea noastră față de dvs. pentru că sunteți un membru activ al comunității. Facem ABP Community Talks , ABP .NET Conference , participăm sau sponsorizăm evenimentele legate de .NET în care oferim câteva cadouri.

Puteți urmări această pagină pentru a vedea tombolele viitoare, a participa la ele sau pentru a vedea tombolele anterioare pe care le extragem, inclusiv câștigătorii.

Vă mulțumim că sunteți un membru activ! Ne vedem la tombolele viitoare.", - "RafflesInfoTitle": "Tombole comunitare ABP" + "RafflesInfoTitle": "Tombole comunitare ABP", + "MarkdownSupported": "Markdown sprijinit." } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/ru.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/ru.json index 27f2b1203a..07d6a87fe9 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/ru.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/ru.json @@ -258,6 +258,7 @@ "LatestArticles": "Последние статьи", "RaffleHeader": "Привет, участник сообщества ABP!", "RafflesInfo": "
Эта страница розыгрыша посвящена тому, чтобы выразить нашу признательность вам за то, что вы являетесь активным членом сообщества. Обсуждения сообщества ABP ,Конференция ABP .NET, посещать или спонсировать мероприятия, связанные с .NET, на которых мы раздаем подарки.

Вы можете подписаться на эту страницу, чтобы увидеть предстоящие розыгрыши, посетить их или просмотреть предыдущие розыгрыши, которые мы проводим, включая победителей.

Спасибо за активное участие! ", - "RafflesInfoTitle": "Сообщество АБП Розыгрыши" + "RafflesInfoTitle": "Сообщество АБП Розыгрыши", + "MarkdownSupported": "Markdown поддерживается." } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/sk.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/sk.json index 6ab3c9d074..fa9826b421 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/sk.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/sk.json @@ -255,6 +255,7 @@ "LatestArticles": "Najnovšie články", "RaffleHeader": "Dobrý deň, člen komunity ABP!", "RafflesInfo": "
Toto je stránka žrebovania venovaná na vyjadrenie nášho uznania vám za to, že ste aktívnym členom komunity. Robíme ABP Community Talks , ABP .NET konferenciu , zúčastňujeme sa alebo sponzorujeme podujatia súvisiace s .NET, na ktorých rozdávame nejaké darčeky.

Na tejto stránke si môžete pozrieť pripravované tomboly, zúčastniť sa ich alebo si pozrieť predchádzajúce žrebovanie, ktoré vyžrebujeme vrátane výhercov.

Ďakujeme, že ste aktívnym členom! Vidíme sa v najbližšom žrebovaní.", - "RafflesInfoTitle": "Komunitné tomboly ABP" + "RafflesInfoTitle": "Komunitné tomboly ABP", + "MarkdownSupported": "Markdown podporované." } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/sl.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/sl.json index 23763c6f78..81e103cd17 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/sl.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/sl.json @@ -255,6 +255,7 @@ "LatestArticles": "Najnovejši članki", "RaffleHeader": "Pozdravljeni član skupnosti ABP!", "RafflesInfo": "
To je stran za nagradno igro, namenjena izkazovanju naše hvaležnosti do vas, ker ste aktivni član skupnosti. Izvajamo ABP Community Talks , ABP .NET Conference , se udeležujemo ali sponzoriramo dogodke, povezane z .NET, na katerih podarimo nekaj daril.

To stran lahko spremljate in si ogledate prihajajoče nagradne igre, se jih udeležite ali si ogledate prejšnje nagradne igre, ki smo jih izžrebali, vključno z zmagovalci.

Hvala, ker ste aktivni član! Se vidimo na prihajajočih nagradnih igrah.", - "RafflesInfoTitle": "Žrebanje skupnosti ABP" + "RafflesInfoTitle": "Žrebanje skupnosti ABP", + "MarkdownSupported": "Markdown podprt." } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/tr.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/tr.json index 2d52d01ed2..d184bb63d1 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/tr.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/tr.json @@ -189,6 +189,7 @@ "Layout_MetaDescription": "ABP Topluluğu, insanların ABP çerçevesi hakkında paylaşımlarda bulunabileceği ve projeleri takip edebileceği bir ortamdır.", "Index_Page_CommunityIntroduction": "Burası ABP Çerçevesi, .NET ve yazılım geliştirme için bir merkezdir. Makaleleri okuyabilir, eğitim videolarını izleyebilir, ABP'nin gelişim süreci ve ABP ile ilgili etkinlikler hakkında bilgi alabilir, diğer geliştiricilere yardımcı olabilir ve uzmanlığınızı ABP topluluğu ile paylaşabilirsiniz.", "IConsentToMedium": "Bu yazının https://medium.com/volosoft adresinde yayınlanmasına izin veriyorum.", - "DiscordPageTitle": "ABP Discord Topluluğu" + "DiscordPageTitle": "ABP Discord Topluluğu", + "MarkdownSupported": "Markdown destekleniyor." } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/vi.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/vi.json index a36ec9b0e8..d7febbb014 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/vi.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/vi.json @@ -255,6 +255,7 @@ "LatestArticles": "Bài viết mới nhất", "RaffleHeader": "Xin chào Thành viên Cộng đồng ABP!", "RafflesInfo": "
Đây là trang xổ số dành riêng để thể hiện sự đánh giá cao của chúng tôi đối với bạn vì đã trở thành Thành viên cộng đồng tích cực. Chúng tôi tổ chức các buổi nói chuyện cộng đồng ABP , Hội nghị ABP .NET , tham dự hoặc tài trợ cho các sự kiện liên quan đến .NET mà trong đó chúng tôi tặng một số quà tặng.

Bạn có thể theo dõi trang này để xem các cuộc xổ số sắp tới, tham dự hoặc xem các cuộc xổ số trước đây mà chúng tôi rút ra bao gồm cả những người chiến thắng.

Cảm ơn bạn đã là thành viên tích cực! Hẹn gặp lại các bạn trong đợt xổ số sắp tới.", - "RafflesInfoTitle": "Xổ số cộng đồng ABP" + "RafflesInfoTitle": "Xổ số cộng đồng ABP", + "MarkdownSupported": "Markdown được hỗ trợ." } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/zh-Hans.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/zh-Hans.json index e899a94872..c0aaf2678b 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/zh-Hans.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/zh-Hans.json @@ -255,6 +255,7 @@ "LatestArticles": "最新文章", "RaffleHeader": "你好,ABP 社区成员!", "RafflesInfo": "
这是一个抽奖页面,旨在感谢您成为活跃的社区成员。我们举办 ABP 社区讲座 、ABP .NET 会议,参加或赞助与 .NET 相关的活动,并在活动中赠送一些礼品。

您可以关注此页面,查看即将举行的抽奖活动、参加这些活动或查看我们以前举行的抽奖活动(包括获奖者)。

感谢您成为我们的活跃成员!在即将举行的抽奖活动中再见。", - "RafflesInfoTitle": "ABP 社区来抽奖来抽奖Markdown 支持的。" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/zh-Hant.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/zh-Hant.json index ebec42dd8a..7f8e58f7df 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/zh-Hant.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/zh-Hant.json @@ -255,6 +255,7 @@ "LatestArticles": "最新的文章", "RaffleHeader": "ABP 社群成員您好!", "RafflesInfo": "
這是抽獎頁面,旨在表達我們對您作為活躍社區成員的感謝。我們舉辦ABP 社群講座、ABP .NET 會議、參加或贊助 .NET 相關活動,並在活動中贈送一些禮物。

您可以關注此頁面查看即將舉行的抽獎活動、參加抽獎活動或查看我們之前抽獎的抽獎活動(包括獲獎者)。

感謝您成為活躍會員!在即將到來的抽獎活動中再見。", - "RafflesInfoTitle": "ABP 社區萊佛士" + "RafflesInfoTitle": "ABP 社區萊佛士", + "MarkdownSupported": "Markdown 支持的。" } } \ No newline at end of file From 368eb9c565543934ab4d23b706b59a1f7e8556c1 Mon Sep 17 00:00:00 2001 From: maliming Date: Thu, 25 Jan 2024 13:53:30 +0800 Subject: [PATCH 76/98] Migration notes for NormalizedName property of Tenant. Resolve #18857 --- docs/en/Migration-Guides/Abp-8_1.md | 86 +++++++++++++++++++++++++++++ docs/en/Multi-Tenancy.md | 2 +- 2 files changed, 87 insertions(+), 1 deletion(-) create mode 100644 docs/en/Migration-Guides/Abp-8_1.md diff --git a/docs/en/Migration-Guides/Abp-8_1.md b/docs/en/Migration-Guides/Abp-8_1.md new file mode 100644 index 0000000000..d5ec87a3ca --- /dev/null +++ b/docs/en/Migration-Guides/Abp-8_1.md @@ -0,0 +1,86 @@ +# ABP Version 8.1 Migration Guide + +This document is a guide for upgrading ABP v8.0 solutions to ABP v8.1. There are some changes in this version that may affect your applications, please read it carefully and apply the necessary changes to your application. + +## Added `NormalizedName` property to `Tenant` + +The `Tenant` entity has a new property called `NormalizedName`. It is used to find/cache a tenant by its name in a case-insensitive way. +This property is automatically set when a tenant is created or updated. It gets the normalized name of the tenant name by `UpperInvariantTenantNormalizer(ITenantNormalizer)` service. You can implement this service to change the normalization logic. + +### `ITenantStore` + +The `ITenantStore` will use the `NormalizedName` parameter to get tenants, Please use the `ITenantNormalizer` to normalize the tenant name before calling the `ITenantStore` methods. + +### Update `NormalizedName` in `appsettings.json` + +If your tenants defined in the `appsettings.json` file, you should add the `NormalizedName` property to your tenants. + +````json +"Tenants": [ + { + "Id": "446a5211-3d72-4339-9adc-845151f8ada0", + "Name": "tenant1", + "NormalizedName": "TENANT1" // <-- Add this property + }, + { + "Id": "25388015-ef1c-4355-9c18-f6b6ddbaf89d", + "Name": "tenant2", + "NormalizedName": "TENANT2", // <-- Add this property + "ConnectionStrings": { + "Default": "...tenant2's db connection string here..." + } + } + ] +```` + +### Update `NormalizedName` in the database + +Please add a sql script to your migration to set the `NormalizedName` property of the existing tenants. You can use the following script: + +> This script is for the SQL Server database. You can change it for your database. + +> The table name `SaasTenants` is used for ABP commercial Saas module. `AbpTenants` is for the ABP open-source Tenant Management module. + +```sql +UPDATE SaasTenants SET NormalizedName = UPPER(Name) WHERE NormalizedName IS NULL OR NormalizedName = '' +``` + +```csharp +/// +public partial class Add_NormalizedName : Migration +{ + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "NormalizedName", + table: "SaasTenants", + type: "citext", + maxLength: 64, + nullable: false, + defaultValue: ""); + + migrationBuilder.Sql("UPDATE SaasTenants SET NormalizedName = UPPER(Name) WHERE NormalizedName IS NULL OR NormalizedName = ''"); + + migrationBuilder.CreateIndex( + name: "IX_SaasTenants_NormalizedName", + table: "SaasTenants", + column: "NormalizedName"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropIndex( + name: "IX_SaasTenants_NormalizedName", + table: "SaasTenants"); + + migrationBuilder.DropColumn( + name: "NormalizedName", + table: "SaasTenants"); + } +} +``` + +See https://learn.microsoft.com/en-us/ef/core/managing-schemas/migrations/managing?tabs=dotnet-core-cli#adding-raw-sql to learn how to add raw SQL to migrations. + diff --git a/docs/en/Multi-Tenancy.md b/docs/en/Multi-Tenancy.md index 392bea6809..698879bdf1 100644 --- a/docs/en/Multi-Tenancy.md +++ b/docs/en/Multi-Tenancy.md @@ -394,7 +394,7 @@ app.UseMultiTenancy(); `ITenantStore` is used to get the tenant configuration from a data source. -> Tenant names are not case-sensitive. `ITenantStore` will use the `NormalizedName` parameter to get tenants, You need to use `ITenantNormalizer to normalize tenant names. +> Tenant names are not case-sensitive. `ITenantStore` will use the `NormalizedName` parameter to get tenants, You need to use `ITenantNormalizer`` to normalize tenant names. #### Tenant Management Module From 1fe4a25b9cf73921b84305f8d258126f9db09436 Mon Sep 17 00:00:00 2001 From: maliming Date: Thu, 25 Jan 2024 13:55:42 +0800 Subject: [PATCH 77/98] Update Multi-Tenancy.md --- docs/en/Multi-Tenancy.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/en/Multi-Tenancy.md b/docs/en/Multi-Tenancy.md index 698879bdf1..922976767d 100644 --- a/docs/en/Multi-Tenancy.md +++ b/docs/en/Multi-Tenancy.md @@ -394,7 +394,7 @@ app.UseMultiTenancy(); `ITenantStore` is used to get the tenant configuration from a data source. -> Tenant names are not case-sensitive. `ITenantStore` will use the `NormalizedName` parameter to get tenants, You need to use `ITenantNormalizer`` to normalize tenant names. +> Tenant names are not case-sensitive. `ITenantStore` will use the `NormalizedName` parameter to get tenants, You need to use `ITenantNormalizer` to normalize tenant names. #### Tenant Management Module From 1bffcc7220b99eb9346fc4f88ca70722168e970d Mon Sep 17 00:00:00 2001 From: maliming Date: Thu, 25 Jan 2024 14:05:36 +0800 Subject: [PATCH 78/98] Update Abp-8_1.md --- docs/en/Migration-Guides/Abp-8_1.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/docs/en/Migration-Guides/Abp-8_1.md b/docs/en/Migration-Guides/Abp-8_1.md index d5ec87a3ca..6f4c316d3f 100644 --- a/docs/en/Migration-Guides/Abp-8_1.md +++ b/docs/en/Migration-Guides/Abp-8_1.md @@ -55,8 +55,7 @@ public partial class Add_NormalizedName : Migration migrationBuilder.AddColumn( name: "NormalizedName", table: "SaasTenants", - type: "citext", - maxLength: 64, + type: "nvarchar(64)", nullable: false, defaultValue: ""); From 9438b57bbe4a3fca3cf2b995307459b2fe6591f9 Mon Sep 17 00:00:00 2001 From: maliming Date: Thu, 25 Jan 2024 14:17:32 +0800 Subject: [PATCH 79/98] Add index for `NormalizedName` peroperty. --- .../AbpTenantManagementDbContextModelCreatingExtensions.cs | 1 + ...nitial.Designer.cs => 20240125061235_Initial.Designer.cs} | 4 +++- .../{20240110051639_Initial.cs => 20240125061235_Initial.cs} | 5 +++++ .../Migrations/MyProjectNameDbContextModelSnapshot.cs | 2 ++ ...nitial.Designer.cs => 20240125061501_Initial.Designer.cs} | 4 +++- .../Server/Migrations/20240125061501_Initial.cs} | 5 +++++ .../Server/Migrations/MyProjectNameDbContextModelSnapshot.cs | 2 ++ ...nitial.Designer.cs => 20240125061101_Initial.Designer.cs} | 4 +++- .../{20240110051553_Initial.cs => 20240125061101_Initial.cs} | 5 +++++ .../Migrations/MyProjectNameDbContextModelSnapshot.cs | 2 ++ ...nitial.Designer.cs => 20240125061143_Initial.Designer.cs} | 4 +++- .../{20240110051615_Initial.cs => 20240125061143_Initial.cs} | 5 +++++ .../Migrations/MyProjectNameDbContextModelSnapshot.cs | 2 ++ ...nitial.Designer.cs => 20240125061248_Initial.Designer.cs} | 4 +++- .../{20240110051649_Initial.cs => 20240125061248_Initial.cs} | 5 +++++ .../Migrations/MyProjectNameDbContextModelSnapshot.cs | 2 ++ ...nitial.Designer.cs => 20240125061344_Initial.Designer.cs} | 4 +++- .../Migrations/20240125061344_Initial.cs} | 5 +++++ .../Migrations/AuthServerDbContextModelSnapshot.cs | 2 ++ ...nitial.Designer.cs => 20240125061321_Initial.Designer.cs} | 4 +++- .../{20240110051713_Initial.cs => 20240125061321_Initial.cs} | 5 +++++ .../Migrations/UnifiedDbContextModelSnapshot.cs | 2 ++ ...nitial.Designer.cs => 20240125061400_Initial.Designer.cs} | 2 +- .../{20240110051748_Initial.cs => 20240125061400_Initial.cs} | 0 ...nitial.Designer.cs => 20240125061424_Initial.Designer.cs} | 4 +++- .../{20240110051810_Initial.cs => 20240125061424_Initial.cs} | 5 +++++ .../Migrations/UnifiedDbContextModelSnapshot.cs | 2 ++ 27 files changed, 82 insertions(+), 9 deletions(-) rename templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/{20240110051639_Initial.Designer.cs => 20240125061235_Initial.Designer.cs} (99%) rename templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/{20240110051639_Initial.cs => 20240125061235_Initial.cs} (99%) rename templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/{20240110051838_Initial.Designer.cs => 20240125061501_Initial.Designer.cs} (99%) rename templates/{module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/20240110051734_Initial.cs => app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/20240125061501_Initial.cs} (99%) rename templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/{20240110051553_Initial.Designer.cs => 20240125061101_Initial.Designer.cs} (99%) rename templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/{20240110051553_Initial.cs => 20240125061101_Initial.cs} (99%) rename templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/{20240110051615_Initial.Designer.cs => 20240125061143_Initial.Designer.cs} (99%) rename templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/{20240110051615_Initial.cs => 20240125061143_Initial.cs} (99%) rename templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/{20240110051649_Initial.Designer.cs => 20240125061248_Initial.Designer.cs} (99%) rename templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/{20240110051649_Initial.cs => 20240125061248_Initial.cs} (99%) rename templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/{20240110051734_Initial.Designer.cs => 20240125061344_Initial.Designer.cs} (99%) rename templates/{app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/20240110051838_Initial.cs => module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/20240125061344_Initial.cs} (99%) rename templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/{20240110051713_Initial.Designer.cs => 20240125061321_Initial.Designer.cs} (99%) rename templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/{20240110051713_Initial.cs => 20240125061321_Initial.cs} (99%) rename templates/module/aspnet-core/host/MyCompanyName.MyProjectName.HttpApi.Host/Migrations/{20240110051748_Initial.Designer.cs => 20240125061400_Initial.Designer.cs} (96%) rename templates/module/aspnet-core/host/MyCompanyName.MyProjectName.HttpApi.Host/Migrations/{20240110051748_Initial.cs => 20240125061400_Initial.cs} (100%) rename templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/{20240110051810_Initial.Designer.cs => 20240125061424_Initial.Designer.cs} (99%) rename templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/{20240110051810_Initial.cs => 20240125061424_Initial.cs} (99%) diff --git a/modules/tenant-management/src/Volo.Abp.TenantManagement.EntityFrameworkCore/Volo/Abp/TenantManagement/EntityFrameworkCore/AbpTenantManagementDbContextModelCreatingExtensions.cs b/modules/tenant-management/src/Volo.Abp.TenantManagement.EntityFrameworkCore/Volo/Abp/TenantManagement/EntityFrameworkCore/AbpTenantManagementDbContextModelCreatingExtensions.cs index bb189e72a1..a91cf066e5 100644 --- a/modules/tenant-management/src/Volo.Abp.TenantManagement.EntityFrameworkCore/Volo/Abp/TenantManagement/EntityFrameworkCore/AbpTenantManagementDbContextModelCreatingExtensions.cs +++ b/modules/tenant-management/src/Volo.Abp.TenantManagement.EntityFrameworkCore/Volo/Abp/TenantManagement/EntityFrameworkCore/AbpTenantManagementDbContextModelCreatingExtensions.cs @@ -28,6 +28,7 @@ public static class AbpTenantManagementDbContextModelCreatingExtensions b.HasMany(u => u.ConnectionStrings).WithOne().HasForeignKey(uc => uc.TenantId).IsRequired(); b.HasIndex(u => u.Name); + b.HasIndex(u => u.NormalizedName); b.ApplyObjectExtensionMappings(); }); diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/20240110051639_Initial.Designer.cs b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/20240125061235_Initial.Designer.cs similarity index 99% rename from templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/20240110051639_Initial.Designer.cs rename to templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/20240125061235_Initial.Designer.cs index 720730ac29..2f3a437364 100644 --- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/20240110051639_Initial.Designer.cs +++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/20240125061235_Initial.Designer.cs @@ -13,7 +13,7 @@ using Volo.Abp.EntityFrameworkCore; namespace MyCompanyName.MyProjectName.Blazor.Server.Migrations { [DbContext(typeof(MyProjectNameDbContext))] - [Migration("20240110051639_Initial")] + [Migration("20240125061235_Initial")] partial class Initial { /// @@ -1696,6 +1696,8 @@ namespace MyCompanyName.MyProjectName.Blazor.Server.Migrations b.HasIndex("Name"); + b.HasIndex("NormalizedName"); + b.ToTable("AbpTenants", (string)null); }); diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/20240110051639_Initial.cs b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/20240125061235_Initial.cs similarity index 99% rename from templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/20240110051639_Initial.cs rename to templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/20240125061235_Initial.cs index f55e1bd71a..dd96c605e7 100644 --- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/20240110051639_Initial.cs +++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/20240125061235_Initial.cs @@ -914,6 +914,11 @@ namespace MyCompanyName.MyProjectName.Blazor.Server.Migrations table: "AbpTenants", column: "Name"); + migrationBuilder.CreateIndex( + name: "IX_AbpTenants_NormalizedName", + table: "AbpTenants", + column: "NormalizedName"); + migrationBuilder.CreateIndex( name: "IX_AbpUserClaims_UserId", table: "AbpUserClaims", diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/MyProjectNameDbContextModelSnapshot.cs b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/MyProjectNameDbContextModelSnapshot.cs index 94403eda52..652e7b674d 100644 --- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/MyProjectNameDbContextModelSnapshot.cs +++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/MyProjectNameDbContextModelSnapshot.cs @@ -1693,6 +1693,8 @@ namespace MyCompanyName.MyProjectName.Blazor.Server.Migrations b.HasIndex("Name"); + b.HasIndex("NormalizedName"); + b.ToTable("AbpTenants", (string)null); }); diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/20240110051838_Initial.Designer.cs b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/20240125061501_Initial.Designer.cs similarity index 99% rename from templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/20240110051838_Initial.Designer.cs rename to templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/20240125061501_Initial.Designer.cs index d8f8a2f32c..f25d60e99b 100644 --- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/20240110051838_Initial.Designer.cs +++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/20240125061501_Initial.Designer.cs @@ -13,7 +13,7 @@ using Volo.Abp.EntityFrameworkCore; namespace MyCompanyName.MyProjectName.Migrations { [DbContext(typeof(MyProjectNameDbContext))] - [Migration("20240110051838_Initial")] + [Migration("20240125061501_Initial")] partial class Initial { /// @@ -1696,6 +1696,8 @@ namespace MyCompanyName.MyProjectName.Migrations b.HasIndex("Name"); + b.HasIndex("NormalizedName"); + b.ToTable("AbpTenants", (string)null); }); diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/20240110051734_Initial.cs b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/20240125061501_Initial.cs similarity index 99% rename from templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/20240110051734_Initial.cs rename to templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/20240125061501_Initial.cs index 42da66e3e2..b0cb9b0e6f 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/20240110051734_Initial.cs +++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/20240125061501_Initial.cs @@ -914,6 +914,11 @@ namespace MyCompanyName.MyProjectName.Migrations table: "AbpTenants", column: "Name"); + migrationBuilder.CreateIndex( + name: "IX_AbpTenants_NormalizedName", + table: "AbpTenants", + column: "NormalizedName"); + migrationBuilder.CreateIndex( name: "IX_AbpUserClaims_UserId", table: "AbpUserClaims", diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/MyProjectNameDbContextModelSnapshot.cs b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/MyProjectNameDbContextModelSnapshot.cs index 2085b9d8cd..72f44ed239 100644 --- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/MyProjectNameDbContextModelSnapshot.cs +++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/MyProjectNameDbContextModelSnapshot.cs @@ -1693,6 +1693,8 @@ namespace MyCompanyName.MyProjectName.Migrations b.HasIndex("Name"); + b.HasIndex("NormalizedName"); + b.ToTable("AbpTenants", (string)null); }); diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/20240110051553_Initial.Designer.cs b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/20240125061101_Initial.Designer.cs similarity index 99% rename from templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/20240110051553_Initial.Designer.cs rename to templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/20240125061101_Initial.Designer.cs index a17b97362f..364eaa6b57 100644 --- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/20240110051553_Initial.Designer.cs +++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/20240125061101_Initial.Designer.cs @@ -13,7 +13,7 @@ using Volo.Abp.EntityFrameworkCore; namespace MyCompanyName.MyProjectName.Host.Migrations { [DbContext(typeof(MyProjectNameDbContext))] - [Migration("20240110051553_Initial")] + [Migration("20240125061101_Initial")] partial class Initial { /// @@ -1696,6 +1696,8 @@ namespace MyCompanyName.MyProjectName.Host.Migrations b.HasIndex("Name"); + b.HasIndex("NormalizedName"); + b.ToTable("AbpTenants", (string)null); }); diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/20240110051553_Initial.cs b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/20240125061101_Initial.cs similarity index 99% rename from templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/20240110051553_Initial.cs rename to templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/20240125061101_Initial.cs index 0b4123ab8d..bfb34fcaad 100644 --- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/20240110051553_Initial.cs +++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/20240125061101_Initial.cs @@ -914,6 +914,11 @@ namespace MyCompanyName.MyProjectName.Host.Migrations table: "AbpTenants", column: "Name"); + migrationBuilder.CreateIndex( + name: "IX_AbpTenants_NormalizedName", + table: "AbpTenants", + column: "NormalizedName"); + migrationBuilder.CreateIndex( name: "IX_AbpUserClaims_UserId", table: "AbpUserClaims", diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/MyProjectNameDbContextModelSnapshot.cs b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/MyProjectNameDbContextModelSnapshot.cs index 6035862d19..f2b46a651f 100644 --- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/MyProjectNameDbContextModelSnapshot.cs +++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/MyProjectNameDbContextModelSnapshot.cs @@ -1693,6 +1693,8 @@ namespace MyCompanyName.MyProjectName.Host.Migrations b.HasIndex("Name"); + b.HasIndex("NormalizedName"); + b.ToTable("AbpTenants", (string)null); }); diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/20240110051615_Initial.Designer.cs b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/20240125061143_Initial.Designer.cs similarity index 99% rename from templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/20240110051615_Initial.Designer.cs rename to templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/20240125061143_Initial.Designer.cs index e2a3ff5a34..54929eb8e9 100644 --- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/20240110051615_Initial.Designer.cs +++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/20240125061143_Initial.Designer.cs @@ -13,7 +13,7 @@ using Volo.Abp.EntityFrameworkCore; namespace MyCompanyName.MyProjectName.Mvc.Migrations { [DbContext(typeof(MyProjectNameDbContext))] - [Migration("20240110051615_Initial")] + [Migration("20240125061143_Initial")] partial class Initial { /// @@ -1696,6 +1696,8 @@ namespace MyCompanyName.MyProjectName.Mvc.Migrations b.HasIndex("Name"); + b.HasIndex("NormalizedName"); + b.ToTable("AbpTenants", (string)null); }); diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/20240110051615_Initial.cs b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/20240125061143_Initial.cs similarity index 99% rename from templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/20240110051615_Initial.cs rename to templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/20240125061143_Initial.cs index 6fd77905c4..44eddb6abb 100644 --- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/20240110051615_Initial.cs +++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/20240125061143_Initial.cs @@ -914,6 +914,11 @@ namespace MyCompanyName.MyProjectName.Mvc.Migrations table: "AbpTenants", column: "Name"); + migrationBuilder.CreateIndex( + name: "IX_AbpTenants_NormalizedName", + table: "AbpTenants", + column: "NormalizedName"); + migrationBuilder.CreateIndex( name: "IX_AbpUserClaims_UserId", table: "AbpUserClaims", diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/MyProjectNameDbContextModelSnapshot.cs b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/MyProjectNameDbContextModelSnapshot.cs index 7f594fe2e5..8041069541 100644 --- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/MyProjectNameDbContextModelSnapshot.cs +++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/MyProjectNameDbContextModelSnapshot.cs @@ -1693,6 +1693,8 @@ namespace MyCompanyName.MyProjectName.Mvc.Migrations b.HasIndex("Name"); + b.HasIndex("NormalizedName"); + b.ToTable("AbpTenants", (string)null); }); diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20240110051649_Initial.Designer.cs b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20240125061248_Initial.Designer.cs similarity index 99% rename from templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20240110051649_Initial.Designer.cs rename to templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20240125061248_Initial.Designer.cs index 5749fe8a39..e211d7e755 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20240110051649_Initial.Designer.cs +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20240125061248_Initial.Designer.cs @@ -13,7 +13,7 @@ using Volo.Abp.EntityFrameworkCore; namespace MyCompanyName.MyProjectName.Migrations { [DbContext(typeof(MyProjectNameDbContext))] - [Migration("20240110051649_Initial")] + [Migration("20240125061248_Initial")] partial class Initial { /// @@ -1748,6 +1748,8 @@ namespace MyCompanyName.MyProjectName.Migrations b.HasIndex("Name"); + b.HasIndex("NormalizedName"); + b.ToTable("AbpTenants", (string)null); }); diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20240110051649_Initial.cs b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20240125061248_Initial.cs similarity index 99% rename from templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20240110051649_Initial.cs rename to templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20240125061248_Initial.cs index 2fe3338034..9fc3a5a0b9 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20240110051649_Initial.cs +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20240125061248_Initial.cs @@ -940,6 +940,11 @@ namespace MyCompanyName.MyProjectName.Migrations table: "AbpTenants", column: "Name"); + migrationBuilder.CreateIndex( + name: "IX_AbpTenants_NormalizedName", + table: "AbpTenants", + column: "NormalizedName"); + migrationBuilder.CreateIndex( name: "IX_AbpUserClaims_UserId", table: "AbpUserClaims", diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/MyProjectNameDbContextModelSnapshot.cs b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/MyProjectNameDbContextModelSnapshot.cs index 1b7c95358e..877bff36e8 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/MyProjectNameDbContextModelSnapshot.cs +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/MyProjectNameDbContextModelSnapshot.cs @@ -1745,6 +1745,8 @@ namespace MyCompanyName.MyProjectName.Migrations b.HasIndex("Name"); + b.HasIndex("NormalizedName"); + b.ToTable("AbpTenants", (string)null); }); diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/20240110051734_Initial.Designer.cs b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/20240125061344_Initial.Designer.cs similarity index 99% rename from templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/20240110051734_Initial.Designer.cs rename to templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/20240125061344_Initial.Designer.cs index d732cf68bb..b6dd932e2f 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/20240110051734_Initial.Designer.cs +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/20240125061344_Initial.Designer.cs @@ -13,7 +13,7 @@ using Volo.Abp.EntityFrameworkCore; namespace MyCompanyName.MyProjectName.Migrations { [DbContext(typeof(AuthServerDbContext))] - [Migration("20240110051734_Initial")] + [Migration("20240125061344_Initial")] partial class Initial { /// @@ -1696,6 +1696,8 @@ namespace MyCompanyName.MyProjectName.Migrations b.HasIndex("Name"); + b.HasIndex("NormalizedName"); + b.ToTable("AbpTenants", (string)null); }); diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/20240110051838_Initial.cs b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/20240125061344_Initial.cs similarity index 99% rename from templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/20240110051838_Initial.cs rename to templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/20240125061344_Initial.cs index 42da66e3e2..b0cb9b0e6f 100644 --- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/20240110051838_Initial.cs +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/20240125061344_Initial.cs @@ -914,6 +914,11 @@ namespace MyCompanyName.MyProjectName.Migrations table: "AbpTenants", column: "Name"); + migrationBuilder.CreateIndex( + name: "IX_AbpTenants_NormalizedName", + table: "AbpTenants", + column: "NormalizedName"); + migrationBuilder.CreateIndex( name: "IX_AbpUserClaims_UserId", table: "AbpUserClaims", diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/AuthServerDbContextModelSnapshot.cs b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/AuthServerDbContextModelSnapshot.cs index 95ab069a86..c3fb7f9ff0 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/AuthServerDbContextModelSnapshot.cs +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/AuthServerDbContextModelSnapshot.cs @@ -1693,6 +1693,8 @@ namespace MyCompanyName.MyProjectName.Migrations b.HasIndex("Name"); + b.HasIndex("NormalizedName"); + b.ToTable("AbpTenants", (string)null); }); diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/20240110051713_Initial.Designer.cs b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/20240125061321_Initial.Designer.cs similarity index 99% rename from templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/20240110051713_Initial.Designer.cs rename to templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/20240125061321_Initial.Designer.cs index fa01be30fc..3c17670e22 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/20240110051713_Initial.Designer.cs +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/20240125061321_Initial.Designer.cs @@ -13,7 +13,7 @@ using Volo.Abp.EntityFrameworkCore; namespace MyCompanyName.MyProjectName.Blazor.Server.Host.Migrations { [DbContext(typeof(UnifiedDbContext))] - [Migration("20240110051713_Initial")] + [Migration("20240125061321_Initial")] partial class Initial { /// @@ -1337,6 +1337,8 @@ namespace MyCompanyName.MyProjectName.Blazor.Server.Host.Migrations b.HasIndex("Name"); + b.HasIndex("NormalizedName"); + b.ToTable("AbpTenants", (string)null); }); diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/20240110051713_Initial.cs b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/20240125061321_Initial.cs similarity index 99% rename from templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/20240110051713_Initial.cs rename to templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/20240125061321_Initial.cs index a27989973a..1a8774f577 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/20240110051713_Initial.cs +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/20240125061321_Initial.cs @@ -778,6 +778,11 @@ namespace MyCompanyName.MyProjectName.Blazor.Server.Host.Migrations table: "AbpTenants", column: "Name"); + migrationBuilder.CreateIndex( + name: "IX_AbpTenants_NormalizedName", + table: "AbpTenants", + column: "NormalizedName"); + migrationBuilder.CreateIndex( name: "IX_AbpUserClaims_UserId", table: "AbpUserClaims", diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/UnifiedDbContextModelSnapshot.cs b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/UnifiedDbContextModelSnapshot.cs index 9835c59cd3..4acfb0c562 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/UnifiedDbContextModelSnapshot.cs +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/UnifiedDbContextModelSnapshot.cs @@ -1334,6 +1334,8 @@ namespace MyCompanyName.MyProjectName.Blazor.Server.Host.Migrations b.HasIndex("Name"); + b.HasIndex("NormalizedName"); + b.ToTable("AbpTenants", (string)null); }); diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.HttpApi.Host/Migrations/20240110051748_Initial.Designer.cs b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.HttpApi.Host/Migrations/20240125061400_Initial.Designer.cs similarity index 96% rename from templates/module/aspnet-core/host/MyCompanyName.MyProjectName.HttpApi.Host/Migrations/20240110051748_Initial.Designer.cs rename to templates/module/aspnet-core/host/MyCompanyName.MyProjectName.HttpApi.Host/Migrations/20240125061400_Initial.Designer.cs index 2eb38813a6..c58552ea60 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.HttpApi.Host/Migrations/20240110051748_Initial.Designer.cs +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.HttpApi.Host/Migrations/20240125061400_Initial.Designer.cs @@ -12,7 +12,7 @@ using Volo.Abp.EntityFrameworkCore; namespace MyCompanyName.MyProjectName.Migrations { [DbContext(typeof(MyProjectNameHttpApiHostMigrationsDbContext))] - [Migration("20240110051748_Initial")] + [Migration("20240125061400_Initial")] partial class Initial { /// diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.HttpApi.Host/Migrations/20240110051748_Initial.cs b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.HttpApi.Host/Migrations/20240125061400_Initial.cs similarity index 100% rename from templates/module/aspnet-core/host/MyCompanyName.MyProjectName.HttpApi.Host/Migrations/20240110051748_Initial.cs rename to templates/module/aspnet-core/host/MyCompanyName.MyProjectName.HttpApi.Host/Migrations/20240125061400_Initial.cs diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/20240110051810_Initial.Designer.cs b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/20240125061424_Initial.Designer.cs similarity index 99% rename from templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/20240110051810_Initial.Designer.cs rename to templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/20240125061424_Initial.Designer.cs index f7363bd08d..04cad1c308 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/20240110051810_Initial.Designer.cs +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/20240125061424_Initial.Designer.cs @@ -13,7 +13,7 @@ using Volo.Abp.EntityFrameworkCore; namespace MyCompanyName.MyProjectName.Migrations { [DbContext(typeof(UnifiedDbContext))] - [Migration("20240110051810_Initial")] + [Migration("20240125061424_Initial")] partial class Initial { /// @@ -1337,6 +1337,8 @@ namespace MyCompanyName.MyProjectName.Migrations b.HasIndex("Name"); + b.HasIndex("NormalizedName"); + b.ToTable("AbpTenants", (string)null); }); diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/20240110051810_Initial.cs b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/20240125061424_Initial.cs similarity index 99% rename from templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/20240110051810_Initial.cs rename to templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/20240125061424_Initial.cs index 014376034b..469e6eac08 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/20240110051810_Initial.cs +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/20240125061424_Initial.cs @@ -778,6 +778,11 @@ namespace MyCompanyName.MyProjectName.Migrations table: "AbpTenants", column: "Name"); + migrationBuilder.CreateIndex( + name: "IX_AbpTenants_NormalizedName", + table: "AbpTenants", + column: "NormalizedName"); + migrationBuilder.CreateIndex( name: "IX_AbpUserClaims_UserId", table: "AbpUserClaims", diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/UnifiedDbContextModelSnapshot.cs b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/UnifiedDbContextModelSnapshot.cs index 7a50a01df4..b6fd7b9e97 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/UnifiedDbContextModelSnapshot.cs +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/UnifiedDbContextModelSnapshot.cs @@ -1334,6 +1334,8 @@ namespace MyCompanyName.MyProjectName.Migrations b.HasIndex("Name"); + b.HasIndex("NormalizedName"); + b.ToTable("AbpTenants", (string)null); }); From 5f5085a48554953df5befa0ddfb59f0e45f962ef Mon Sep 17 00:00:00 2001 From: maliming Date: Thu, 25 Jan 2024 14:34:55 +0800 Subject: [PATCH 80/98] Remove `Nito.AsyncEx.Coordination` package from `Volo.Abp.Core`. --- framework/src/Volo.Abp.Core/Volo.Abp.Core.csproj | 1 - 1 file changed, 1 deletion(-) diff --git a/framework/src/Volo.Abp.Core/Volo.Abp.Core.csproj b/framework/src/Volo.Abp.Core/Volo.Abp.Core.csproj index 042cbd270c..8804c8868f 100644 --- a/framework/src/Volo.Abp.Core/Volo.Abp.Core.csproj +++ b/framework/src/Volo.Abp.Core/Volo.Abp.Core.csproj @@ -31,7 +31,6 @@ - From 771e93ecfc65edd7d48a7b9809a1cf82c448b102 Mon Sep 17 00:00:00 2001 From: maliming Date: Thu, 25 Jan 2024 14:35:20 +0800 Subject: [PATCH 81/98] Update Directory.Packages.props --- Directory.Packages.props | 1 - 1 file changed, 1 deletion(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index b9c94c0106..f5cf8871de 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -107,7 +107,6 @@ - From bf3b665de17487a5ccb262d743aa9afcc70b53bb Mon Sep 17 00:00:00 2001 From: Salih Date: Thu, 25 Jan 2024 09:48:27 +0300 Subject: [PATCH 82/98] Update en.json --- .../AbpIoLocalization/Admin/Localization/Resources/en.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json index aa16e3931c..ee660f72e4 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json @@ -592,6 +592,8 @@ "OrganizationId": "Organization Id", "RemoveAllWinnersConfirmationMessage": "Are you sure you want to remove all winners?", "AutoRenewals": "Auto Renewals", - "OrganizationHasCreditCard": "Organization has credit card. Please remove credit card first!" + "OrganizationHasCreditCard": "Organization has credit card. Please remove credit card first!", + "DisplayName:DontSendEmailForLicenseExpire": "Don't Send Email For License Expire", + "DontSendEmailForLicenseExpire": "Don't Send Email For License Expire" } } From 46afb5e3f9f96356457ee1b7e2c1dc5aafc32cee Mon Sep 17 00:00:00 2001 From: Enis Necipoglu Date: Thu, 25 Jan 2024 10:30:01 +0300 Subject: [PATCH 83/98] Update EmailSettingGroupViewComponent.razor --- .../EmailSettingGroup/EmailSettingGroupViewComponent.razor | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.Blazor/Pages/SettingManagement/EmailSettingGroup/EmailSettingGroupViewComponent.razor b/modules/setting-management/src/Volo.Abp.SettingManagement.Blazor/Pages/SettingManagement/EmailSettingGroup/EmailSettingGroupViewComponent.razor index e80115cfde..177f1d75fa 100644 --- a/modules/setting-management/src/Volo.Abp.SettingManagement.Blazor/Pages/SettingManagement/EmailSettingGroup/EmailSettingGroupViewComponent.razor +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.Blazor/Pages/SettingManagement/EmailSettingGroup/EmailSettingGroupViewComponent.razor @@ -95,7 +95,7 @@ @if (HasSendTestEmailPermission) { - + } From 5d8d15917a94c3eb8a868f4d5dd1d1cf59dcd421 Mon Sep 17 00:00:00 2001 From: Salih Date: Thu, 25 Jan 2024 11:17:17 +0300 Subject: [PATCH 84/98] Update en.json --- .../AbpIoLocalization/Commercial/Localization/Resources/en.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json index e5d8c15ac2..dcf3423484 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json @@ -1129,7 +1129,7 @@ "NameOnCard": "Name on Card", "BillingDetails": "Billing Details", "ThereIsNoDeveloper": "There is no developer.", - "CardDetails": "Card Details", + "CardDetails": "Debit/Credit Card Details", "NoActiveLicence": "You are not eligible for this action! You have no active license." } } From aa832dbfaadc218dc98ea6f997060c22a9f9b1e0 Mon Sep 17 00:00:00 2001 From: Engincan VESKE Date: Thu, 25 Jan 2024 13:39:30 +0300 Subject: [PATCH 85/98] Update Post.md --- .../2024-01-04-CLI-Online-Translate/Post.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/en/Community-Articles/2024-01-04-CLI-Online-Translate/Post.md b/docs/en/Community-Articles/2024-01-04-CLI-Online-Translate/Post.md index abddfd43fd..285d7d5dc9 100644 --- a/docs/en/Community-Articles/2024-01-04-CLI-Online-Translate/Post.md +++ b/docs/en/Community-Articles/2024-01-04-CLI-Online-Translate/Post.md @@ -1,12 +1,12 @@ # Use Deepl to translate localization files -Translating localized text during the development ABP modules is a boring work. For this reason we have added the `translate` command to the CLI tool to translate the localization files, but it still requires manual translate texts by the developer. +Translating localized text during the development of ABP modules is a boring job. For this reason, we have added the `translate` command to the CLI tool to translate the localization files, but it still requires manual translation of texts by the developer. -Now, We introduce a new way to translate the target language, which is to use the [Deepl](https://www.deepl.com/translator) translation service to translate the target language. +Now, we introduce a new way to translate the target language, which is to use the [Deepl](https://www.deepl.com/translator) translation service to translate the target language. -You can use the `translate --online` command to in your module directory to translate the target language. +You can use the `translate --online` command in your module directory to translate the target language. -For example, You have added all `en` localization texts to your module, and you want to translate them to `zh-Hans`, you can run the following command: +For example, if you have added all `en` localization texts to your module, and you want to translate them to `zh-Hans`, you can run the following command: ``` abp translate -r en -c zh-Hans --online --deepl-auth-key your_auth_key From 2282441869e7b821dce4684f377ee1822eedac22 Mon Sep 17 00:00:00 2001 From: Salih Date: Thu, 25 Jan 2024 15:42:50 +0300 Subject: [PATCH 86/98] Fix: Selects on docs shrinks to unusable sizes on mobile --- .../Pages/Documents/Project/Index.cshtml | 55 ++++++++++++------- 1 file changed, 36 insertions(+), 19 deletions(-) diff --git a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml index 85d402c11d..d285ae5338 100644 --- a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml +++ b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml @@ -332,28 +332,45 @@ - @foreach (var parameter in Model.DocumentPreferences.Parameters) - { -
-
- @(parameter.DisplayName) - + @foreach (var value in parameter.Values.OrderBy(p => p.Value)) { - + @if (value.Key == (Model.UserPreferences.ContainsKey(parameter.Name) ? Model.UserPreferences[parameter.Name] : null)) + { + + } + else + { + + } } - } - + +
- + } }
From 6784765b793ffef95b808c8abc5e3243481f97e3 Mon Sep 17 00:00:00 2001 From: Enis Necipoglu Date: Thu, 25 Jan 2024 15:47:25 +0300 Subject: [PATCH 87/98] Update FeatureManagementModal.cshtml --- .../Pages/FeatureManagement/FeatureManagementModal.cshtml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Web/Pages/FeatureManagement/FeatureManagementModal.cshtml b/modules/feature-management/src/Volo.Abp.FeatureManagement.Web/Pages/FeatureManagement/FeatureManagementModal.cshtml index ca38284046..a3a00a89c1 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.Web/Pages/FeatureManagement/FeatureManagementModal.cshtml +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Web/Pages/FeatureManagement/FeatureManagementModal.cshtml @@ -123,8 +123,8 @@
- @L["ResetToDefault"] - @L["Cancel"] + @L["Cancel"] + @L["ResetToDefault"] @L["Save"] } From 66cf8377cfe50b86d0789fa1f9cf3f729ee7cc9d Mon Sep 17 00:00:00 2001 From: Enis Necipoglu Date: Thu, 25 Jan 2024 15:50:43 +0300 Subject: [PATCH 88/98] Update Create.cshtml --- .../Volo.CmsKit.Admin.Web/Pages/CmsKit/BlogPosts/Create.cshtml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/BlogPosts/Create.cshtml b/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/BlogPosts/Create.cshtml index 190df58ecb..5c855e9ffe 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/BlogPosts/Create.cshtml +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/BlogPosts/Create.cshtml @@ -132,7 +132,7 @@ - + @if ((await AuthorizationService.AuthorizeAsync(CmsKitAdminPermissions.BlogPosts.Publish)).Succeeded) { From 893b038efc72edb3fb0b7ae351d3180bb0c311da Mon Sep 17 00:00:00 2001 From: Salih Date: Thu, 25 Jan 2024 15:57:53 +0300 Subject: [PATCH 89/98] Update Index.cshtml --- .../src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml index d285ae5338..83f4c7a775 100644 --- a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml +++ b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml @@ -337,12 +337,13 @@ var count = Model.DocumentPreferences.Parameters.Count; var rowCount = count / maxCellCount + (count % maxCellCount > 0 ? 1 : 0); var cellSize = 12 / (count > maxCellCount ? maxCellCount : count); + var latestCellSize = 12 / count - (rowCount - 1) * maxCellCount; string BuildParameterDivClass(int index) { var row = index / maxCellCount; var isLastRow = row == rowCount - 1; - var currentCellSize = isLastRow ? 12 / (count % maxCellCount) : cellSize; + var currentCellSize = isLastRow ? latestCellSize : cellSize; return $"col-12 col-lg-{currentCellSize} mb-lg-{(isLastRow ? "0" : "2")} {(index == count - 1 ? "" : "mb-2")}"; } From 50e952bd6263b1bd95de377be4a3c291b6e20dce Mon Sep 17 00:00:00 2001 From: Salih Date: Thu, 25 Jan 2024 16:19:12 +0300 Subject: [PATCH 90/98] Add new localizations --- .../AbpIoLocalization/Www/Localization/Resources/en.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/en.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/en.json index d1bc23b308..ec2d301a29 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/en.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/en.json @@ -353,6 +353,8 @@ "BuildSolutionsWithAbp": "Build maintainable .NET solutions by following software development best practices using ABP.", "BuyOnAmazon": "Buy on Amazon", "BuyOnPackt": "Buy on Packt", + "BuyOnDangDang": "Buy on DangDang", + "BuyOnJD": "Buy on JD", "Discounted": "Discounted", "MasteringAbpFramework_Book_KeyFeatures": "Key Features", "MasteringAbpFramework_Book_Key_Features_Description_1": "Build robust, maintainable, modular, and scalable software solutions using ABP Framework.", From 0fe8b8ab6f29561319979723ca60b2e574bacec5 Mon Sep 17 00:00:00 2001 From: Salih Date: Thu, 25 Jan 2024 16:42:24 +0300 Subject: [PATCH 91/98] Update zh-Hant.json --- .../AbpIoLocalization/Www/Localization/Resources/zh-Hant.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/zh-Hant.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/zh-Hant.json index 81664b5f8d..dc396ce8b9 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/zh-Hant.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/zh-Hant.json @@ -353,6 +353,8 @@ "BuildSolutionsWithAbp": "使用 ABP 遵循軟體開發最佳實務來建立可維護的 .NET 解決方案。", "BuyOnAmazon": "在亞馬遜上購買", "BuyOnPackt": "在 Packt 上購買", + "BuyOnDangDang": "在當當上購買", + "BuyOnJD": "在京東上購買", "Discounted": "折扣", "MasteringAbpFramework_Book_KeyFeatures": "主要特徵", "MasteringAbpFramework_Book_Key_Features_Description_1": "使用 ABP 框架建構健壯、可維護、模組化和可擴展的軟體解決方案。", From 8f6f075944a6f177c1632683ecbe18c49e65cb50 Mon Sep 17 00:00:00 2001 From: Salih Date: Thu, 25 Jan 2024 16:42:26 +0300 Subject: [PATCH 92/98] Update zh-Hans.json --- .../AbpIoLocalization/Www/Localization/Resources/zh-Hans.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/zh-Hans.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/zh-Hans.json index 9fb6a08b32..88d56a6303 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/zh-Hans.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/zh-Hans.json @@ -353,6 +353,8 @@ "BuildSolutionsWithAbp": "使用 ABP,遵循软件开发最佳实践,构建可维护的 .NET 解决方案。", "BuyOnAmazon": "在亚马逊上购买", "BuyOnPackt": "在 Packt 购买", + "BuyOnDangDang": "在当当网购买", + "BuyOnJD": "在京东上购买", "Discounted": "折扣", "MasteringAbpFramework_Book_KeyFeatures": "主要功能", "MasteringAbpFramework_Book_Key_Features_Description_1": "使用 ABP 框架构建稳健、可维护、模块化和可扩展的软件解决方案。", From 446de0b438eff6b465b678369824b24208f37b83 Mon Sep 17 00:00:00 2001 From: Enis Necipoglu Date: Thu, 25 Jan 2024 16:49:39 +0300 Subject: [PATCH 93/98] Reorder buttons in email setting group component --- .../Components/EmailSettingGroup/Default.cshtml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.Web/Pages/SettingManagement/Components/EmailSettingGroup/Default.cshtml b/modules/setting-management/src/Volo.Abp.SettingManagement.Web/Pages/SettingManagement/Components/EmailSettingGroup/Default.cshtml index 61d4dbe996..ee8db3e38f 100644 --- a/modules/setting-management/src/Volo.Abp.SettingManagement.Web/Pages/SettingManagement/Components/EmailSettingGroup/Default.cshtml +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.Web/Pages/SettingManagement/Components/EmailSettingGroup/Default.cshtml @@ -26,15 +26,15 @@
- - @L["Save"] - @if (await PermissionChecker.IsGrantedAsync(SettingManagementPermissions.EmailingTest)) { @L["SendTestEmail"] } + + @L["Save"] +
From 707b99f35a0d905b5d77037d8fea9f8fe1e9a7f5 Mon Sep 17 00:00:00 2001 From: Enis Necipoglu Date: Thu, 25 Jan 2024 16:52:02 +0300 Subject: [PATCH 94/98] Refactor email setting group view component --- .../EmailSettingGroup/EmailSettingGroupViewComponent.razor | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.Blazor/Pages/SettingManagement/EmailSettingGroup/EmailSettingGroupViewComponent.razor b/modules/setting-management/src/Volo.Abp.SettingManagement.Blazor/Pages/SettingManagement/EmailSettingGroup/EmailSettingGroupViewComponent.razor index 177f1d75fa..19f95ca52a 100644 --- a/modules/setting-management/src/Volo.Abp.SettingManagement.Blazor/Pages/SettingManagement/EmailSettingGroup/EmailSettingGroupViewComponent.razor +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.Blazor/Pages/SettingManagement/EmailSettingGroup/EmailSettingGroupViewComponent.razor @@ -92,11 +92,11 @@ - @if (HasSendTestEmailPermission) { } + From d3058a9a3ecd2d22717dfcb257416b9b76e7ac04 Mon Sep 17 00:00:00 2001 From: liangshiwei Date: Fri, 26 Jan 2024 10:01:29 +0800 Subject: [PATCH 95/98] Throw exception if provder was not found --- .../Volo/Abp/FeatureManagement/FeatureManager.cs | 2 +- .../Abp/FeatureManagement/FeatureManager_Tests.cs | 11 +++++++++++ .../PermissionManager_Tests.cs | 15 +++++++++++++++ .../Volo/Abp/SettingManagement/SettingManager.cs | 2 +- .../SettingManager_Basic_Tests.cs | 7 ++++--- 5 files changed, 32 insertions(+), 5 deletions(-) diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/FeatureManager.cs b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/FeatureManager.cs index 1a5356a1be..9805f03752 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/FeatureManager.cs +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/FeatureManager.cs @@ -144,7 +144,7 @@ public class FeatureManager : IFeatureManager, ISingletonDependency if (!providers.Any()) { - return; + throw new AbpException($"Unknown feature value provider: {providerName}"); } if (providers.Count > 1 && !forceToSet && value != null) diff --git a/modules/feature-management/test/Volo.Abp.FeatureManagement.Domain.Tests/Volo/Abp/FeatureManagement/FeatureManager_Tests.cs b/modules/feature-management/test/Volo.Abp.FeatureManagement.Domain.Tests/Volo/Abp/FeatureManagement/FeatureManager_Tests.cs index 831d021e38..fd4ea324ea 100644 --- a/modules/feature-management/test/Volo.Abp.FeatureManagement.Domain.Tests/Volo/Abp/FeatureManagement/FeatureManager_Tests.cs +++ b/modules/feature-management/test/Volo.Abp.FeatureManagement.Domain.Tests/Volo/Abp/FeatureManagement/FeatureManager_Tests.cs @@ -209,4 +209,15 @@ public class FeatureManager_Tests : FeatureManagementDomainTestBase (await _featureManager.GetOrNullAsync(TestFeatureDefinitionProvider.BackupCount, TenantFeatureValueProvider.ProviderName, TestEditionIds.TenantId.ToString())).ShouldBe("0"); } + + [Fact] + public async Task Set_Should_Throw_Exception_If_Provider_Not_Found() + { + var exception = await Assert.ThrowsAsync(async () => + { + await _featureManager.SetAsync(TestFeatureDefinitionProvider.EmailSupport, "true", "UndefinedProvider", "Test"); + }); + + exception.Message.ShouldBe("Unknown feature value provider: UndefinedProvider"); + } } diff --git a/modules/permission-management/test/Volo.Abp.PermissionManagement.Domain.Tests/Volo/Abp/PermissionManagement/PermissionManager_Tests.cs b/modules/permission-management/test/Volo.Abp.PermissionManagement.Domain.Tests/Volo/Abp/PermissionManagement/PermissionManager_Tests.cs index 1f771bdb3b..3f2e9c7565 100644 --- a/modules/permission-management/test/Volo.Abp.PermissionManagement.Domain.Tests/Volo/Abp/PermissionManagement/PermissionManager_Tests.cs +++ b/modules/permission-management/test/Volo.Abp.PermissionManagement.Domain.Tests/Volo/Abp/PermissionManagement/PermissionManager_Tests.cs @@ -134,6 +134,21 @@ public class PermissionManager_Tests : PermissionTestBase "Test", true); } + + [Fact] + public async Task Set_Should_Throw_Exception_If_Provider_Not_Found() + { + var exception = await Assert.ThrowsAsync(async () => + { + await _permissionManager.SetAsync( + "MyPermission1", + "UndefinedProvider", + "Test", + true); + }); + + exception.Message.ShouldBe("Unknown permission management provider: UndefinedProvider"); + } [Fact] public async Task UpdateProviderKey() diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain/Volo/Abp/SettingManagement/SettingManager.cs b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain/Volo/Abp/SettingManagement/SettingManager.cs index 68d66ee4b0..ddf451154d 100644 --- a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain/Volo/Abp/SettingManagement/SettingManager.cs +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain/Volo/Abp/SettingManagement/SettingManager.cs @@ -125,7 +125,7 @@ public class SettingManager : ISettingManager, ISingletonDependency if (!providers.Any()) { - throw new AbpException($"Could not find a setting provider named '{providerName}'."); + throw new AbpException($"Unknown setting value provider: {providerName}"); } if (setting.IsEncrypted) diff --git a/modules/setting-management/test/Volo.Abp.SettingManagement.Tests/Volo/Abp/SettingManagement/SettingManager_Basic_Tests.cs b/modules/setting-management/test/Volo.Abp.SettingManagement.Tests/Volo/Abp/SettingManagement/SettingManager_Basic_Tests.cs index 00dc337c0f..ca9db64c70 100644 --- a/modules/setting-management/test/Volo.Abp.SettingManagement.Tests/Volo/Abp/SettingManagement/SettingManager_Basic_Tests.cs +++ b/modules/setting-management/test/Volo.Abp.SettingManagement.Tests/Volo/Abp/SettingManagement/SettingManager_Basic_Tests.cs @@ -1,3 +1,4 @@ +using System; using System.Threading.Tasks; using Shouldly; using Volo.Abp.Settings; @@ -65,13 +66,13 @@ public class SettingManager_Basic_Tests : SettingsTestBase } [Fact] - public async Task Should_Throw_Exception_If_Provider_Not_Found() + public async Task Set_Should_Throw_Exception_If_Provider_Not_Found() { var exception = await Assert.ThrowsAsync(async () => { - await _settingManager.SetAsync("MySetting1", "43", "UndefinedProvider", "UndefinedProviderKey"); + await _settingManager.SetAsync("MySetting1", "43", "UndefinedProvider", "Test"); }); - exception.Message.ShouldBe("Could not find a setting provider named 'UndefinedProvider'."); + exception.Message.ShouldBe("Unknown setting value provider: UndefinedProvider"); } } \ No newline at end of file From 88e6fc7aa81b615c5c6d68194ca3024b4a518745 Mon Sep 17 00:00:00 2001 From: denizdemirkan Date: Fri, 26 Jan 2024 13:21:03 +0300 Subject: [PATCH 96/98] Preview word added --- .../AbpIoLocalization/Community/Localization/Resources/ar.json | 3 ++- .../AbpIoLocalization/Community/Localization/Resources/cs.json | 3 ++- .../AbpIoLocalization/Community/Localization/Resources/de.json | 3 ++- .../Community/Localization/Resources/en-GB.json | 3 ++- .../AbpIoLocalization/Community/Localization/Resources/en.json | 3 ++- .../AbpIoLocalization/Community/Localization/Resources/es.json | 3 ++- .../AbpIoLocalization/Community/Localization/Resources/fi.json | 3 ++- .../AbpIoLocalization/Community/Localization/Resources/fr.json | 3 ++- .../AbpIoLocalization/Community/Localization/Resources/hi.json | 3 ++- .../AbpIoLocalization/Community/Localization/Resources/hr.json | 3 ++- .../AbpIoLocalization/Community/Localization/Resources/hu.json | 3 ++- .../AbpIoLocalization/Community/Localization/Resources/is.json | 3 ++- .../AbpIoLocalization/Community/Localization/Resources/it.json | 3 ++- .../AbpIoLocalization/Community/Localization/Resources/nl.json | 3 ++- .../Community/Localization/Resources/pl-PL.json | 3 ++- .../Community/Localization/Resources/pt-BR.json | 3 ++- .../Community/Localization/Resources/ro-RO.json | 3 ++- .../AbpIoLocalization/Community/Localization/Resources/ru.json | 3 ++- .../AbpIoLocalization/Community/Localization/Resources/sk.json | 3 ++- .../AbpIoLocalization/Community/Localization/Resources/sl.json | 3 ++- .../AbpIoLocalization/Community/Localization/Resources/tr.json | 3 ++- .../AbpIoLocalization/Community/Localization/Resources/vi.json | 3 ++- .../Community/Localization/Resources/zh-Hans.json | 3 ++- .../Community/Localization/Resources/zh-Hant.json | 3 ++- 24 files changed, 48 insertions(+), 24 deletions(-) diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/ar.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/ar.json index df39dea75d..7151345ea9 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/ar.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/ar.json @@ -256,6 +256,7 @@ "RaffleHeader": "مرحبًا عضو مجتمع برنامج الجسر الأكاديمي!", "RafflesInfo": "
هذه هي صفحة السحب المخصصة لإظهار تقديرنا لك لكونك عضوًا نشطًا في المجتمع. نحن نقوم بإجراء محادثات مجتمعية لبرنامج ABP ، ومؤتمر ABP .NET ، ونحضر أو نرعى الأحداث المتعلقة بـ .NET والتي نقدم فيها بعض الهدايا.

يمكنك متابعة هذه الصفحة لرؤية السحوبات القادمة أو حضورها أو الاطلاع على السحوبات السابقة التي قمنا بسحبها بما في ذلك الفائزين.

شكرا لكونك عضوا نشطا! نراكم في السحوبات القادمة.", "RafflesInfoTitle": "سحوبات مجتمع ABP", - "MarkdownSupported": "Markdown أيد." + "MarkdownSupported": "Markdown أيد.", + "Preview": "معاينة" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/cs.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/cs.json index 4c6a229861..252b0dcb2b 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/cs.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/cs.json @@ -256,6 +256,7 @@ "RaffleHeader": "Dobrý den, člen komunity ABP!", "RafflesInfo": "
Toto je stránka s losováním věnovaná tomu, abychom vám ukázali naše uznání za to, že jste aktivním členem komunity. Pořádáme ABP Community Talks , ABP .NET Conference , účastníme se nebo sponzorujeme akce související s .NET, ve kterých rozdáváme nějaké dárky.

Na této stránce můžete sledovat nadcházející tomboly, zúčastnit se jich nebo si prohlédnout předchozí tomboly, které losujeme, včetně výherců.

Děkujeme, že jste aktivním členem! Uvidíme se v nadcházejícím slosování.", "RafflesInfoTitle": "Komunitní tomboly ABP", - "MarkdownSupported": "Markdown podporováno." + "MarkdownSupported": "Markdown podporováno.", + "Preview": "Náhled" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/de.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/de.json index 146985eb49..4326ff88ef 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/de.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/de.json @@ -256,6 +256,7 @@ "RaffleHeader": "Hallo ABP-Community-Mitglied!", "RafflesInfo": "
Auf dieser Verlosungsseite möchten wir Ihnen unsere Wertschätzung dafür zeigen, dass Sie ein aktives Community-Mitglied sind. Wir veranstalten ABP Community Talks und ABP .NET Conferences , nehmen an .NET-bezogenen Veranstaltungen teil oder sponsern diese, bei denen wir einige Geschenke verschenken.

Sie können dieser Seite folgen, um die bevorstehenden Verlosungen zu sehen, daran teilzunehmen oder frühere Verlosungen, die wir verlosen, einschließlich der Gewinner, anzusehen.

Vielen Dank, dass Sie ein aktives Mitglied sind! Wir sehen uns bei den kommenden Gewinnspielen.", "RafflesInfoTitle": "ABP-Community- Verlosungen", - "MarkdownSupported": "Markdown unterstützt." + "MarkdownSupported": "Markdown unterstützt.", + "Preview": "Vorschau" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/en-GB.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/en-GB.json index fc21345c05..347b18ce4b 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/en-GB.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/en-GB.json @@ -104,6 +104,7 @@ "CreatePostLanguageInfo": "Language of the post", "SeeMore": "See More", "MemberNotPublishedPostYet": "This member hasn't published any posts yet.", - "MarkdownSupported": "Markdown supported." + "MarkdownSupported": "Markdown supported.", + "Preview": "Preview" } } diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/en.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/en.json index 4bcd1bd525..b22fc19de8 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/en.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/en.json @@ -257,6 +257,7 @@ "RafflesInfo": "
This is the raffle page dedicated to show our appreciation towards you for being an active Community Member. We do ABP Community Talks ,ABP .NET Conference, attend or sponsor to the .NET-related events in which we give away some gifts.

You can follow this page to see the upcoming raffles, attend them, or see previous raffles we draw including the winners.

Thank you for being an active member! See you in the upcoming raffles.", "RafflesInfoTitle": "ABP Community Raffles", "ToLuckyWinner": "to 1 lucky winner", - "MarkdownSupported": "Markdown supported." + "MarkdownSupported": "Markdown supported.", + "Preview": "Preview" } } diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/es.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/es.json index f24cb1d511..c53b45ab81 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/es.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/es.json @@ -256,6 +256,7 @@ "RaffleHeader": "¡Hola miembro de la comunidad ABP!", "RafflesInfo": "
Esta es la página del sorteo dedicada a mostrarle nuestro agradecimiento por ser un miembro activo de la comunidad. Realizamos charlas comunitarias de ABP , conferencias ABP .NET , asistimos o patrocinamos eventos relacionados con .NET en los que regalamos algunos obsequios.

Puedes seguir esta página para ver los próximos sorteos, asistir a ellos o ver sorteos anteriores que sorteamos incluyendo a los ganadores.

¡Gracias por ser un miembro activo! Nos vemos en los próximos sorteos.", "RafflesInfoTitle": "Rifas de la Comunidad ABP", - "MarkdownSupported": "Markdown soportado." + "MarkdownSupported": "Markdown soportado.", + "Preview": "Avance" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/fi.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/fi.json index a42a7d693f..abd8cdd21f 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/fi.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/fi.json @@ -256,6 +256,7 @@ "RaffleHeader": "Hei ABP-yhteisön jäsen!", "RafflesInfo": "
Tämä on arvontasivu, joka on omistettu osoittamaan kiitollisuuttamme sinua kohtaan, että olet aktiivinen yhteisön jäsen. Teemme ABP Community Talksia , ABP .NET -konferenssia , osallistumme tai sponsoroimme .NET-tapahtumia, joissa annamme lahjoja.

Voit seurata tätä sivua nähdäksesi tulevat arvonnat, osallistua niihin tai nähdäksesi aiemmat arvonnamme, mukaan lukien voittajat.

Kiitos aktiivisesta jäsenyydestäsi! Nähdään tulevissa arvonnassa.", "RafflesInfoTitle": "ABP-yhteisön arpajaiset", - "MarkdownSupported": "Markdown tuettu." + "MarkdownSupported": "Markdown tuettu.", + "Preview": "Esikatselu" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/fr.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/fr.json index 2ed85aaa95..1f259aac6d 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/fr.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/fr.json @@ -256,6 +256,7 @@ "RaffleHeader": "Bonjour membre de la communauté ABP !", "RafflesInfo": "
Ceci est la page de tirage au sort dédiée à vous montrer notre gratitude pour votre participation active à la communauté. Nous organisons des discussions communautaires ABP , des conférences ABP .NET , assistons ou sponsorisons des événements liés à .NET au cours desquels nous offrons des cadeaux.

Vous pouvez suivre cette page pour voir les tirages au sort à venir, y assister ou voir les tirages au sort précédents que nous tirons, y compris les gagnants.

Merci d'être un membre actif ! Rendez-vous lors des prochains tirages au sort.", "RafflesInfoTitle": "Tirages au sort communautaires ABP", - "MarkdownSupported": "Markdown prise en charge." + "MarkdownSupported": "Markdown prise en charge.", + "Preview": "Aperçu" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/hi.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/hi.json index 6a969b99f3..b868260ae6 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/hi.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/hi.json @@ -256,6 +256,7 @@ "RaffleHeader": "नमस्ते एबीपी समुदाय सदस्य!", "RafflesInfo": "
यह रैफ़ल पेज है जो एक सक्रिय समुदाय सदस्य होने के लिए आपके प्रति हमारी सराहना दिखाने के लिए समर्पित है। हम एबीपी सामुदायिक वार्ता , एबीपी .NET सम्मेलन करते हैं, .NET से संबंधित कार्यक्रमों में भाग लेते हैं या प्रायोजित करते हैं जिसमें हम कुछ उपहार देते हैं।

आप आगामी रैफ़ल देखने, उनमें भाग लेने, या विजेताओं सहित हमारे द्वारा निकाले गए पिछले रैफ़ल देखने के लिए इस पृष्ठ का अनुसरण कर सकते हैं।

सक्रिय सदस्य बनने के लिए धन्यवाद! आगामी रैफ़ल में मिलते हैं।", "RafflesInfoTitle": "एबीपी कम्युनिटी रैफल्स", - "MarkdownSupported": "Markdown का समर्थन किया।" + "MarkdownSupported": "Markdown का समर्थन किया।", + "Preview": "पूर्व दर्शन" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/hr.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/hr.json index 4e213a9c66..eb3b66d9c8 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/hr.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/hr.json @@ -256,6 +256,7 @@ "RaffleHeader": "Pozdrav članu ABP zajednice!", "RafflesInfo": "
Ovo je stranica za nagradnu igru namijenjena da vam pokažemo našu zahvalnost što ste aktivni član zajednice. Vodimo razgovore o ABP zajednici , ABP .NET konferenciji , prisustvujemo ili sponzoriramo događaje vezane uz .NET na kojima dijelimo neke darove.

Možete pratiti ovu stranicu kako biste vidjeli nadolazeće nagradne igre, prisustvovali im ili vidjeli prethodne nagradne igre koje izvlačimo uključujući dobitnike.

Hvala vam što ste aktivan član! Vidimo se u nadolazećim nagradnim igrama.", "RafflesInfoTitle": "Izvlačenje nagradne igre zajednice ABP", - "MarkdownSupported": "Markdown podržan." + "MarkdownSupported": "Markdown podržan.", + "Preview": "Pregled" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/hu.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/hu.json index f489cdc571..08917573ff 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/hu.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/hu.json @@ -256,6 +256,7 @@ "RaffleHeader": "Kedves ABP közösségi tag!", "RafflesInfo": "
Ez az a sorsolási oldal, amelynek célja, hogy kifejezzük hálánkat feléd, amiért aktív közösségi tag vagy. Az ABP Community Talks-okat , az ABP .NET konferenciákat szervezzük, részt veszünk vagy szponzorálunk olyan .NET-hez kapcsolódó eseményeket, amelyeken ajándékokat adunk.

Ezt az oldalt követheti, hogy megtekinthesse a közelgő sorsolásokat, részt vegyen azokon, vagy megtekinthesse korábbi sorsolásainkat, beleértve a nyerteseket is.

Köszönjük, hogy aktív tag vagy! Találkozunk a sorsoláson.", "RafflesInfoTitle": "ABP közösségi tombola", - "MarkdownSupported": "Markdown támogatott." + "MarkdownSupported": "Markdown támogatott.", + "Preview": "Előnézet" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/is.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/is.json index 32284f5f37..0d8eb6cb48 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/is.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/is.json @@ -256,6 +256,7 @@ "RaffleHeader": "Halló ABP samfélagsmeðlimur!", "RafflesInfo": "
Þetta er happdrættisíðan sem er tileinkuð þér að þakka þér fyrir að vera virkur samfélagsmeðlimur. Við gerum ABP Community Talks , ABP .NET ráðstefnu , sækjum eða styrkjum .NET tengda viðburði þar sem við gefum nokkrar gjafir.

Þú getur fylgst með þessari síðu til að sjá komandi happdrætti, mæta á þær eða sjá fyrri happdrætti sem við drögum út, þar á meðal vinningshafa.

Þakka þér fyrir að vera virkur meðlimur! Sjáumst í komandi happdrætti.", "RafflesInfoTitle": "ABP samfélagshappdrætti", - "MarkdownSupported": "Markdown stutt." + "MarkdownSupported": "Markdown stutt.", + "Preview": "Forskoðun" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/it.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/it.json index 301c1e84e7..a301a7f482 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/it.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/it.json @@ -256,6 +256,7 @@ "RaffleHeader": "Ciao membro della comunità ABP!", "RafflesInfo": "
Questa è la pagina della lotteria dedicata a mostrare il nostro apprezzamento nei tuoi confronti per essere un membro attivo della comunità. Organizziamo ABP Community Talks , ABP .NET Conference , partecipiamo o sponsorizziamo eventi relativi a .NET in cui regaliamo alcuni regali.

Puoi seguire questa pagina per vedere le prossime lotterie, parteciparvi o vedere le lotterie precedenti che estraiamo, compresi i vincitori.

Grazie per essere un membro attivo! Ci vediamo alle prossime lotterie.", "RafflesInfoTitle": "Lotterie comunitarie ABP", - "MarkdownSupported": "Markdown supportato." + "MarkdownSupported": "Markdown supportato.", + "Preview": "Anteprima" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/nl.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/nl.json index 8beba46650..45b3024c96 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/nl.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/nl.json @@ -256,6 +256,7 @@ "RaffleHeader": "Hallo ABP Community-lid!", "RafflesInfo": "
Dit is de loterijpagina die bedoeld is om onze waardering voor u te tonen omdat u een actief lid van de community bent. We houden ABP Community Talks , ABP .NET Conference , wonen of sponsoren de .NET-gerelateerde evenementen bij waarin we een aantal geschenken weggeven.

U kunt deze pagina volgen om de komende loterijen te zien, deze bij te wonen of eerdere loterijen te zien die we trekken, inclusief de winnaars.

Bedankt dat u een actief lid bent! Tot ziens bij de komende loterijen.", "RafflesInfoTitle": "ABP- gemeenschaploterijen", - "MarkdownSupported": "Markdown ondersteund." + "MarkdownSupported": "Markdown ondersteund.", + "Preview": "Voorbeeld" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/pl-PL.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/pl-PL.json index e47be75ccc..124f910ac0 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/pl-PL.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/pl-PL.json @@ -256,6 +256,7 @@ "RaffleHeader": "Witaj, członku społeczności ABP!", "RafflesInfo": "
To jest strona loterii, której celem jest wyrażenie naszego uznania dla Ciebie za bycie aktywnym członkiem społeczności. Prowadzimy rozmowy społecznościowe ABP , konferencje ABP .NET , uczestniczymy lub sponsorujemy wydarzenia związane z .NET, podczas których rozdajemy prezenty.

Możesz śledzić tę stronę, aby zobaczyć nadchodzące loterie, wziąć w nich udział lub zobaczyć poprzednie loterie, które losowaliśmy, w tym zwycięzców.

Dziękujemy za bycie aktywnym członkiem! Do zobaczenia w nadchodzących loteriach.", "RafflesInfoTitle": "Loterie społecznościowe ABP", - "MarkdownSupported": "Markdown utrzymany." + "MarkdownSupported": "Markdown utrzymany.", + "Preview": "Zapowiedź" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/pt-BR.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/pt-BR.json index d987c03211..419ef77140 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/pt-BR.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/pt-BR.json @@ -256,6 +256,7 @@ "RaffleHeader": "Olá, membro da comunidade ABP!", "RafflesInfo": "
Esta é a página do sorteio dedicada a mostrar nosso agradecimento por você ser um membro ativo da comunidade. Fazemos ABP Community Talks , ABP .NET Conference , participamos ou patrocinamos eventos relacionados ao .NET nos quais distribuímos alguns presentes.

Você pode seguir esta página para ver os próximos sorteios, participar deles ou ver os sorteios anteriores que sorteamos, incluindo os vencedores.

Obrigado por ser um membro ativo! Nos vemos nos próximos sorteios.", "RafflesInfoTitle": "Sorteios da Comunidade ABP", - "MarkdownSupported": "Markdown suportado." + "MarkdownSupported": "Markdown suportado.", + "Preview": "Visualização" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/ro-RO.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/ro-RO.json index 06ecc4dea8..47e513f125 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/ro-RO.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/ro-RO.json @@ -256,6 +256,7 @@ "RaffleHeader": "Bună ziua, membru al comunității ABP!", "RafflesInfo": "
Aceasta este pagina de tombolă dedicată pentru a arăta aprecierea noastră față de dvs. pentru că sunteți un membru activ al comunității. Facem ABP Community Talks , ABP .NET Conference , participăm sau sponsorizăm evenimentele legate de .NET în care oferim câteva cadouri.

Puteți urmări această pagină pentru a vedea tombolele viitoare, a participa la ele sau pentru a vedea tombolele anterioare pe care le extragem, inclusiv câștigătorii.

Vă mulțumim că sunteți un membru activ! Ne vedem la tombolele viitoare.", "RafflesInfoTitle": "Tombole comunitare ABP", - "MarkdownSupported": "Markdown sprijinit." + "MarkdownSupported": "Markdown sprijinit.", + "Preview": "previzualizare" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/ru.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/ru.json index 07d6a87fe9..b91893ce94 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/ru.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/ru.json @@ -259,6 +259,7 @@ "RaffleHeader": "Привет, участник сообщества ABP!", "RafflesInfo": "
Эта страница розыгрыша посвящена тому, чтобы выразить нашу признательность вам за то, что вы являетесь активным членом сообщества. Обсуждения сообщества ABP ,Конференция ABP .NET, посещать или спонсировать мероприятия, связанные с .NET, на которых мы раздаем подарки.

Вы можете подписаться на эту страницу, чтобы увидеть предстоящие розыгрыши, посетить их или просмотреть предыдущие розыгрыши, которые мы проводим, включая победителей.

Спасибо за активное участие! ", "RafflesInfoTitle": "Сообщество АБП Розыгрыши", - "MarkdownSupported": "Markdown поддерживается." + "MarkdownSupported": "Markdown поддерживается.", + "Preview": "Предварительный просмотр" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/sk.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/sk.json index fa9826b421..25a73a6bd7 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/sk.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/sk.json @@ -256,6 +256,7 @@ "RaffleHeader": "Dobrý deň, člen komunity ABP!", "RafflesInfo": "
Toto je stránka žrebovania venovaná na vyjadrenie nášho uznania vám za to, že ste aktívnym členom komunity. Robíme ABP Community Talks , ABP .NET konferenciu , zúčastňujeme sa alebo sponzorujeme podujatia súvisiace s .NET, na ktorých rozdávame nejaké darčeky.

Na tejto stránke si môžete pozrieť pripravované tomboly, zúčastniť sa ich alebo si pozrieť predchádzajúce žrebovanie, ktoré vyžrebujeme vrátane výhercov.

Ďakujeme, že ste aktívnym členom! Vidíme sa v najbližšom žrebovaní.", "RafflesInfoTitle": "Komunitné tomboly ABP", - "MarkdownSupported": "Markdown podporované." + "MarkdownSupported": "Markdown podporované.", + "Preview": "Náhľad" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/sl.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/sl.json index 81e103cd17..b6192142c6 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/sl.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/sl.json @@ -256,6 +256,7 @@ "RaffleHeader": "Pozdravljeni član skupnosti ABP!", "RafflesInfo": "
To je stran za nagradno igro, namenjena izkazovanju naše hvaležnosti do vas, ker ste aktivni član skupnosti. Izvajamo ABP Community Talks , ABP .NET Conference , se udeležujemo ali sponzoriramo dogodke, povezane z .NET, na katerih podarimo nekaj daril.

To stran lahko spremljate in si ogledate prihajajoče nagradne igre, se jih udeležite ali si ogledate prejšnje nagradne igre, ki smo jih izžrebali, vključno z zmagovalci.

Hvala, ker ste aktivni član! Se vidimo na prihajajočih nagradnih igrah.", "RafflesInfoTitle": "Žrebanje skupnosti ABP", - "MarkdownSupported": "Markdown podprt." + "MarkdownSupported": "Markdown podprt.", + "Preview": "Predogled" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/tr.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/tr.json index d184bb63d1..88c88208e8 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/tr.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/tr.json @@ -190,6 +190,7 @@ "Index_Page_CommunityIntroduction": "Burası ABP Çerçevesi, .NET ve yazılım geliştirme için bir merkezdir. Makaleleri okuyabilir, eğitim videolarını izleyebilir, ABP'nin gelişim süreci ve ABP ile ilgili etkinlikler hakkında bilgi alabilir, diğer geliştiricilere yardımcı olabilir ve uzmanlığınızı ABP topluluğu ile paylaşabilirsiniz.", "IConsentToMedium": "Bu yazının https://medium.com/volosoft adresinde yayınlanmasına izin veriyorum.", "DiscordPageTitle": "ABP Discord Topluluğu", - "MarkdownSupported": "Markdown destekleniyor." + "MarkdownSupported": "Markdown destekleniyor.", + "Preview": "Ön izleme" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/vi.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/vi.json index d7febbb014..e195a80fa5 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/vi.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/vi.json @@ -256,6 +256,7 @@ "RaffleHeader": "Xin chào Thành viên Cộng đồng ABP!", "RafflesInfo": "
Đây là trang xổ số dành riêng để thể hiện sự đánh giá cao của chúng tôi đối với bạn vì đã trở thành Thành viên cộng đồng tích cực. Chúng tôi tổ chức các buổi nói chuyện cộng đồng ABP , Hội nghị ABP .NET , tham dự hoặc tài trợ cho các sự kiện liên quan đến .NET mà trong đó chúng tôi tặng một số quà tặng.

Bạn có thể theo dõi trang này để xem các cuộc xổ số sắp tới, tham dự hoặc xem các cuộc xổ số trước đây mà chúng tôi rút ra bao gồm cả những người chiến thắng.

Cảm ơn bạn đã là thành viên tích cực! Hẹn gặp lại các bạn trong đợt xổ số sắp tới.", "RafflesInfoTitle": "Xổ số cộng đồng ABP", - "MarkdownSupported": "Markdown được hỗ trợ." + "MarkdownSupported": "Markdown được hỗ trợ.", + "Preview": "Xem trước" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/zh-Hans.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/zh-Hans.json index c0aaf2678b..fd1130b894 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/zh-Hans.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/zh-Hans.json @@ -256,6 +256,7 @@ "RaffleHeader": "你好,ABP 社区成员!", "RafflesInfo": "
这是一个抽奖页面,旨在感谢您成为活跃的社区成员。我们举办 ABP 社区讲座 、ABP .NET 会议,参加或赞助与 .NET 相关的活动,并在活动中赠送一些礼品。

您可以关注此页面,查看即将举行的抽奖活动、参加这些活动或查看我们以前举行的抽奖活动(包括获奖者)。

感谢您成为我们的活跃成员!在即将举行的抽奖活动中再见。", "RafflesInfoTitle": "ABP 社区来抽奖Markdown 支持的。" + "MarkdownSupported": "Markdown 支持的。", + "Preview": "预览" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/zh-Hant.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/zh-Hant.json index 7f8e58f7df..e5725ce996 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/zh-Hant.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/zh-Hant.json @@ -256,6 +256,7 @@ "RaffleHeader": "ABP 社群成員您好!", "RafflesInfo": "
這是抽獎頁面,旨在表達我們對您作為活躍社區成員的感謝。我們舉辦ABP 社群講座、ABP .NET 會議、參加或贊助 .NET 相關活動,並在活動中贈送一些禮物。

您可以關注此頁面查看即將舉行的抽獎活動、參加抽獎活動或查看我們之前抽獎的抽獎活動(包括獲獎者)。

感謝您成為活躍會員!在即將到來的抽獎活動中再見。", "RafflesInfoTitle": "ABP 社區萊佛士", - "MarkdownSupported": "Markdown 支持的。" + "MarkdownSupported": "Markdown 支持的。", + "Preview": "预览" } } \ No newline at end of file From ed266b79bf9317bb6e7527256e811a9a17fcc65e Mon Sep 17 00:00:00 2001 From: Salih Date: Fri, 26 Jan 2024 18:33:33 +0300 Subject: [PATCH 97/98] Fix: tooltip seems broken --- modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/index.js b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/index.js index f23100d34a..fef573f413 100644 --- a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/index.js +++ b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/index.js @@ -283,7 +283,7 @@ initDocumentNodeBreadcrumb(); Element.prototype.querySelector = function (selector) { - var result = $(decodeURI(selector)); + var result = $(this).find(decodeURI(selector)); if(result.length > 0){ return result[0]; } From 8d9e3e09f8046ab71114103a67e7d9669e4bc717 Mon Sep 17 00:00:00 2001 From: liangshiwei Date: Mon, 29 Jan 2024 09:37:42 +0800 Subject: [PATCH 98/98] Improve --- .../PermissionValueProviderManager.cs | 17 ++++++++--------- .../Abp/Features/FeatureValueProviderManager.cs | 17 ++++++++--------- .../Abp/Settings/SettingValueProviderManager.cs | 17 ++++++++--------- 3 files changed, 24 insertions(+), 27 deletions(-) diff --git a/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/PermissionValueProviderManager.cs b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/PermissionValueProviderManager.cs index 09b2da2acb..aebd14f36e 100644 --- a/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/PermissionValueProviderManager.cs +++ b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/PermissionValueProviderManager.cs @@ -9,29 +9,28 @@ namespace Volo.Abp.Authorization.Permissions; public class PermissionValueProviderManager : IPermissionValueProviderManager, ISingletonDependency { - public IReadOnlyList ValueProviders => GetProviders(); + public IReadOnlyList ValueProviders => _lazyProviders.Value; private readonly Lazy> _lazyProviders; protected AbpPermissionOptions Options { get; } + protected IServiceProvider ServiceProvider { get; } public PermissionValueProviderManager( IServiceProvider serviceProvider, IOptions options) { Options = options.Value; + ServiceProvider = serviceProvider; - _lazyProviders = new Lazy>( - () => Options - .ValueProviders - .Select(c => serviceProvider.GetRequiredService(c) as IPermissionValueProvider) - .ToList()!, - true - ); + _lazyProviders = new Lazy>(GetProviders, true); } protected virtual List GetProviders() { - var providers = _lazyProviders.Value; + var providers = Options + .ValueProviders + .Select(type => (ServiceProvider.GetRequiredService(type) as IPermissionValueProvider)!) + .ToList(); var multipleProviders = providers.GroupBy(p => p.Name).FirstOrDefault(x => x.Count() > 1); if(multipleProviders != null) diff --git a/framework/src/Volo.Abp.Features/Volo/Abp/Features/FeatureValueProviderManager.cs b/framework/src/Volo.Abp.Features/Volo/Abp/Features/FeatureValueProviderManager.cs index 98d73dd4e4..c793ee8ce5 100644 --- a/framework/src/Volo.Abp.Features/Volo/Abp/Features/FeatureValueProviderManager.cs +++ b/framework/src/Volo.Abp.Features/Volo/Abp/Features/FeatureValueProviderManager.cs @@ -9,29 +9,28 @@ namespace Volo.Abp.Features; public class FeatureValueProviderManager : IFeatureValueProviderManager, ISingletonDependency { - public IReadOnlyList ValueProviders => GetProviders(); + public IReadOnlyList ValueProviders => _lazyProviders.Value; private readonly Lazy> _lazyProviders; protected AbpFeatureOptions Options { get; } + protected IServiceProvider ServiceProvider { get; } public FeatureValueProviderManager( IServiceProvider serviceProvider, IOptions options) { Options = options.Value; + ServiceProvider = serviceProvider; - _lazyProviders = new Lazy>( - () => Options - .ValueProviders - .Select(c => serviceProvider.GetRequiredService(c) as IFeatureValueProvider) - .ToList()!, - true - ); + _lazyProviders = new Lazy>(GetProviders, true); } protected virtual List GetProviders() { - var providers = _lazyProviders.Value; + var providers = Options + .ValueProviders + .Select(type => (ServiceProvider.GetRequiredService(type) as IFeatureValueProvider)!) + .ToList(); var multipleProviders = providers.GroupBy(p => p.Name).FirstOrDefault(x => x.Count() > 1); if(multipleProviders != null) diff --git a/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingValueProviderManager.cs b/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingValueProviderManager.cs index c13f884e98..116fae5643 100644 --- a/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingValueProviderManager.cs +++ b/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingValueProviderManager.cs @@ -9,9 +9,10 @@ namespace Volo.Abp.Settings; public class SettingValueProviderManager : ISettingValueProviderManager, ISingletonDependency { - public List Providers => GetProviders(); + public List Providers => _lazyProviders.Value; protected AbpSettingOptions Options { get; } + protected IServiceProvider ServiceProvider { get; } private readonly Lazy> _lazyProviders; public SettingValueProviderManager( @@ -20,19 +21,17 @@ public class SettingValueProviderManager : ISettingValueProviderManager, ISingle { Options = options.Value; + ServiceProvider = serviceProvider; - _lazyProviders = new Lazy>( - () => Options - .ValueProviders - .Select(type => serviceProvider.GetRequiredService(type) as ISettingValueProvider) - .ToList()!, - true - ); + _lazyProviders = new Lazy>(GetProviders, true); } protected virtual List GetProviders() { - var providers = _lazyProviders.Value; + var providers = Options + .ValueProviders + .Select(type => (ServiceProvider.GetRequiredService(type) as ISettingValueProvider)!) + .ToList(); var multipleProviders = providers.GroupBy(p => p.Name).FirstOrDefault(x => x.Count() > 1); if(multipleProviders != null)