Merge
This commit is contained in:
159
src/Umbraco.Core/Resolving/ManyWeightedResolved.cs
Normal file
159
src/Umbraco.Core/Resolving/ManyWeightedResolved.cs
Normal file
@@ -0,0 +1,159 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Umbraco.Core.Resolving
|
||||
{
|
||||
public class ManyWeightedResolved<TResolved>
|
||||
{
|
||||
List<TResolved> _resolved = new List<TResolved>();
|
||||
Dictionary<Type, int> _weights = new Dictionary<Type, int>();
|
||||
|
||||
public ManyWeightedResolved()
|
||||
{
|
||||
Resolution.Frozen += (sender, e) =>
|
||||
{
|
||||
_resolved = _resolved.OrderBy(r => _weights[r.GetType()]).ToList();
|
||||
_weights = null;
|
||||
};
|
||||
}
|
||||
|
||||
public ManyWeightedResolved(IEnumerable<TResolved> resolved)
|
||||
: this()
|
||||
{
|
||||
_resolved.AddRange(resolved);
|
||||
foreach (var type in _resolved.Select(r => r.GetType()))
|
||||
_weights.Add(type, ResolutionWeightAttribute.ReadWeight(type));
|
||||
}
|
||||
|
||||
public IEnumerable<TResolved> Values
|
||||
{
|
||||
get { return _resolved; }
|
||||
}
|
||||
|
||||
#region Manage collection
|
||||
|
||||
public void Add(TResolved value)
|
||||
{
|
||||
Resolution.EnsureNotFrozen();
|
||||
|
||||
var type = value.GetType();
|
||||
EnsureNotExists(type);
|
||||
_resolved.Add(value);
|
||||
_weights[type] = ResolutionWeightAttribute.ReadWeight(type);
|
||||
}
|
||||
|
||||
public void Add(TResolved value, int weight)
|
||||
{
|
||||
Resolution.EnsureNotFrozen();
|
||||
|
||||
var type = value.GetType();
|
||||
EnsureNotExists(type);
|
||||
_resolved.Add(value);
|
||||
_weights[type] = weight;
|
||||
}
|
||||
|
||||
public void AddRange(IEnumerable<TResolved> values)
|
||||
{
|
||||
Resolution.EnsureNotFrozen();
|
||||
|
||||
foreach (var value in values)
|
||||
{
|
||||
var type = value.GetType();
|
||||
EnsureNotExists(type);
|
||||
_resolved.Add(value);
|
||||
_weights[type] = ResolutionWeightAttribute.ReadWeight(type);
|
||||
}
|
||||
}
|
||||
|
||||
//public void SetWeight(TResolved value, int weight)
|
||||
//{
|
||||
// Resolution.EnsureNotFrozen();
|
||||
|
||||
// var type = value.GetType();
|
||||
// EnsureExists(type);
|
||||
// _weights[type] = weight;
|
||||
//}
|
||||
|
||||
public void SetWeight<TResolving>(int weight)
|
||||
{
|
||||
Resolution.EnsureNotFrozen();
|
||||
|
||||
var type = typeof(TResolving);
|
||||
EnsureExists(type);
|
||||
_weights[type] = weight;
|
||||
}
|
||||
|
||||
//public int GetWeight(TResolved value)
|
||||
//{
|
||||
// var type = value.GetType();
|
||||
// EnsureExists(type);
|
||||
// return _weights[value.GetType()];
|
||||
//}
|
||||
|
||||
public int GetWeight<TResolving>()
|
||||
{
|
||||
var type = typeof(TResolving);
|
||||
EnsureExists(type);
|
||||
return _weights[type];
|
||||
}
|
||||
|
||||
//public void Remove(TResolved value)
|
||||
//{
|
||||
// Resolution.EnsureNotFrozen();
|
||||
|
||||
// var type = value.GetType();
|
||||
// var remove = _resolved.SingleOrDefault(r => r.GetType() == type);
|
||||
// if (remove != null)
|
||||
// {
|
||||
// _resolved.Remove(remove);
|
||||
// _weights.Remove(remove.GetType());
|
||||
// }
|
||||
//}
|
||||
|
||||
public void Remove<TResolving>()
|
||||
{
|
||||
Resolution.EnsureNotFrozen();
|
||||
|
||||
var type = typeof(TResolving);
|
||||
var remove = _resolved.SingleOrDefault(r => r.GetType() == type);
|
||||
if (remove != null)
|
||||
{
|
||||
_resolved.Remove(remove);
|
||||
_weights.Remove(remove.GetType());
|
||||
}
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
Resolution.EnsureNotFrozen();
|
||||
|
||||
_resolved = new List<TResolved>();
|
||||
_weights = new Dictionary<Type, int>();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Utilities
|
||||
|
||||
public bool Exists(Type type)
|
||||
{
|
||||
return _resolved.Any(r => r.GetType() == type);
|
||||
}
|
||||
|
||||
void EnsureExists(Type type)
|
||||
{
|
||||
if (!Exists(type))
|
||||
throw new InvalidOperationException("There is not value of that type in the collection.");
|
||||
}
|
||||
|
||||
void EnsureNotExists(Type type)
|
||||
{
|
||||
if (Exists(type))
|
||||
throw new InvalidOperationException("A value of that type already exists in the collection.");
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
66
src/Umbraco.Core/Resolving/ManyWeightedResolverBase.cs
Normal file
66
src/Umbraco.Core/Resolving/ManyWeightedResolverBase.cs
Normal file
@@ -0,0 +1,66 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Umbraco.Core.Resolving
|
||||
{
|
||||
public abstract class ManyWeightedResolverBase<TResolver, TResolved> : ResolverBase<TResolver>
|
||||
{
|
||||
ManyWeightedResolved<TResolved> _resolved;
|
||||
|
||||
protected ManyWeightedResolverBase()
|
||||
{
|
||||
_resolved = new ManyWeightedResolved<TResolved>();
|
||||
}
|
||||
|
||||
protected ManyWeightedResolverBase(IEnumerable<TResolved> values)
|
||||
{
|
||||
_resolved = new ManyWeightedResolved<TResolved>(values);
|
||||
}
|
||||
|
||||
protected IEnumerable<TResolved> Values
|
||||
{
|
||||
get { return _resolved.Values; }
|
||||
}
|
||||
|
||||
#region Manage collection
|
||||
|
||||
public void Add(TResolved value)
|
||||
{
|
||||
_resolved.Add(value);
|
||||
}
|
||||
|
||||
public void Add(TResolved value, int weight)
|
||||
{
|
||||
_resolved.Add(value, weight);
|
||||
}
|
||||
|
||||
public void AddRange(IEnumerable<TResolved> values)
|
||||
{
|
||||
_resolved.AddRange(values);
|
||||
}
|
||||
|
||||
public void SetWeight<TResolving>(int weight)
|
||||
{
|
||||
_resolved.SetWeight<TResolving>(weight);
|
||||
}
|
||||
|
||||
public int GetWeight<TResolving>()
|
||||
{
|
||||
return _resolved.GetWeight<TResolving>();
|
||||
}
|
||||
|
||||
public void Remove<TResolving>()
|
||||
{
|
||||
_resolved.Remove<TResolving>();
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
_resolved.Clear();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
34
src/Umbraco.Core/Resolving/Resolution.cs
Normal file
34
src/Umbraco.Core/Resolving/Resolution.cs
Normal file
@@ -0,0 +1,34 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Umbraco.Core.Resolving
|
||||
{
|
||||
// notes: nothing in Resolving is thread-safe because everything should happen when the app is starting
|
||||
|
||||
public class Resolution
|
||||
{
|
||||
public static event EventHandler Freezing;
|
||||
public static event EventHandler Frozen;
|
||||
|
||||
public static bool IsFrozen { get; private set; }
|
||||
|
||||
public static void EnsureNotFrozen()
|
||||
{
|
||||
if (Resolution.IsFrozen)
|
||||
throw new InvalidOperationException("Resolution is frozen. It is not possible to modify resolvers once resolution is frozen.");
|
||||
}
|
||||
|
||||
public static void Freeze()
|
||||
{
|
||||
if (Resolution.IsFrozen)
|
||||
throw new InvalidOperationException("Resolution is frozen. It is not possible to freeze it again.");
|
||||
if (Freezing != null)
|
||||
Freezing(null, null);
|
||||
IsFrozen = true;
|
||||
if (Frozen != null)
|
||||
Frozen(null, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
26
src/Umbraco.Core/Resolving/ResolutionWeightAttribute.cs
Normal file
26
src/Umbraco.Core/Resolving/ResolutionWeightAttribute.cs
Normal file
@@ -0,0 +1,26 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Umbraco.Core.Resolving
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Class, AllowMultiple=false, Inherited=false)]
|
||||
public class ResolutionWeightAttribute : Attribute
|
||||
{
|
||||
public const int DefaultWeight = 100;
|
||||
|
||||
public ResolutionWeightAttribute(int weight)
|
||||
{
|
||||
this.Weight = weight;
|
||||
}
|
||||
|
||||
public int Weight { get; private set; }
|
||||
|
||||
public static int ReadWeight(Type type)
|
||||
{
|
||||
var attr = type.GetCustomAttribute<ResolutionWeightAttribute>(false);
|
||||
return attr != null ? attr.Weight : DefaultWeight;
|
||||
}
|
||||
}
|
||||
}
|
||||
36
src/Umbraco.Core/Resolving/ResolverBase.cs
Normal file
36
src/Umbraco.Core/Resolving/ResolverBase.cs
Normal file
@@ -0,0 +1,36 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
|
||||
namespace Umbraco.Core.Resolving
|
||||
{
|
||||
public abstract class ResolverBase<TResolver>
|
||||
{
|
||||
static TResolver _resolver;
|
||||
static readonly ReaderWriterLockSlim ResolversLock = new ReaderWriterLockSlim();
|
||||
|
||||
public static TResolver Current
|
||||
{
|
||||
get
|
||||
{
|
||||
using (new ReadLock(ResolversLock))
|
||||
{
|
||||
if (_resolver == null)
|
||||
throw new InvalidOperationException("Current has not been initialized. You must initialize Current before trying to read it.");
|
||||
return _resolver;
|
||||
}
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
using (new WriteLock(ResolversLock))
|
||||
{
|
||||
if (value == null)
|
||||
throw new ArgumentNullException("value");
|
||||
if (_resolver != null)
|
||||
throw new InvalidOperationException("Current has already been initialized. It is not possible to re-initialize Current once it has been initialized.");
|
||||
_resolver = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
48
src/Umbraco.Core/Resolving/SingleResolved.cs
Normal file
48
src/Umbraco.Core/Resolving/SingleResolved.cs
Normal file
@@ -0,0 +1,48 @@
|
||||
using System;
|
||||
|
||||
namespace Umbraco.Core.Resolving
|
||||
{
|
||||
public class SingleResolved<TResolved>
|
||||
{
|
||||
TResolved _resolved;
|
||||
bool _canBeNull;
|
||||
|
||||
public SingleResolved()
|
||||
: this(false)
|
||||
{ }
|
||||
|
||||
public SingleResolved(TResolved value)
|
||||
: this(false)
|
||||
{
|
||||
_resolved = value;
|
||||
}
|
||||
|
||||
public SingleResolved(bool canBeNull)
|
||||
{
|
||||
_canBeNull = canBeNull;
|
||||
}
|
||||
|
||||
public SingleResolved(TResolved value, bool canBeNull)
|
||||
{
|
||||
_resolved = value;
|
||||
_canBeNull = canBeNull;
|
||||
}
|
||||
|
||||
public TResolved Value
|
||||
{
|
||||
get
|
||||
{
|
||||
return _resolved;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
Resolution.EnsureNotFrozen();
|
||||
|
||||
if (!_canBeNull && value == null)
|
||||
throw new ArgumentNullException("value");
|
||||
_resolved = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
48
src/Umbraco.Core/Resolving/SingleResolverBase.cs
Normal file
48
src/Umbraco.Core/Resolving/SingleResolverBase.cs
Normal file
@@ -0,0 +1,48 @@
|
||||
using System;
|
||||
|
||||
namespace Umbraco.Core.Resolving
|
||||
{
|
||||
public abstract class SingleResolverBase<TResolver, TResolved> : ResolverBase<TResolver>
|
||||
{
|
||||
TResolved _resolved;
|
||||
bool _canBeNull;
|
||||
|
||||
protected SingleResolverBase()
|
||||
: this(false)
|
||||
{ }
|
||||
|
||||
protected SingleResolverBase(TResolved value)
|
||||
: this(false)
|
||||
{
|
||||
_resolved = value;
|
||||
}
|
||||
|
||||
protected SingleResolverBase(bool canBeNull)
|
||||
{
|
||||
_canBeNull = canBeNull;
|
||||
}
|
||||
|
||||
protected SingleResolverBase(TResolved value, bool canBeNull)
|
||||
{
|
||||
_resolved = value;
|
||||
_canBeNull = canBeNull;
|
||||
}
|
||||
|
||||
protected TResolved Value
|
||||
{
|
||||
get
|
||||
{
|
||||
return _resolved;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
Resolution.EnsureNotFrozen();
|
||||
|
||||
if (!_canBeNull && value == null)
|
||||
throw new ArgumentNullException("value");
|
||||
_resolved = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
|
||||
@@ -48,6 +48,14 @@
|
||||
<Compile Include="ApplicationContext.cs" />
|
||||
<Compile Include="ExpressionHelper.cs" />
|
||||
<Compile Include="LambdaExpressionCacheKey.cs" />
|
||||
<Compile Include="Resolving\ManyWeightedResolved.cs" />
|
||||
<Compile Include="Resolving\ManyWeightedResolverBase.cs" />
|
||||
<Compile Include="Resolving\Resolution.cs" />
|
||||
<Compile Include="Resolving\ResolutionWeightAttribute.cs" />
|
||||
<Compile Include="Resolving\ResolverBase.cs" />
|
||||
<Compile Include="Resolving\SingleResolved.cs" />
|
||||
<Compile Include="Resolving\SingleResolverBase.cs" />
|
||||
<Compile Include="TypeExtensions.cs" />
|
||||
<Compile Include="ReadLock.cs" />
|
||||
<Compile Include="SystemUtilities.cs" />
|
||||
<Compile Include="TypeExtensions.cs" />
|
||||
|
||||
@@ -1,158 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Web;
|
||||
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Web.Routing;
|
||||
|
||||
using umbraco;
|
||||
using umbraco.IO;
|
||||
using umbraco.cms.businesslogic.web;
|
||||
|
||||
namespace Umbraco.Web
|
||||
{
|
||||
/// <summary>
|
||||
/// Resolves NiceUrls for a given node id
|
||||
/// </summary>
|
||||
internal class NiceUrlResolver
|
||||
{
|
||||
public NiceUrlResolver(ContentStore contentStore, UmbracoContext umbracoContext)
|
||||
{
|
||||
_umbracoContext = umbracoContext;
|
||||
_contentStore = contentStore;
|
||||
}
|
||||
|
||||
private readonly UmbracoContext _umbracoContext;
|
||||
private readonly ContentStore _contentStore;
|
||||
|
||||
// note: this could be a parameter...
|
||||
const string UrlNameProperty = "@urlName";
|
||||
|
||||
#region GetNiceUrl
|
||||
|
||||
public string GetNiceUrl(int nodeId)
|
||||
{
|
||||
return GetNiceUrl(nodeId, _umbracoContext.UmbracoUrl, false);
|
||||
}
|
||||
|
||||
public string GetNiceUrl(int nodeId, Uri current, bool absolute)
|
||||
{
|
||||
string path;
|
||||
Uri domainUri;
|
||||
|
||||
// will not read cache if previewing!
|
||||
var route = _umbracoContext.InPreviewMode
|
||||
? null
|
||||
: _umbracoContext.RoutesCache.GetRoute(nodeId);
|
||||
|
||||
if (route != null)
|
||||
{
|
||||
// route is <id>/<path> eg "-1/", "-1/foo", "123/", "123/foo/bar"...
|
||||
int pos = route.IndexOf('/');
|
||||
path = route.Substring(pos);
|
||||
int id = int.Parse(route.Substring(0, pos)); // will be -1 or 1234
|
||||
domainUri = id > 0 ? DomainUriAtNode(id, current) : null;
|
||||
}
|
||||
else
|
||||
{
|
||||
var node = _contentStore.GetNodeById(nodeId);
|
||||
if (node == null)
|
||||
return "#"; // legacy wrote to the log here...
|
||||
|
||||
var pathParts = new List<string>();
|
||||
int id = nodeId;
|
||||
domainUri = DomainUriAtNode(id, current);
|
||||
while (domainUri == null && id > 0)
|
||||
{
|
||||
pathParts.Add(_contentStore.GetNodeProperty(node, UrlNameProperty));
|
||||
node = _contentStore.GetNodeParent(node);
|
||||
id = int.Parse(_contentStore.GetNodeProperty(node, "@id")); // will be -1 or 1234
|
||||
domainUri = id > 0 ? DomainUriAtNode(id, current) : null;
|
||||
}
|
||||
|
||||
// no domain, respect HideTopLevelNodeFromPath for legacy purposes
|
||||
if (domainUri == null && global::umbraco.GlobalSettings.HideTopLevelNodeFromPath)
|
||||
pathParts.RemoveAt(pathParts.Count - 1);
|
||||
|
||||
pathParts.Reverse();
|
||||
path = "/" + string.Join("/", pathParts); // will be "/" or "/foo" or "/foo/bar" etc
|
||||
route = id.ToString() + path;
|
||||
|
||||
if (!_umbracoContext.InPreviewMode)
|
||||
_umbracoContext.RoutesCache.Store(nodeId, route);
|
||||
}
|
||||
|
||||
return AssembleUrl(domainUri, path, current, absolute).ToString();
|
||||
}
|
||||
|
||||
Uri AssembleUrl(Uri domain, string path, Uri current, bool absolute)
|
||||
{
|
||||
Uri uri;
|
||||
|
||||
if (domain == null)
|
||||
{
|
||||
// no domain was found : return a relative url, add vdir if any
|
||||
uri = new Uri(global::umbraco.IO.SystemDirectories.Root + path, UriKind.Relative);
|
||||
}
|
||||
else
|
||||
{
|
||||
// a domain was found : return an absolute or relative url
|
||||
// cannot handle vdir, has to be in domain uri
|
||||
if (!absolute && current != null && domain.GetLeftPart(UriPartial.Authority) == current.GetLeftPart(UriPartial.Authority))
|
||||
uri = new Uri(domain.AbsolutePath.TrimEnd('/') + path, UriKind.Relative); // relative
|
||||
else
|
||||
uri = new Uri(domain.GetLeftPart(UriPartial.Path).TrimEnd('/') + path); // absolute
|
||||
}
|
||||
|
||||
return UriFromUmbraco(uri);
|
||||
}
|
||||
|
||||
Uri DomainUriAtNode(int nodeId, Uri current)
|
||||
{
|
||||
// be safe
|
||||
if (nodeId <= 0)
|
||||
return null;
|
||||
|
||||
// apply filter on domains defined on that node
|
||||
var domainAndUri = Domains.ApplicableDomains(Domain.GetDomainsById(nodeId), current, true);
|
||||
return domainAndUri == null ? null : domainAndUri.Uri;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Map public urls to/from umbraco urls
|
||||
|
||||
// fixme - what about vdir?
|
||||
// path = path.Substring(UriUtility.AppVirtualPathPrefix.Length); // remove virtual directory
|
||||
|
||||
public static Uri UriFromUmbraco(Uri uri)
|
||||
{
|
||||
var path = uri.GetSafeAbsolutePath();
|
||||
if (path == "/")
|
||||
return uri;
|
||||
|
||||
if (!global::umbraco.GlobalSettings.UseDirectoryUrls)
|
||||
path += ".aspx";
|
||||
else if (global::umbraco.UmbracoSettings.AddTrailingSlash)
|
||||
path += "/";
|
||||
|
||||
return uri.Rewrite(path);
|
||||
}
|
||||
|
||||
public static Uri UriToUmbraco(Uri uri)
|
||||
{
|
||||
var path = uri.GetSafeAbsolutePath();
|
||||
|
||||
path = path.ToLower();
|
||||
if (path != "/")
|
||||
path = path.TrimEnd('/');
|
||||
if (path.EndsWith(".aspx"))
|
||||
path = path.Substring(0, path.Length - ".aspx".Length);
|
||||
|
||||
return uri.Rewrite(path);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -13,7 +13,7 @@ namespace Umbraco.Web
|
||||
public static class PluginResolverExtensions
|
||||
{
|
||||
|
||||
private static volatile IEnumerable<IRequestDocumentResolver> _lookups;
|
||||
private static volatile IEnumerable<IDocumentLookup> _lookups;
|
||||
private static readonly object Locker = new object();
|
||||
|
||||
/// <summary>
|
||||
@@ -21,7 +21,7 @@ namespace Umbraco.Web
|
||||
/// </summary>
|
||||
/// <param name="plugins"></param>
|
||||
/// <returns></returns>
|
||||
internal static IEnumerable<IRequestDocumentResolver> ResolveLookups(this PluginResolver plugins)
|
||||
internal static IEnumerable<IDocumentLookup> ResolveLookups(this PluginResolver plugins)
|
||||
{
|
||||
if (_lookups == null)
|
||||
{
|
||||
@@ -29,14 +29,13 @@ namespace Umbraco.Web
|
||||
{
|
||||
if (_lookups == null)
|
||||
{
|
||||
var typeFinder = new TypeFinder2();
|
||||
var lookupTypes = typeFinder.FindClassesOfType<IRequestDocumentResolver>();
|
||||
var lookups = new List<IRequestDocumentResolver>();
|
||||
var lookupTypes = TypeFinder.FindClassesOfType<IDocumentLookup>();
|
||||
var lookups = new List<IDocumentLookup>();
|
||||
foreach (var l in lookupTypes)
|
||||
{
|
||||
try
|
||||
{
|
||||
var typeInstance = Activator.CreateInstance(l) as IRequestDocumentResolver;
|
||||
var typeInstance = Activator.CreateInstance(l) as IDocumentLookup;
|
||||
lookups.Add(typeInstance);
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
||||
@@ -6,7 +6,7 @@ using Umbraco.Core;
|
||||
namespace Umbraco.Web.Routing
|
||||
{
|
||||
/// <summary>
|
||||
/// The default implementation of IRoutesCache
|
||||
/// Provides a default implementation of <see cref="IRoutesCache"/>.
|
||||
/// </summary>
|
||||
internal class DefaultRoutesCache : IRoutesCache
|
||||
{
|
||||
@@ -14,23 +14,31 @@ namespace Umbraco.Web.Routing
|
||||
private Dictionary<int, string> _routes;
|
||||
private Dictionary<string, int> _nodeIds;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="DefaultRoutesCache"/> class.
|
||||
/// </summary>
|
||||
public DefaultRoutesCache()
|
||||
{
|
||||
Clear();
|
||||
|
||||
// here we should register handlers to clear the cache when content changes
|
||||
// at the moment this is done by library, which clears everything when content changed
|
||||
//
|
||||
// but really, we should do some partial refreshes!
|
||||
// otherwise, we could even cache 404 errors...
|
||||
//
|
||||
// these are the two events used by library in legacy code...
|
||||
// is it enough?
|
||||
//FIXME:
|
||||
//
|
||||
// here we must register handlers to clear the cache when content changes
|
||||
// this was done by presentation.library, which cleared everything when content changed
|
||||
// but really, we should do some partial refreshes
|
||||
|
||||
// these are the two events that were used by presentation.library
|
||||
// are they enough?
|
||||
|
||||
global::umbraco.content.AfterRefreshContent += (sender, e) => Clear();
|
||||
global::umbraco.content.AfterUpdateDocumentCache += (sender, e) => Clear();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stores a route for a node.
|
||||
/// </summary>
|
||||
/// <param name="nodeId">The node identified.</param>
|
||||
/// <param name="route">The route.</param>
|
||||
public void Store(int nodeId, string route)
|
||||
{
|
||||
using (new WriteLock(_lock))
|
||||
@@ -40,6 +48,11 @@ namespace Umbraco.Web.Routing
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a route for a node.
|
||||
/// </summary>
|
||||
/// <param name="nodeId">The node identifier.</param>
|
||||
/// <returns>The route for the node, else null.</returns>
|
||||
public string GetRoute(int nodeId)
|
||||
{
|
||||
lock (new ReadLock(_lock))
|
||||
@@ -48,6 +61,11 @@ namespace Umbraco.Web.Routing
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a node for a route.
|
||||
/// </summary>
|
||||
/// <param name="route">The route.</param>
|
||||
/// <returns>The node identified for the route, else zero.</returns>
|
||||
public int GetNodeId(string route)
|
||||
{
|
||||
using (new ReadLock(_lock))
|
||||
@@ -56,6 +74,10 @@ namespace Umbraco.Web.Routing
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clears the route for a node.
|
||||
/// </summary>
|
||||
/// <param name="nodeId">The node identifier.</param>
|
||||
public void ClearNode(int nodeId)
|
||||
{
|
||||
using (var lck = new UpgradeableReadLock(_lock))
|
||||
@@ -69,6 +91,9 @@ namespace Umbraco.Web.Routing
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clears all routes.
|
||||
/// </summary>
|
||||
public void Clear()
|
||||
{
|
||||
using (new WriteLock(_lock))
|
||||
|
||||
@@ -140,22 +140,22 @@ namespace Umbraco.Web.Routing
|
||||
|
||||
#endregion
|
||||
|
||||
#region Resolve
|
||||
#region Lookup
|
||||
|
||||
/// <summary>
|
||||
/// Determines the site root (if any) matching the http request.
|
||||
/// </summary>
|
||||
/// <returns>A value indicating whether a domain was found.</returns>
|
||||
public bool ResolveDomain()
|
||||
public bool LookupDomain()
|
||||
{
|
||||
const string tracePrefix = "ResolveDomain: ";
|
||||
const string tracePrefix = "LookupDomain: ";
|
||||
|
||||
// note - we are not handling schemes nor ports here.
|
||||
|
||||
Trace.TraceInformation("{0}Uri=\"{1}\"", tracePrefix, this.Uri);
|
||||
|
||||
// try to find a domain matching the current request
|
||||
var domainAndUri = Domains.ApplicableDomains(Domain.GetDomains(), RoutingContext.UmbracoContext.UmbracoUrl, false);
|
||||
var domainAndUri = Domains.DomainMatch(Domain.GetDomains(), RoutingContext.UmbracoContext.UmbracoUrl, false);
|
||||
|
||||
// handle domain
|
||||
if (domainAndUri != null)
|
||||
@@ -193,17 +193,17 @@ namespace Umbraco.Web.Routing
|
||||
/// Determines the Umbraco document (if any) matching the http request.
|
||||
/// </summary>
|
||||
/// <returns>A value indicating whether a document and template nave been found.</returns>
|
||||
public bool ResolveDocument()
|
||||
public bool LookupDocument()
|
||||
{
|
||||
const string tracePrefix = "ResolveDocument: ";
|
||||
const string tracePrefix = "LookupDocument: ";
|
||||
Trace.TraceInformation("{0}Path=\"{1}\"", tracePrefix, this.Uri.AbsolutePath);
|
||||
|
||||
// look for the document
|
||||
// the first successful resolver, if any, will set this.Node, and may also set this.Template
|
||||
// some lookups may implement caching
|
||||
Trace.TraceInformation("{0}Begin resolvers", tracePrefix);
|
||||
var resolvers = RoutingContext.RouteLookups.GetLookups();
|
||||
resolvers.Any(resolver => resolver.TrySetDocument(this));
|
||||
var lookups = RoutingContext.DocumentLookupsResolver.DocumentLookups;
|
||||
lookups.Any(lookup => lookup.TrySetDocument(this));
|
||||
Trace.TraceInformation("{0}End resolvers, {1}", tracePrefix, (this.HasNode ? "a document was found" : "no document was found"));
|
||||
|
||||
// fixme - not handling umbracoRedirect
|
||||
@@ -211,7 +211,7 @@ namespace Umbraco.Web.Routing
|
||||
// so after ResolveDocument2() => docreq.IsRedirect => handled by the module!
|
||||
|
||||
// handle not-found, redirects, access, template
|
||||
ResolveDocument2();
|
||||
LookupDocument2();
|
||||
|
||||
// handle umbracoRedirect (moved from umbraco.page)
|
||||
FollowRedirect();
|
||||
@@ -224,9 +224,9 @@ namespace Umbraco.Web.Routing
|
||||
/// Performs the document resolution second pass.
|
||||
/// </summary>
|
||||
/// <remarks>The second pass consists in handling "not found", internal redirects, access validation, and template.</remarks>
|
||||
void ResolveDocument2()
|
||||
void LookupDocument2()
|
||||
{
|
||||
const string tracePrefix = "ResolveDocument2: ";
|
||||
const string tracePrefix = "LookupDocument2: ";
|
||||
|
||||
// handle "not found", follow internal redirects, validate access, template
|
||||
// because these might loop, we have to have some sort of infinite loop detection
|
||||
@@ -240,10 +240,11 @@ namespace Umbraco.Web.Routing
|
||||
if (!this.HasNode)
|
||||
{
|
||||
this.Is404 = true;
|
||||
Trace.TraceInformation("{0}No document, try notFound lookup", tracePrefix);
|
||||
Trace.TraceInformation("{0}No document, try last chance lookup", tracePrefix);
|
||||
|
||||
// if it fails then give up, there isn't much more that we can do
|
||||
if (RoutingContext.LookupNotFound == null || !RoutingContext.LookupNotFound.TrySetDocument(this))
|
||||
var lastChance = RoutingContext.DocumentLookupsResolver.DocumentLastChanceLookup;
|
||||
if (lastChance == null || !lastChance.TrySetDocument(this))
|
||||
{
|
||||
Trace.TraceInformation("{0}Failed to find a document, give up", tracePrefix);
|
||||
break;
|
||||
@@ -266,7 +267,7 @@ namespace Umbraco.Web.Routing
|
||||
|
||||
// resolve template
|
||||
if (this.HasNode)
|
||||
ResolveTemplate();
|
||||
LookupTemplate();
|
||||
|
||||
// loop while we don't have page, ie the redirect or access
|
||||
// got us to nowhere and now we need to run the notFoundLookup again
|
||||
@@ -383,9 +384,9 @@ namespace Umbraco.Web.Routing
|
||||
/// <summary>
|
||||
/// Resolves a template for the current node.
|
||||
/// </summary>
|
||||
void ResolveTemplate()
|
||||
void LookupTemplate()
|
||||
{
|
||||
const string tracePrefix = "ResolveTemplate: ";
|
||||
const string tracePrefix = "LookupTemplate: ";
|
||||
|
||||
if (this.Node == null)
|
||||
throw new InvalidOperationException("There is no node.");
|
||||
@@ -446,7 +447,7 @@ namespace Umbraco.Web.Routing
|
||||
redirectId = -1;
|
||||
string redirectUrl = "#";
|
||||
if (redirectId > 0)
|
||||
redirectUrl = RoutingContext.NiceUrlResolver.GetNiceUrl(redirectId);
|
||||
redirectUrl = RoutingContext.NiceUrlProvider.GetNiceUrl(redirectId);
|
||||
if (redirectUrl != "#")
|
||||
this.RedirectUrl = redirectUrl;
|
||||
}
|
||||
|
||||
@@ -8,20 +8,48 @@ using umbraco.cms.businesslogic.web;
|
||||
|
||||
namespace Umbraco.Web.Routing
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides utilities to handle domains.
|
||||
/// </summary>
|
||||
public class Domains
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents an Umbraco domain and its normalized uri.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>In Umbraco it is valid to create domains with name such as <c>example.com</c>, <c>https://www.example.com</c>, <c>example.com/foo/</c>.</para>
|
||||
/// <para>The normalized uri of a domain begins with a scheme and ends with no slash, eg <c>http://example.com/</c>, <c>https://www.example.com/</c>, <c>http://example.com/foo/</c>.</para>
|
||||
/// </remarks>
|
||||
public class DomainAndUri
|
||||
{
|
||||
/// <summary>
|
||||
/// The Umbraco domain.
|
||||
/// </summary>
|
||||
public Domain Domain;
|
||||
|
||||
/// <summary>
|
||||
/// The normalized uri of the domain.
|
||||
/// </summary>
|
||||
public Uri Uri;
|
||||
|
||||
/// <summary>
|
||||
/// Gets a string that represents the <see cref="DomainAndUri"/> instance.
|
||||
/// </summary>
|
||||
/// <returns>A string that represents the current <see cref="DomainAndUri"/> instance.</returns>
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format("{{ \"{0}\", \"{1}\" }}", Domain.Name, Uri);
|
||||
}
|
||||
}
|
||||
|
||||
public static DomainAndUri ApplicableDomains(IEnumerable<Domain> domains, Uri current, bool defaultToFirst)
|
||||
/// <summary>
|
||||
/// Finds the domain that best matches the current uri, into an enumeration of domains.
|
||||
/// </summary>
|
||||
/// <param name="domains">The enumeration of Umbraco domains.</param>
|
||||
/// <param name="current">The uri of the current request, or null.</param>
|
||||
/// <param name="defaultToFirst">A value indicating whether to return the first domain of the list when no domain matches.</param>
|
||||
/// <returns>The domain and its normalized uri, that best matches the current uri, else the first domain (if <c>defaultToFirst</c> is <c>true</c>), else null.</returns>
|
||||
public static DomainAndUri DomainMatch(IEnumerable<Domain> domains, Uri current, bool defaultToFirst)
|
||||
{
|
||||
if (!domains.Any())
|
||||
return null;
|
||||
@@ -57,6 +85,29 @@ namespace Umbraco.Web.Routing
|
||||
return domainAndUri;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets an enumeration of <see cref="DomainAndUri"/> matching an enumeration of Umbraco domains.
|
||||
/// </summary>
|
||||
/// <param name="domains">The enumeration of Umbraco domains.</param>
|
||||
/// <param name="current">The uri of the current request, or null.</param>
|
||||
/// <returns>The enumeration of <see cref="DomainAndUri"/> matching the enumeration of Umbraco domains.</returns>
|
||||
public static IEnumerable<DomainAndUri> DomainMatches(IEnumerable<Domain> domains, Uri current)
|
||||
{
|
||||
var scheme = current == null ? Uri.UriSchemeHttp : current.Scheme;
|
||||
var domainsAndUris = domains
|
||||
.Select(d => new { Domain = d, UriString = UriUtility.TrimPathEndSlash(UriUtility.StartWithScheme(d.Name, scheme)) })
|
||||
.OrderByDescending(t => t.UriString)
|
||||
.Select(t => new DomainAndUri { Domain = t.Domain, Uri = new Uri(t.UriString) });
|
||||
return domainsAndUris;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the part of a path relative to the uri of a domain.
|
||||
/// </summary>
|
||||
/// <param name="domainUri">The normalized uri of the domain.</param>
|
||||
/// <param name="path">The full path of the uri.</param>
|
||||
/// <returns>The path part relative to the uri of the domain.</returns>
|
||||
/// <remarks>Eg the relative part of <c>/foo/bar/nil</c> to domain <c>example.com/foo</c> is <c>/bar/nil</c>.</remarks>
|
||||
public static string PathRelativeToDomain(Uri domainUri, string path)
|
||||
{
|
||||
return path.Substring(domainUri.AbsolutePath.Length).EnsureStartsWith('/');
|
||||
|
||||
@@ -1,11 +1,44 @@
|
||||
namespace Umbraco.Web.Routing
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a bi-directional cache that binds node identifiers and routes.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>The cache is used both for inbound (map a route to a node) and outbound (map a node to a url).</para>
|
||||
/// <para>A route is <c>[rootId]/path/to/node</c> where <c>rootId</c> is the id of the node holding an Umbraco domain, or -1.</para>
|
||||
/// </remarks>
|
||||
internal interface IRoutesCache
|
||||
{
|
||||
/// <summary>
|
||||
/// Stores a route for a node.
|
||||
/// </summary>
|
||||
/// <param name="nodeId">The node identified.</param>
|
||||
/// <param name="route">The route.</param>
|
||||
void Store(int nodeId, string route);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a route for a node.
|
||||
/// </summary>
|
||||
/// <param name="nodeId">The node identifier.</param>
|
||||
/// <returns>The route for the node, else null.</returns>
|
||||
string GetRoute(int nodeId);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a node for a route.
|
||||
/// </summary>
|
||||
/// <param name="route">The route.</param>
|
||||
/// <returns>The node identified for the route, else zero.</returns>
|
||||
int GetNodeId(string route);
|
||||
|
||||
/// <summary>
|
||||
/// Clears the route for a node.
|
||||
/// </summary>
|
||||
/// <param name="nodeId">The node identifier.</param>
|
||||
void ClearNode(int nodeId);
|
||||
|
||||
/// <summary>
|
||||
/// Clears all routes.
|
||||
/// </summary>
|
||||
void Clear();
|
||||
}
|
||||
}
|
||||
260
src/Umbraco.Web/Routing/NiceUrlProvider.cs
Normal file
260
src/Umbraco.Web/Routing/NiceUrlProvider.cs
Normal file
@@ -0,0 +1,260 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Web;
|
||||
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Web.Routing;
|
||||
|
||||
using umbraco;
|
||||
using umbraco.IO;
|
||||
using umbraco.cms.businesslogic.web;
|
||||
|
||||
namespace Umbraco.Web.Routing
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides nice urls for a nodes.
|
||||
/// </summary>
|
||||
internal class NiceUrlProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="NiceUrlProvider"/> class.
|
||||
/// </summary>
|
||||
/// <param name="contentStore">The content store.</param>
|
||||
/// <param name="umbracoContext">The Umbraco context.</param>
|
||||
public NiceUrlProvider(ContentStore contentStore, UmbracoContext umbracoContext)
|
||||
{
|
||||
_umbracoContext = umbracoContext;
|
||||
_contentStore = contentStore;
|
||||
}
|
||||
|
||||
private readonly UmbracoContext _umbracoContext;
|
||||
private readonly ContentStore _contentStore;
|
||||
|
||||
// note: this could be a parameter...
|
||||
const string UrlNameProperty = "@urlName";
|
||||
|
||||
#region GetNiceUrl
|
||||
|
||||
/// <summary>
|
||||
/// Gets the nice url of a node.
|
||||
/// </summary>
|
||||
/// <param name="nodeId">The node id.</param>
|
||||
/// <returns>The nice url for the node.</returns>
|
||||
/// <remarks>The url is absolute or relative depending on the current url.</remarks>
|
||||
public string GetNiceUrl(int nodeId)
|
||||
{
|
||||
return GetNiceUrl(nodeId, _umbracoContext.UmbracoUrl, false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the nice url of a node.
|
||||
/// </summary>
|
||||
/// <param name="nodeId">The node id.</param>
|
||||
/// <param name="current">The current url.</param>
|
||||
/// <param name="absolute">A value indicating whether the url should be absolute in any case.</param>
|
||||
/// <returns>The nice url for the node.</returns>
|
||||
/// <remarks>The url is absolute or relative depending on the current url, unless absolute is true, and then it is always absolute.</remarks>
|
||||
public string GetNiceUrl(int nodeId, Uri current, bool absolute)
|
||||
{
|
||||
string path;
|
||||
Uri domainUri;
|
||||
|
||||
// will not read cache if previewing!
|
||||
var route = _umbracoContext.InPreviewMode
|
||||
? null
|
||||
: _umbracoContext.RoutesCache.GetRoute(nodeId);
|
||||
|
||||
if (route != null)
|
||||
{
|
||||
// route is <id>/<path> eg "-1/", "-1/foo", "123/", "123/foo/bar"...
|
||||
int pos = route.IndexOf('/');
|
||||
path = route.Substring(pos);
|
||||
int id = int.Parse(route.Substring(0, pos)); // will be -1 or 1234
|
||||
domainUri = id > 0 ? DomainUriAtNode(id, current) : null;
|
||||
}
|
||||
else
|
||||
{
|
||||
var node = _contentStore.GetNodeById(nodeId);
|
||||
if (node == null)
|
||||
return "#"; // legacy wrote to the log here...
|
||||
|
||||
var pathParts = new List<string>();
|
||||
int id = nodeId;
|
||||
domainUri = DomainUriAtNode(id, current);
|
||||
while (domainUri == null && id > 0)
|
||||
{
|
||||
pathParts.Add(_contentStore.GetNodeProperty(node, UrlNameProperty));
|
||||
node = _contentStore.GetNodeParent(node);
|
||||
id = int.Parse(_contentStore.GetNodeProperty(node, "@id")); // will be -1 or 1234
|
||||
domainUri = id > 0 ? DomainUriAtNode(id, current) : null;
|
||||
}
|
||||
|
||||
// no domain, respect HideTopLevelNodeFromPath for legacy purposes
|
||||
if (domainUri == null && global::umbraco.GlobalSettings.HideTopLevelNodeFromPath)
|
||||
pathParts.RemoveAt(pathParts.Count - 1);
|
||||
|
||||
pathParts.Reverse();
|
||||
path = "/" + string.Join("/", pathParts); // will be "/" or "/foo" or "/foo/bar" etc
|
||||
route = id.ToString() + path;
|
||||
|
||||
if (!_umbracoContext.InPreviewMode)
|
||||
_umbracoContext.RoutesCache.Store(nodeId, route);
|
||||
}
|
||||
|
||||
return AssembleUrl(domainUri, path, current, absolute).ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the nice urls of a node.
|
||||
/// </summary>
|
||||
/// <param name="nodeId">The node id.</param>
|
||||
/// <param name="current">The current url.</param>
|
||||
/// <returns>An enumeration of all valid urls for the node.</returns>
|
||||
/// <remarks>The urls are absolute. A node can have more than one url if more than one domain is defined.</remarks>
|
||||
public IEnumerable<string> GetNiceUrls(int nodeId, Uri current)
|
||||
{
|
||||
// this is for editContent.aspx which had its own, highly buggy, implementation of NiceUrl...
|
||||
//TODO: finalize & test implementation then replace in editContent.aspx
|
||||
|
||||
string path;
|
||||
IEnumerable<Uri> domainUris;
|
||||
|
||||
// will not read cache if previewing!
|
||||
var route = _umbracoContext.InPreviewMode
|
||||
? null
|
||||
: _umbracoContext.RoutesCache.GetRoute(nodeId);
|
||||
|
||||
if (route != null)
|
||||
{
|
||||
// route is <id>/<path> eg "-1/", "-1/foo", "123/", "123/foo/bar"...
|
||||
int pos = route.IndexOf('/');
|
||||
path = route.Substring(pos);
|
||||
int id = int.Parse(route.Substring(0, pos)); // will be -1 or 1234
|
||||
domainUris = id > 0 ? DomainUrisAtNode(id, current) : new Uri[] { };
|
||||
}
|
||||
else
|
||||
{
|
||||
var node = _contentStore.GetNodeById(nodeId);
|
||||
if (node == null)
|
||||
return new string[] { "#" }; // legacy wrote to the log here...
|
||||
|
||||
var pathParts = new List<string>();
|
||||
int id = nodeId;
|
||||
domainUris = DomainUrisAtNode(id, current);
|
||||
while (!domainUris.Any() && id > 0)
|
||||
{
|
||||
pathParts.Add(_contentStore.GetNodeProperty(node, UrlNameProperty));
|
||||
node = _contentStore.GetNodeParent(node);
|
||||
id = int.Parse(_contentStore.GetNodeProperty(node, "@id")); // will be -1 or 1234
|
||||
domainUris = id > 0 ? DomainUrisAtNode(id, current) : new Uri[] { };
|
||||
}
|
||||
|
||||
// no domain, respect HideTopLevelNodeFromPath for legacy purposes
|
||||
if (!domainUris.Any() && global::umbraco.GlobalSettings.HideTopLevelNodeFromPath)
|
||||
pathParts.RemoveAt(pathParts.Count - 1);
|
||||
|
||||
pathParts.Reverse();
|
||||
path = "/" + string.Join("/", pathParts); // will be "/" or "/foo" or "/foo/bar" etc
|
||||
route = id.ToString() + path;
|
||||
|
||||
if (!_umbracoContext.InPreviewMode)
|
||||
_umbracoContext.RoutesCache.Store(nodeId, route);
|
||||
}
|
||||
|
||||
return AssembleUrls(domainUris, path, current).Select(uri => uri.ToString());
|
||||
}
|
||||
|
||||
Uri AssembleUrl(Uri domainUri, string path, Uri current, bool absolute)
|
||||
{
|
||||
Uri uri;
|
||||
|
||||
if (domainUri == null)
|
||||
{
|
||||
// no domain was found : return a relative url, add vdir if any
|
||||
uri = new Uri(global::umbraco.IO.SystemDirectories.Root + path, UriKind.Relative);
|
||||
}
|
||||
else
|
||||
{
|
||||
// a domain was found : return an absolute or relative url
|
||||
// cannot handle vdir, has to be in domain uri
|
||||
if (!absolute && current != null && domainUri.GetLeftPart(UriPartial.Authority) == current.GetLeftPart(UriPartial.Authority))
|
||||
uri = new Uri(domainUri.AbsolutePath.TrimEnd('/') + path, UriKind.Relative); // relative
|
||||
else
|
||||
uri = new Uri(domainUri.GetLeftPart(UriPartial.Path).TrimEnd('/') + path); // absolute
|
||||
}
|
||||
|
||||
return UriFromUmbraco(uri);
|
||||
}
|
||||
|
||||
IEnumerable<Uri> AssembleUrls(IEnumerable<Uri> domainUris, string path, Uri current)
|
||||
{
|
||||
if (domainUris.Any())
|
||||
{
|
||||
return domainUris.Select(domainUri => new Uri(domainUri.GetLeftPart(UriPartial.Path).TrimEnd('/') + path));
|
||||
}
|
||||
else
|
||||
{
|
||||
// no domain was found : return a relative url, add vdir if any
|
||||
return new Uri[] { new Uri(global::umbraco.IO.SystemDirectories.Root + path, UriKind.Relative) };
|
||||
}
|
||||
}
|
||||
|
||||
Uri DomainUriAtNode(int nodeId, Uri current)
|
||||
{
|
||||
// be safe
|
||||
if (nodeId <= 0)
|
||||
return null;
|
||||
|
||||
// apply filter on domains defined on that node
|
||||
var domainAndUri = Domains.DomainMatch(Domain.GetDomainsById(nodeId), current, true);
|
||||
return domainAndUri == null ? null : domainAndUri.Uri;
|
||||
}
|
||||
|
||||
IEnumerable<Uri> DomainUrisAtNode(int nodeId, Uri current)
|
||||
{
|
||||
// be safe
|
||||
if (nodeId <= 0)
|
||||
return new Uri[] { };
|
||||
|
||||
var domainAndUris = Domains.DomainMatches(Domain.GetDomainsById(nodeId), current);
|
||||
return domainAndUris.Select(d => d.Uri);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Map public urls to/from umbraco urls
|
||||
|
||||
// fixme - what about vdir?
|
||||
// path = path.Substring(UriUtility.AppVirtualPathPrefix.Length); // remove virtual directory
|
||||
|
||||
public static Uri UriFromUmbraco(Uri uri)
|
||||
{
|
||||
var path = uri.GetSafeAbsolutePath();
|
||||
if (path == "/")
|
||||
return uri;
|
||||
|
||||
if (!global::umbraco.GlobalSettings.UseDirectoryUrls)
|
||||
path += ".aspx";
|
||||
else if (global::umbraco.UmbracoSettings.AddTrailingSlash)
|
||||
path += "/";
|
||||
|
||||
return uri.Rewrite(path);
|
||||
}
|
||||
|
||||
public static Uri UriToUmbraco(Uri uri)
|
||||
{
|
||||
var path = uri.GetSafeAbsolutePath();
|
||||
|
||||
path = path.ToLower();
|
||||
if (path != "/")
|
||||
path = path.TrimEnd('/');
|
||||
if (path.EndsWith(".aspx"))
|
||||
path = path.Substring(0, path.Length - ".aspx".Length);
|
||||
|
||||
return uri.Rewrite(path);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace Umbraco.Web.Routing
|
||||
{
|
||||
/// <summary>
|
||||
/// Specifies the relative weight of an <c>IRequestDocumentResolver</c> implementation.
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)]
|
||||
internal class RequestDocumentResolverWeightAttribute : Attribute
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the default weight.
|
||||
/// </summary>
|
||||
public const int DefaultWeight = 100;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="RequestDocumentResolverWeightAttribute"/> class with the weight.
|
||||
/// </summary>
|
||||
/// <param name="weight">The weight.</param>
|
||||
public RequestDocumentResolverWeightAttribute(int weight)
|
||||
: base()
|
||||
{
|
||||
this.Weight = weight;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the weight.
|
||||
/// </summary>
|
||||
public int Weight { get; private set; }
|
||||
}
|
||||
}
|
||||
48
src/Umbraco.Web/Routing/RequestDocumentResolversResolver.cs
Normal file
48
src/Umbraco.Web/Routing/RequestDocumentResolversResolver.cs
Normal file
@@ -0,0 +1,48 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Resolving;
|
||||
|
||||
namespace Umbraco.Web.Routing
|
||||
{
|
||||
class RequestDocumentResolversResolver : ResolverBase<RequestDocumentResolversResolver>
|
||||
{
|
||||
internal RequestDocumentResolversResolver(IEnumerable<IRequestDocumentResolver> resolvers, IRequestDocumentLastChanceResolver lastChanceResolver)
|
||||
{
|
||||
_resolvers.AddRange(resolvers);
|
||||
_lastChanceResolver.Value = lastChanceResolver;
|
||||
}
|
||||
|
||||
#region LastChanceResolver
|
||||
|
||||
SingleResolved<IRequestDocumentLastChanceResolver> _lastChanceResolver = new SingleResolved<IRequestDocumentLastChanceResolver>(true);
|
||||
|
||||
public IRequestDocumentLastChanceResolver RequestDocumentLastChanceResolver
|
||||
{
|
||||
get { return _lastChanceResolver.Value; }
|
||||
set { _lastChanceResolver.Value = value; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Resolvers
|
||||
|
||||
ManyWeightedResolved<IRequestDocumentResolver> _resolvers = new ManyWeightedResolved<IRequestDocumentResolver>();
|
||||
|
||||
public IEnumerable<IRequestDocumentResolver> RequestDocumentResolvers
|
||||
{
|
||||
get { return _resolvers.Values; }
|
||||
}
|
||||
|
||||
public ManyWeightedResolved<IRequestDocumentResolver> RequestDocumentResolversResolution
|
||||
{
|
||||
get { return _resolvers; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.Diagnostics;
|
||||
using System.Xml;
|
||||
using Umbraco.Core.Resolving;
|
||||
|
||||
namespace Umbraco.Web.Routing
|
||||
{
|
||||
@@ -10,7 +11,7 @@ namespace Umbraco.Web.Routing
|
||||
// at the moment aliases are not cleaned up into nice urls
|
||||
//
|
||||
|
||||
[RequestDocumentResolverWeight(50)]
|
||||
[ResolutionWeight(50)]
|
||||
internal class ResolveByAlias : IRequestDocumentResolver
|
||||
{
|
||||
static readonly TraceSource Trace = new TraceSource("ResolveByAlias");
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Xml;
|
||||
using Umbraco.Core.Resolving;
|
||||
|
||||
namespace Umbraco.Web.Routing
|
||||
{
|
||||
|
||||
// handles /1234 where 1234 is the id of a document
|
||||
//
|
||||
[RequestDocumentResolverWeight(20)]
|
||||
[ResolutionWeight(20)]
|
||||
internal class ResolveById : IRequestDocumentResolver
|
||||
{
|
||||
static readonly TraceSource Trace = new TraceSource("ResolveById");
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
using System.Diagnostics;
|
||||
using System.Xml;
|
||||
using Umbraco.Core.Resolving;
|
||||
|
||||
namespace Umbraco.Web.Routing
|
||||
{
|
||||
// handles "/foo/bar" where "/foo/bar" is the path to a document
|
||||
//
|
||||
|
||||
[RequestDocumentResolverWeight(10)]
|
||||
[ResolutionWeight(10)]
|
||||
internal class ResolveByNiceUrl : IRequestDocumentResolver
|
||||
{
|
||||
static readonly TraceSource Trace = new TraceSource("ResolveByNiceUrl");
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.Diagnostics;
|
||||
using System.Xml;
|
||||
using Umbraco.Core.Resolving;
|
||||
using umbraco.cms.businesslogic.template;
|
||||
|
||||
namespace Umbraco.Web.Routing
|
||||
@@ -8,7 +9,7 @@ namespace Umbraco.Web.Routing
|
||||
// handles /foo/bar/<template> where <template> is a valid template alias
|
||||
// and /foo/bar the nice url of a document
|
||||
//
|
||||
[RequestDocumentResolverWeight(30)]
|
||||
[ResolutionWeight(30)]
|
||||
internal class ResolveByNiceUrlAndTemplate : ResolveByNiceUrl, IRequestDocumentResolver
|
||||
{
|
||||
static readonly TraceSource Trace = new TraceSource("ResolveByNiceUrlAndTemplate");
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.Diagnostics;
|
||||
using System.Xml;
|
||||
using Umbraco.Core.Resolving;
|
||||
using umbraco;
|
||||
|
||||
namespace Umbraco.Web.Routing
|
||||
@@ -11,7 +12,7 @@ namespace Umbraco.Web.Routing
|
||||
//
|
||||
// we're keeping it here only for backward compatibility.
|
||||
//
|
||||
[RequestDocumentResolverWeight(40)]
|
||||
[ResolutionWeight(40)]
|
||||
internal class ResolveByProfile : ResolveByNiceUrl, IRequestDocumentResolver
|
||||
{
|
||||
static readonly TraceSource Trace = new TraceSource("ResolveByProfile");
|
||||
|
||||
@@ -1,112 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using Umbraco.Core;
|
||||
|
||||
namespace Umbraco.Web.Routing
|
||||
{
|
||||
// fixme - this class is broken in various ways
|
||||
// + we can't reproduce that sort of code for everything we need to discover
|
||||
|
||||
/// <summary>
|
||||
/// Represents a collection of ILookup used for routing that are registered in the application
|
||||
/// </summary>
|
||||
internal class RouteLookups
|
||||
{
|
||||
private static readonly List<IRequestDocumentResolver> Lookups = new List<IRequestDocumentResolver>();
|
||||
private static readonly ReaderWriterLockSlim Lock = new ReaderWriterLockSlim();
|
||||
|
||||
/// <summary>
|
||||
/// Singleton accessor
|
||||
/// </summary>
|
||||
public static RouteLookups Current { get; internal set; }
|
||||
|
||||
internal RouteLookups(IEnumerable<IRequestDocumentResolver> lookups)
|
||||
{
|
||||
Lookups.AddRange(SortByWeight(lookups));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns all of the lookups
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public IEnumerable<IRequestDocumentResolver> GetLookups()
|
||||
{
|
||||
using(new ReadLock(Lock))
|
||||
{
|
||||
return Lookups;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes an ILookup based on the specified Type
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
public void RemoveLookup<T>()
|
||||
where T : IRequestDocumentResolver
|
||||
{
|
||||
using (new WriteLock(Lock))
|
||||
{
|
||||
Lookups.Remove(Lookups.SingleOrDefault(x => x is T));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Adds a new lookup to the end of the list
|
||||
/// </summary>
|
||||
/// <param name="lookup"></param>
|
||||
public void AddLookup(IRequestDocumentResolver lookup)
|
||||
{
|
||||
using (var l = new UpgradeableReadLock(Lock))
|
||||
{
|
||||
if (CheckExists(lookup))
|
||||
throw new InvalidOperationException(string.Format("The lookup type \"{0}\" already exists in the lookup collection.", lookup));
|
||||
l.UpgradeToWriteLock();
|
||||
Lookups.Add(lookup);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Inserts a lookup at the specified index
|
||||
/// </summary>
|
||||
/// <param name="index"></param>
|
||||
/// <param name="lookup"></param>
|
||||
public void InsertLookup(int index, IRequestDocumentResolver lookup)
|
||||
{
|
||||
using (var l = new UpgradeableReadLock(Lock))
|
||||
{
|
||||
if (CheckExists(lookup))
|
||||
throw new InvalidOperationException("The lookup type " + lookup + " already exists in the lookup collection");
|
||||
l.UpgradeToWriteLock();
|
||||
Lookups.Insert(index, lookup);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// checks if a lookup already exists by type
|
||||
/// </summary>
|
||||
/// <param name="lookup"></param>
|
||||
/// <returns></returns>
|
||||
private static bool CheckExists(IRequestDocumentResolver lookup)
|
||||
{
|
||||
return Lookups.Any(x => x.GetType() == lookup.GetType());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sorts the ILookups in the list based on an attribute weight if one is specified
|
||||
/// </summary>
|
||||
/// <param name="lookups"></param>
|
||||
/// <returns></returns>
|
||||
private static IEnumerable<IRequestDocumentResolver> SortByWeight(IEnumerable<IRequestDocumentResolver> lookups)
|
||||
{
|
||||
return lookups.OrderBy(x =>
|
||||
{
|
||||
var attribute = x.GetType().GetCustomAttributes(true).OfType<RequestDocumentResolverWeightAttribute>().SingleOrDefault();
|
||||
return attribute == null ? RequestDocumentResolverWeightAttribute.DefaultWeight : attribute.Weight;
|
||||
}).ToList();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,61 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace Umbraco.Web.Routing
|
||||
{
|
||||
// this is a bi-directional cache that contains
|
||||
// - nodeId to route (used for NiceUrl)
|
||||
// - route to nodeId (used for inbound requests)
|
||||
//
|
||||
// a route is [rootId]/path/to/node
|
||||
// where rootId is the id of the "site root" node
|
||||
//
|
||||
internal class RoutesCache
|
||||
{
|
||||
private static readonly RoutesCache Instance = new RoutesCache();
|
||||
private static IRoutesCache _provider;
|
||||
|
||||
/// <summary>
|
||||
/// public contructor assigns the DefaultRoutesCache as the default provider
|
||||
/// </summary>
|
||||
public RoutesCache()
|
||||
:this(null)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor sets a custom provider if specified
|
||||
/// </summary>
|
||||
/// <param name="provider"></param>
|
||||
internal RoutesCache(IRoutesCache provider)
|
||||
{
|
||||
_provider = provider ?? new DefaultRoutesCache();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the routes cache provider
|
||||
/// </summary>
|
||||
/// <param name="provider"></param>
|
||||
public static void SetProvider(IRoutesCache provider)
|
||||
{
|
||||
if (provider == null) throw new ArgumentNullException("provider");
|
||||
_provider = provider;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Singleton accessor
|
||||
/// </summary>
|
||||
public static RoutesCache Current
|
||||
{
|
||||
get { return Instance; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the current provider
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public IRoutesCache GetProvider()
|
||||
{
|
||||
return _provider;
|
||||
}
|
||||
}
|
||||
}
|
||||
28
src/Umbraco.Web/Routing/RoutesCacheResolver.cs
Normal file
28
src/Umbraco.Web/Routing/RoutesCacheResolver.cs
Normal file
@@ -0,0 +1,28 @@
|
||||
using System;
|
||||
using Umbraco.Core.Resolving;
|
||||
|
||||
namespace Umbraco.Web.Routing
|
||||
{
|
||||
/// <summary>
|
||||
/// Resolves the <see cref="IRoutesCache"/> implementation.
|
||||
/// </summary>
|
||||
class RoutesCacheResolver : SingleResolverBase<RoutesCacheResolver, IRoutesCache>
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="RoutesCacheResolve"/> class with an <see cref="IRoutesCache"/> implementation.
|
||||
/// </summary>
|
||||
/// <param name="routesCache">The <see cref="IRoutesCache"/> implementation.</param>
|
||||
internal RoutesCacheResolver(IRoutesCache routesCache)
|
||||
: base(routesCache)
|
||||
{ }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the <see cref="IRoutesCache"/> implementation.
|
||||
/// </summary>
|
||||
public IRoutesCache RoutesCache
|
||||
{
|
||||
get { return this.Value; }
|
||||
set { this.Value = value; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,29 +5,47 @@ namespace Umbraco.Web.Routing
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// represents a request for one specified Umbraco document to be rendered by one specified template,
|
||||
/// using one particular culture.
|
||||
/// Provides context for the routing of a request.
|
||||
/// </summary>
|
||||
internal class RoutingContext
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="RoutingContext"/> class.
|
||||
/// </summary>
|
||||
/// <param name="umbracoContext">The Umbraco context.</param>
|
||||
/// <param name="documentLookupsResolver">The document lookups resolver.</param>
|
||||
/// <param name="contentStore">The content store.</param>
|
||||
/// <param name="niceUrlResolver">The nice urls resolver.</param>
|
||||
public RoutingContext(
|
||||
UmbracoContext umbracoContext,
|
||||
RouteLookups lookups,
|
||||
IRequestDocumentLastChanceResolver lookupNotFound,
|
||||
DocumentLookupsResolver documentLookupsResolver,
|
||||
ContentStore contentStore,
|
||||
NiceUrlResolver niceUrlResolver)
|
||||
NiceUrlProvider niceUrlResolver)
|
||||
{
|
||||
UmbracoContext = umbracoContext;
|
||||
RouteLookups = lookups;
|
||||
LookupNotFound = lookupNotFound;
|
||||
ContentStore = contentStore;
|
||||
NiceUrlResolver = niceUrlResolver;
|
||||
this.UmbracoContext = umbracoContext;
|
||||
this.DocumentLookupsResolver = documentLookupsResolver;
|
||||
this.ContentStore = contentStore;
|
||||
this.NiceUrlProvider = niceUrlResolver;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Umbraco context.
|
||||
/// </summary>
|
||||
public UmbracoContext UmbracoContext { get; private set; }
|
||||
public RouteLookups RouteLookups { get; private set; }
|
||||
public IRequestDocumentLastChanceResolver LookupNotFound { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the document lookups resolver.
|
||||
/// </summary>
|
||||
public DocumentLookupsResolver DocumentLookupsResolver { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the content store.
|
||||
/// </summary>
|
||||
public ContentStore ContentStore { get; private set; }
|
||||
public NiceUrlResolver NiceUrlResolver { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the nice urls provider.
|
||||
/// </summary>
|
||||
public NiceUrlProvider NiceUrlProvider { get; private set; }
|
||||
}
|
||||
}
|
||||
@@ -240,23 +240,22 @@
|
||||
<Compile Include="ContentStore.cs" />
|
||||
<Compile Include="LegacyRequestInitializer.cs" />
|
||||
<Compile Include="Mvc\ControllerExtensions.cs" />
|
||||
<Compile Include="NiceUrlResolver.cs" />
|
||||
<Compile Include="Routing\NiceUrlProvider.cs" />
|
||||
<Compile Include="PluginResolverExtensions.cs" />
|
||||
<Compile Include="Routing\Domains.cs" />
|
||||
<Compile Include="Routing\RouteLookups.cs" />
|
||||
<Compile Include="Routing\DocumentLookupsResolver.cs" />
|
||||
<Compile Include="Routing\DocumentRequest.cs" />
|
||||
<Compile Include="Routing\IRequestDocumentResolver.cs" />
|
||||
<Compile Include="Routing\IRequestDocumentLastChanceResolver.cs" />
|
||||
<Compile Include="Routing\IDocumentLookup.cs" />
|
||||
<Compile Include="Routing\IDocumentLastChanceLookup.cs" />
|
||||
<Compile Include="Routing\IRoutesCache.cs" />
|
||||
<Compile Include="Routing\ResolveByAlias.cs" />
|
||||
<Compile Include="Routing\ResolveById.cs" />
|
||||
<Compile Include="Routing\ResolveByNiceUrl.cs" />
|
||||
<Compile Include="Routing\ResolveByNiceUrlAndTemplate.cs" />
|
||||
<Compile Include="Routing\ResolveByProfile.cs" />
|
||||
<Compile Include="Routing\ResolveLastChance.cs" />
|
||||
<Compile Include="Routing\RequestDocumentResolverWeightAttribute.cs" />
|
||||
<Compile Include="Routing\LookupByAlias.cs" />
|
||||
<Compile Include="Routing\LookupById.cs" />
|
||||
<Compile Include="Routing\LookupByNiceUrl.cs" />
|
||||
<Compile Include="Routing\LookupByNiceUrlAndTemplate.cs" />
|
||||
<Compile Include="Routing\LookupByProfile.cs" />
|
||||
<Compile Include="Routing\DefaultLastChanceLookup.cs" />
|
||||
<Compile Include="Routing\DefaultRoutesCache.cs" />
|
||||
<Compile Include="Routing\RoutesCache.cs" />
|
||||
<Compile Include="Routing\RoutesCacheResolver.cs" />
|
||||
<Compile Include="Routing\RoutingContext.cs" />
|
||||
<Compile Include="umbraco.presentation\EnsureSystemPathsApplicationStartupHandler.cs" />
|
||||
<Compile Include="umbraco.presentation\install\steps\database.ascx.cs">
|
||||
@@ -1814,7 +1813,9 @@
|
||||
<Content Include="umbraco.presentation\umbraco\dialogs\Preview.aspx" />
|
||||
<Content Include="umbraco.presentation\umbraco\controls\passwordChanger.ascx" />
|
||||
<Content Include="umbraco.presentation\umbraco\controls\ProgressBar.ascx" />
|
||||
<Content Include="umbraco.presentation\umbraco\controls\ContentTypeControlNew.ascx" />
|
||||
<Content Include="umbraco.presentation\umbraco\controls\ContentTypeControlNew.ascx">
|
||||
<SubType>ASPXCodeBehind</SubType>
|
||||
</Content>
|
||||
<Content Include="umbraco.presentation\umbraco\controls\GenericProperties\GenericProperty.ascx" />
|
||||
<Content Include="umbraco.presentation\umbraco\create\DLRScripting.ascx" />
|
||||
<Content Include="umbraco.presentation\umbraco\controls\Images\ImageViewer.ascx" />
|
||||
|
||||
@@ -35,8 +35,11 @@ namespace Umbraco.Web
|
||||
IsReady = true // fixme
|
||||
};
|
||||
|
||||
//create the route lookups singleton
|
||||
RouteLookups.Current = new RouteLookups(ApplicationContext.Current.Plugins.ResolveLookups());
|
||||
// create the resolvers
|
||||
DocumentLookupsResolver.Current = new DocumentLookupsResolver(ApplicationContext.Current.Plugins.ResolveLookups(), new DefaultLastChanceLookup());
|
||||
RoutesCacheResolver.Current = new RoutesCacheResolver(new DefaultRoutesCache());
|
||||
|
||||
Umbraco.Core.Resolving.Resolution.Freeze();
|
||||
|
||||
Trace.TraceInformation("AppDomain is initialized");
|
||||
}
|
||||
|
||||
@@ -132,7 +132,7 @@ namespace Umbraco.Web
|
||||
set
|
||||
{
|
||||
_requestUrl = value;
|
||||
this.UmbracoUrl = NiceUrlResolver.UriToUmbraco(_requestUrl);
|
||||
this.UmbracoUrl = NiceUrlProvider.UriToUmbraco(_requestUrl);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ namespace Umbraco.Web
|
||||
var umbracoContext = new UmbracoContext(
|
||||
new HttpContextWrapper(httpContext),
|
||||
ApplicationContext.Current,
|
||||
RoutesCache.Current.GetProvider());
|
||||
RoutesCacheResolver.Current.RoutesCache);
|
||||
UmbracoContext.Current = umbracoContext;
|
||||
|
||||
// NO!
|
||||
@@ -54,12 +54,11 @@ namespace Umbraco.Web
|
||||
//create a content store
|
||||
var contentStore = new ContentStore(umbracoContext);
|
||||
//create the nice urls
|
||||
var niceUrls = new NiceUrlResolver(contentStore, umbracoContext);
|
||||
var niceUrls = new NiceUrlProvider(contentStore, umbracoContext);
|
||||
//create the RoutingContext (one per http request)
|
||||
var routingContext = new RoutingContext(
|
||||
umbracoContext,
|
||||
RouteLookups.Current,
|
||||
new ResolveLastChance(),
|
||||
DocumentLookupsResolver.Current,
|
||||
contentStore,
|
||||
niceUrls);
|
||||
// NOT HERE BUT SEE **THERE** BELOW
|
||||
@@ -107,11 +106,11 @@ namespace Umbraco.Web
|
||||
|
||||
//**THERE** we should create the doc request
|
||||
// before, we're not sure we handling a doc request
|
||||
docreq.ResolveDomain();
|
||||
docreq.LookupDomain();
|
||||
if (docreq.IsRedirect)
|
||||
httpContext.Response.Redirect(docreq.RedirectUrl, true);
|
||||
Thread.CurrentThread.CurrentUICulture = Thread.CurrentThread.CurrentCulture = docreq.Culture;
|
||||
docreq.ResolveDocument();
|
||||
docreq.LookupDocument();
|
||||
if (docreq.IsRedirect)
|
||||
httpContext.Response.Redirect(docreq.RedirectUrl, true);
|
||||
|
||||
|
||||
@@ -355,10 +355,8 @@ namespace umbraco
|
||||
/// <returns>String with a friendly url from a node</returns>
|
||||
public static string NiceUrl(int nodeID)
|
||||
{
|
||||
return Umbraco.Web.UmbracoContext.Current
|
||||
.DocumentRequest
|
||||
.RoutingContext
|
||||
.NiceUrlResolver.GetNiceUrl(nodeID);
|
||||
var niceUrlsProvider = Umbraco.Web.UmbracoContext.Current.DocumentRequest.RoutingContext.NiceUrlProvider;
|
||||
return niceUrlsProvider.GetNiceUrl(nodeID);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -380,10 +378,8 @@ namespace umbraco
|
||||
/// <returns>String with a friendly url with full domain from a node</returns>
|
||||
public static string NiceUrlWithDomain(int nodeID)
|
||||
{
|
||||
return Umbraco.Web.UmbracoContext.Current
|
||||
.DocumentRequest
|
||||
.RoutingContext
|
||||
.NiceUrlResolver.GetNiceUrl(nodeID, Umbraco.Web.UmbracoContext.Current.UmbracoUrl, true);
|
||||
var niceUrlsProvider = Umbraco.Web.UmbracoContext.Current.DocumentRequest.RoutingContext.NiceUrlProvider;
|
||||
return niceUrlsProvider.GetNiceUrl(nodeID, Umbraco.Web.UmbracoContext.Current.UmbracoUrl, true);
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user