/// <summary> /// Gets the other URLs of a published content. /// </summary> /// <param name="umbracoContextAccessor">The Umbraco context.</param> /// <param name="id">The published content id.</param> /// <param name="current">The current absolute URL.</param> /// <returns>The other URLs for the published content.</returns> /// <remarks> /// <para> /// Other URLs are those that <c>GetUrl</c> would not return in the current context, but would be valid /// URLs for the node in other contexts (different domain for current request, umbracoUrlAlias...). /// </para> /// </remarks> public virtual IEnumerable <UrlInfo> GetOtherUrls(int id, Uri current) { IUmbracoContext umbracoContext = _umbracoContextAccessor.GetRequiredUmbracoContext(); IPublishedContent node = umbracoContext.Content.GetById(id); if (node == null) { yield break; } // look for domains, walking up the tree IPublishedContent n = node; IEnumerable <DomainAndUri> domainUris = DomainUtilities.DomainsForNode(umbracoContext.PublishedSnapshot.Domains, _siteDomainMapper, n.Id, current, false); while (domainUris == null && n != null) // n is null at root { n = n.Parent; // move to parent node domainUris = n == null ? null : DomainUtilities.DomainsForNode(umbracoContext.PublishedSnapshot.Domains, _siteDomainMapper, n.Id, current); } // no domains = exit if (domainUris == null) { yield break; } foreach (DomainAndUri d in domainUris) { var culture = d?.Culture; // although we are passing in culture here, if any node in this path is invariant, it ignores the culture anyways so this is ok var route = umbracoContext.Content.GetRouteById(id, culture); if (route == null) { continue; } // need to strip off the leading ID for the route if it exists (occurs if the route is for a node with a domain assigned) var pos = route.IndexOf('/'); var path = pos == 0 ? route : route.Substring(pos); var uri = new Uri(CombinePaths(d.Uri.GetLeftPart(UriPartial.Path), path)); uri = _uriUtility.UriFromUmbraco(uri, _requestSettings); yield return(UrlInfo.Url(uri.ToString(), culture)); } }
/// <summary> /// Gets the other URLs of a published content. /// </summary> /// <param name="umbracoContext">The Umbraco context.</param> /// <param name="id">The published content id.</param> /// <param name="current">The current absolute URL.</param> /// <returns>The other URLs for the published content.</returns> /// <remarks> /// <para>Other URLs are those that <c>GetUrl</c> would not return in the current context, but would be valid /// URLs for the node in other contexts (different domain for current request, umbracoUrlAlias...).</para> /// </remarks> public IEnumerable <UrlInfo> GetOtherUrls(int id, Uri current) { var umbracoContext = _umbracoContextAccessor.GetRequiredUmbracoContext(); var node = umbracoContext.Content.GetById(id); if (node == null) { yield break; } if (!node.HasProperty(Constants.Conventions.Content.UrlAlias)) { yield break; } // look for domains, walking up the tree var n = node; var domainUris = DomainUtilities.DomainsForNode(umbracoContext.PublishedSnapshot.Domains, _siteDomainMapper, n.Id, current, false); while (domainUris == null && n != null) // n is null at root { // move to parent node n = n.Parent; domainUris = n == null ? null : DomainUtilities.DomainsForNode(umbracoContext.PublishedSnapshot.Domains, _siteDomainMapper, n.Id, current, excludeDefault: false); } // determine whether the alias property varies var varies = node.GetProperty(Constants.Conventions.Content.UrlAlias).PropertyType.VariesByCulture(); if (domainUris == null) { // no domain // if the property is invariant, then URL "/<alias>" is ok // if the property varies, then what are we supposed to do? // the content finder may work, depending on the 'current' culture, // but there's no way we can return something meaningful here if (varies) { yield break; } var umbracoUrlName = node.Value <string>(_publishedValueFallback, Constants.Conventions.Content.UrlAlias); var aliases = umbracoUrlName?.Split(Constants.CharArrays.Comma, StringSplitOptions.RemoveEmptyEntries); if (aliases == null || aliases.Any() == false) { yield break; } foreach (var alias in aliases.Distinct()) { var path = "/" + alias; var uri = new Uri(path, UriKind.Relative); yield return(UrlInfo.Url(_uriUtility.UriFromUmbraco(uri, _requestConfig).ToString())); } } else { // some domains: one URL per domain, which is "<domain>/<alias>" foreach (var domainUri in domainUris) { // if the property is invariant, get the invariant value, URL is "<domain>/<invariant-alias>" // if the property varies, get the variant value, URL is "<domain>/<variant-alias>" // but! only if the culture is published, else ignore if (varies && !node.HasCulture(domainUri.Culture)) { continue; } var umbracoUrlName = varies ? node.Value <string>(_publishedValueFallback, Constants.Conventions.Content.UrlAlias, culture: domainUri.Culture) : node.Value <string>(_publishedValueFallback, Constants.Conventions.Content.UrlAlias); var aliases = umbracoUrlName?.Split(Constants.CharArrays.Comma, StringSplitOptions.RemoveEmptyEntries); if (aliases == null || aliases.Any() == false) { continue; } foreach (var alias in aliases.Distinct()) { var path = "/" + alias; var uri = new Uri(CombinePaths(domainUri.Uri.GetLeftPart(UriPartial.Path), path)); yield return(UrlInfo.Url(_uriUtility.UriFromUmbraco(uri, _requestConfig).ToString(), domainUri.Culture)); } } } }