diff --git a/MVC/MVC.Libraries/Libraries/AutoMapperMaps.cs b/MVC/MVC.Libraries/Libraries/AutoMapperMaps.cs index ccc2788..8ff5008 100644 --- a/MVC/MVC.Libraries/Libraries/AutoMapperMaps.cs +++ b/MVC/MVC.Libraries/Libraries/AutoMapperMaps.cs @@ -159,24 +159,6 @@ public void Process(TreeNode source, SitemapNode destination, ResolutionContext } } - public class PageIdentityMapping : IMappingAction - { - private readonly IPageUrlRetriever _pageUrlRetriever; - - public PageIdentityMapping(IPageUrlRetriever pageUrlRetriever) - { - _pageUrlRetriever = pageUrlRetriever; - } - - public void Process(TreeNode source, PageIdentity destination, ResolutionContext context) - { - var url = _pageUrlRetriever.Retrieve(source); - destination.RelativeUrl = url.RelativePath; - destination.AbsoluteUrl = url.AbsoluteUrl; - } - } - - public class SearchItemMapping : IMappingAction { diff --git a/MVC/MVC.Libraries/Libraries/Extensions/TreeNodeExtensions.cs b/MVC/MVC.Libraries/Libraries/Extensions/TreeNodeExtensions.cs index cfbab22..49a0b72 100644 --- a/MVC/MVC.Libraries/Libraries/Extensions/TreeNodeExtensions.cs +++ b/MVC/MVC.Libraries/Libraries/Extensions/TreeNodeExtensions.cs @@ -6,7 +6,6 @@ using Generic.Models; using Kentico.Content.Web.Mvc; using System; -using System.Collections.Generic; using System.Linq; namespace Generic.Libraries.Extensions @@ -18,25 +17,14 @@ public static class TreeNodeExtensions /// /// /// - public static PageIdentity ToPageIdentity(this TreeNode node) + public static PageIdentity ToPageIdentity(this TPage node) where TPage : TreeNode { - var pageIdentity = new PageIdentity() - { - NodeID = node.NodeID, - NodeGUID = node.NodeGUID, - DocumentID = node.DocumentID, - DocumentGUID = node.DocumentGUID, - Path = node.NodeAliasPath, - Alias = node.NodeAlias, - Name = node.DocumentName, - NodeLevel = node.NodeLevel - }; - + // Get Urls var relativeAndAbsoluteUrl = CacheHelper.Cache(cs => { if (cs.Cached) { - cs.CacheDependency = CacheHelper.GetCacheDependency($"documentid|{pageIdentity.DocumentID}"); + cs.CacheDependency = CacheHelper.GetCacheDependency($"documentid|{node.DocumentID}"); } try { @@ -51,7 +39,7 @@ public static PageIdentity ToPageIdentity(this TreeNode node) { // Will need to re-query the page, must be missing columns } - if (pageIdentity.DocumentID > 0) + if (node.DocumentID > 0) { // get full page var fullNode = CacheHelper.Cache(cs => @@ -60,7 +48,7 @@ public static PageIdentity ToPageIdentity(this TreeNode node) { cs.CacheDependency = CacheHelper.GetCacheDependency(new string[] { - $"documentid{ pageIdentity.DocumentID }" + $"documentid{ node.DocumentID }" }); } return new DocumentQuery() @@ -68,7 +56,7 @@ public static PageIdentity ToPageIdentity(this TreeNode node) .EnsureUrls() .GetEnumerableTypedResult() .FirstOrDefault(); - }, new CacheSettings(10, "GetDocumentForUrlRetrieval", pageIdentity.DocumentID)); + }, new CacheSettings(10, "GetDocumentForUrlRetrieval", node.DocumentID)); string url = DocumentURLProvider.GetUrl(fullNode); return new Tuple(url.Replace("~", ""), GetAbsoluteUrlOptimized(url, fullNode.NodeSiteID, fullNode.DocumentCulture, true)); @@ -78,11 +66,27 @@ public static PageIdentity ToPageIdentity(this TreeNode node) return new Tuple(string.Empty, string.Empty); } }, new CacheSettings(10, "GetNodeUrlsForPageIdentity", node.DocumentID)); - pageIdentity.RelativeUrl = relativeAndAbsoluteUrl.Item1; - pageIdentity.AbsoluteUrl = relativeAndAbsoluteUrl.Item2; + + var pageIdentity = new PageIdentity() + { + NodeID = node.NodeID, + NodeGUID = node.NodeGUID, + DocumentID = node.DocumentID, + DocumentGUID = node.DocumentGUID, + Path = node.NodeAliasPath, + Alias = node.NodeAlias, + Name = node.DocumentName, + NodeLevel = node.NodeLevel, + RelativeUrl = relativeAndAbsoluteUrl.Item1, + AbsoluteUrl = relativeAndAbsoluteUrl.Item2, + Data = node + }; + return pageIdentity; } + + /// /// DocumentURLProvider.GetPresentationUrl() does various uncached database calls, this caches that to minimize calls for absolute url /// @@ -127,6 +131,17 @@ private static string GetAbsoluteUrlOptimized(string virtualPath, SiteInfoIdenti return str; } } +} +// Kentico specific typed variation +namespace Generic.Models +{ + public record PageIdentity : PageIdentity where TPage : TreeNode + { + public PageIdentity() + : base() + { -} + } + } +} \ No newline at end of file diff --git a/MVC/MVC.Libraries/Repositories/Implementations/PageContextRepository.cs b/MVC/MVC.Libraries/Repositories/Implementations/PageContextRepository.cs index 387b9d7..63d038f 100644 --- a/MVC/MVC.Libraries/Repositories/Implementations/PageContextRepository.cs +++ b/MVC/MVC.Libraries/Repositories/Implementations/PageContextRepository.cs @@ -7,14 +7,12 @@ using MVCCaching.Base.Core.Interfaces; using System; using System.Linq; -using System.Reflection; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; using CMS.Base.Internal; using Kentico.Web.Mvc; using Kentico.PageBuilder.Web.Mvc; using Generic.Libraries.Extensions; -using CMS.DocumentEngine.Routing; namespace Generic.Repositories.Implementations { @@ -48,7 +46,7 @@ public Task GetCurrentPageAsync() if (_pageDataContextRetriever.TryRetrieve(out var currentPage)) { builder.Node(currentPage.Page.NodeID); - return Task.FromResult(currentPage.Page.ToPageIdentity()); + return Task.FromResult((PageIdentity)currentPage.Page.ToPageIdentity()); } else { diff --git a/MVC/MVC.Libraries/Services/Implementations/PageIdentityFactory.cs b/MVC/MVC.Libraries/Services/Implementations/PageIdentityFactory.cs new file mode 100644 index 0000000..999c809 --- /dev/null +++ b/MVC/MVC.Libraries/Services/Implementations/PageIdentityFactory.cs @@ -0,0 +1,37 @@ +using AutoMapper; +using Generic.Models; +using Generic.Services.Interfaces; + +namespace Generic.Services.Implementations +{ + public class PageIdentityFactory : IPageIdentityFactory + { + private readonly IMapper _mapper; + + public PageIdentityFactory(IMapper mapper) + { + _mapper = mapper; + } + + public PageIdentity Convert(PageIdentity pageIdentity) + { + // Convert data using AutoMapper + TData data = (pageIdentity.Data != null ? _mapper.Map(pageIdentity.Data) : default); + + return new PageIdentity() + { + Data = data, + DocumentGUID = pageIdentity.DocumentGUID, + DocumentID = pageIdentity.DocumentID, + NodeGUID = pageIdentity.NodeGUID, + NodeID = pageIdentity.NodeID, + NodeLevel = pageIdentity.NodeLevel, + AbsoluteUrl = pageIdentity.AbsoluteUrl, + RelativeUrl = pageIdentity.RelativeUrl, + Alias = pageIdentity.Alias, + Name = pageIdentity.Name, + Path = pageIdentity.Path + }; + } + } +} diff --git a/MVC/MVC.Models/Models/PageIdentity.cs b/MVC/MVC.Models/Models/PageIdentity.cs index 3a85464..0f1f79b 100644 --- a/MVC/MVC.Models/Models/PageIdentity.cs +++ b/MVC/MVC.Models/Models/PageIdentity.cs @@ -2,17 +2,64 @@ namespace Generic.Models { - public class PageIdentity + public record PageIdentity { - public string Name { get; set; } - public string Alias { get; set; } - public int NodeID { get; set; } - public Guid NodeGUID { get; set; } - public int DocumentID { get; set; } - public Guid DocumentGUID { get; set; } - public string Path { get; set; } - public string RelativeUrl { get; set; } - public string AbsoluteUrl { get; set; } - public int NodeLevel { get; set; } + /// + /// The Name of the page + /// + public string Name { get; init; } + + /// + /// The Code Name of the page + /// + public string Alias { get; init; } + + /// + /// The Page's int identity (culture agnostic) + /// + public int NodeID { get; init; } + + /// + /// The Page's guid identity (culture agnostic) + /// + public Guid NodeGUID { get; init; } + + /// + /// The Page's int identity (culture specific) + /// + public int DocumentID { get; init; } + + /// + /// The Page's guid identity (culture specific) + /// + public Guid DocumentGUID { get; init; } + + /// + /// The content path of the page + /// + public string Path { get; init; } + + /// + /// Relative URL of the page + /// + public string RelativeUrl { get; init; } + + /// + /// Absolute URL of the page + /// + public string AbsoluteUrl { get; init; } + + /// + /// Nesting level of the page. + /// + public int NodeLevel { get; init; } + } + + public record PageIdentity : PageIdentity + { + /// + /// Typed page data + /// + public T Data { get; set; } } } diff --git a/MVC/MVC.Models/Services/Interfaces/IPageIdentityFactory.cs b/MVC/MVC.Models/Services/Interfaces/IPageIdentityFactory.cs new file mode 100644 index 0000000..66e2328 --- /dev/null +++ b/MVC/MVC.Models/Services/Interfaces/IPageIdentityFactory.cs @@ -0,0 +1,10 @@ +using Generic.Models; +using MVCCaching; + +namespace Generic.Services.Interfaces +{ + public interface IPageIdentityFactory : IService + { + PageIdentity Convert(PageIdentity pageIdentity); + } +} diff --git a/MVC/MVC/Features/TabParent/TabParentPageTemplate.cshtml b/MVC/MVC/Features/TabParent/TabParentPageTemplate.cshtml index 358f0c6..79e6e84 100644 --- a/MVC/MVC/Features/TabParent/TabParentPageTemplate.cshtml +++ b/MVC/MVC/Features/TabParent/TabParentPageTemplate.cshtml @@ -1,5 +1,18 @@ @model ComponentViewModel +@using CMS.DocumentEngine.Types.Generic; +@using Generic.Models; +@using Generic.Libraries.Extensions; +@inject IPageIdentityFactory pageIdentityFactory @section head{ } - \ No newline at end of file +@{ + // This component requires the Page be specifically a TabParent + if (Model.Page is not TabParent tabParent) + { + return; + } + // Convert to identity with our TabParentItem model + var identity = pageIdentityFactory.Convert(tabParent.ToPageIdentity()); +} + diff --git a/MVC/MVC/Features/TabParent/TabParentViewComponent.cs b/MVC/MVC/Features/TabParent/TabParentViewComponent.cs index 81b1950..42be696 100644 --- a/MVC/MVC/Features/TabParent/TabParentViewComponent.cs +++ b/MVC/MVC/Features/TabParent/TabParentViewComponent.cs @@ -16,18 +16,20 @@ public TabParentViewComponent(ITabRepository tabRepository) _tabRepository = tabRepository; } - public async Task InvokeAsync(PageIdentity page) + public async Task InvokeAsync(PageIdentity page) { var model = new TabParentViewModel(); - if(page == null) + if (page == null) { model = new TabParentViewModel() { Name = "Unknown", Tabs = new List() }; - } else { - model.Name = (await _tabRepository.GetTabParentAsync(page.NodeID)).Name; + } + else + { + model.Name = page.Data.Name; model.Tabs = await _tabRepository.GetTabsAsync(page.Path); } return View("TabParent", model);