Skip to content

Instantly share code, notes, and snippets.

@AndyButland
Last active April 18, 2025 05:44
Show Gist options
  • Save AndyButland/5929089a5940913c8823a69594fcd355 to your computer and use it in GitHub Desktop.
Save AndyButland/5929089a5940913c8823a69594fcd355 to your computer and use it in GitHub Desktop.
using Microsoft.Extensions.Options;
using Umbraco.Cms.Core.Configuration.Models;
using Umbraco.Cms.Core.Models.PublishedContent;
using Umbraco.Cms.Core.PublishedCache;
using Umbraco.Cms.Core.Routing;
using Umbraco.Cms.Core.Services;
using Umbraco.Cms.Core.Services.Navigation;
using Umbraco.Cms.Core.Strings;
using Umbraco.Cms.Core.Web;
namespace MyProject.Web.Customization;
public class SoftwarePageUrlProvider : NewDefaultUrlProvider
{
private readonly IPublishedContentCache _publishedContentCache;
private readonly IDocumentNavigationQueryService _navigationQueryService;
private readonly IShortStringHelper _shortStringHelper;
public SoftwarePageUrlProvider(
IOptionsMonitor<RequestHandlerSettings> requestSettings,
ILogger<DefaultUrlProvider> logger,
ISiteDomainMapper siteDomainMapper,
IUmbracoContextAccessor umbracoContextAccessor,
UriUtility uriUtility,
ILocalizationService localizationService,
IPublishedContentCache publishedContentCache,
IDomainCache domainCache,
IIdKeyMap idKeyMap,
IDocumentUrlService documentUrlService,
IDocumentNavigationQueryService navigationQueryService,
IPublishedContentStatusFilteringService publishedContentStatusFilteringService,
IShortStringHelper shortStringHelper)
: base(
requestSettings,
logger,
siteDomainMapper,
umbracoContextAccessor,
uriUtility,
localizationService,
publishedContentCache,
domainCache,
idKeyMap,
documentUrlService,
navigationQueryService,
publishedContentStatusFilteringService)
{
_publishedContentCache = publishedContentCache;
_navigationQueryService = navigationQueryService;
_shortStringHelper = shortStringHelper;
}
public override UrlInfo? GetUrl(IPublishedContent content, UrlMode mode, string? culture, Uri current)
{
// Only apply this provider for software pages.
if (SoftwarePageUrlHelper.IsSoftwarePage(content.ContentType.Alias, content.Name) is false)
{
return base.GetUrl(content, mode, culture, current);
}
UrlInfo? defaultUrlInfo = base.GetUrl(content, mode, culture, current);
if (defaultUrlInfo is null)
{
return null;
}
if (_navigationQueryService.TryGetAncestorsKeys(content.Key, out IEnumerable<Guid>? ancestorsKeys) is false)
{
return null;
}
IEnumerable<string> ancestorContentSegments = ancestorsKeys
.Reverse()
.Skip(1)
.Select(x => _publishedContentCache.GetById(false, x))
.Where(x => x is not null)
.Select(x => CreateSoftwarePageUrlSegment(x!));
var url = $"/{string.Join('/', ancestorContentSegments)}/{content.Name.ToUrlSegment(_shortStringHelper)}";
return new UrlInfo(url, true, defaultUrlInfo.Culture);
}
private string CreateSoftwarePageUrlSegment(IPublishedContent content)
=> content.Name.ToUrlSegment(_shortStringHelper).Replace("-software", string.Empty);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment