Browse Source

Merge pull request #17642 from abpframework/cmskit-page-rework

Handle CmsKit Pages routing in a DynamicRouteValueTransformer
pull/17740/head
Halil İbrahim Kalkan 2 years ago
committed by GitHub
parent
commit
377a8ed671
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 11
      modules/cms-kit/host/Volo.CmsKit.Web.Unified/CmsKitWebUnifiedModule.cs
  2. 7
      modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/Pages/PageAdminAppService.cs
  3. 8
      modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Pages/PageConsts.cs
  4. 2
      modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Menus/MenuItemManager.cs
  5. 5
      modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Pages/PageCacheItem.cs
  6. 2
      modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Pages/PageManager.cs
  7. 11
      modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/SlugNormalizer.cs
  8. 1
      modules/cms-kit/src/Volo.CmsKit.Public.Application.Contracts/Volo/CmsKit/Public/Pages/IPagePublicAppService.cs
  9. 45
      modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/CmsKit/Public/Pages/PagePublicAppService.cs
  10. 8
      modules/cms-kit/src/Volo.CmsKit.Public.HttpApi.Client/ClientProxies/Volo/CmsKit/Public/Pages/PagesPublicClientProxy.Generated.cs
  11. 62
      modules/cms-kit/src/Volo.CmsKit.Public.HttpApi.Client/ClientProxies/cms-kit-generate-proxy.json
  12. 15
      modules/cms-kit/src/Volo.CmsKit.Public.HttpApi/Volo/CmsKit/Public/Pages/PagesPublicController.cs
  13. 39
      modules/cms-kit/src/Volo.CmsKit.Public.Web/CmsKitPagesConfigurationExtensions.cs
  14. 25
      modules/cms-kit/src/Volo.CmsKit.Public.Web/CmsKitPublicWebModule.cs
  15. 34
      modules/cms-kit/src/Volo.CmsKit.Public.Web/DefaultHomePageMiddleware.cs
  16. 11
      modules/cms-kit/src/Volo.CmsKit.Public.Web/HomePageDefaultMiddlewareExtensions.cs
  17. 40
      modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKitHomePageRouteValueTransformer.cs
  18. 43
      modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKitPageRouteValueTransformer.cs
  19. 2
      modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/Public/CmsKit/Pages/Index.cshtml
  20. 3
      modules/cms-kit/test/Volo.CmsKit.Application.Tests/Menus/MenuItemAdminAppService_Tests.cs
  21. 16
      modules/cms-kit/test/Volo.CmsKit.Application.Tests/Pages/PagePublicAppService_Tests.cs
  22. 28
      modules/cms-kit/test/Volo.CmsKit.Domain.Tests/Blogs/SlugExtensions_Tests.cs
  23. 2
      modules/cms-kit/test/Volo.CmsKit.Domain.Tests/Menus/MenuManager_Test.cs

11
modules/cms-kit/host/Volo.CmsKit.Web.Unified/CmsKitWebUnifiedModule.cs

@ -36,6 +36,13 @@ using Volo.CmsKit.Reactions;
using Volo.CmsKit.Tags;
using Volo.CmsKit.Web;
using Volo.CmsKit.Web.Contents;
using Microsoft.AspNetCore.Routing;
using Microsoft.AspNetCore.Mvc.Routing;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Volo.Abp.DependencyInjection;
using Volo.CmsKit.Public.Pages;
#if EntityFrameworkCore
using Volo.Abp.SettingManagement.EntityFrameworkCore;
@ -54,7 +61,6 @@ using Volo.Abp.TenantManagement.MongoDB;
using Volo.Abp.Identity.MongoDB;
using Volo.Abp.PermissionManagement.MongoDB;
using Volo.Abp.FeatureManagement.MongoDB;
using Volo.Abp.MongoDB;
using Volo.Abp.BlobStoring.Database.MongoDB;
using Volo.Abp.AuditLogging.MongoDB;
using Volo.CmsKit.MongoDB;
@ -266,6 +272,7 @@ public class CmsKitWebUnifiedModule : AbpModule
app.UseAuditing();
app.UseAbpSerilogEnrichers();
app.UseConfiguredEndpoints();
using (var scope = context.ServiceProvider.CreateScope())
@ -278,4 +285,4 @@ public class CmsKitWebUnifiedModule : AbpModule
});
}
}
}
}

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

@ -66,6 +66,8 @@ public class PageAdminAppService : CmsKitAdminAppServiceBase, IPageAdminAppServi
input.MapExtraPropertiesTo(page);
await PageRepository.InsertAsync(page);
await PageCache.RemoveAsync(PageCacheItem.GetKey(page.Slug));
return ObjectMapper.Map<Page, PageDto>(page);
}
@ -77,6 +79,8 @@ public class PageAdminAppService : CmsKitAdminAppServiceBase, IPageAdminAppServi
{
await InvalidateDefaultHomePageCacheAsync(considerUow: true);
}
await PageCache.RemoveAsync(PageCacheItem.GetKey(page.Slug));
await PageManager.SetSlugAsync(page, input.Slug);
@ -102,6 +106,7 @@ public class PageAdminAppService : CmsKitAdminAppServiceBase, IPageAdminAppServi
}
await PageRepository.DeleteAsync(page);
await PageCache.RemoveAsync(PageCacheItem.GetKey(page.Slug));
}
[Authorize(CmsKitAdminPermissions.Pages.SetAsHomePage)]
@ -115,6 +120,6 @@ public class PageAdminAppService : CmsKitAdminAppServiceBase, IPageAdminAppServi
protected virtual async Task InvalidateDefaultHomePageCacheAsync(bool considerUow = false)
{
await PageCache.RemoveAsync(PageConsts.DefaultHomePageCacheKey, considerUow: considerUow);
await PageCache.RemoveAsync(PageCacheItem.GetKey(PageConsts.DefaultHomePageCacheKey), considerUow: considerUow);
}
}

8
modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Pages/PageConsts.cs

@ -16,11 +16,5 @@ public static class PageConsts
public static int MaxStyleLength { get; set; } = int.MaxValue;
public static string DefaultHomePageCacheKey { get; set; } = "DefaultHomePage";
private static string _urlPrefix = "/";
public static string UrlPrefix {
get => _urlPrefix;
set => _urlPrefix = value.EnsureEndsWith('/').EnsureStartsWith('/');
}
public static string DefaultHomePageCacheKey { get; set; } = "__DefaultHomePage";
}

2
modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Menus/MenuItemManager.cs

@ -22,7 +22,7 @@ public class MenuItemManager : CmsKitDomainServiceBase
public virtual void SetPageUrl(MenuItem menuItem, Page page)
{
menuItem.SetPageId(page.Id);
menuItem.SetUrl(PageConsts.UrlPrefix + page.Slug);
menuItem.SetUrl(page.Slug.EnsureStartsWith('/'));
}
[UnitOfWork]

5
modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Pages/PageCacheItem.cs

@ -16,4 +16,9 @@ public class PageCacheItem : ExtensibleObject
public string Script { get; set; }
public string Style { get; set; }
public static string GetKey(string slug)
{
return $"CmsPage_{slug}";
}
}

2
modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Pages/PageManager.cs

@ -37,7 +37,7 @@ public class PageManager : DomainService
CurrentTenant.Id);
}
public virtual async Task SetSlugAsync(Page page, string newSlug)
public virtual async Task SetSlugAsync(Page page, [NotNull] string newSlug)
{
if (page.Slug != newSlug)
{

11
modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/SlugNormalizer.cs

@ -5,9 +5,16 @@ namespace Volo.CmsKit;
public static class SlugNormalizer
{
static readonly SlugHelper SlugHelper = new();
static readonly SlugHelper SlugHelper = new(new SlugHelperConfiguration
{
AllowedChars =
{
'/'
}
});
public static string Normalize(string value)
{
return SlugHelper.GenerateSlug(value?.Unidecode());
return SlugHelper.GenerateSlug(value?.Unidecode()).Trim('/');
}
}

1
modules/cms-kit/src/Volo.CmsKit.Public.Application.Contracts/Volo/CmsKit/Public/Pages/IPagePublicAppService.cs

@ -8,5 +8,6 @@ namespace Volo.CmsKit.Public.Pages;
public interface IPagePublicAppService : IApplicationService
{
Task<PageDto> FindBySlugAsync([NotNull] string slug);
Task<bool> DoesSlugExistAsync([NotNull] string slug);
Task<PageDto> FindDefaultHomePageAsync();
}

45
modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/CmsKit/Public/Pages/PagePublicAppService.cs

@ -1,5 +1,6 @@
using System;
using System.Threading.Tasks;
using JetBrains.Annotations;
using Microsoft.Extensions.Caching.Distributed;
using Volo.Abp.Caching;
using Volo.Abp.Features;
@ -16,31 +17,35 @@ namespace Volo.CmsKit.Public.Pages;
public class PagePublicAppService : CmsKitPublicAppServiceBase, IPagePublicAppService
{
protected IPageRepository PageRepository { get; }
protected PageManager PageManager { get; }
protected PageManager PageManager { get; }
protected IDistributedCache<PageCacheItem> PageCache { get; }
public PagePublicAppService(IPageRepository pageRepository, PageManager pageManager, IDistributedCache<PageCacheItem> pageCache)
public PagePublicAppService(
IPageRepository pageRepository,
PageManager pageManager,
IDistributedCache<PageCacheItem> pageCache)
{
PageRepository = pageRepository;
PageManager = pageManager;
PageCache = pageCache;
PageCache = pageCache;
}
public virtual async Task<PageDto> FindBySlugAsync(string slug)
{
var page = await PageRepository.FindBySlugAsync(slug);
if (page == null)
var cachedPage = await FindAndCacheBySlugAsync(slug);
if (cachedPage == null)
{
return null;
}
return ObjectMapper.Map<Page, PageDto>(page);
return ObjectMapper.Map<PageCacheItem, PageDto>(cachedPage);
}
public virtual async Task<PageDto> FindDefaultHomePageAsync()
{
var pageCacheItem = await PageCache.GetAsync(PageConsts.DefaultHomePageCacheKey);
var pageCacheItem = await PageCache.GetAsync(PageCacheItem.GetKey(PageConsts.DefaultHomePageCacheKey));
if (pageCacheItem is null)
{
var page = await PageManager.GetHomePageAsync();
@ -51,10 +56,34 @@ public class PagePublicAppService : CmsKitPublicAppServiceBase, IPagePublicAppSe
pageCacheItem = ObjectMapper.Map<Page, PageCacheItem>(page);
await PageCache.SetAsync(PageConsts.DefaultHomePageCacheKey, pageCacheItem,
await PageCache.SetAsync(PageCacheItem.GetKey(PageConsts.DefaultHomePageCacheKey), pageCacheItem,
new DistributedCacheEntryOptions { AbsoluteExpiration = DateTimeOffset.Now.AddHours(1) });
}
return ObjectMapper.Map<PageCacheItem, PageDto>(pageCacheItem);
}
public virtual async Task<bool> DoesSlugExistAsync([NotNull] string slug)
{
var cached = await FindAndCacheBySlugAsync(slug);
return cached != null;
}
internal virtual async Task<PageCacheItem> FindAndCacheBySlugAsync(string slug)
{
var pageCacheItem = await PageCache.GetOrAddAsync(PageCacheItem.GetKey(slug), async () =>
{
var page = await PageRepository.FindBySlugAsync(slug);
// If page is not found, cache it as null to prevent further queries.
if (page is null)
{
return null;
}
return ObjectMapper.Map<Page, PageCacheItem>(page);
});
return pageCacheItem;
}
}

8
modules/cms-kit/src/Volo.CmsKit.Public.HttpApi.Client/ClientProxies/Volo/CmsKit/Public/Pages/PagesPublicClientProxy.Generated.cs

@ -30,4 +30,12 @@ public partial class PagesPublicClientProxy : ClientProxyBase<IPagePublicAppServ
{
return await RequestAsync<PageDto>(nameof(FindDefaultHomePageAsync));
}
public virtual async Task<bool> DoesSlugExistAsync(string slug)
{
return await RequestAsync<bool>(nameof(DoesSlugExistAsync), new ClientProxyRequestTypeValue
{
{ typeof(string), slug }
});
}
}

62
modules/cms-kit/src/Volo.CmsKit.Public.HttpApi.Client/ClientProxies/cms-kit-generate-proxy.json

@ -829,6 +829,23 @@
"typeSimple": "Volo.CmsKit.Contents.PageDto"
}
},
{
"name": "DoesSlugExistAsync",
"parametersOnMethod": [
{
"name": "slug",
"typeAsString": "System.String, System.Private.CoreLib",
"type": "System.String",
"typeSimple": "string",
"isOptional": false,
"defaultValue": null
}
],
"returnValue": {
"type": "System.Boolean",
"typeSimple": "boolean"
}
},
{
"name": "FindDefaultHomePageAsync",
"parametersOnMethod": [],
@ -845,7 +862,7 @@
"uniqueName": "FindBySlugAsyncBySlug",
"name": "FindBySlugAsync",
"httpMethod": "GET",
"url": "api/cms-kit-public/pages/{slug}",
"url": "api/cms-kit-public/pages/by-slug",
"supportedVersions": [],
"parametersOnMethod": [
{
@ -866,8 +883,8 @@
"typeSimple": "string",
"isOptional": false,
"defaultValue": null,
"constraintTypes": [],
"bindingSourceId": "Path",
"constraintTypes": null,
"bindingSourceId": "Query",
"descriptorName": ""
}
],
@ -882,7 +899,7 @@
"uniqueName": "FindDefaultHomePageAsync",
"name": "FindDefaultHomePageAsync",
"httpMethod": "GET",
"url": "api/cms-kit-public/pages",
"url": "api/cms-kit-public/pages/home",
"supportedVersions": [],
"parametersOnMethod": [],
"parameters": [],
@ -892,6 +909,43 @@
},
"allowAnonymous": null,
"implementFrom": "Volo.CmsKit.Public.Pages.IPagePublicAppService"
},
"DoesSlugExistAsyncBySlug": {
"uniqueName": "DoesSlugExistAsyncBySlug",
"name": "DoesSlugExistAsync",
"httpMethod": "GET",
"url": "api/cms-kit-public/pages/exist",
"supportedVersions": [],
"parametersOnMethod": [
{
"name": "slug",
"typeAsString": "System.String, System.Private.CoreLib",
"type": "System.String",
"typeSimple": "string",
"isOptional": false,
"defaultValue": null
}
],
"parameters": [
{
"nameOnMethod": "slug",
"name": "slug",
"jsonName": null,
"type": "System.String",
"typeSimple": "string",
"isOptional": false,
"defaultValue": null,
"constraintTypes": null,
"bindingSourceId": "Query",
"descriptorName": ""
}
],
"returnValue": {
"type": "System.Boolean",
"typeSimple": "boolean"
},
"allowAnonymous": null,
"implementFrom": "Volo.CmsKit.Public.Pages.IPagePublicAppService"
}
}
},

15
modules/cms-kit/src/Volo.CmsKit.Public.HttpApi/Volo/CmsKit/Public/Pages/PagesPublicController.cs

@ -1,4 +1,5 @@
using System.Threading.Tasks;
using JetBrains.Annotations;
using Microsoft.AspNetCore.Mvc;
using Volo.Abp;
using Volo.Abp.Features;
@ -24,15 +25,23 @@ public class PagesPublicController : CmsKitPublicControllerBase, IPagePublicAppS
}
[HttpGet]
[Route("{slug}")]
public virtual Task<PageDto> FindBySlugAsync(string slug)
[Route("by-slug")]
public virtual Task<PageDto> FindBySlugAsync([FromQuery]string slug)
{
return PageAppService.FindBySlugAsync(slug);
}
[HttpGet]
public Task<PageDto> FindDefaultHomePageAsync()
[Route("home")]
public virtual Task<PageDto> FindDefaultHomePageAsync()
{
return PageAppService.FindDefaultHomePageAsync();
}
[HttpGet]
[Route("exist")]
public virtual Task<bool> DoesSlugExistAsync([NotNull][FromQuery] string slug)
{
return PageAppService.DoesSlugExistAsync(slug);
}
}

39
modules/cms-kit/src/Volo.CmsKit.Public.Web/CmsKitPagesConfigurationExtensions.cs

@ -0,0 +1,39 @@
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Routing;
using Volo.Abp.GlobalFeatures;
using Volo.CmsKit.GlobalFeatures;
using Volo.CmsKit.Public.Web.Pages;
namespace Volo.CmsKit.Public.Web;
public static class CmsKitPagesConfigurationExtensions
{
/// <summary>
/// Maps CMS Kit to the routing.
/// </summary>
/// <param name="builder"></param>
/// <param name="order">The matching order for the dynamic route. Lower is prior.</param>
public static IEndpointRouteBuilder MapCmsPageRoute(this IEndpointRouteBuilder builder, int? order = null)
{
if (!GlobalFeatureManager.Instance.IsEnabled<PagesFeature>())
{
return builder;
}
builder
.MapDynamicPageRoute<CmsKitHomePageRouteValueTransformer>("/", state: null, order: int.MinValue);
if (order is null)
{
builder
.MapDynamicPageRoute<CmsKitPageRouteValueTransformer>("{**slug}");
}
else
{
builder
.MapDynamicPageRoute<CmsKitPageRouteValueTransformer>("{**slug}", state: default, order: order.Value);
}
return builder;
}
}

25
modules/cms-kit/src/Volo.CmsKit.Public.Web/CmsKitPublicWebModule.cs

@ -1,18 +1,17 @@
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp;
using Volo.Abp.AspNetCore.Mvc.Localization;
using Volo.Abp.Ui.LayoutHooks;
using Volo.Abp.AutoMapper;
using Volo.Abp.Caching;
using Volo.Abp.GlobalFeatures;
using Volo.Abp.Http.ProxyScripting.Generators.JQuery;
using Volo.Abp.Modularity;
using Volo.Abp.Ui.LayoutHooks;
using Volo.Abp.UI.Navigation;
using Volo.Abp.VirtualFileSystem;
using Volo.CmsKit.GlobalFeatures;
using Volo.CmsKit.Localization;
using Volo.CmsKit.Pages;
using Volo.CmsKit.Public.Web.Menus;
using Volo.CmsKit.Public.Web.Pages.CmsKit.Shared.Components.GlobalResources.Script;
using Volo.CmsKit.Public.Web.Pages.CmsKit.Shared.Components.GlobalResources.Style;
@ -73,6 +72,14 @@ public class CmsKitPublicWebModule : AbpModule
{
options.KeyPrefix = "CmsKit:";
});
Configure<AbpEndpointRouterOptions>(options =>
{
options.EndpointConfigureActions.Add(context =>
{
context.Endpoints.MapCmsPageRoute();
});
});
}
public override void PostConfigureServices(ServiceConfigurationContext context)
@ -81,7 +88,6 @@ public class CmsKitPublicWebModule : AbpModule
{
Configure<RazorPagesOptions>(options =>
{
options.Conventions.AddPageRoute("/Public/CmsKit/Pages/Index", PageConsts.UrlPrefix + "{slug:minlength(1)}");
options.Conventions.AddPageRoute("/Public/CmsKit/Blogs/Index", @"/blogs/{blogSlug:minlength(1)}");
options.Conventions.AddPageRoute("/Public/CmsKit/Blogs/BlogPost", @"/blogs/{blogSlug}/{blogPostSlug:minlength(1)}");
});
@ -101,16 +107,5 @@ public class CmsKitPublicWebModule : AbpModule
);
});
}
}
public override void OnApplicationInitialization(ApplicationInitializationContext context)
{
var app = context.GetApplicationBuilder();
if (GlobalFeatureManager.Instance.IsEnabled<PagesFeature>())
{
app.UseHomePageDefaultMiddleware();
}
}
}

34
modules/cms-kit/src/Volo.CmsKit.Public.Web/DefaultHomePageMiddleware.cs

@ -1,34 +0,0 @@
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Features;
using Volo.CmsKit.Features;
using Volo.CmsKit.Pages;
using Volo.CmsKit.Public.Pages;
namespace Volo.CmsKit.Public.Web;
public class DefaultHomePageMiddleware : IMiddleware, ITransientDependency
{
public async Task InvokeAsync(HttpContext context, RequestDelegate next)
{
var featureChecker = context.RequestServices.GetRequiredService<IFeatureChecker>();
if (context.Request.Path.Value == "/")
{
if (await featureChecker.IsEnabledAsync(CmsKitFeatures.PageEnable))
{
var pagePublicAppService = context.RequestServices.GetRequiredService<IPagePublicAppService>();
var page = await pagePublicAppService.FindDefaultHomePageAsync();
if (page != null)
{
context.Request.Path = $"{PageConsts.UrlPrefix}{page.Slug}";
}
}
}
await next(context);
}
}

11
modules/cms-kit/src/Volo.CmsKit.Public.Web/HomePageDefaultMiddlewareExtensions.cs

@ -1,11 +0,0 @@
using Microsoft.AspNetCore.Builder;
namespace Volo.CmsKit.Public.Web;
public static class HomePageDefaultMiddlewareExtensions
{
public static IApplicationBuilder UseHomePageDefaultMiddleware(this IApplicationBuilder builder)
{
return builder.UseMiddleware<DefaultHomePageMiddleware>();
}
}

40
modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKitHomePageRouteValueTransformer.cs

@ -0,0 +1,40 @@
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.Routing;
using Microsoft.AspNetCore.Routing;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Features;
using Volo.CmsKit.Features;
using Volo.CmsKit.Public.Pages;
namespace Volo.CmsKit.Public.Web.Pages;
public class CmsKitHomePageRouteValueTransformer : DynamicRouteValueTransformer, ITransientDependency
{
protected IFeatureChecker FeatureChecker { get; }
protected IPagePublicAppService PagePublicAppService { get; }
public CmsKitHomePageRouteValueTransformer(IFeatureChecker featureChecker, IPagePublicAppService pagePublicAppService)
{
FeatureChecker = featureChecker;
PagePublicAppService = pagePublicAppService;
}
public override async ValueTask<RouteValueDictionary> TransformAsync(HttpContext httpContext, RouteValueDictionary values)
{
if (await FeatureChecker.IsEnabledAsync(CmsKitFeatures.PageEnable))
{
var page = await PagePublicAppService.FindDefaultHomePageAsync();
if (page is not null)
{
values = new RouteValueDictionary();
values["page"] = "/Public/CmsKit/Pages/Index";
values["slug"] = page.Slug;
}
}
return values;
}
}

43
modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKitPageRouteValueTransformer.cs

@ -0,0 +1,43 @@
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.Routing;
using Microsoft.AspNetCore.Routing;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Features;
using Volo.CmsKit.Features;
using Volo.CmsKit.Public.Pages;
namespace Volo.CmsKit.Public.Web.Pages;
public class CmsKitPageRouteValueTransformer : DynamicRouteValueTransformer, ITransientDependency
{
protected IFeatureChecker FeatureChecker { get; }
protected IPagePublicAppService PagePublicAppService { get; }
public CmsKitPageRouteValueTransformer(IFeatureChecker featureChecker, IPagePublicAppService pagePublicAppService)
{
FeatureChecker = featureChecker;
PagePublicAppService = pagePublicAppService;
}
public override async ValueTask<RouteValueDictionary> TransformAsync(HttpContext httpContext, RouteValueDictionary values)
{
if (values.TryGetValue("slug", out var slugParameter) && slugParameter is not null)
{
if (!await FeatureChecker.IsEnabledAsync(CmsKitFeatures.PageEnable))
{
return values;
}
var slug = slugParameter.ToString().TrimStart('/');
var exist = await PagePublicAppService.DoesSlugExistAsync(slug);
if (exist)
{
values["page"] = "/Public/CmsKit/Pages/Index";
}
}
return values;
}
}

2
modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/Public/CmsKit/Pages/Index.cshtml

@ -1,4 +1,4 @@
@page
@page "/pages/{**slug}"
@addTagHelper *, Volo.Abp.AspNetCore.Mvc.UI.Bootstrap
@using Volo.CmsKit.Contents
@using Volo.CmsKit.Web.Pages.CmsKit.Components.Contents

3
modules/cms-kit/test/Volo.CmsKit.Application.Tests/Menus/MenuItemAdminAppService_Tests.cs

@ -32,6 +32,7 @@ public class MenuItemAdminAppService_Tests : CmsKitApplicationTestBase
menu.ShouldNotBeNull();
}
[Fact]
public async Task GetListAsync_ShouldWorkProperly()
{
var result = await MenuAdminAppService.GetListAsync();
@ -69,7 +70,6 @@ public class MenuItemAdminAppService_Tests : CmsKitApplicationTestBase
});
});
var menu = await MenuRepository.FindAsync(TestData.MenuItem_1_Id);
menu.ShouldNotBeNull();
@ -82,7 +82,6 @@ public class MenuItemAdminAppService_Tests : CmsKitApplicationTestBase
{
await MenuAdminAppService.DeleteAsync(TestData.MenuItem_1_Id);
var menu = await MenuRepository.FindAsync(TestData.MenuItem_1_Id);
menu.ShouldBeNull();

16
modules/cms-kit/test/Volo.CmsKit.Application.Tests/Pages/PagePublicAppService_Tests.cs

@ -33,4 +33,20 @@ public class PagePublicAppService_Tests : CmsKitApplicationTestBase
page.ShouldBeNull();
}
[Fact]
public async Task DoesSlugExistAsync_ShouldReturnTrue_WhenExists()
{
var result = await _pageAppService.DoesSlugExistAsync(_data.Page_1_Slug);
result.ShouldBeTrue();
}
[Fact]
public async Task DoesSlugExistAsync_ShouldReturnFalse_WhenDoesNotExist()
{
var result = await _pageAppService.DoesSlugExistAsync("not-exist-url");
result.ShouldBeFalse();
}
}

28
modules/cms-kit/test/Volo.CmsKit.Domain.Tests/Blogs/SlugExtensions_Tests.cs

@ -129,4 +129,32 @@ public class SlugExtensions_Tests
// Assert
actual.ShouldBe(expected);
}
[Fact]
public void NormalizeSlug_ShouldWorkProperly_WithMultipleLevel()
{
// Arrange
var name = "path/to/my/page";
var expected = "path/to/my/page";
// Act
var actual = SlugNormalizer.Normalize(name);
// Assert
actual.ShouldBe(expected);
}
[Fact]
public void NormalizeSlug_ShouldWorkProperly_WithMultipleLevelStartingSlash()
{
// Arrange
var name = "/path/to/my/page";
var expected = "path/to/my/page";
// Act
var actual = SlugNormalizer.Normalize(name);
// Assert
actual.ShouldBe(expected);
}
}

2
modules/cms-kit/test/Volo.CmsKit.Domain.Tests/Menus/MenuManager_Test.cs

@ -32,7 +32,7 @@ public class MenuManager_Test : CmsKitDomainTestBase
menuManager.SetPageUrl(menuItem, page);
menuItem.Url.ShouldNotBeNullOrEmpty();
menuItem.Url.ShouldBe(PageConsts.UrlPrefix + page.Slug);
menuItem.Url.ShouldBe(page.Slug.EnsureStartsWith('/'));
}
[Fact]

Loading…
Cancel
Save