diff --git a/src/Umbraco.Web/ContentStore.cs b/src/Umbraco.Web/ContentStore.cs
index d123342f22..e13714c9ac 100644
--- a/src/Umbraco.Web/ContentStore.cs
+++ b/src/Umbraco.Web/ContentStore.cs
@@ -12,8 +12,15 @@ namespace Umbraco.Web
///
internal class ContentStore
{
- private readonly UmbracoContext _umbracoContext;
+ ///
+ /// Delegate to return the current UmbracoContext
+ ///
+ private readonly UmbracoContext _umbracoContext;
+ ///
+ /// Constructor accepting a delegate to resolve the UmbracoContext
+ ///
+ ///
public ContentStore(UmbracoContext umbracoContext)
{
_umbracoContext = umbracoContext;
diff --git a/src/Umbraco.Web/NiceUrls.cs b/src/Umbraco.Web/NiceUrlResolver.cs
similarity index 86%
rename from src/Umbraco.Web/NiceUrls.cs
rename to src/Umbraco.Web/NiceUrlResolver.cs
index ae2ff6cf70..1e7da3b26e 100644
--- a/src/Umbraco.Web/NiceUrls.cs
+++ b/src/Umbraco.Web/NiceUrlResolver.cs
@@ -7,9 +7,12 @@ using umbraco.cms.businesslogic.web;
namespace Umbraco.Web
{
- internal class NiceUrls
+ ///
+ /// Resolves NiceUrls for a given node id
+ ///
+ internal class NiceUrlResolver
{
- public NiceUrls(ContentStore contentStore, UmbracoContext umbracoContext, RoutesCache routesCache)
+ public NiceUrlResolver(ContentStore contentStore, UmbracoContext umbracoContext, IRoutesCache routesCache)
{
_umbracoContext = umbracoContext;
_contentStore = contentStore;
@@ -18,7 +21,7 @@ namespace Umbraco.Web
private readonly UmbracoContext _umbracoContext;
private readonly ContentStore _contentStore;
- private readonly RoutesCache _routesCache;
+ private readonly IRoutesCache _routesCache;
// note: this could be a parameter...
const string UrlNameProperty = "@urlName";
@@ -34,10 +37,13 @@ namespace Umbraco.Web
public virtual string GetNiceUrl(int nodeId, int startNodeDepth, bool forceDomain)
{
- string route;
- string path;
+ string path;
+
+ // will not read cache if previewing!
+ var route = !_umbracoContext.InPreviewMode
+ ? _routesCache.GetRoute(nodeId)
+ : null;
- route = _routesCache.GetRoute(nodeId); // will not read cache if previewing
if (route != null)
{
int pos = route.IndexOf('/');
@@ -85,7 +91,11 @@ namespace Umbraco.Web
parts.Reverse();
path = "/" + string.Join("/", parts);
route = string.Format("{0}{1}", id, path);
- _routesCache.Store(nodeId, route); // will not write if previewing
+
+ if (!_umbracoContext.InPreviewMode)
+ {
+ _routesCache.Store(nodeId, route); // will not write if previewing
+ }
return FormatUrl(domain, path);
}
diff --git a/src/Umbraco.Web/Routing/DefaultRoutesCache.cs b/src/Umbraco.Web/Routing/DefaultRoutesCache.cs
new file mode 100644
index 0000000000..a755e9c489
--- /dev/null
+++ b/src/Umbraco.Web/Routing/DefaultRoutesCache.cs
@@ -0,0 +1,72 @@
+using System;
+using System.Collections.Generic;
+
+namespace Umbraco.Web.Routing
+{
+ ///
+ /// The default implementation of IRoutesCache
+ ///
+ internal class DefaultRoutesCache : IRoutesCache
+ {
+ private readonly object _lock = new object();
+ private Dictionary _routes;
+ private Dictionary _nodeIds;
+
+ 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...
+ }
+
+ public void Store(int nodeId, string route)
+ {
+ lock (_lock)
+ {
+ _routes[nodeId] = route;
+ _nodeIds[route] = nodeId;
+ }
+ }
+
+ public string GetRoute(int nodeId)
+ {
+ lock (_lock)
+ {
+ return _routes.ContainsKey(nodeId) ? _routes[nodeId] : null;
+ }
+ }
+
+ public int GetNodeId(string route)
+ {
+ lock (_lock)
+ {
+ return _nodeIds.ContainsKey(route) ? _nodeIds[route] : 0;
+ }
+ }
+
+ public void ClearNode(int nodeId)
+ {
+ lock (_lock)
+ {
+ if (_routes.ContainsKey(nodeId))
+ {
+ _nodeIds.Remove(_routes[nodeId]);
+ _routes.Remove(nodeId);
+ }
+ }
+ }
+
+ public void Clear()
+ {
+ lock (_lock)
+ {
+ _routes = new Dictionary();
+ _nodeIds = new Dictionary();
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Umbraco.Web/Routing/DocumentRequest.cs b/src/Umbraco.Web/Routing/DocumentRequest.cs
index efa44a1881..65844d84c8 100644
--- a/src/Umbraco.Web/Routing/DocumentRequest.cs
+++ b/src/Umbraco.Web/Routing/DocumentRequest.cs
@@ -16,12 +16,12 @@ namespace Umbraco.Web.Routing
{
static readonly TraceSource Trace = new TraceSource("DocumentRequest");
- public DocumentRequest(Uri uri, RoutingEnvironment lookups, UmbracoContext umbracoContext, NiceUrls niceUrls)
+ public DocumentRequest(Uri uri, RoutingEnvironment lookups, UmbracoContext umbracoContext, NiceUrlResolver niceUrlResolver)
{
// register lookups
_environment = lookups;
- _umbracoContext = umbracoContext;
- _niceUrls = niceUrls;
+ UmbracoContext = umbracoContext;
+ _niceUrlResolver = niceUrlResolver;
// prepare the host
var host = uri.Host;
@@ -55,13 +55,25 @@ namespace Umbraco.Web.Routing
this.QueryString = uri.Query.TrimStart('?');
}
+ readonly RoutingEnvironment _environment;
+ private readonly NiceUrlResolver _niceUrlResolver;
+
+ ///
+ /// the id of the requested node, if any, else zero.
+ ///
+ int _nodeId = 0;
+
+ ///
+ /// the requested node, if any, else null.
+ ///
+ XmlNode _node = null;
+
#region Properties
- // the id of the requested node, if any, else zero.
- int _nodeId = 0;
-
- // the requested node, if any, else null.
- XmlNode _node = null;
+ ///
+ /// Returns the current UmbracoContext
+ ///
+ public UmbracoContext UmbracoContext { get; private set; }
///
/// Gets the request host name.
@@ -176,15 +188,9 @@ namespace Umbraco.Web.Routing
#region Resolve
- readonly RoutingEnvironment _environment;
- private readonly UmbracoContext _umbracoContext;
- private readonly NiceUrls _niceUrls;
-
///
/// Determines the site root (if any) matching the http request.
- ///
- /// The host name part of the http request, eg. www.example.com.
- /// The url part of the http request, starting with a slash, eg. /foo/bar.
+ ///
/// A value indicating whether a domain was found.
public bool ResolveSiteRoot()
{
@@ -432,9 +438,9 @@ namespace Umbraco.Web.Routing
if (this.Node == null)
throw new InvalidOperationException("There is no node.");
- var templateAlias = _umbracoContext.HttpContext.Request.QueryString["altTemplate"];
+ var templateAlias = UmbracoContext.HttpContext.Request.QueryString["altTemplate"];
if (string.IsNullOrWhiteSpace(templateAlias))
- templateAlias = _umbracoContext.HttpContext.Request.Form["altTemplate"];
+ templateAlias = UmbracoContext.HttpContext.Request.Form["altTemplate"];
// fixme - we might want to support cookies?!? NO but provide a hook to change the template
@@ -488,7 +494,7 @@ namespace Umbraco.Web.Routing
redirectId = -1;
string redirectUrl = "#";
if (redirectId > 0)
- redirectUrl = _niceUrls.GetNiceUrl(redirectId);
+ redirectUrl = _niceUrlResolver.GetNiceUrl(redirectId);
if (redirectUrl != "#")
this.RedirectUrl = redirectUrl;
}
diff --git a/src/Umbraco.Web/Routing/IRoutesCache.cs b/src/Umbraco.Web/Routing/IRoutesCache.cs
new file mode 100644
index 0000000000..0f4a1044ec
--- /dev/null
+++ b/src/Umbraco.Web/Routing/IRoutesCache.cs
@@ -0,0 +1,11 @@
+namespace Umbraco.Web.Routing
+{
+ internal interface IRoutesCache
+ {
+ void Store(int nodeId, string route);
+ string GetRoute(int nodeId);
+ int GetNodeId(string route);
+ void ClearNode(int nodeId);
+ void Clear();
+ }
+}
\ No newline at end of file
diff --git a/src/Umbraco.Web/Routing/LookupByPath.cs b/src/Umbraco.Web/Routing/LookupByPath.cs
index d5e9dbba19..30dc31f546 100644
--- a/src/Umbraco.Web/Routing/LookupByPath.cs
+++ b/src/Umbraco.Web/Routing/LookupByPath.cs
@@ -9,7 +9,7 @@ namespace Umbraco.Web.Routing
[LookupWeight(10)]
internal class LookupByPath : ILookup
{
- public LookupByPath(ContentStore contentStore, RoutesCache routesCache)
+ public LookupByPath(ContentStore contentStore, IRoutesCache routesCache)
{
ContentStore = contentStore;
RoutesCache = routesCache;
@@ -18,7 +18,7 @@ namespace Umbraco.Web.Routing
static readonly TraceSource Trace = new TraceSource("LookupByPath");
protected ContentStore ContentStore;
- protected RoutesCache RoutesCache;
+ protected IRoutesCache RoutesCache;
public virtual bool LookupDocument(DocumentRequest docreq)
{
@@ -31,7 +31,12 @@ namespace Umbraco.Web.Routing
{
Trace.TraceInformation("Test route \"{0}\"", route);
- var nodeId = RoutesCache.GetNodeId(route);
+ //return '0' if in preview mode!
+ var nodeId = !docreq.UmbracoContext.InPreviewMode
+ ? RoutesCache.GetNodeId(route)
+ : 0;
+
+
XmlNode node = null;
if (nodeId > 0)
{
@@ -55,7 +60,12 @@ namespace Umbraco.Web.Routing
{
docreq.Node = node;
Trace.TraceInformation("Query matches, id={0}", docreq.NodeId);
- RoutesCache.Store(docreq.NodeId, route);
+
+ if (!docreq.UmbracoContext.InPreviewMode)
+ {
+ RoutesCache.Store(docreq.NodeId, route); // will not write if previewing
+ }
+
}
else
{
diff --git a/src/Umbraco.Web/Routing/LookupByPathWithTemplate.cs b/src/Umbraco.Web/Routing/LookupByPathWithTemplate.cs
index 1b91be23aa..11454bcdb2 100644
--- a/src/Umbraco.Web/Routing/LookupByPathWithTemplate.cs
+++ b/src/Umbraco.Web/Routing/LookupByPathWithTemplate.cs
@@ -13,7 +13,7 @@ namespace Umbraco.Web.Routing
{
static readonly TraceSource Trace = new TraceSource("LookupByPathWithTemplate");
- public LookupByPathWithTemplate(ContentStore contentStore, RoutesCache routesCache)
+ public LookupByPathWithTemplate(ContentStore contentStore, IRoutesCache routesCache)
: base(contentStore, routesCache)
{
}
diff --git a/src/Umbraco.Web/Routing/LookupByProfile.cs b/src/Umbraco.Web/Routing/LookupByProfile.cs
index a65eafac2e..c3044349e7 100644
--- a/src/Umbraco.Web/Routing/LookupByProfile.cs
+++ b/src/Umbraco.Web/Routing/LookupByProfile.cs
@@ -18,7 +18,7 @@ namespace Umbraco.Web.Routing
static readonly TraceSource Trace = new TraceSource("LookupByProfile");
- public LookupByProfile(ContentStore contentStore, RoutesCache routesCache, UmbracoContext umbracoContext)
+ public LookupByProfile(ContentStore contentStore, IRoutesCache routesCache, UmbracoContext umbracoContext)
: base(contentStore, routesCache)
{
_umbracoContext = umbracoContext;
diff --git a/src/Umbraco.Web/Routing/RoutesCache.cs b/src/Umbraco.Web/Routing/RoutesCache.cs
index d366dc23f9..dcb7843e1b 100644
--- a/src/Umbraco.Web/Routing/RoutesCache.cs
+++ b/src/Umbraco.Web/Routing/RoutesCache.cs
@@ -1,81 +1,57 @@
-using System.Collections.Generic;
+using System;
namespace Umbraco.Web.Routing
{
- internal class RoutesCache
- {
- private readonly object _lock = new object();
- private Dictionary _routes;
- private Dictionary _nodeIds;
+ ///
+ /// A singly registered object to assign and get the current IRoutesCache provider
+ ///
+ internal class RoutesCache
+ {
+ private static readonly RoutesCache Instance = new RoutesCache();
+ private static IRoutesCache _provider;
- private readonly UmbracoContext _umbracoContext;
+ ///
+ /// public contructor assigns the DefaultRoutesCache as the default provider
+ ///
+ public RoutesCache()
+ :this(null)
+ {
+ }
- public RoutesCache(UmbracoContext umbracoContext)
- {
- _umbracoContext = umbracoContext;
+ ///
+ /// Constructor sets a custom provider if specified
+ ///
+ ///
+ internal RoutesCache(IRoutesCache provider)
+ {
+ _provider = provider ?? new DefaultRoutesCache();
+ }
- Clear();
+ ///
+ /// Set the routes cache provider
+ ///
+ ///
+ public static void SetProvider(IRoutesCache provider)
+ {
+ if (provider == null) throw new ArgumentNullException("provider");
+ _provider = provider;
+ }
- // 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...
- }
+ ///
+ /// Singleton accessor
+ ///
+ public static RoutesCache Current
+ {
+ get { return Instance; }
+ }
- public void Store(int nodeId, string route)
- {
- if (_umbracoContext.InPreviewMode)
- return;
-
- lock (_lock)
- {
- _routes[nodeId] = route;
- _nodeIds[route] = nodeId;
- }
- }
-
- public string GetRoute(int nodeId)
- {
- if (_umbracoContext.InPreviewMode)
- return null;
-
- lock (_lock)
- {
- return _routes.ContainsKey(nodeId) ? _routes[nodeId] : null;
- }
- }
-
- public int GetNodeId(string route)
- {
- if (_umbracoContext.InPreviewMode)
- return 0;
-
- lock (_lock)
- {
- return _nodeIds.ContainsKey(route) ? _nodeIds[route] : 0;
- }
- }
-
- public void ClearNode(int nodeId)
- {
- lock (_lock)
- {
- if (_routes.ContainsKey(nodeId))
- {
- _nodeIds.Remove(_routes[nodeId]);
- _routes.Remove(nodeId);
- }
- }
- }
-
- public void Clear()
- {
- lock (_lock)
- {
- _routes = new Dictionary();
- _nodeIds = new Dictionary();
- }
- }
- }
+ ///
+ /// Get the current provider
+ ///
+ ///
+ public IRoutesCache GetProvider()
+ {
+ return _provider;
+ }
+ }
}
\ No newline at end of file
diff --git a/src/Umbraco.Web/Routing/RoutingEnvironment.cs b/src/Umbraco.Web/Routing/RoutingEnvironment.cs
index cf848625be..0affeb6799 100644
--- a/src/Umbraco.Web/Routing/RoutingEnvironment.cs
+++ b/src/Umbraco.Web/Routing/RoutingEnvironment.cs
@@ -3,10 +3,11 @@ using System.Linq;
namespace Umbraco.Web.Routing
{
- // represents a request for one specified Umbraco document to be rendered
- // by one specified template, using one particular culture.
- //
-
+
+ ///
+ /// represents a request for one specified Umbraco document to be rendered by one specified template,
+ /// using one particular culture.
+ ///
internal class RoutingEnvironment
{
public RoutingEnvironment(
@@ -28,13 +29,9 @@ namespace Umbraco.Web.Routing
}).ToList();
}
- public IEnumerable Lookups
- {
- get;
- private set;
- }
+ public IEnumerable Lookups { get; private set; }
- public ILookupNotFound LookupNotFound { get; private set; }
+ public ILookupNotFound LookupNotFound { get; private set; }
public ContentStore ContentStore { get; private set; }
diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj
index a9174e4cfb..b3ec0b677e 100644
--- a/src/Umbraco.Web/Umbraco.Web.csproj
+++ b/src/Umbraco.Web/Umbraco.Web.csproj
@@ -240,11 +240,12 @@
-
+
+
@@ -252,6 +253,7 @@
+
diff --git a/src/Umbraco.Web/UmbracoContext.cs b/src/Umbraco.Web/UmbracoContext.cs
index 4992fa3e07..6d6729b7c7 100644
--- a/src/Umbraco.Web/UmbracoContext.cs
+++ b/src/Umbraco.Web/UmbracoContext.cs
@@ -49,7 +49,7 @@ namespace Umbraco.Web
///
/// Gets the current Umbraco Context.
///
- public static UmbracoContext Current
+ public static UmbracoContext Current
{
get
{
@@ -126,6 +126,16 @@ namespace Umbraco.Web
///
internal DocumentRequest DocumentRequest { get; set; }
+ ///
+ /// Gets/sets the NiceUrlResolver object
+ ///
+ internal NiceUrlResolver NiceUrlResolver { get; set; }
+
+ ///
+ /// Gets/sets the RoutingEnvironment object
+ ///
+ internal RoutingEnvironment RoutingEnvironment { get; set; }
+
///
/// Exposes the HttpContext for the current request
///
@@ -193,29 +203,7 @@ namespace Umbraco.Web
&& !currentUrl.StartsWith(IOHelper.ResolveUrl(SystemDirectories.Umbraco)); // is not in admin UI
}
}
-
- ///
- /// Gets the current Live Editing Context.
- ///
- public virtual ILiveEditingContext LiveEditingContext
- {
- get
- {
- //TODO: this should be done with a wrapper: http://issues.umbraco.org/issue/U4-61
- var value = (ILiveEditingContext)HttpContext.Items["LiveEditingContext"];
- if (value == null)
- {
- LiveEditingContext = value = new DefaultLiveEditingContext();
- }
- return value;
- }
-
- set
- {
- //TODO: this should be done with a wrapper: http://issues.umbraco.org/issue/U4-61
- HttpContext.Items["LiveEditingContext"] = value;
- }
- }
+
}
}
\ No newline at end of file
diff --git a/src/Umbraco.Web/UmbracoModule.cs b/src/Umbraco.Web/UmbracoModule.cs
index d4b2ba0d35..1087e61fe3 100644
--- a/src/Umbraco.Web/UmbracoModule.cs
+++ b/src/Umbraco.Web/UmbracoModule.cs
@@ -37,11 +37,9 @@ namespace Umbraco.Web
UmbracoContext.Current = umbracoContext;
//create a content store
- var contentStore = new ContentStore(umbracoContext);
- //create the routes cache
- var routesCache = new RoutesCache(umbracoContext);
+ var contentStore = new ContentStore(umbracoContext);
//create the nice urls
- var niceUrls = new NiceUrls(contentStore, umbracoContext, routesCache);
+ var niceUrls = new NiceUrlResolver(contentStore, umbracoContext, RoutesCache.Current.GetProvider());
//create the RoutingEnvironment (one per http request as it relies on the umbraco context!)
var routingEnvironment = new RoutingEnvironment(
ApplicationContext.Current.Plugins.ResolveLookups().ToArray(),
@@ -49,9 +47,15 @@ namespace Umbraco.Web
contentStore);
// create the new document request which will cleanup the uri once and for all
var docreq = new DocumentRequest(uri, routingEnvironment, umbracoContext, niceUrls);
-
- // initialize the document request on the UmbracoContext (this is circular dependency!!!)
+
+ //NOTE: we are putting these objects on the UmbracoContext because these might be handy for developers in the future to
+ // access if we make them public.
+ // initialize the DocumentRequest on the UmbracoContext (this is circular dependency!!!)
umbracoContext.DocumentRequest = docreq;
+ // initialize the RoutingEnvironment on the UmbracoContext (this is circular dependency!!!)
+ umbracoContext.RoutingEnvironment = routingEnvironment;
+ // initialize the RoutingEnvironment on the UmbracoContext (this is circular dependency!!!)
+ umbracoContext.NiceUrlResolver = niceUrls;
//create the LegacyRequestInitializer (one per http request as it relies on the umbraco context!)
var legacyRequestInitializer = new LegacyRequestInitializer(umbracoContext);