Web.Routing - implement UrlProviderMode

This commit is contained in:
Stephan
2013-03-01 13:56:11 -01:00
parent e8e8053063
commit 9fc5ee897f
9 changed files with 166 additions and 43 deletions

View File

@@ -155,7 +155,7 @@ namespace Umbraco.Tests.Routing
Assert.AreEqual("http://example.com/home/sub1/custom-sub-1/", routingContext.UrlProvider.GetUrl(1177));
SettingsForTests.UseDomainPrefixes = false;
routingContext.UrlProvider.EnforceAbsoluteUrls = true;
routingContext.UrlProvider.Mode = UrlProviderMode.Absolute;
Assert.AreEqual("http://example.com/home/sub1/custom-sub-1/", routingContext.UrlProvider.GetUrl(1177));
}
@@ -172,7 +172,7 @@ namespace Umbraco.Tests.Routing
SettingsForTests.UseDomainPrefixes = true;
Assert.AreEqual("#", routingContext.UrlProvider.GetUrl(999999));
SettingsForTests.UseDomainPrefixes = false;
routingContext.UrlProvider.EnforceAbsoluteUrls = true;
routingContext.UrlProvider.Mode = UrlProviderMode.Absolute;
Assert.AreEqual("#", routingContext.UrlProvider.GetUrl(999999));
}
}

View File

@@ -368,7 +368,7 @@ namespace Umbraco.Tests.Routing
Assert.AreEqual("http://domain3.com/en/1003-1-1/", routingContext.UrlProvider.GetUrl(100311));
SettingsForTests.UseDomainPrefixes = false;
routingContext.UrlProvider.EnforceAbsoluteUrls = true;
routingContext.UrlProvider.Mode = UrlProviderMode.Absolute;
Assert.AreEqual("http://domain1.com/en/1001-1-1/", routingContext.UrlProvider.GetUrl(100111));
Assert.AreEqual("http://domain3.com/en/1003-1-1/", routingContext.UrlProvider.GetUrl(100311));
}

View File

@@ -11,14 +11,17 @@ namespace Umbraco.Web.Configuration
internal class WebRouting : UmbracoConfigurationSection
{
private const string KeyTrySkipIisCustomErrors = "trySkipIisCustomErrors";
private const string KeyUrlProviderMode = "urlProviderMode";
private bool? _trySkipIisCustomErrors;
private Routing.UrlProviderMode? _urlProviderMode;
internal protected override void ResetSection()
{
base.ResetSection();
_trySkipIisCustomErrors = null;
_urlProviderMode = null;
}
/// <summary>
@@ -35,5 +38,21 @@ namespace Umbraco.Web.Configuration
}
internal set { _trySkipIisCustomErrors = value; }
}
/// <summary>
/// Gets or sets the url provider mode.
/// </summary>
[ConfigurationProperty(KeyUrlProviderMode, DefaultValue = Routing.UrlProviderMode.AutoLegacy, IsRequired = false)]
[TypeConverter(typeof(CaseInsensitiveEnumConfigConverter<Routing.UrlProviderMode>))]
public Routing.UrlProviderMode UrlProviderMode
{
get
{
return _urlProviderMode ?? (IsPresent
? (Routing.UrlProviderMode)this[KeyUrlProviderMode]
: Routing.UrlProviderMode.Auto);
}
internal set { _urlProviderMode = value; }
}
}
}

View File

@@ -23,14 +23,14 @@ namespace Umbraco.Web.Routing
/// <param name="contentCache">The content cache.</param>
/// <param name="id">The published content id.</param>
/// <param name="current">The current absolute url.</param>
/// <param name="absolute">A value indicating whether the url should be absolute in any case.</param>
/// <param name="mode">The url mode.</param>
/// <returns>The url for the published content.</returns>
/// <remarks>
/// <para>The url is absolute or relative depending on url indicated by <c>current</c> and settings, unless
/// <c>absolute</c> is true, in which case the url is always absolute.</para>
/// <para>If the provider is unable to provide a url, it should return <c>null</c>.</para>
/// </remarks>
public string GetUrl(UmbracoContext umbracoContext, IPublishedContentStore contentCache, int id, Uri current, bool absolute)
public string GetUrl(UmbracoContext umbracoContext, IPublishedContentStore contentCache, int id, Uri current, UrlProviderMode mode)
{
return null; // we have nothing to say
}

View File

@@ -23,14 +23,13 @@ namespace Umbraco.Web.Routing
/// <param name="contentCache">The content cache.</param>
/// <param name="id">The published content id.</param>
/// <param name="current">The current absolute url.</param>
/// <param name="absolute">A value indicating whether the url should be absolute in any case.</param>
/// <param name="mode">The url mode.</param>
/// <returns>The url for the published content.</returns>
/// <remarks>
/// <para>The url is absolute or relative depending on url indicated by <c>current</c> and settings, unless
/// <c>absolute</c> is true, in which case the url is always absolute.</para>
/// <para>The url is absolute or relative depending on <c>mode</c> and on <c>current</c>.</para>
/// <para>If the provider is unable to provide a url, it should return <c>null</c>.</para>
/// </remarks>
public virtual string GetUrl(UmbracoContext umbracoContext, IPublishedContentStore contentCache, int id, Uri current, bool absolute)
public virtual string GetUrl(UmbracoContext umbracoContext, IPublishedContentStore contentCache, int id, Uri current, UrlProviderMode mode)
{
DomainAndUri domainUri;
string path;
@@ -49,7 +48,7 @@ namespace Umbraco.Web.Routing
{
// there was a route in the cache - extract domainUri and path
// route is /<path> or <domainRootId>/<path>
int pos = route.IndexOf('/');
var pos = route.IndexOf('/');
path = pos == 0 ? route : route.Substring(pos);
domainUri = pos == 0 ? null : DomainHelper.DomainForNode(int.Parse(route.Substring(0, pos)), current);
}
@@ -97,7 +96,7 @@ namespace Umbraco.Web.Routing
}
// assemble the url from domainUri (maybe null) and path
return AssembleUrl(domainUri, path, current, absolute).ToString();
return AssembleUrl(domainUri, path, current, mode).ToString();
}
#endregion
@@ -185,27 +184,65 @@ namespace Umbraco.Web.Routing
#region Utilities
Uri AssembleUrl(DomainAndUri domainUri, string path, Uri current, bool absolute)
Uri AssembleUrl(DomainAndUri domainUri, string path, Uri current, UrlProviderMode mode)
{
Uri uri;
if (domainUri == null)
// ignore vdir at that point, UriFromUmbraco will do it
if (mode == UrlProviderMode.AutoLegacy)
{
// no domain was found : return an absolute or relative url
// ignore vdir at that point
if (!absolute || current == null)
uri = new Uri(path, UriKind.Relative);
else
uri = new Uri(current.GetLeftPart(UriPartial.Authority) + path);
mode = Core.Configuration.UmbracoSettings.UseDomainPrefixes
? UrlProviderMode.Absolute
: UrlProviderMode.Auto;
}
else
if (mode == UrlProviderMode.AutoLegacy)
{
// a domain was found : return an absolute or relative url
// ignore vdir at that point
if (!absolute && current != null && domainUri.Uri.GetLeftPart(UriPartial.Authority) == current.GetLeftPart(UriPartial.Authority))
uri = new Uri(CombinePaths(domainUri.Uri.AbsolutePath, path), UriKind.Relative); // relative
else
uri = new Uri(CombinePaths(domainUri.Uri.GetLeftPart(UriPartial.Path), path)); // absolute
mode = Core.Configuration.UmbracoSettings.UseDomainPrefixes
? UrlProviderMode.Absolute
: UrlProviderMode.Auto;
}
if (domainUri == null) // no domain was found
{
if (current == null)
mode = UrlProviderMode.Relative; // best we can do
switch (mode)
{
case UrlProviderMode.Absolute:
uri = new Uri(current.GetLeftPart(UriPartial.Authority) + path);
break;
case UrlProviderMode.Relative:
case UrlProviderMode.Auto:
uri = new Uri(path, UriKind.Relative);
break;
default:
throw new ArgumentOutOfRangeException("mode");
}
}
else // a domain was found
{
if (mode == UrlProviderMode.Auto)
{
if (current != null && domainUri.Uri.GetLeftPart(UriPartial.Authority) == current.GetLeftPart(UriPartial.Authority))
mode = UrlProviderMode.Relative;
else
mode = UrlProviderMode.Absolute;
}
switch (mode)
{
case UrlProviderMode.Absolute:
uri = new Uri(CombinePaths(domainUri.Uri.GetLeftPart(UriPartial.Path), path));
break;
case UrlProviderMode.Relative:
uri = new Uri(CombinePaths(domainUri.Uri.AbsolutePath, path), UriKind.Relative);
break;
default:
throw new ArgumentOutOfRangeException("mode");
}
}
// UriFromUmbraco will handle vdir

View File

@@ -15,14 +15,13 @@ namespace Umbraco.Web.Routing
/// <param name="contentCache">The content cache.</param>
/// <param name="id">The published content id.</param>
/// <param name="current">The current absolute url.</param>
/// <param name="absolute">A value indicating whether the url should be absolute in any case.</param>
/// <param name="mode">The url mode.</param>
/// <returns>The url for the published content.</returns>
/// <remarks>
/// <para>The url is absolute or relative depending on url indicated by <c>current</c> and settings, unless
/// <c>absolute</c> is true, in which case the url is always absolute.</para>
/// <para>The url is absolute or relative depending on <c>mode</c> and on <c>current</c>.</para>
/// <para>If the provider is unable to provide a url, it should return <c>null</c>.</para>
/// </remarks>
string GetUrl(UmbracoContext umbracoContext, IPublishedContentStore contentCache, int id, Uri current, bool absolute);
string GetUrl(UmbracoContext umbracoContext, IPublishedContentStore contentCache, int id, Uri current, UrlProviderMode mode);
/// <summary>
/// Gets the other urls of a published content.

View File

@@ -24,7 +24,7 @@ namespace Umbraco.Web.Routing
_umbracoContext = umbracoContext;
_contentCache = contentCache;
_urlProviders = urlProviders;
EnforceAbsoluteUrls = false;
Mode = UmbracoSettings.For<Configuration.WebRouting>().UrlProviderMode;
}
private readonly UmbracoContext _umbracoContext;
@@ -32,9 +32,9 @@ namespace Umbraco.Web.Routing
private readonly IEnumerable<IUrlProvider> _urlProviders;
/// <summary>
/// Gets or sets a value indicating whether the provider should enforce absolute urls.
/// Gets or sets the provider url mode.
/// </summary>
public bool EnforceAbsoluteUrls { get; set; }
public UrlProviderMode Mode { get; set; }
#endregion
@@ -46,13 +46,12 @@ namespace Umbraco.Web.Routing
/// <param name="id">The published content identifier.</param>
/// <returns>The url for the published content.</returns>
/// <remarks>
/// <para>The url is absolute or relative depending on the current url, settings, and options.</para>
/// <para>The url is absolute or relative depending on <c>Mode</c> and on the current url.</para>
/// <para>If the provider is unable to provide a url, it returns "#".</para>
/// </remarks>
public string GetUrl(int id)
{
var absolute = UmbracoSettings.UseDomainPrefixes | EnforceAbsoluteUrls;
return GetUrl(id, _umbracoContext.CleanedUmbracoUrl, absolute);
return GetUrl(id, _umbracoContext.CleanedUmbracoUrl, Mode);
}
/// <summary>
@@ -62,14 +61,14 @@ namespace Umbraco.Web.Routing
/// <param name="absolute">A value indicating whether the url should be absolute in any case.</param>
/// <returns>The url for the published content.</returns>
/// <remarks>
/// <para>The url is absolute or relative depending on the current url and settings, unless <c>absolute</c> is true,
/// in which case the url is always absolute.</para>
/// <para>The url is absolute or relative depending on <c>Mode</c> and on <c>current</c>, unless
/// <c>absolute</c> is true, in which case the url is always absolute.</para>
/// <para>If the provider is unable to provide a url, it returns "#".</para>
/// </remarks>
public string GetUrl(int id, bool absolute)
{
absolute = absolute | EnforceAbsoluteUrls;
return GetUrl(id, _umbracoContext.CleanedUmbracoUrl, absolute);
var mode = absolute ? UrlProviderMode.Absolute : Mode;
return GetUrl(id, _umbracoContext.CleanedUmbracoUrl, mode);
}
/// <summary>
@@ -80,14 +79,46 @@ namespace Umbraco.Web.Routing
/// <param name="absolute">A value indicating whether the url should be absolute in any case.</param>
/// <returns>The url for the published content.</returns>
/// <remarks>
/// <para>The url is absolute or relative depending on url indicated by <c>current</c> and settings, unless
/// <para>The url is absolute or relative depending on <c>Mode</c> and on <c>current</c>, unless
/// <c>absolute</c> is true, in which case the url is always absolute.</para>
/// <para>If the provider is unable to provide a url, it returns "#".</para>
/// </remarks>
public string GetUrl(int id, Uri current, bool absolute)
{
absolute = absolute | EnforceAbsoluteUrls;
var url = _urlProviders.Select(provider => provider.GetUrl(_umbracoContext, _contentCache, id, current, absolute)).FirstOrDefault(u => u != null);
var mode = absolute ? UrlProviderMode.Absolute : Mode;
return GetUrl(id, current, mode);
}
/// <summary>
/// Gets the nice url of a published content.
/// </summary>
/// <param name="id">The published content identifier.</param>
/// <param name="mode">The url mode.</param>
/// <returns>The url for the published content.</returns>
/// <remarks>
/// <para>The url is absolute or relative depending on <c>mode</c> and on the current url.</para>
/// <para>If the provider is unable to provide a url, it returns "#".</para>
/// </remarks>
public string GetUrl(int id, UrlProviderMode mode)
{
return GetUrl(id, _umbracoContext.CleanedUmbracoUrl, mode);
}
/// <summary>
/// Gets the nice url of a published content.
/// </summary>
/// <param name="id">The published content id.</param>
/// <param name="current">The current absolute url.</param>
/// <param name="mode">The url mode.</param>
/// <returns>The url for the published content.</returns>
/// <remarks>
/// <para>The url is absolute or relative depending on <c>mode</c> and on <c>current</c>.</para>
/// <para>If the provider is unable to provide a url, it returns "#".</para>
/// </remarks>
public string GetUrl(int id, Uri current, UrlProviderMode mode)
{
var url = _urlProviders.Select(provider => provider.GetUrl(_umbracoContext, _contentCache, id, current, mode))
.FirstOrDefault(u => u != null);
return url ?? "#"; // legacy wants this
}

View File

@@ -0,0 +1,36 @@
namespace Umbraco.Web.Routing
{
/// <summary>
/// Specifies the type of urls that the url provider should produce.
/// </summary>
/// <remarks>
/// <para>The <c>AutoLegacy</c> option is equivalent to <c>Auto</c> but it also respects the legacy <c>useDomainPrefixes</c> setting.
/// When that setting is true, then all urls are absolute. Otherwise, urls will be relative or absolute, depending on hostnames.</para>
/// <para>The <c>Relative</c> option can lead to invalid results when combined with hostnames, but it is the only way to reproduce
/// the true, pre-4.10, always-relative behavior of Umbraco.</para>
/// <para>For the time being, the default option is <c>AutoLegacy</c> although in the future it will be <c>Auto</c>.</para>
/// </remarks>
internal enum UrlProviderMode
{
/// <summary>
/// Indicates that the url provider should determine automatically whether to return relative or absolute urls,
/// and also respect the legacy <c>useDomainPrefixes</c> setting.
/// </summary>
AutoLegacy,
/// <summary>
/// Indicates that the url provider should produce relative urls exclusively.
/// </summary>
Relative,
/// <summary>
/// Indicates that the url provider should produce absolute urls exclusively.
/// </summary>
Absolute,
/// <summary>
/// Indicates that the url provider should determine automatically whether to return relative or absolute urls.
/// </summary>
Auto
}
}

View File

@@ -325,6 +325,7 @@
<Compile Include="Mvc\MemberAuthorizeAttribute.cs" />
<Compile Include="Mvc\ControllerFactoryExtensions.cs" />
<Compile Include="Mvc\SurfaceRouteHandler.cs" />
<Compile Include="Routing\UrlProviderMode.cs" />
<Compile Include="Search\ExamineIndexerModel.cs" />
<Compile Include="Search\LuceneIndexerExtensions.cs" />
<Compile Include="umbraco.presentation\umbraco\dialogs\AssignDomain2.aspx.cs">