Serverside generated preview URLs (#20021)

* Serverside generated preview URLs

* Add URL provider notation to UrlInfo

* Change preview URL generation to happen at preview time based on provider alias

* Update XML docs

* Always add culture (if available) to preview URL

* Do not log user input (security vulnerability)

* Fix typo

* Re-generate TypeScript client

from Management API

* Deprecated `UmbDocumentPreviewRepository.enter()` (for v19)

Fixed TS errors

Added temp stub for `getPreviewUrl`

* Adds `previewOption` extension-type

* Adds "default" `previewOption` kind

* Relocated "Save and Preview" workspace action

reworked using the "default" `previewOption` kind.

* Added stub for "urlProvider" `previewOption` kind

* Renamed "workspace-action-default-kind.element.ts"

to a more suitable filename.

Exported element so can be reused in other packages,
e.g. documents, for the new "save and preview" feature.

* Refactored "Save and Preview" button

to work with first action's manifest/API.

* Reverted `previewOption` extension-type

Re-engineered to make a "urlProvider" kind for `workspaceActionMenuItem`.
This is to simplify the extension point and surrounding logic.

* Modified `saveAndPreview` Document Workspace Context

to accept a URL Provider Alias.

* Refactored "Save and Preview" button

to extend `UmbWorkspaceActionElement`.

This did mean exposing certain methods/properties to be overridable.

* Used `umbPeekError` to surface any errors to the user

* Renamed `urlProvider` kind to `previewOption`

* Relocated `urlProviderAlias` inside the `meta` property

* also throw an error

* Added missing `await`

* Fix build errors after forward merge

---------

Co-authored-by: leekelleher <leekelleher@gmail.com>
Co-authored-by: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com>
Co-authored-by: Laura Neto <12862535+lauraneto@users.noreply.github.com>
This commit is contained in:
Kenn Jacobsen
2025-10-08 08:27:01 +02:00
committed by GitHub
parent 74328e9496
commit 17a5477242
52 changed files with 787 additions and 222 deletions

View File

@@ -0,0 +1,11 @@
namespace Umbraco.Cms.Core;
public static partial class Constants
{
public static class UrlProviders
{
public const string Content = "umbDocumentUrlProvider";
public const string Media = "umbMediaUrlProvider";
}
}

View File

@@ -108,7 +108,7 @@ public class AddUnroutableContentWarningsWhenPublishingNotificationHandler : INo
EventMessages eventMessages = _eventMessagesFactory.Get();
foreach (var culture in successfulCultures)
{
if (urls.Where(u => u.Culture == culture || culture == "*").All(u => u.IsUrl is false))
if (urls.Where(u => u.Culture == culture || culture == "*").All(u => u.Url is null))
{
eventMessages.Add(new EventMessage("Content published", "The document does not have a URL, possibly due to a naming collision with another document. More details can be found under Info.", EventMessageType.Warning));

View File

@@ -1,5 +1,6 @@
using Microsoft.Extensions.Options;
using Umbraco.Cms.Core.Configuration.Models;
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.Models.PublishedContent;
using Umbraco.Cms.Core.Services.Navigation;
using Umbraco.Cms.Core.Web;
@@ -40,6 +41,9 @@ public class AliasUrlProvider : IUrlProvider
requestConfig.OnChange(x => _requestConfig = x);
}
/// <inheritdoc />
public string Alias => $"{Constants.UrlProviders.Content}ByAlias";
// note - at the moment we seem to accept pretty much anything as an alias
// without any form of validation ... could even prob. kill the XPath ...
// ok, this is somewhat experimental and is NOT enabled by default
@@ -120,7 +124,7 @@ public class AliasUrlProvider : IUrlProvider
{
var path = "/" + alias;
var uri = new Uri(path, UriKind.Relative);
yield return UrlInfo.Url(_uriUtility.UriFromUmbraco(uri, _requestConfig).ToString());
yield return UrlInfo.FromUri(_uriUtility.UriFromUmbraco(uri, _requestConfig), Alias);
}
}
else
@@ -152,9 +156,7 @@ public class AliasUrlProvider : IUrlProvider
{
var path = "/" + alias;
var uri = new Uri(CombinePaths(domainUri.Uri.GetLeftPart(UriPartial.Authority), path));
yield return UrlInfo.Url(
_uriUtility.UriFromUmbraco(uri, _requestConfig).ToString(),
domainUri.Culture);
yield return UrlInfo.FromUri(_uriUtility.UriFromUmbraco(uri, _requestConfig), Alias, domainUri.Culture);
}
}
}
@@ -162,6 +164,14 @@ public class AliasUrlProvider : IUrlProvider
#endregion
#region GetPreviewUrl
/// <inheritdoc />
public Task<UrlInfo?> GetPreviewUrlAsync(IContent content, string? culture, string? segment)
=> Task.FromResult<UrlInfo?>(null);
#endregion
#region Utilities
private string CombinePaths(string path1, string path2)

View File

@@ -39,7 +39,7 @@ public class DefaultMediaUrlProvider : IMediaUrlProvider
if (_mediaPathGenerators.TryGetMediaPath(propType?.EditorAlias, value, out var path))
{
Uri url = _urlAssembler.AssembleUrl(path!, current, mode);
return UrlInfo.Url(url.ToString(), culture);
return UrlInfo.FromUri(url, Constants.UrlProviders.Media, culture);
}
return null;

View File

@@ -4,8 +4,8 @@ using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Umbraco.Cms.Core.Configuration.Models;
using Umbraco.Cms.Core.DependencyInjection;
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.Models.PublishedContent;
using Umbraco.Cms.Core.PublishedCache;
using Umbraco.Cms.Core.Services;
using Umbraco.Cms.Core.Services.Navigation;
using Umbraco.Cms.Core.Web;
@@ -16,6 +16,7 @@ namespace Umbraco.Cms.Core.Routing;
/// <summary>
/// Provides urls.
/// </summary>
[Obsolete("Use NewDefaultUrlProvider instead. Scheduled for removal in V18.")]
public class DefaultUrlProvider : IUrlProvider
{
private readonly ILocalizationService _localizationService;
@@ -76,6 +77,9 @@ public class DefaultUrlProvider : IUrlProvider
{
}
/// <inheritdoc />
public string Alias => $"{Constants.UrlProviders.Content}Legacy";
#region GetOtherUrls
/// <summary>
@@ -136,7 +140,7 @@ public class DefaultUrlProvider : IUrlProvider
var uri = new Uri(CombinePaths(d.Uri.GetLeftPart(UriPartial.Path), path));
uri = _uriUtility.UriFromUmbraco(uri, _requestSettings);
yield return UrlInfo.Url(uri.ToString(), culture);
yield return UrlInfo.FromUri(uri, Alias, culture);
}
}
@@ -196,8 +200,8 @@ public class DefaultUrlProvider : IUrlProvider
if (domainUri is not null || string.IsNullOrEmpty(culture) ||
culture.Equals(defaultCulture, StringComparison.InvariantCultureIgnoreCase))
{
var url = AssembleUrl(domainUri, path, current, mode).ToString();
return UrlInfo.Url(url, culture);
Uri url = AssembleUrl(domainUri, path, current, mode);
return UrlInfo.FromUri(url, Alias, culture);
}
return null;
@@ -205,6 +209,14 @@ public class DefaultUrlProvider : IUrlProvider
#endregion
#region GetPreviewUrl
/// <inheritdoc />
public Task<UrlInfo?> GetPreviewUrlAsync(IContent content, string? culture, string? segment)
=> Task.FromResult<UrlInfo?>(null);
#endregion
#region Utilities
private Uri AssembleUrl(DomainAndUri? domainUri, string path, Uri current, UrlMode mode)

View File

@@ -1,3 +1,4 @@
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.Models.PublishedContent;
namespace Umbraco.Cms.Core.Routing;

View File

@@ -1,3 +1,4 @@
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.Models.PublishedContent;
namespace Umbraco.Cms.Core.Routing;
@@ -38,4 +39,18 @@ public interface IUrlProvider
/// </para>
/// </remarks>
IEnumerable<UrlInfo> GetOtherUrls(int id, Uri current);
/// <summary>
/// Gets the preview URL of a content item.
/// </summary>
/// <param name="content">The content item.</param>
/// <param name="culture">The culture to preview (null means invariant).</param>
/// <param name="segment">The segment to preview (null means no specific segment).</param>
/// <returns>The preview URLs of the content item.</returns>
Task<UrlInfo?> GetPreviewUrlAsync(IContent content, string? culture, string? segment);
/// <summary>
/// Gets the alias for the URL provider.
/// </summary>
public string Alias { get; }
}

View File

@@ -1,9 +1,7 @@
using System.Globalization;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Umbraco.Cms.Core.Configuration.Models;
using Umbraco.Cms.Core.DependencyInjection;
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.Models.PublishedContent;
using Umbraco.Cms.Core.PublishedCache;
@@ -25,7 +23,7 @@ public class NewDefaultUrlProvider : IUrlProvider
private readonly IDocumentUrlService _documentUrlService;
private readonly IDocumentNavigationQueryService _navigationQueryService;
private readonly IPublishedContentStatusFilteringService _publishedContentStatusFilteringService;
private readonly ILogger<DefaultUrlProvider> _logger;
private readonly ILogger<NewDefaultUrlProvider> _logger;
private readonly ISiteDomainMapper _siteDomainMapper;
private readonly IUmbracoContextAccessor _umbracoContextAccessor;
private readonly UriUtility _uriUtility;
@@ -39,7 +37,7 @@ public class NewDefaultUrlProvider : IUrlProvider
/// </summary>
public NewDefaultUrlProvider(
IOptionsMonitor<RequestHandlerSettings> requestSettings,
ILogger<DefaultUrlProvider> logger,
ILogger<NewDefaultUrlProvider> logger,
ISiteDomainMapper siteDomainMapper,
IUmbracoContextAccessor umbracoContextAccessor,
UriUtility uriUtility,
@@ -67,6 +65,9 @@ public class NewDefaultUrlProvider : IUrlProvider
requestSettings.OnChange(x => _requestSettings = x);
}
/// <inheritdoc />
public string Alias => Constants.UrlProviders.Content;
/// <summary>
/// Gets the other URLs of a published content.
/// </summary>
@@ -133,10 +134,23 @@ public class NewDefaultUrlProvider : IUrlProvider
var uri = new Uri(CombinePaths(d.Uri.GetLeftPart(UriPartial.Path), path));
uri = _uriUtility.UriFromUmbraco(uri, _requestSettings);
yield return UrlInfo.Url(uri.ToString(), culture);
yield return UrlInfo.FromUri(uri, Alias, culture);
}
}
#region GetPreviewUrl
/// <inheritdoc />
public Task<UrlInfo?> GetPreviewUrlAsync(IContent content, string? culture, string? segment)
=> Task.FromResult<UrlInfo?>(
UrlInfo.AsUrl(
$"/{Constants.System.UmbracoPathSegment}/preview?id={content.Key}&culture={culture}&segment={segment}",
Alias,
culture,
isExternal: false));
#endregion
/// <summary>
/// Gets the legacy route format by id
/// </summary>
@@ -221,8 +235,8 @@ public class NewDefaultUrlProvider : IUrlProvider
string.IsNullOrEmpty(culture) ||
culture.Equals(defaultCulture, StringComparison.InvariantCultureIgnoreCase))
{
var url = AssembleUrl(domainUri, path, current, mode).ToString();
return UrlInfo.Url(url, culture);
Uri url = AssembleUrl(domainUri, path, current, mode);
return UrlInfo.FromUri(url, Alias, culture);
}
return null;

View File

@@ -10,6 +10,8 @@ namespace Umbraco.Cms.Core.Routing;
public class PublishedUrlInfoProvider : IPublishedUrlInfoProvider
{
private const string UrlProviderAlias = Constants.UrlProviders.Content;
private readonly IPublishedUrlProvider _publishedUrlProvider;
private readonly ILanguageService _languageService;
private readonly IPublishedRouter _publishedRouter;
@@ -53,7 +55,7 @@ public class PublishedUrlInfoProvider : IPublishedUrlInfoProvider
// Handle "could not get URL"
if (url is "#" or "#ex")
{
urlInfos.Add(UrlInfo.Message(_localizedTextService.Localize("content", "getUrlException"), culture));
urlInfos.Add(UrlInfo.AsMessage(_localizedTextService.Localize("content", "getUrlException"), UrlProviderAlias, culture));
continue;
}
@@ -66,7 +68,7 @@ public class PublishedUrlInfoProvider : IPublishedUrlInfoProvider
continue;
}
urlInfos.Add(UrlInfo.Url(url, culture));
urlInfos.Add(UrlInfo.AsUrl(url, UrlProviderAlias, culture));
}
// If the content is trashed, we can't get the other URLs, as we have no parent structure to navigate through.
@@ -77,7 +79,7 @@ public class PublishedUrlInfoProvider : IPublishedUrlInfoProvider
// Then get "other" urls - I.E. Not what you'd get with GetUrl(), this includes all the urls registered using domains.
// for these 'other' URLs, we don't check whether they are routable, collide, anything - we just report them.
foreach (UrlInfo otherUrl in _publishedUrlProvider.GetOtherUrls(content.Id).OrderBy(x => x.Text).ThenBy(x => x.Culture))
foreach (UrlInfo otherUrl in _publishedUrlProvider.GetOtherUrls(content.Id).OrderBy(x => x.Message).ThenBy(x => x.Culture))
{
urlInfos.Add(otherUrl);
}
@@ -106,7 +108,7 @@ public class PublishedUrlInfoProvider : IPublishedUrlInfoProvider
_logger.LogDebug(logMsg, url, uri, culture);
}
var urlInfo = UrlInfo.Message(_localizedTextService.Localize("content", "routeErrorCannotRoute"), culture);
var urlInfo = UrlInfo.AsMessage(_localizedTextService.Localize("content", "routeErrorCannotRoute"), UrlProviderAlias, culture);
return Attempt.Succeed(urlInfo);
}
@@ -119,7 +121,7 @@ public class PublishedUrlInfoProvider : IPublishedUrlInfoProvider
{
var collidingContent = publishedRequest.PublishedContent?.Key.ToString();
var urlInfo = UrlInfo.Message(_localizedTextService.Localize("content", "routeError", [collidingContent]), culture);
var urlInfo = UrlInfo.AsMessage(_localizedTextService.Localize("content", "routeError", [collidingContent]), UrlProviderAlias, culture);
return Attempt.Succeed(urlInfo);
}

View File

@@ -1,4 +1,5 @@
using System.Runtime.Serialization;
using Umbraco.Extensions;
namespace Umbraco.Cms.Core.Routing;
@@ -11,18 +12,50 @@ public class UrlInfo : IEquatable<UrlInfo>
/// <summary>
/// Initializes a new instance of the <see cref="UrlInfo" /> class.
/// </summary>
public UrlInfo(string text, bool isUrl, string? culture)
public UrlInfo(Uri url, string provider, string? culture, string? message = null, bool isExternal = false)
{
if (string.IsNullOrWhiteSpace(text))
if (provider.IsNullOrWhiteSpace())
{
throw new ArgumentException("Value cannot be null or whitespace.", nameof(text));
throw new ArgumentException("Value cannot be null or whitespace.", nameof(provider));
}
IsUrl = isUrl;
Text = text;
Url = url;
Provider = provider;
Culture = culture;
Message = message;
IsExternal = isExternal;
}
/// <summary>
/// Initializes a new instance of the <see cref="UrlInfo" /> class as a "message only" - that is, not an actual URL.
/// </summary>
public UrlInfo(string message, string provider, string? culture = null)
{
if (message.IsNullOrWhiteSpace())
{
throw new ArgumentException("Value cannot be null or whitespace.", nameof(message));
}
if (provider.IsNullOrWhiteSpace())
{
throw new ArgumentException("Value cannot be null or whitespace.", nameof(provider));
}
Url = null;
Provider = provider;
Message = message;
Culture = culture;
}
public static UrlInfo AsUrl(string url, string provider, string? culture = null, bool isExternal = false)
=> new(new Uri(url, UriKind.RelativeOrAbsolute), provider, culture: culture, isExternal: isExternal);
public static UrlInfo AsMessage(string message, string provider, string? culture = null)
=> new(message, provider, culture: culture);
public static UrlInfo FromUri(Uri uri, string provider, string? culture = null, bool isExternal = false)
=> new(uri, provider, culture: culture, isExternal: isExternal);
/// <summary>
/// Gets the culture.
/// </summary>
@@ -30,34 +63,32 @@ public class UrlInfo : IEquatable<UrlInfo>
public string? Culture { get; }
/// <summary>
/// Gets a value indicating whether the URL is a true URL.
/// Gets the URL.
/// </summary>
/// <remarks>Otherwise, it is a message.</remarks>
[DataMember(Name = "isUrl")]
public bool IsUrl { get; }
[DataMember(Name = "url")]
public Uri? Url { get; }
public string Provider { get; }
/// <summary>
/// Gets the text, which is either the URL, or a message.
/// Gets the message.
/// </summary>
[DataMember(Name = "text")]
public string Text { get; }
[DataMember(Name = "message")]
public string? Message { get; }
/// <summary>
/// Gets whether this is considered an external or a local URL (remote or local host).
/// </summary>
[DataMember(Name = "isExternal")]
public bool IsExternal { get; }
public static bool operator ==(UrlInfo left, UrlInfo right) => Equals(left, right);
/// <summary>
/// Creates a <see cref="UrlInfo" /> instance representing a true URL.
/// </summary>
public static UrlInfo Url(string text, string? culture = null) => new(text, true, culture);
/// <summary>
/// Checks equality
/// </summary>
/// <param name="other"></param>
/// <returns></returns>
/// <remarks>
/// Compare both culture and Text as invariant strings since URLs are not case sensitive, nor are culture names within
/// Umbraco
/// </remarks>
public bool Equals(UrlInfo? other)
{
if (ReferenceEquals(null, other))
@@ -70,15 +101,12 @@ public class UrlInfo : IEquatable<UrlInfo>
return true;
}
return string.Equals(Culture, other.Culture, StringComparison.InvariantCultureIgnoreCase) &&
IsUrl == other.IsUrl && string.Equals(Text, other.Text, StringComparison.InvariantCultureIgnoreCase);
return string.Equals(Culture, other.Culture, StringComparison.InvariantCultureIgnoreCase)
&& Url == other.Url
&& string.Equals(Message, other.Message, StringComparison.InvariantCultureIgnoreCase)
&& IsExternal == other.IsExternal;
}
/// <summary>
/// Creates a <see cref="UrlInfo" /> instance representing a message.
/// </summary>
public static UrlInfo Message(string text, string? culture = null) => new(text, false, culture);
public override bool Equals(object? obj)
{
if (ReferenceEquals(null, obj))
@@ -104,14 +132,16 @@ public class UrlInfo : IEquatable<UrlInfo>
unchecked
{
var hashCode = Culture != null ? StringComparer.InvariantCultureIgnoreCase.GetHashCode(Culture) : 0;
hashCode = (hashCode * 397) ^ IsUrl.GetHashCode();
hashCode = (hashCode * 397) ^
(Text != null ? StringComparer.InvariantCultureIgnoreCase.GetHashCode(Text) : 0);
(Url != null ? Url.GetHashCode() : 0);
hashCode = (hashCode * 397) ^
(Message != null ? StringComparer.InvariantCultureIgnoreCase.GetHashCode(Message) : 0);
hashCode = (hashCode * 397) ^ IsExternal.GetHashCode();
return hashCode;
}
}
public static bool operator !=(UrlInfo left, UrlInfo right) => !Equals(left, right);
public override string ToString() => Text;
public override string ToString() => Url?.ToString() ?? Message ?? "[empty]";
}

View File

@@ -2,6 +2,7 @@ using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using Umbraco.Cms.Core.Configuration.Models;
using Umbraco.Cms.Core.DependencyInjection;
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.Models.PublishedContent;
using Umbraco.Cms.Core.PublishedCache;
using Umbraco.Cms.Core.Services.Navigation;
@@ -143,7 +144,7 @@ namespace Umbraco.Cms.Core.Routing
UrlInfo? url = _urlProviders.Select(provider => provider.GetUrl(content, mode, culture, current))
.FirstOrDefault(u => u is not null);
return url?.Text ?? "#"; // legacy wants this
return url?.Url?.ToString() ?? "#"; // legacy wants this
}
public string GetUrlFromRoute(int id, string? route, string? culture)
@@ -152,7 +153,7 @@ namespace Umbraco.Cms.Core.Routing
NewDefaultUrlProvider? provider = _urlProviders.OfType<NewDefaultUrlProvider>().FirstOrDefault();
var url = provider == null
? route // what else?
: provider.GetUrlFromRoute(route, id, umbracoContext.CleanedUmbracoUrl, Mode, culture)?.Text;
: provider.GetUrlFromRoute(route, id, umbracoContext.CleanedUmbracoUrl, Mode, culture)?.Url?.ToString();
return url ?? "#";
}
@@ -261,7 +262,7 @@ namespace Umbraco.Cms.Core.Routing
provider.GetMediaUrl(content, propertyAlias, mode, culture, current))
.FirstOrDefault(u => u is not null);
return url?.Text ?? string.Empty;
return url?.Url?.ToString() ?? string.Empty;
}
#endregion

View File

@@ -1,11 +1,8 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Umbraco.Cms.Core;
using Umbraco.Cms.Core.DependencyInjection;
using Umbraco.Cms.Core.Extensions;
using Umbraco.Cms.Core.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;
@@ -15,6 +12,8 @@ namespace Umbraco.Extensions;
public static class UrlProviderExtensions
{
private const string UrlProviderAlias = Constants.UrlProviders.Content;
/// <summary>
/// Gets the URLs of the content item.
/// </summary>
@@ -51,7 +50,7 @@ public static class UrlProviderExtensions
if (content.Published == false)
{
result.Add(UrlInfo.Message(textService.Localize("content", "itemNotPublished")));
result.Add(UrlInfo.AsMessage(textService.Localize("content", "itemNotPublished"), UrlProviderAlias));
return result;
}
@@ -77,14 +76,14 @@ public static class UrlProviderExtensions
}
// return the real URLs first, then the messages
foreach (IGrouping<bool, UrlInfo> urlGroup in urls.GroupBy(x => x.IsUrl).OrderByDescending(x => x.Key))
foreach (IGrouping<bool, UrlInfo> urlGroup in urls.GroupBy(x => x.Url is not null).OrderByDescending(x => x.Key))
{
// in some cases there will be the same URL for multiple cultures:
// * The entire branch is invariant
// * If there are less domain/cultures assigned to the branch than the number of cultures/languages installed
if (urlGroup.Key)
{
result.AddRange(urlGroup.DistinctBy(x => x.Text, StringComparer.OrdinalIgnoreCase).OrderBy(x => x.Text)
result.AddRange(urlGroup.DistinctBy(x => x.Url?.ToString(), StringComparer.OrdinalIgnoreCase).OrderBy(x => x.Url?.ToString())
.ThenBy(x => x.Culture));
}
else
@@ -95,7 +94,7 @@ public static class UrlProviderExtensions
// get the 'other' URLs - ie not what you'd get with GetUrl() but URLs that would route to the document, nevertheless.
// for these 'other' URLs, we don't check whether they are routable, collide, anything - we just report them.
foreach (UrlInfo otherUrl in publishedUrlProvider.GetOtherUrls(content.Id).OrderBy(x => x.Text)
foreach (UrlInfo otherUrl in publishedUrlProvider.GetOtherUrls(content.Id).OrderBy(x => x.Message)
.ThenBy(x => x.Culture))
{
// avoid duplicates
@@ -156,7 +155,7 @@ public static class UrlProviderExtensions
// deal with exceptions
case "#ex":
result.Add(UrlInfo.Message(textService.Localize("content", "getUrlException"), culture));
result.Add(UrlInfo.AsMessage(textService.Localize("content", "getUrlException"), UrlProviderAlias, culture));
break;
// got a URL, deal with collisions, add URL
@@ -169,7 +168,7 @@ public static class UrlProviderExtensions
}
else
{
result.Add(UrlInfo.Url(url, culture));
result.Add(UrlInfo.AsUrl(url, UrlProviderAlias, culture));
}
break;
@@ -194,18 +193,19 @@ public static class UrlProviderExtensions
if (parent == null)
{
// oops, internal error
return UrlInfo.Message(textService.Localize("content", "parentNotPublishedAnomaly"), culture);
return UrlInfo.AsMessage(textService.Localize("content", "parentNotPublishedAnomaly"), UrlProviderAlias, culture);
}
if (!parent.Published)
{
// totally not published
return UrlInfo.Message(textService.Localize("content", "parentNotPublished", new[] { parent.Name }), culture);
return UrlInfo.AsMessage(textService.Localize("content", "parentNotPublished", new[] { parent.Name }), UrlProviderAlias, culture);
}
// culture not published
return UrlInfo.Message(
return UrlInfo.AsMessage(
textService.Localize("content", "parentCultureNotPublished", new[] { parent.Name }),
UrlProviderAlias,
culture);
}
@@ -243,7 +243,7 @@ public static class UrlProviderExtensions
logger.LogDebug(logMsg, url, uri, culture);
}
var urlInfo = UrlInfo.Message(textService.Localize("content", "routeErrorCannotRoute"), culture);
var urlInfo = UrlInfo.AsMessage(textService.Localize("content", "routeErrorCannotRoute"), UrlProviderAlias, culture);
return Attempt.Succeed(urlInfo);
}
@@ -265,7 +265,7 @@ public static class UrlProviderExtensions
l.Reverse();
var s = "/" + string.Join("/", l) + " (id=" + pcr.PublishedContent?.Id + ")";
var urlInfo = UrlInfo.Message(textService.Localize("content", "routeError", new[] { s }), culture);
var urlInfo = UrlInfo.AsMessage(textService.Localize("content", "routeError", new[] { s }), UrlProviderAlias, culture);
return Attempt.Succeed(urlInfo);
}