Adds a couple of tests which yielded some other issues with getting urls by culture, those are now fixed

This commit is contained in:
Shannon
2018-04-27 13:27:15 +10:00
parent 73567ffdce
commit c19dbeda23
11 changed files with 226 additions and 96 deletions

View File

@@ -11,6 +11,7 @@ using Umbraco.Core.Models;
using Umbraco.Core.Models.PublishedContent;
using Umbraco.Core.PropertyEditors;
using Umbraco.Tests.TestHelpers;
using Umbraco.Tests.TestHelpers.Stubs;
using Umbraco.Web;
using Umbraco.Web.PublishedCache;
@@ -99,7 +100,7 @@ namespace Umbraco.Tests.Published
var element1 = new PublishedElement(elementType1, Guid.NewGuid(), new Dictionary<string, object> { { "prop1", "1234" } }, false);
var cntType1 = contentTypeFactory.CreateContentType(1001, "cnt1", Array.Empty<PublishedPropertyType>());
var cnt1 = new PublishedSnapshotTestObjects.TestPublishedContent(cntType1, 1234, Guid.NewGuid(), new Dictionary<string, object>(), false);
var cnt1 = new TestPublishedContent(cntType1, 1234, Guid.NewGuid(), new Dictionary<string, object>(), false);
cacheContent[cnt1.Id] = cnt1;
Assert.AreSame(cnt1, element1.Value("prop1"));
@@ -200,8 +201,8 @@ namespace Umbraco.Tests.Published
var element1 = new PublishedElement(elementType1, Guid.NewGuid(), new Dictionary<string, object> { { "prop1", "val1" } }, false);
var element2 = new PublishedElement(elementType2, Guid.NewGuid(), new Dictionary<string, object> { { "prop2", "1003" } }, false);
var cnt1 = new PublishedSnapshotTestObjects.TestPublishedContent(contentType1, 1003, Guid.NewGuid(), new Dictionary<string, object> { { "prop1", "val1" } }, false);
var cnt2 = new PublishedSnapshotTestObjects.TestPublishedContent(contentType2, 1004, Guid.NewGuid(), new Dictionary<string, object> { { "prop2", "1003" } }, false);
var cnt1 = new TestPublishedContent(contentType1, 1003, Guid.NewGuid(), new Dictionary<string, object> { { "prop1", "val1" } }, false);
var cnt2 = new TestPublishedContent(contentType2, 1004, Guid.NewGuid(), new Dictionary<string, object> { { "prop2", "1003" } }, false);
cacheContent[cnt1.Id] = cnt1.CreateModel();
cacheContent[cnt2.Id] = cnt2.CreateModel();

View File

@@ -8,8 +8,6 @@ namespace Umbraco.Tests.Published
{
public class PublishedSnapshotTestObjects
{
#region Published models
[PublishedModel("element1")]
public class TestElementModel1 : PublishedElementModel
{
@@ -49,66 +47,6 @@ namespace Umbraco.Tests.Published
public IEnumerable<TestContentModel1> Prop2 => this.Value<IEnumerable<TestContentModel1>>("prop2");
}
#endregion
#region Support classes
internal class TestPublishedContent : PublishedElement, IPublishedContent
{
public TestPublishedContent(PublishedContentType contentType, int id, Guid key, Dictionary<string, object> values, bool previewing)
: base(contentType, key, values, previewing)
{
Id = id;
}
public int Id { get; }
public int TemplateId { get; set; }
public int SortOrder { get; set; }
public string Name { get; set; }
public IReadOnlyDictionary<string, PublishedCultureName> CultureNames => throw new NotSupportedException();
public string UrlName { get; set; }
public string DocumentTypeAlias => ContentType.Alias;
public int DocumentTypeId { get; set; }
public string WriterName { get; set; }
public string CreatorName { get; set; }
public int WriterId { get; set; }
public int CreatorId { get; set; }
public string Path { get; set; }
public DateTime CreateDate { get; set; }
public DateTime UpdateDate { get; set; }
public Guid Version { get; set; }
public int Level { get; set; }
public string Url { get; set; }
public PublishedItemType ItemType => ContentType.ItemType;
public bool IsDraft { get; set; }
public IPublishedContent Parent { get; set; }
public IEnumerable<IPublishedContent> Children { get; set; }
// copied from PublishedContentBase
public IPublishedProperty GetProperty(string alias, bool recurse)
{
var property = GetProperty(alias);
if (recurse == false) return property;
IPublishedContent content = this;
var firstNonNullProperty = property;
while (content != null && (property == null || property.HasValue() == false))
{
content = content.Parent;
property = content?.GetProperty(alias);
if (firstNonNullProperty == null && property != null) firstNonNullProperty = property;
}
// if we find a content with the property with a value, return that property
// if we find no content with the property, return null
// if we find a content with the property without a value, return that property
// have to save that first property while we look further up, hence firstNonNullProperty
return property != null && property.HasValue() ? property : firstNonNullProperty;
}
}
#endregion
}
}

View File

@@ -1,9 +1,13 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using Moq;
using NUnit.Framework;
using Umbraco.Core.Configuration.UmbracoSettings;
using Umbraco.Core.Models.PublishedContent;
using Umbraco.Tests.TestHelpers;
using Umbraco.Tests.TestHelpers.Stubs;
using Umbraco.Tests.Testing;
using Umbraco.Web.PublishedCache;
using Umbraco.Web.PublishedCache.XmlPublishedCache;
@@ -44,11 +48,11 @@ namespace Umbraco.Tests.Routing
globalSettings.Setup(x => x.HideTopLevelNodeFromPath).Returns(false);
SettingsForTests.ConfigureSettings(globalSettings.Object);
var umbracoContext = GetUmbracoContext("/test", 1111, urlProviders: new []
var umbracoContext = GetUmbracoContext("/test", 1111, urlProviders: new[]
{
new DefaultUrlProvider(_umbracoSettings.RequestHandler, Logger, globalSettings.Object, new SiteDomainHelper())
}, globalSettings:globalSettings.Object);
}, globalSettings: globalSettings.Object);
var requestHandlerMock = Mock.Get(_umbracoSettings.RequestHandler);
requestHandlerMock.Setup(x => x.AddTrailingSlash).Returns(false);// (cached routes have none)
@@ -110,7 +114,7 @@ namespace Umbraco.Tests.Routing
var umbracoContext = GetUmbracoContext("/test", 1111, urlProviders: new[]
{
new DefaultUrlProvider(_umbracoSettings.RequestHandler, Logger, globalSettings.Object, new SiteDomainHelper())
}, globalSettings:globalSettings.Object);
}, globalSettings: globalSettings.Object);
var requestMock = Mock.Get(_umbracoSettings.RequestHandler);
requestMock.Setup(x => x.UseDomainPrefixes).Returns(false);
@@ -140,7 +144,7 @@ namespace Umbraco.Tests.Routing
var umbracoContext = GetUmbracoContext("/test", 1111, urlProviders: new[]
{
new DefaultUrlProvider(_umbracoSettings.RequestHandler, Logger, globalSettings.Object, new SiteDomainHelper())
}, globalSettings:globalSettings.Object);
}, globalSettings: globalSettings.Object);
var requestMock = Mock.Get(_umbracoSettings.RequestHandler);
requestMock.Setup(x => x.UseDomainPrefixes).Returns(false);
@@ -149,14 +153,118 @@ namespace Umbraco.Tests.Routing
Assert.AreEqual(niceUrlMatch, result);
}
/// <summary>
/// This tests DefaultUrlProvider.GetUrl with a specific culture when the current URL is the culture specific domain
/// </summary>
[Test]
public void Get_Nice_Url_Relative_Or_Absolute()
public void Get_Url_For_Culture_Variant_With_Current_Url()
{
const string currentUri = "http://example.com/fr/test";
var globalSettings = Mock.Get(TestObjects.GetGlobalSettings()); //this will modify the IGlobalSettings instance stored in the container
globalSettings.Setup(x => x.UseDirectoryUrls).Returns(true);
globalSettings.Setup(x => x.HideTopLevelNodeFromPath).Returns(false);
SettingsForTests.ConfigureSettings(globalSettings.Object);
var requestMock = Mock.Get(_umbracoSettings.RequestHandler);
requestMock.Setup(x => x.UseDomainPrefixes).Returns(false);
var publishedContentCache = new Mock<IPublishedContentCache>();
publishedContentCache.Setup(x => x.GetRouteById(1234, "fr-FR"))
.Returns("9876/home/test-fr"); //prefix with the root id node with the domain assigned as per the umbraco standard
var domainCache = new Mock<IDomainCache>();
domainCache.Setup(x => x.GetAssigned(It.IsAny<int>(), false))
.Returns((int contentId, bool includeWildcards) =>
{
if (contentId != 9876) return Enumerable.Empty<Domain>();
return new[]
{
new Domain(2, "example.com/en", 9876, CultureInfo.GetCultureInfo("en-US"), false, true), //default
new Domain(3, "example.com/fr", 9876, CultureInfo.GetCultureInfo("fr-FR"), false, true)
};
});
var snapshot = Mock.Of<IPublishedSnapshot>(x => x.Content == publishedContentCache.Object && x.Domains == domainCache.Object);
var snapshotService = new Mock<IPublishedSnapshotService>();
snapshotService.Setup(x => x.CreatePublishedSnapshot(It.IsAny<string>()))
.Returns(snapshot);
var umbracoContext = GetUmbracoContext(currentUri, umbracoSettings: _umbracoSettings,
urlProviders: new[] {
new DefaultUrlProvider(_umbracoSettings.RequestHandler, Logger, globalSettings.Object, new SiteDomainHelper())
},
globalSettings: globalSettings.Object,
snapshotService: snapshotService.Object);
var url = umbracoContext.UrlProvider.GetUrl(1234, "fr-FR");
//the current uri is the culture specific domain we want, so the result is a relative path since we are on the culture specific domain
Assert.AreEqual("/fr/home/test-fr/", url);
}
/// <summary>
/// This tests DefaultUrlProvider.GetUrl with a specific culture when the current URL is not the culture specific domain
/// </summary>
[Test]
public void Get_Url_For_Culture_Variant_Non_Current_Url()
{
const string currentUri = "http://example.com/en/test";
var globalSettings = Mock.Get(TestObjects.GetGlobalSettings()); //this will modify the IGlobalSettings instance stored in the container
globalSettings.Setup(x => x.UseDirectoryUrls).Returns(true);
globalSettings.Setup(x => x.HideTopLevelNodeFromPath).Returns(false);
SettingsForTests.ConfigureSettings(globalSettings.Object);
var requestMock = Mock.Get(_umbracoSettings.RequestHandler);
requestMock.Setup(x => x.UseDomainPrefixes).Returns(false);
var publishedContentCache = new Mock<IPublishedContentCache>();
publishedContentCache.Setup(x => x.GetRouteById(1234, "fr-FR"))
.Returns("9876/home/test-fr"); //prefix with the root id node with the domain assigned as per the umbraco standard
var domainCache = new Mock<IDomainCache>();
domainCache.Setup(x => x.GetAssigned(It.IsAny<int>(), false))
.Returns((int contentId, bool includeWildcards) =>
{
if (contentId != 9876) return Enumerable.Empty<Domain>();
return new[]
{
new Domain(2, "example.com/en", 9876, CultureInfo.GetCultureInfo("en-US"), false, true), //default
new Domain(3, "example.com/fr", 9876, CultureInfo.GetCultureInfo("fr-FR"), false, true)
};
});
var snapshot = Mock.Of<IPublishedSnapshot>(x => x.Content == publishedContentCache.Object && x.Domains == domainCache.Object);
var snapshotService = new Mock<IPublishedSnapshotService>();
snapshotService.Setup(x => x.CreatePublishedSnapshot(It.IsAny<string>()))
.Returns(snapshot);
var umbracoContext = GetUmbracoContext(currentUri, umbracoSettings: _umbracoSettings,
urlProviders: new[] {
new DefaultUrlProvider(_umbracoSettings.RequestHandler, Logger, globalSettings.Object, new SiteDomainHelper())
},
globalSettings: globalSettings.Object,
snapshotService: snapshotService.Object);
var url = umbracoContext.UrlProvider.GetUrl(1234, "fr-FR");
//the current uri is not the culture specific domain we want, so the result is an absolute path to the culture specific domain
Assert.AreEqual("http://example.com/fr/home/test-fr/", url);
}
[Test]
public void Get_Url_Relative_Or_Absolute()
{
var globalSettings = Mock.Get(TestObjects.GetGlobalSettings()); //this will modify the IGlobalSettings instance stored in the container
globalSettings.Setup(x => x.UseDirectoryUrls).Returns(true);
globalSettings.Setup(x => x.HideTopLevelNodeFromPath).Returns(false);
SettingsForTests.ConfigureSettings(globalSettings.Object);
var requestMock = Mock.Get(_umbracoSettings.RequestHandler);
requestMock.Setup(x => x.UseDomainPrefixes).Returns(false);
@@ -164,7 +272,7 @@ namespace Umbraco.Tests.Routing
var umbracoContext = GetUmbracoContext("http://example.com/test", 1111, umbracoSettings: _umbracoSettings, urlProviders: new[]
{
new DefaultUrlProvider(_umbracoSettings.RequestHandler, Logger, globalSettings.Object, new SiteDomainHelper())
}, globalSettings:globalSettings.Object);
}, globalSettings: globalSettings.Object);
Assert.AreEqual("/home/sub1/custom-sub-1/", umbracoContext.UrlProvider.GetUrl(1177));
@@ -187,7 +295,7 @@ namespace Umbraco.Tests.Routing
var umbracoContext = GetUmbracoContext("http://example.com/test", 1111, urlProviders: new[]
{
new DefaultUrlProvider(_umbracoSettings.RequestHandler, Logger, globalSettings.Object, new SiteDomainHelper())
}, globalSettings:globalSettings.Object);
}, globalSettings: globalSettings.Object);
//mock the Umbraco settings that we need
var requestMock = Mock.Get(_umbracoSettings.RequestHandler);

View File

@@ -0,0 +1,66 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Umbraco.Core.Models.PublishedContent;
using Umbraco.Web.PublishedCache;
namespace Umbraco.Tests.TestHelpers.Stubs
{
internal class TestPublishedContent : PublishedElement, IPublishedContent
{
public TestPublishedContent(PublishedContentType contentType, int id, Guid key, Dictionary<string, object> values, bool previewing, Dictionary<string, PublishedCultureName> cultureNames = null)
: base(contentType, key, values, previewing)
{
Id = id;
CultureNames = cultureNames;
}
public int Id { get; }
public int TemplateId { get; set; }
public int SortOrder { get; set; }
public string Name { get; set; }
public IReadOnlyDictionary<string, PublishedCultureName> CultureNames { get; set; }
public string UrlName { get; set; }
public string DocumentTypeAlias => ContentType.Alias;
public int DocumentTypeId { get; set; }
public string WriterName { get; set; }
public string CreatorName { get; set; }
public int WriterId { get; set; }
public int CreatorId { get; set; }
public string Path { get; set; }
public DateTime CreateDate { get; set; }
public DateTime UpdateDate { get; set; }
public Guid Version { get; set; }
public int Level { get; set; }
public string Url { get; set; }
public PublishedItemType ItemType => ContentType.ItemType;
public bool IsDraft { get; set; }
public IPublishedContent Parent { get; set; }
public IEnumerable<IPublishedContent> Children { get; set; }
// copied from PublishedContentBase
public IPublishedProperty GetProperty(string alias, bool recurse)
{
var property = GetProperty(alias);
if (recurse == false) return property;
IPublishedContent content = this;
var firstNonNullProperty = property;
while (content != null && (property == null || property.HasValue() == false))
{
content = content.Parent;
property = content?.GetProperty(alias);
if (firstNonNullProperty == null && property != null) firstNonNullProperty = property;
}
// if we find a content with the property with a value, return that property
// if we find no content with the property, return null
// if we find a content with the property without a value, return that property
// have to save that first property while we look further up, hence firstNonNullProperty
return property != null && property.HasValue() ? property : firstNonNullProperty;
}
}
}

View File

@@ -366,7 +366,8 @@ namespace Umbraco.Tests.TestHelpers
var umbracoContext = new UmbracoContext(
httpContext,
service,
new WebSecurity(httpContext, Container.GetInstance<IUserService>(), Container.GetInstance<IGlobalSettings>()),
new WebSecurity(httpContext, Container.GetInstance<IUserService>(),
Container.GetInstance<IGlobalSettings>()),
umbracoSettings ?? Container.GetInstance<IUmbracoSettingsSection>(),
urlProviders ?? Enumerable.Empty<IUrlProvider>(),
globalSettings ?? Container.GetInstance<IGlobalSettings>(),

View File

@@ -178,6 +178,7 @@
<Compile Include="TestHelpers\Entities\MockedUserGroup.cs" />
<Compile Include="TestHelpers\NoHttpContextAccessor.cs" />
<Compile Include="TestHelpers\Stubs\TestExamineManager.cs" />
<Compile Include="TestHelpers\Stubs\TestPublishedContent.cs" />
<Compile Include="Testing\ContentBaseExtensions.cs" />
<Compile Include="Testing\TestDatabase.cs" />
<Compile Include="Testing\TestingTests\NUnitTests.cs" />

View File

@@ -2,15 +2,23 @@
using Umbraco.Core.Models;
using Umbraco.Web.Composing;
using Umbraco.Web.Models.ContentEditing;
using Umbraco.Web.Routing;
namespace Umbraco.Web.Models.Mapping
{
internal class RedirectUrlMapperProfile : Profile
{
private readonly UrlProvider _urlProvider;
public RedirectUrlMapperProfile(UrlProvider urlProvider)
{
_urlProvider = urlProvider;
}
public RedirectUrlMapperProfile()
{
CreateMap<IRedirectUrl, ContentRedirectUrl>()
.ForMember(x => x.OriginalUrl, expression => expression.MapFrom(item => Current.UmbracoContext.UrlProvider.GetUrlFromRoute(item.ContentId, item.Url)))
.ForMember(x => x.OriginalUrl, expression => expression.MapFrom(item => _urlProvider.GetUrlFromRoute(item.ContentId, item.Url, null)))
.ForMember(x => x.DestinationUrl, expression => expression.Ignore())
.ForMember(x => x.RedirectId, expression => expression.MapFrom(item => item.Key));
}

View File

@@ -163,7 +163,9 @@ namespace Umbraco.Web.PublishedCache.NuCache
// assemble the route
pathParts.Reverse();
var path = "/" + string.Join("/", pathParts); // will be "/" or "/foo" or "/foo/bar" etc
var route = (n?.Id.ToString(CultureInfo.InvariantCulture) ?? "") + path;
//prefix the root node id containing the domain if it exists (this is a standard way of creating route paths)
//and is done so that we know the ID of the domain node for the path
var route = (n?.Id.ToString(CultureInfo.InvariantCulture) ?? "") + path;
return route;
}

View File

@@ -32,7 +32,7 @@ namespace Umbraco.Web.Routing
#region GetUrl
/// <summary>
/// Gets the nice url of a published content.
/// Gets the url of a published content.
/// </summary>
/// <param name="umbracoContext">The Umbraco context.</param>
/// <param name="id">The published content id.</param>
@@ -51,10 +51,10 @@ namespace Umbraco.Web.Routing
// will not use cache if previewing
var route = umbracoContext.ContentCache.GetRouteById(id, culture);
return GetUrlFromRoute(route, umbracoContext, id, current, mode);
return GetUrlFromRoute(route, umbracoContext, id, current, mode, culture);
}
internal string GetUrlFromRoute(string route, UmbracoContext umbracoContext, int id, Uri current, UrlProviderMode mode)
internal string GetUrlFromRoute(string route, UmbracoContext umbracoContext, int id, Uri current, UrlProviderMode mode, string culture)
{
if (string.IsNullOrWhiteSpace(route))
{
@@ -71,7 +71,7 @@ namespace Umbraco.Web.Routing
var path = pos == 0 ? route : route.Substring(pos);
var domainUri = pos == 0
? null
: domainHelper.DomainForNode(int.Parse(route.Substring(0, pos)), current);
: domainHelper.DomainForNode(int.Parse(route.Substring(0, pos)), current, culture);
// assemble the url from domainUri (maybe null) and path
return AssembleUrl(domainUri, path, current, mode).ToString();
@@ -119,8 +119,7 @@ namespace Umbraco.Web.Routing
var route = umbracoContext.ContentCache.GetRouteById(id, d?.Culture?.Name);
if (route == null) continue;
//need to strip off the leading ID for the route
//TODO: Is there a nicer way to deal with this?
//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);
@@ -170,7 +169,7 @@ namespace Umbraco.Web.Routing
{
if (mode == UrlProviderMode.Auto)
{
if (current != null && domainUri.Uri.GetLeftPart(UriPartial.Authority) == current.GetLeftPart(UriPartial.Authority))
if (current != null && current.GetLeftPart(UriPartial.Path).InvariantStartsWith(domainUri.Uri.GetLeftPart(UriPartial.Path)))
mode = UrlProviderMode.Relative;
else
mode = UrlProviderMode.Absolute;

View File

@@ -31,7 +31,7 @@ namespace Umbraco.Web.Routing
/// <returns>The domain and its uri, if any, that best matches the specified uri, else null.</returns>
/// <remarks>If at least a domain is set on the node then the method returns the domain that
/// best matches the specified uri, else it returns null.</remarks>
internal DomainAndUri DomainForNode(int nodeId, Uri current)
internal DomainAndUri DomainForNode(int nodeId, Uri current, string culture = null)
{
// be safe
if (nodeId <= 0)
@@ -45,7 +45,7 @@ namespace Umbraco.Web.Routing
return null;
// else filter
var domainAndUri = DomainForUri(domains, current, domainAndUris => _siteDomainHelper.MapDomain(current, domainAndUris));
var domainAndUri = DomainForUri(domains, current, culture, domainAndUris => _siteDomainHelper.MapDomain(current, domainAndUris));
if (domainAndUri == null)
throw new Exception("DomainForUri returned null.");
@@ -108,14 +108,13 @@ namespace Umbraco.Web.Routing
/// the right one, unless it is <c>null</c>, in which case the method returns <c>null</c>.</para>
/// <para>The filter, if any, will be called only with a non-empty argument, and _must_ return something.</para>
/// </remarks>
internal static DomainAndUri DomainForUri(IEnumerable<Domain> domains, Uri current, Func<DomainAndUri[], DomainAndUri> filter = null)
internal static DomainAndUri DomainForUri(IEnumerable<Domain> domains, Uri current, string culture = null, Func<DomainAndUri[], DomainAndUri> filter = null)
{
// sanitize the list to have proper uris for comparison (scheme, path end with /)
// we need to end with / because example.com/foo cannot match example.com/foobar
// we need to order so example.com/foo matches before example.com/
var domainsAndUris = domains
.Where(d => d.IsWildcard == false)
//.Select(SanitizeForBackwardCompatibility)
.Select(d => new DomainAndUri(d, current))
.OrderByDescending(d => d.Uri.ToString())
.ToArray();
@@ -126,8 +125,12 @@ namespace Umbraco.Web.Routing
DomainAndUri domainAndUri;
if (current == null)
{
//get the default domain (there should be one)
domainAndUri = domainsAndUris.FirstOrDefault(x => x.IsDefault);
//get the default domain or the one matching the culture if specified
domainAndUri = domainsAndUris.FirstOrDefault(x => culture.IsNullOrWhiteSpace() ? x.IsDefault : x.Culture.Name.InvariantEquals(culture));
if (domainAndUri == null && !culture.IsNullOrWhiteSpace())
throw new InvalidOperationException($"No domain was found by the specified culture '{culture}'");
if (domainAndUri == null)
domainAndUri = domainsAndUris.First(); // take the first one by default (what else can we do?)
}
@@ -138,13 +141,17 @@ namespace Umbraco.Web.Routing
var currentWithSlash = current.EndPathWithSlash();
domainAndUri = domainsAndUris
.FirstOrDefault(d => d.Uri.EndPathWithSlash().IsBaseOf(currentWithSlash));
if (domainAndUri != null) return domainAndUri;
//is culture specified? if so this will need to match too
if (domainAndUri != null && (culture.IsNullOrWhiteSpace() || domainAndUri.Culture.Name.InvariantEquals(culture)))
return domainAndUri;
// if none matches, try again without the port
// ie current is www.example.com:1234/foo/bar, look for domain www.example.com
domainAndUri = domainsAndUris
.FirstOrDefault(d => d.Uri.EndPathWithSlash().IsBaseOf(currentWithSlash.WithoutPort()));
if (domainAndUri != null) return domainAndUri;
//is culture specified? if so this will need to match too
if (domainAndUri != null && (culture.IsNullOrWhiteSpace() || domainAndUri.Culture.Name.InvariantEquals(culture)))
return domainAndUri;
// if none matches, then try to run the filter to pick a domain
if (filter != null)
@@ -170,7 +177,6 @@ namespace Umbraco.Web.Routing
{
return domains
.Where(d => d.IsWildcard == false)
//.Select(SanitizeForBackwardCompatibility)
.Select(d => new DomainAndUri(d, current))
.OrderByDescending(d => d.Uri.ToString());
}

View File

@@ -216,12 +216,12 @@ namespace Umbraco.Web.Routing
return url ?? "#"; // legacy wants this
}
internal string GetUrlFromRoute(int id, string route)
internal string GetUrlFromRoute(int id, string route, string culture)
{
var provider = _urlProviders.OfType<DefaultUrlProvider>().FirstOrDefault();
var url = provider == null
? route // what else?
: provider.GetUrlFromRoute(route, UmbracoContext.Current, id, _umbracoContext.CleanedUmbracoUrl, Mode);
: provider.GetUrlFromRoute(route, UmbracoContext.Current, id, _umbracoContext.CleanedUmbracoUrl, Mode, culture);
return url ?? "#";
}