/// <summary> /// Gets the localized URL. /// </summary> /// <param name="umbracoContext">The umbraco context.</param> /// <param name="id">The identifier.</param> /// <param name="current">The current.</param> /// <param name="mode">The mode.</param> /// <param name="culture">The culture.</param> /// <returns></returns> /// <exception cref="System.ArgumentException">Current url must be absolute.;current</exception> public string GetUrl( UmbracoContext umbracoContext, int id, Uri current, UrlProviderMode mode, CultureInfo culture) { if (FindByUrlAliasEnabled /* && umbracoContext.IsFrontEndUmbracoRequest*/) { if (current.IsAbsoluteUri == false) { throw new ArgumentException("Current url must be absolute.", "current"); } if (OnUrlGenerating != null) { OnUrlGeneratingEventArgs e = new OnUrlGeneratingEventArgs(umbracoContext, id, current, mode, culture); OnUrlGenerating(this, e); if (e.Cancel) { return(null); } } string isoCode = culture.Name; // will not use cache if previewing bool anyLocalizedUrl; string route = _routingHelper.GetRouteById( umbracoContext, umbracoContext.InPreviewMode, id, isoCode, out anyLocalizedUrl); // NO! We want to localize it because of Surface/Api Controller! //if (anyLocalizedUrl == false) return null; // other provider should take care of it if (string.IsNullOrWhiteSpace(route)) { LogHelper.Debug <AliasUrlProvider>( "Couldn't find any page with contentId={0}. This is most likely caused by the page not being published.", () => id); return(null); } // assemble the url from domainUri (maybe null) and path return(_routingHelper.AssembleUrl( route: route, current: current, mode: mode, isoCode: isoCode)); } else { return(null); // Other provider should take care of it. } }
/// <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> /// 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...). /// </remarks> public IEnumerable <string> GetOtherUrls(UmbracoContext umbracoContext, int id, Uri current) { if (FindByUrlAliasEnabled == false) { return(Enumerable.Empty <string>()); } IPublishedContent content = umbracoContext.ContentCache.GetById(id); if (OnOtherUrlsGenerating != null) { OnUrlGeneratingEventArgs e = new OnUrlGeneratingEventArgs(umbracoContext, id, current); OnOtherUrlsGenerating(this, e); if (e.Cancel) { return(Enumerable.Empty <string>()); } } bool hasDomains = _routingHelper.NodeHasDomains( contentId: content.Id); if (hasDomains) { // If content has domains we do not have to walk up // but when not then we have to, because we don't know if somewhere is a localized url return(Enumerable.Empty <string>()); } IPublishedContent node = content; IEnumerable <DomainAndUri> domainUris = _routingHelper.UmbracoDomainsForNode( contentId: node.Id, current: current, excludeDefault: false); List <IPublishedContent> parents = new List <IPublishedContent>(); while (domainUris == null && node != null) // n is null at root { // move to parent node node = node.Parent; if (node != null) { parents.Add(node); } domainUris = node == null ? null : _routingHelper.UmbracoDomainsForNode( contentId: node.Id, current: current, excludeDefault: false); } /*parents.Reverse(); // Reverse from root down to the node*/ List <string> otherUrls = new List <string>(); if (domainUris == null) { // If there are no domains (hostnames) we don't have to do anything // because we do not have smth. like /de /en, right?! return(otherUrls); } // We have to assemble the other urls by the url alias // but we have to do that with all possible languages // because the urlAlias could be null but the parent could have one /*string path; * bool isLocalized; * UrlAlias alias;*/ string path; foreach (CultureInfo cultureInfo in LocalizationContext.Cultures) { //TODO: We use the same as the Frontend would use it... the question is, if that is ok? // Due to performance... I don't know we have less code here but populate always the parents and it's domains? path = content.GetLocalizedUrl(language: cultureInfo.TwoLetterISOLanguageName); // Url per language will be added because of the domainAndUris // so /about-us is possible for all languages e.g. /en/about-us /de/about-us /it/about-us... foreach (DomainAndUri domainUri in domainUris) { // We have to replace the host and the language so we can populate the other urls correctly path = path.Replace(domainUri.Uri.GetBaseUrl(), string.Empty); path = path.EnsureStartsWith('/').EnsureEndsWith('/'); path = path.Replace("/" + cultureInfo.TwoLetterISOLanguageName.ToLowerInvariant() + "/", string.Empty); path = path.EnsureStartsWith('/').EnsureEndsWith('/'); } //alias = urlAlias.SingleOrDefault(o => o.ISOCode.Equals(cultureInfo.Name)); //otherUrls.Add(path); /*path = "/" + string.Join("/", _routingHelper.GetUrlNamesByISOCode(contents: parents, isoCode: cultureInfo.Name)); * path += (parents.Count > 1 ? "/" : string.Empty) + _routingHelper.GetUrlName(false, content, alias, out isLocalized);*/ otherUrls.AddRange(AssembleOtherUrls( domainUris: domainUris, path: path)); } return(otherUrls .Where(o => o.Equals(content.Url) == false) // Except the url made from umbraco .OrderBy(o => o) .Distinct() .ToList()); }