diff --git a/src/Umbraco.Core/ApplicationContext.cs b/src/Umbraco.Core/ApplicationContext.cs
index 4f1e449a20..6d4892e911 100644
--- a/src/Umbraco.Core/ApplicationContext.cs
+++ b/src/Umbraco.Core/ApplicationContext.cs
@@ -12,11 +12,7 @@ namespace Umbraco.Core
///
public class ApplicationContext
{
-
- private static ApplicationContext _instance;
- private static readonly object Locker = new object();
-
- ///
+ ///
/// Constructor
///
///
@@ -25,25 +21,12 @@ namespace Umbraco.Core
Plugins = pluginResolver;
}
- ///
- /// Singleton accessor
- ///
- public static ApplicationContext Current
- {
- get
- {
- return _instance;
- }
- set
- {
- lock (Locker)
- {
- _instance = value;
- }
- }
- }
+ ///
+ /// Singleton accessor
+ ///
+ public static ApplicationContext Current { get; internal set; }
- // IsReady is set to true by the boot manager once it has successfully booted
+ // IsReady is set to true by the boot manager once it has successfully booted
// note - the original umbraco module checks on content.Instance in umbraco.dll
// now, the boot task that setup the content store ensures that it is ready
bool _isReady = false;
diff --git a/src/Umbraco.Web.UI/Global.asax b/src/Umbraco.Web.UI/Global.asax
new file mode 100644
index 0000000000..1627b363bc
--- /dev/null
+++ b/src/Umbraco.Web.UI/Global.asax
@@ -0,0 +1 @@
+<%@ Application Codebehind="Global.asax.cs" Inherits="Umbraco.Web.UmbracoApplication" Language="C#" %>
diff --git a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj
index 6f4ac938d7..97a5a03c2b 100644
--- a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj
+++ b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj
@@ -306,6 +306,7 @@
UI.xml
+
diff --git a/src/Umbraco.Web.UI/web.Template.config b/src/Umbraco.Web.UI/web.Template.config
index 773c4e0f47..ac9db87f0b 100644
--- a/src/Umbraco.Web.UI/web.Template.config
+++ b/src/Umbraco.Web.UI/web.Template.config
@@ -1,263 +1,267 @@
-
-
-
+
+
+
-
-
-
+
+
+
-
-
-
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
+ -->
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
-
+ -->
+
+
+
+
-
-
+
+
-
-
+ -->
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
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/NiceUrlResolver.cs b/src/Umbraco.Web/NiceUrlResolver.cs
new file mode 100644
index 0000000000..57d5e2f78c
--- /dev/null
+++ b/src/Umbraco.Web/NiceUrlResolver.cs
@@ -0,0 +1,159 @@
+using System.Collections.Generic;
+using System.Linq;
+using Umbraco.Web.Routing;
+using umbraco;
+using umbraco.IO;
+using umbraco.cms.businesslogic.web;
+
+namespace Umbraco.Web
+{
+ ///
+ /// Resolves NiceUrls for a given node id
+ ///
+ 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";
+
+ public virtual string GetNiceUrl(int nodeId)
+ {
+ int startNodeDepth = 1;
+ if (GlobalSettings.HideTopLevelNodeFromPath)
+ startNodeDepth = 2;
+
+ return GetNiceUrl(nodeId, startNodeDepth, false);
+ }
+
+ public virtual string GetNiceUrl(int nodeId, int startNodeDepth, bool forceDomain)
+ {
+ string path;
+
+ // will not read cache if previewing!
+ var route = !_umbracoContext.InPreviewMode
+ ? _umbracoContext.RoutesCache.GetRoute(nodeId)
+ : null;
+
+ if (route != null)
+ {
+ int pos = route.IndexOf('/');
+ path = route.Substring(pos);
+
+ if (UmbracoSettings.UseDomainPrefixes || forceDomain)
+ {
+ int rootNodeId = int.Parse(route.Substring(0, pos));
+ if (rootNodeId > 0)
+ return DomainAtNode(rootNodeId) + path;
+ }
+
+ return path;
+ }
+
+ // else there was not route in the cache, must build route...
+
+ var node = _contentStore.GetNodeById(nodeId);
+ if (node == null)
+ return "#"; // legacy wrote to the log here...
+
+ var parts = new List();
+ var depth = int.Parse(_contentStore.GetNodeProperty(node, "@level"));
+ var id = nodeId;
+ string domain = null;
+ while (depth >= 1)
+ {
+ // if not hiding that depth, add urlName
+ if (depth >= startNodeDepth)
+ parts.Add(_contentStore.GetNodeProperty(node, UrlNameProperty));
+
+ var tmp = DomainAtNode(id);
+ if (tmp != null)
+ {
+ if (UmbracoSettings.UseDomainPrefixes || forceDomain)
+ domain = tmp;
+ break; // break to capture the id
+ }
+
+ node = _contentStore.GetNodeParent(node);
+ id = int.Parse(_contentStore.GetNodeProperty(node, "@id"));
+ depth--;
+ }
+
+ parts.Reverse();
+ path = "/" + string.Join("/", parts);
+ route = string.Format("{0}{1}", id, path);
+
+ if (!_umbracoContext.InPreviewMode)
+ {
+ _umbracoContext.RoutesCache.Store(nodeId, route); // will not write if previewing
+ }
+
+ return FormatUrl(domain, path);
+ }
+
+ protected string DomainAtNode(int nodeId)
+ {
+ // be safe
+ if (nodeId <= 0)
+ return null;
+
+ // get domains defined on that node
+ Domain[] domains = Domain.GetDomainsById(nodeId);
+
+ // no domain set on that node, return null
+ if (domains.Length == 0)
+ return null;
+
+ // else try to find the first domain that matches the current request
+ // else take the first domain of the list
+ Domain domain = domains.FirstOrDefault(d => UrlUtility.IsBaseOf(d.Name, _umbracoContext.OriginalUrl)) ?? domains[0];
+
+ var domainName = domain.Name.TrimEnd('/');
+ domainName = UrlUtility.EnsureScheme(domainName, _umbracoContext.OriginalUrl.Scheme);
+ var pos = domainName.IndexOf("//");
+ pos = domainName.IndexOf("/", pos + 2);
+ if (pos > 0)
+ domainName = domainName.Substring(0, pos);
+
+ // return a scheme + host eg http://example.com with no trailing slash
+ return domainName;
+ }
+
+ protected string FormatUrl(string domain, string path)
+ {
+ if (domain == null) // else vdir needs to be in the domain
+ {
+ // get the application virtual dir (empty if no vdir)
+ string vdir = SystemDirectories.Root;
+ if (!string.IsNullOrEmpty(vdir))
+ domain = "/" + vdir;
+ }
+
+ string url = (domain ?? "") + path;
+ if (path != "/")
+ {
+ // not at root
+ if (GlobalSettings.UseDirectoryUrls)
+ {
+ // add trailing / if required
+ if (UmbracoSettings.AddTrailingSlash)
+ url += "/";
+ }
+ else
+ {
+ // add .aspx
+ url += ".aspx";
+ }
+ }
+
+ return url;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Umbraco.Web/NiceUrls.cs b/src/Umbraco.Web/NiceUrls.cs
deleted file mode 100644
index efb70b7a96..0000000000
--- a/src/Umbraco.Web/NiceUrls.cs
+++ /dev/null
@@ -1,145 +0,0 @@
-using System.Collections.Generic;
-using System.Linq;
-using Umbraco.Web.Routing;
-using umbraco;
-using umbraco.IO;
-using umbraco.cms.businesslogic.web;
-
-namespace Umbraco.Web
-{
- internal class NiceUrls
- {
- public NiceUrls(ContentStore contentStore, UmbracoContext umbracoContext, RoutesCache routesCache)
- {
- _umbracoContext = umbracoContext;
- _contentStore = contentStore;
- _routesCache = routesCache;
- }
-
- private readonly UmbracoContext _umbracoContext;
- private readonly ContentStore _contentStore;
- private readonly RoutesCache _routesCache;
-
- // note: this could be a parameter...
- const string UrlNameProperty = "@urlName";
-
- public string GetNiceUrl(int nodeId)
- {
- return GetNiceUrl(nodeId, FIXME*Current.UmbracoUrl, false);
- }
-
- public string GetNiceUrl(int nodeId, Uri current, bool absolute)
- {
- string path;
- Uri domainUri;
-
- string route = _routesCache.GetRoute(nodeId); // will get null if previewing
-
- if (route != null)
- {
- // route is / 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 "#";
-
- var pathParts = new List();
- 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"));
- domainUri = id > 0 ? DomainUriAtNode(id, current) : null;
- }
-
- // no domain, respect HideTopLevelNodeFromPath for legacy purposes
- if (domainUri == null && 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;
- _routesCache.Store(nodeId, route); // will not write if previewing
- }
-
- 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(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 (!umbraco.GlobalSettings.UseDirectoryUrls)
- path += ".aspx";
- else if (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
- }
-}
\ No newline at end of file
diff --git a/src/Umbraco.Web/PluginResolverExtensions.cs b/src/Umbraco.Web/PluginResolverExtensions.cs
index fbbf81c853..381fad68fb 100644
--- a/src/Umbraco.Web/PluginResolverExtensions.cs
+++ b/src/Umbraco.Web/PluginResolverExtensions.cs
@@ -7,49 +7,50 @@ using umbraco.BusinessLogic.Utils;
namespace Umbraco.Web
{
- ///
- /// Extension methods for the PluginResolver
- ///
- public static class PluginResolverExtensions
- {
+ ///
+ /// Extension methods for the PluginResolver
+ ///
+ public static class PluginResolverExtensions
+ {
- private static volatile IEnumerable _lookups;
- private static readonly object Locker = new object();
+ private static volatile IEnumerable _lookups;
+ private static readonly object Locker = new object();
- ///
- /// Returns all available ILookup objects
- ///
- ///
- ///
- internal static IEnumerable ResolveLookups(this PluginResolver plugins)
- {
- if (_lookups == null)
- {
- lock(Locker)
- {
- if (_lookups == null)
- {
- var lookupTypes = TypeFinder.FindClassesOfType();
- var lookups = new List();
- foreach (var l in lookupTypes)
- {
- try
- {
- var typeInstance = Activator.CreateInstance(l) as ILookup;
- lookups.Add(typeInstance);
- }
- catch (Exception ex)
- {
- Log.Add(LogTypes.Error, -1, "Error loading ILookup: " + ex.ToString());
- }
- }
- //set the global
- _lookups = lookups;
- }
- }
- }
- return _lookups;
- }
+ ///
+ /// Returns all available ILookup objects
+ ///
+ ///
+ ///
+ internal static IEnumerable ResolveLookups(this PluginResolver plugins)
+ {
+ if (_lookups == null)
+ {
+ lock (Locker)
+ {
+ if (_lookups == null)
+ {
+ var lookupTypes = TypeFinder.FindClassesOfType();
+ var lookups = new List();
+ foreach (var l in lookupTypes)
+ {
+ try
+ {
+ var typeInstance = Activator.CreateInstance(l) as ILookup;
+ lookups.Add(typeInstance);
+ }
+ catch (Exception ex)
+ {
+ //TODO: Need to fix logging so this doesn't bork if no SQL connection
+ //Log.Add(LogTypes.Error, -1, "Error loading ILookup: " + ex.ToString());
+ }
+ }
+ //set the global
+ _lookups = lookups;
+ }
+ }
+ }
+ return _lookups;
+ }
- }
+ }
}
\ No newline at end of file
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 761929b15e..a1e153b342 100644
--- a/src/Umbraco.Web/Routing/DocumentRequest.cs
+++ b/src/Umbraco.Web/Routing/DocumentRequest.cs
@@ -6,6 +6,7 @@ using System.Globalization;
using System.Diagnostics;
// legacy
+using umbraco.BusinessLogic;
using umbraco.cms.businesslogic.web;
using umbraco.cms.businesslogic.template;
using umbraco.cms.businesslogic.member;
@@ -19,21 +20,28 @@ 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, RoutingContext routingContext)
{
this.Uri = uri;
- _environment = lookups;
- _umbracoContext = umbracoContext;
- _niceUrls = niceUrls;
+ RoutingContext = routingContext;
}
+ ///
+ /// 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 RoutingContext
+ ///
+ public RoutingContext RoutingContext { get; private set; }
public Uri Uri { get; private set; }
@@ -74,7 +82,7 @@ namespace Umbraco.Web.Routing
_node = value;
this.Template = null;
if (_node != null)
- _nodeId = int.Parse(_environment.ContentStore.GetNodeProperty(_node, "@id"));
+ _nodeId = int.Parse(RoutingContext.ContentStore.GetNodeProperty(_node, "@id"));
else
_nodeId = 0;
}
@@ -134,15 +142,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 ResolveDomain()
{
@@ -200,7 +202,8 @@ namespace Umbraco.Web.Routing
// the first successful lookup, if any, will set this.Node, and may also set this.Template
// some lookups may implement caching
Trace.TraceInformation("{0}Begin lookup", tracePrefix);
- _environment.Lookups.Any(lookup => lookup.LookupDocument(this));
+ var lookups = RoutingContext.RouteLookups.GetLookups();
+ lookups.Any(lookup => lookup.LookupDocument(this));
Trace.TraceInformation("{0}End lookup, {1}", tracePrefix, (this.HasNode ? "a document was found" : "no document was found"));
// fixme - not handling umbracoRedirect
@@ -240,7 +243,7 @@ namespace Umbraco.Web.Routing
Trace.TraceInformation("{0}No document, try notFound lookup", tracePrefix);
// if it fails then give up, there isn't much more that we can do
- if (_environment.LookupNotFound == null || !_environment.LookupNotFound.LookupDocument(this))
+ if (RoutingContext.LookupNotFound == null || !RoutingContext.LookupNotFound.LookupDocument(this))
{
Trace.TraceInformation("{0}Failed to find a document, give up", tracePrefix);
break;
@@ -292,7 +295,7 @@ namespace Umbraco.Web.Routing
throw new InvalidOperationException("There is no node.");
bool redirect = false;
- string internalRedirect = _environment.ContentStore.GetNodeProperty(this.Node, "umbracoInternalRedirectId");
+ string internalRedirect = RoutingContext.ContentStore.GetNodeProperty(this.Node, "umbracoInternalRedirectId");
if (!string.IsNullOrWhiteSpace(internalRedirect))
{
@@ -316,7 +319,7 @@ namespace Umbraco.Web.Routing
else
{
// redirect to another page
- var node = _environment.ContentStore.GetNodeById(internalRedirectId);
+ var node = RoutingContext.ContentStore.GetNodeById(internalRedirectId);
this.Node = node;
if (node != null)
{
@@ -344,7 +347,7 @@ namespace Umbraco.Web.Routing
if (this.Node == null)
throw new InvalidOperationException("There is no node.");
- var path = _environment.ContentStore.GetNodeProperty(this.Node, "@path");
+ var path = RoutingContext.ContentStore.GetNodeProperty(this.Node, "@path");
if (Access.IsProtected(this.NodeId, path))
{
@@ -357,14 +360,14 @@ namespace Umbraco.Web.Routing
Trace.TraceInformation("{0}Not logged in, redirect to login page", tracePrefix);
var loginPageId = Access.GetLoginPage(path);
if (loginPageId != this.NodeId)
- this.Node = _environment.ContentStore.GetNodeById(loginPageId);
+ this.Node = RoutingContext.ContentStore.GetNodeById(loginPageId);
}
else if (!Access.HasAccces(this.NodeId, user.ProviderUserKey))
{
Trace.TraceInformation("{0}Current member has not access, redirect to error page", tracePrefix);
var errorPageId = Access.GetErrorPage(path);
if (errorPageId != this.NodeId)
- this.Node = _environment.ContentStore.GetNodeById(errorPageId);
+ this.Node = RoutingContext.ContentStore.GetNodeById(errorPageId);
}
else
{
@@ -387,9 +390,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 = RoutingContext.UmbracoContext.HttpContext.Request.QueryString["altTemplate"];
if (string.IsNullOrWhiteSpace(templateAlias))
- templateAlias = _umbracoContext.HttpContext.Request.Form["altTemplate"];
+ templateAlias = RoutingContext.UmbracoContext.HttpContext.Request.Form["altTemplate"];
// fixme - we might want to support cookies?!? NO but provide a hook to change the template
@@ -397,7 +400,7 @@ namespace Umbraco.Web.Routing
{
if (string.IsNullOrWhiteSpace(templateAlias))
{
- templateAlias = _environment.ContentStore.GetNodeProperty(this.Node, "@template");
+ templateAlias = RoutingContext.ContentStore.GetNodeProperty(this.Node, "@template");
Trace.TraceInformation("{0}Look for template id={1}", tracePrefix, templateAlias);
int templateId;
if (!int.TryParse(templateAlias, out templateId))
@@ -439,11 +442,11 @@ namespace Umbraco.Web.Routing
if (this.HasNode)
{
int redirectId;
- if (!int.TryParse(_environment.ContentStore.GetNodeProperty(this.Node, "umbracoRedirect"), out redirectId))
+ if (!int.TryParse(RoutingContext.ContentStore.GetNodeProperty(this.Node, "umbracoRedirect"), out redirectId))
redirectId = -1;
string redirectUrl = "#";
if (redirectId > 0)
- redirectUrl = _niceUrls.GetNiceUrl(redirectId);
+ redirectUrl = RoutingContext.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/LookupByAlias.cs b/src/Umbraco.Web/Routing/LookupByAlias.cs
index 7ed499f107..1580273f14 100644
--- a/src/Umbraco.Web/Routing/LookupByAlias.cs
+++ b/src/Umbraco.Web/Routing/LookupByAlias.cs
@@ -13,14 +13,9 @@ namespace Umbraco.Web.Routing
[LookupWeight(50)]
internal class LookupByAlias : ILookup
{
- public LookupByAlias(ContentStore contentStore)
- {
- _contentStore = contentStore;
- }
-
+
static readonly TraceSource Trace = new TraceSource("LookupByAlias");
- readonly ContentStore _contentStore;
public bool LookupDocument(DocumentRequest docreq)
{
@@ -28,7 +23,7 @@ namespace Umbraco.Web.Routing
if (docreq.Uri.AbsolutePath != "/") // no alias if "/"
{
- node = _contentStore.GetNodeByUrlAlias(docreq.HasDomain ? docreq.Domain.RootNodeId : 0, docreq.Uri.AbsolutePath);
+ node = docreq.RoutingContext.ContentStore.GetNodeByUrlAlias(docreq.HasDomain ? docreq.Domain.RootNodeId : 0, docreq.Uri.AbsolutePath);
if (node != null)
{
Trace.TraceInformation("Path \"{0}\" is an alias for id={1}", docreq.Uri.AbsolutePath, docreq.NodeId);
diff --git a/src/Umbraco.Web/Routing/LookupById.cs b/src/Umbraco.Web/Routing/LookupById.cs
index a01330edec..f9d8ec46aa 100644
--- a/src/Umbraco.Web/Routing/LookupById.cs
+++ b/src/Umbraco.Web/Routing/LookupById.cs
@@ -10,24 +10,9 @@ namespace Umbraco.Web.Routing
[LookupWeight(20)]
internal class LookupById : ILookup
{
- public LookupById(ContentStore contentStore)
- {
- _contentStore = contentStore;
- }
-
+
static readonly TraceSource Trace = new TraceSource("LookupById");
- readonly ContentStore _contentStore;
-
- ////[Import]
- //IContentStore ContentStoreImport
- //{
- // set { _contentStore = value; }
- //}
-
- //public LookupById()
- //{ }
-
public bool LookupDocument(DocumentRequest docreq)
{
XmlNode node = null;
@@ -43,7 +28,7 @@ namespace Umbraco.Web.Routing
if (nodeId > 0)
{
Trace.TraceInformation("Id={0}", nodeId);
- node = _contentStore.GetNodeById(nodeId);
+ node = docreq.RoutingContext.ContentStore.GetNodeById(nodeId);
if (node != null)
{
docreq.Node = node;
diff --git a/src/Umbraco.Web/Routing/LookupByPath.cs b/src/Umbraco.Web/Routing/LookupByPath.cs
index b3e0332c45..4acb683a68 100644
--- a/src/Umbraco.Web/Routing/LookupByPath.cs
+++ b/src/Umbraco.Web/Routing/LookupByPath.cs
@@ -9,17 +9,9 @@ namespace Umbraco.Web.Routing
[LookupWeight(10)]
internal class LookupByPath : ILookup
{
- public LookupByPath(ContentStore contentStore, RoutesCache routesCache)
- {
- ContentStore = contentStore;
- RoutesCache = routesCache;
- }
-
+
static readonly TraceSource Trace = new TraceSource("LookupByPath");
- protected ContentStore ContentStore;
- protected RoutesCache RoutesCache;
-
public virtual bool LookupDocument(DocumentRequest docreq)
{
string route;
@@ -36,11 +28,16 @@ namespace Umbraco.Web.Routing
{
Trace.TraceInformation("Test route \"{0}\"", route);
- var nodeId = RoutesCache.GetNodeId(route);
+ //return '0' if in preview mode!
+ var nodeId = !docreq.RoutingContext.UmbracoContext.InPreviewMode
+ ? docreq.RoutingContext.UmbracoContext.RoutesCache.GetNodeId(route)
+ : 0;
+
+
XmlNode node = null;
if (nodeId > 0)
{
- node = ContentStore.GetNodeById(nodeId);
+ node = docreq.RoutingContext.ContentStore.GetNodeById(nodeId);
if (node != null)
{
docreq.Node = node;
@@ -48,19 +45,24 @@ namespace Umbraco.Web.Routing
}
else
{
- RoutesCache.ClearNode(nodeId);
+ docreq.RoutingContext.UmbracoContext.RoutesCache.ClearNode(nodeId);
}
}
if (node == null)
{
Trace.TraceInformation("Cache miss, query");
- node = ContentStore.GetNodeByRoute(route);
+ node = docreq.RoutingContext.ContentStore.GetNodeByRoute(route);
if (node != null)
{
docreq.Node = node;
Trace.TraceInformation("Query matches, id={0}", docreq.NodeId);
- RoutesCache.Store(docreq.NodeId, route);
+
+ if (!docreq.RoutingContext.UmbracoContext.InPreviewMode)
+ {
+ docreq.RoutingContext.UmbracoContext.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 91450fdabd..a14de76b6e 100644
--- a/src/Umbraco.Web/Routing/LookupByPathWithTemplate.cs
+++ b/src/Umbraco.Web/Routing/LookupByPathWithTemplate.cs
@@ -11,12 +11,7 @@ namespace Umbraco.Web.Routing
[LookupWeight(30)]
internal class LookupByPathWithTemplate : LookupByPath, ILookup
{
- static readonly TraceSource Trace = new TraceSource("LookupByPathWithTemplate");
-
- public LookupByPathWithTemplate(ContentStore contentStore, RoutesCache routesCache)
- : base(contentStore, routesCache)
- {
- }
+ static readonly TraceSource Trace = new TraceSource("LookupByPathWithTemplate");
public override bool LookupDocument(DocumentRequest docreq)
{
diff --git a/src/Umbraco.Web/Routing/LookupByProfile.cs b/src/Umbraco.Web/Routing/LookupByProfile.cs
index 5e7cac1247..21ee4a5811 100644
--- a/src/Umbraco.Web/Routing/LookupByProfile.cs
+++ b/src/Umbraco.Web/Routing/LookupByProfile.cs
@@ -14,15 +14,7 @@ namespace Umbraco.Web.Routing
[LookupWeight(40)]
internal class LookupByProfile : LookupByPath, ILookup
{
- private readonly UmbracoContext _umbracoContext;
- static readonly TraceSource Trace = new TraceSource("LookupByProfile");
-
-
- public LookupByProfile(ContentStore contentStore, RoutesCache routesCache, UmbracoContext umbracoContext)
- : base(contentStore, routesCache)
- {
- _umbracoContext = umbracoContext;
- }
+ static readonly TraceSource Trace = new TraceSource("LookupByProfile");
public override bool LookupDocument(DocumentRequest docreq)
{
@@ -44,7 +36,10 @@ namespace Umbraco.Web.Routing
node = LookupDocumentNode(docreq, route);
if (node != null)
- _umbracoContext.HttpContext.Items["umbMemberLogin"] = memberLogin;
+ {
+ //TODO: Should be handled by Context Items class manager (http://issues.umbraco.org/issue/U4-61)
+ docreq.RoutingContext.UmbracoContext.HttpContext.Items["umbMemberLogin"] = memberLogin;
+ }
else
Trace.TraceInformation("No document matching profile path?");
}
diff --git a/src/Umbraco.Web/Routing/LookupFor404.cs b/src/Umbraco.Web/Routing/LookupFor404.cs
index f3a2354112..863b8c41ac 100644
--- a/src/Umbraco.Web/Routing/LookupFor404.cs
+++ b/src/Umbraco.Web/Routing/LookupFor404.cs
@@ -11,18 +11,12 @@ namespace Umbraco.Web.Routing
{
internal class LookupFor404 : ILookupNotFound
{
- public LookupFor404(ContentStore contentStore)
- {
- _contentStore = contentStore;
- }
-
+
static TraceSource _trace = new TraceSource("LookupByAlias");
- private readonly ContentStore _contentStore;
-
public bool LookupDocument(DocumentRequest docRequest)
{
- docRequest.Node = HandlePageNotFound(docRequest.Uri.AbsolutePath);
+ docRequest.Node = HandlePageNotFound(docRequest);
return docRequest.HasNode;
}
@@ -30,17 +24,17 @@ namespace Umbraco.Web.Routing
// copied from presentation/requestHandler
// temporary!!
- XmlNode HandlePageNotFound(string url)
+ XmlNode HandlePageNotFound(DocumentRequest docRequest)
{
- HttpContext.Current.Trace.Write("NotFoundHandler", string.Format("Running for url='{0}'.", url));
+ HttpContext.Current.Trace.Write("NotFoundHandler", string.Format("Running for url='{0}'.", docRequest.Uri.AbsolutePath));
XmlNode currentPage = null;
foreach (var handler in GetNotFoundHandlers())
{
- if (handler.Execute(url) && handler.redirectID > 0)
+ if (handler.Execute(docRequest.Uri.AbsolutePath) && handler.redirectID > 0)
{
//currentPage = umbracoContent.GetElementById(handler.redirectID.ToString());
- currentPage = _contentStore.GetNodeById(handler.redirectID);
+ currentPage = docRequest.RoutingContext.ContentStore.GetNodeById(handler.redirectID);
// FIXME - could it be null?
diff --git a/src/Umbraco.Web/Routing/RouteLookups.cs b/src/Umbraco.Web/Routing/RouteLookups.cs
new file mode 100644
index 0000000000..137ea8514d
--- /dev/null
+++ b/src/Umbraco.Web/Routing/RouteLookups.cs
@@ -0,0 +1,106 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using Umbraco.Core;
+
+namespace Umbraco.Web.Routing
+{
+ ///
+ /// Represents a collection of ILookup used for routing that are registered in the application
+ ///
+ internal class RouteLookups
+ {
+ private static readonly List Lookups = new List();
+ private static readonly ReaderWriterLockSlim Lock = new ReaderWriterLockSlim();
+
+ ///
+ /// Singleton accessor
+ ///
+ public static RouteLookups Current { get; internal set; }
+
+ internal RouteLookups(IEnumerable lookups)
+ {
+ Lookups.AddRange(SortByWeight(lookups));
+ }
+
+ ///
+ /// Returns all of the lookups
+ ///
+ ///
+ public IEnumerable GetLookups()
+ {
+ return Lookups;
+ }
+
+ ///
+ /// Removes an ILookup based on the specified Type
+ ///
+ ///
+ public void RemoveLookup()
+ where T : ILookup
+ {
+ using (new WriteLock(Lock))
+ {
+ Lookups.Remove(Lookups.SingleOrDefault(x => x is T));
+ }
+ }
+
+
+ ///
+ /// Adds a new lookup to the end of the list
+ ///
+ ///
+ public void AddLookup(ILookup lookup)
+ {
+ if (CheckExists(lookup))
+ throw new InvalidOperationException("The lookup type " + lookup + " already exists in the lookup collection");
+
+ using (new WriteLock(Lock))
+ {
+ Lookups.Add(lookup);
+ }
+ }
+
+ ///
+ /// Inserts a lookup at the specified index
+ ///
+ ///
+ ///
+ public void InsertLookup(int index, ILookup lookup)
+ {
+ if (CheckExists(lookup))
+ throw new InvalidOperationException("The lookup type " + lookup + " already exists in the lookup collection");
+
+ using (new WriteLock(Lock))
+ {
+ Lookups.Insert(index, lookup);
+ }
+ }
+
+ ///
+ /// checks if a lookup already exists by type
+ ///
+ ///
+ ///
+ private static bool CheckExists(ILookup lookup)
+ {
+ return Lookups.Any(x => x.GetType() == lookup.GetType());
+ }
+
+ ///
+ /// Sorts the ILookups in the list based on an attribute weight if one is specified
+ ///
+ ///
+ ///
+ private static IEnumerable SortByWeight(IEnumerable lookups)
+ {
+ return lookups.OrderBy(x =>
+ {
+ var attribute = x.GetType().GetCustomAttributes(true).OfType().SingleOrDefault();
+ return attribute == null ? LookupWeightAttribute.DefaultWeight : attribute.Weight;
+ }).ToList();
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/src/Umbraco.Web/Routing/RoutesCache.cs b/src/Umbraco.Web/Routing/RoutesCache.cs
index cb99ceb2de..e46fa9681c 100644
--- a/src/Umbraco.Web/Routing/RoutesCache.cs
+++ b/src/Umbraco.Web/Routing/RoutesCache.cs
@@ -1,4 +1,4 @@
-using System.Collections.Generic;
+using System;
namespace Umbraco.Web.Routing
{
@@ -8,82 +8,54 @@ namespace Umbraco.Web.Routing
//
// a route is [rootId]/path/to/node
// where rootId is the id of the "site root" node
- // if missing then the "site root" is the content root
//
- internal class RoutesCache
- {
- private readonly object _lock = new object();
- private Dictionary _routes;
- private Dictionary _nodeIds;
+ 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/RoutingContext.cs b/src/Umbraco.Web/Routing/RoutingContext.cs
new file mode 100644
index 0000000000..7f2013a0d9
--- /dev/null
+++ b/src/Umbraco.Web/Routing/RoutingContext.cs
@@ -0,0 +1,33 @@
+using System.Collections.Generic;
+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.
+ ///
+ internal class RoutingContext
+ {
+ public RoutingContext(
+ UmbracoContext umbracoContext,
+ RouteLookups lookups,
+ ILookupNotFound lookupNotFound,
+ ContentStore contentStore,
+ NiceUrlResolver niceUrlResolver)
+ {
+ UmbracoContext = umbracoContext;
+ RouteLookups = lookups;
+ LookupNotFound = lookupNotFound;
+ ContentStore = contentStore;
+ NiceUrlResolver = niceUrlResolver;
+ }
+
+ public UmbracoContext UmbracoContext { get; private set; }
+ public RouteLookups RouteLookups { get; private set; }
+ public ILookupNotFound LookupNotFound { get; private set; }
+ public ContentStore ContentStore { get; private set; }
+ public NiceUrlResolver NiceUrlResolver { get; private set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Umbraco.Web/Routing/RoutingEnvironment.cs b/src/Umbraco.Web/Routing/RoutingEnvironment.cs
deleted file mode 100644
index 8e63f223cd..0000000000
--- a/src/Umbraco.Web/Routing/RoutingEnvironment.cs
+++ /dev/null
@@ -1,38 +0,0 @@
-using System.Collections.Generic;
-using System.Linq;
-
-namespace Umbraco.Web.Routing
-{
- internal class RoutingEnvironment
- {
- public RoutingEnvironment(
- IEnumerable lookups,
- ILookupNotFound lookupNotFound,
- ContentStore contentStore)
- {
- Lookups = SortByPartWeight(lookups);
- LookupNotFound = lookupNotFound;
- ContentStore = contentStore;
- }
-
- private static IEnumerable SortByPartWeight(IEnumerable lookups)
- {
- return lookups.OrderBy(x =>
- {
- var attribute = x.GetType().GetCustomAttributes(true).OfType().SingleOrDefault();
- return attribute == null ? LookupWeightAttribute.DefaultWeight : attribute.Weight;
- }).ToList();
- }
-
- public IEnumerable Lookups
- {
- get;
- private set;
- }
-
- public ILookupNotFound LookupNotFound { get; private set; }
-
- public ContentStore ContentStore { get; private set; }
-
- }
-}
\ No newline at end of file
diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj
index 98d3136fef..0dae665f09 100644
--- a/src/Umbraco.Web/Umbraco.Web.csproj
+++ b/src/Umbraco.Web/Umbraco.Web.csproj
@@ -240,11 +240,13 @@
-
+
+
+
@@ -252,8 +254,9 @@
+
-
+
database.ascx
@@ -1759,6 +1762,7 @@
+
diff --git a/src/Umbraco.Web/UmbracoApplication.cs b/src/Umbraco.Web/UmbracoApplication.cs
new file mode 100644
index 0000000000..5febadc78a
--- /dev/null
+++ b/src/Umbraco.Web/UmbracoApplication.cs
@@ -0,0 +1,54 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Text;
+using Umbraco.Core;
+using Umbraco.Web.Routing;
+
+namespace Umbraco.Web
+{
+ ///
+ /// The Umbraco global.asax class
+ ///
+ public class UmbracoApplication : System.Web.HttpApplication
+ {
+
+ private static readonly TraceSource Trace = new TraceSource("UmbracoApplication");
+
+ ///
+ /// Initializes the Umbraco application
+ ///
+ ///
+ ///
+ protected virtual void Application_Start(object sender, EventArgs e)
+ {
+ Trace.TraceInformation("Initialize AppDomain");
+
+ // Backwards compatibility - set the path and URL type for ClientDependency 1.5.1 [LK]
+ ClientDependency.Core.CompositeFiles.Providers.XmlFileMapper.FileMapVirtualFolder = "~/App_Data/TEMP/ClientDependency";
+ ClientDependency.Core.CompositeFiles.Providers.BaseCompositeFileProcessingProvider.UrlTypeDefault = ClientDependency.Core.CompositeFiles.Providers.CompositeUrlType.Base64QueryStrings;
+
+ //create the ApplicationContext
+ ApplicationContext.Current = new ApplicationContext(new PluginResolver())
+ {
+ IsReady = true // fixme
+ };
+
+ //create the route lookups singleton
+ RouteLookups.Current = new RouteLookups(ApplicationContext.Current.Plugins.ResolveLookups());
+
+ Trace.TraceInformation("AppDomain is initialized");
+ }
+
+ protected virtual void Application_Error(object sender, EventArgs e)
+ {
+
+ }
+
+ protected virtual void Application_End(object sender, EventArgs e)
+ {
+
+ }
+ }
+}
diff --git a/src/Umbraco.Web/UmbracoContext.cs b/src/Umbraco.Web/UmbracoContext.cs
index 4992fa3e07..95625ab475 100644
--- a/src/Umbraco.Web/UmbracoContext.cs
+++ b/src/Umbraco.Web/UmbracoContext.cs
@@ -32,24 +32,32 @@ namespace Umbraco.Web
///
private static UmbracoContext _umbracoContext;
- ///
- /// Creates a new Umbraco context.
- ///
- ///
- ///
- internal UmbracoContext(HttpContextBase httpContext, ApplicationContext applicationContext)
+ ///
+ /// Creates a new Umbraco context.
+ ///
+ ///
+ ///
+ ///
+ internal UmbracoContext(
+ HttpContextBase httpContext,
+ ApplicationContext applicationContext,
+ IRoutesCache routesCache)
{
if (httpContext == null) throw new ArgumentNullException("httpContext");
if (applicationContext == null) throw new ArgumentNullException("applicationContext");
HttpContext = httpContext;
Application = applicationContext;
+ RoutesCache = routesCache;
+
+ //set the original url
+ OriginalUrl = httpContext.Request.Url;
}
///
/// Gets the current Umbraco Context.
///
- public static UmbracoContext Current
+ public static UmbracoContext Current
{
get
{
@@ -91,7 +99,9 @@ namespace Umbraco.Web
///
public ApplicationContext Application { get; private set; }
- ///
+ internal IRoutesCache RoutesCache { get; private set; }
+
+ ///
/// Gets/sets the original URL of the request
///
internal Uri OriginalUrl { get; set; }
@@ -124,7 +134,7 @@ namespace Umbraco.Web
///
/// Gets/sets the DocumentRequest object
///
- internal DocumentRequest DocumentRequest { get; set; }
+ internal DocumentRequest DocumentRequest { 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 178e691695..9d9df6b495 100644
--- a/src/Umbraco.Web/UmbracoModule.cs
+++ b/src/Umbraco.Web/UmbracoModule.cs
@@ -25,6 +25,11 @@ namespace Umbraco.Web
{
Trace.TraceInformation("Process request");
+ //TODO: We need to ensure the below only executes for real requests (i.e. not css, favicon, etc...)
+ // I'm pretty sure we need to bind to the PostHandlerAssigned (or whatever event) and follow the same
+ // practices that is in umbraMVCo
+
+
var uri = httpContext.Request.Url;
var lpath = uri.AbsolutePath.ToLower();
@@ -32,31 +37,37 @@ namespace Umbraco.Web
if (!UmbracoSettings.RemoveUmbracoVersionHeader)
httpContext.Response.AddHeader("X-Umbraco-Version", string.Format("{0}.{1}", GlobalSettings.VersionMajor, GlobalSettings.VersionMinor));
+ //create the legacy UmbracoContext
+ global::umbraco.presentation.UmbracoContext.Current
+ = new global::umbraco.presentation.UmbracoContext(new HttpContextWrapper(httpContext));
+
//create the UmbracoContext singleton, one per request!!
- var umbracoContext = new UmbracoContext(new HttpContextWrapper(httpContext), ApplicationContext.Current);
+ var umbracoContext = new UmbracoContext(
+ new HttpContextWrapper(httpContext),
+ ApplicationContext.Current,
+ RoutesCache.Current.GetProvider());
UmbracoContext.Current = umbracoContext;
// NO!
// these are application-wide singletons!
//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);
- //create the RoutingEnvironment (one per http request as it relies on the umbraco context!)
- var routingEnvironment = new RoutingEnvironment(
- ApplicationContext.Current.Plugins.ResolveLookups().ToArray(),
- new LookupFor404(contentStore),
- contentStore);
-
+ var niceUrls = new NiceUrlResolver(contentStore, umbracoContext);
+ //create the RoutingContext (one per http request)
+ var routingContext = new RoutingContext(
+ umbracoContext,
+ RouteLookups.Current,
+ new LookupFor404(),
+ contentStore,
+ niceUrls);
// NOT HERE BUT SEE **THERE** BELOW
// 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!!!)
+ var docreq = new DocumentRequest(uri, routingContext);
+
+ // initialize the DocumentRequest on the UmbracoContext (this is circular dependency but i think in this case is ok)
umbracoContext.DocumentRequest = docreq;
//create the LegacyRequestInitializer (one per http request as it relies on the umbraco context!)
@@ -307,7 +318,16 @@ namespace Umbraco.Web
// and there may be more than 1 application per application domain
public void Init(HttpApplication app)
{
- InitializeApplication(app);
+ // used to be done in PostAuthorizeRequest but then it disabled OutputCaching due
+ // to rewriting happening too early in the chain (Alex Norcliffe 2010-02).
+ app.PostResolveRequestCache += (sender, e) =>
+ {
+ HttpContext httpContext = ((HttpApplication)sender).Context;
+ ProcessRequest(httpContext);
+ };
+
+ // todo: initialize request errors handler
+ // todo: initialize XML cache flush
}
public void Dispose()
@@ -315,62 +335,5 @@ namespace Umbraco.Web
#endregion
- #region Initialize
-
- private static volatile bool _appDomainInitialized = false;
- static readonly object AppDomainLock = new object();
-
- ///
- /// Initializes the application one time only
- ///
- void InitializeDomain()
- {
- if (!_appDomainInitialized)
- {
- lock (AppDomainLock)
- {
- if (!_appDomainInitialized)
- {
- Trace.TraceInformation("Initialize AppDomain");
-
- //create the ApplicationContext
- ApplicationContext.Current = new ApplicationContext(new PluginResolver());
-
- //TODO: Why is this necessary? if the ApplicationContext is null, then its not ready
- ApplicationContext.Current.IsReady = true; // fixme
-
- // Backwards compatibility - set the path and URL type for ClientDependency 1.5.1 [LK]
- ClientDependency.Core.CompositeFiles.Providers.XmlFileMapper.FileMapVirtualFolder = "~/App_Data/TEMP/ClientDependency";
- ClientDependency.Core.CompositeFiles.Providers.BaseCompositeFileProcessingProvider.UrlTypeDefault = ClientDependency.Core.CompositeFiles.Providers.CompositeUrlType.Base64QueryStrings;
-
- _appDomainInitialized = true;
- }
- Trace.TraceInformation("AppDomain is initialized");
- }
- }
- }
-
- void InitializeApplication(HttpApplication app)
- {
- // we can't do in in module.Init because we need HttpContext.
- app.BeginRequest += (sender, e) =>
- {
- Trace.TraceInformation("Welcome to Umbraco!");
- InitializeDomain();
- };
-
- // used to be done in PostAuthorizeRequest but then it disabled OutputCaching due
- // to rewriting happening too early in the chain (Alex Norcliffe 2010-02).
- app.PostResolveRequestCache += (sender, e) =>
- {
- HttpContext httpContext = ((HttpApplication)sender).Context;
- ProcessRequest(httpContext);
- };
-
- // todo: initialize request errors handler
- // todo: initialize XML cache flush
- }
-
- #endregion
}
}
diff --git a/src/Umbraco.Web/umbraco.presentation/default.aspx.cs b/src/Umbraco.Web/umbraco.presentation/default.aspx.cs
index 53b4b19dc1..f10b0bce4c 100644
--- a/src/Umbraco.Web/umbraco.presentation/default.aspx.cs
+++ b/src/Umbraco.Web/umbraco.presentation/default.aspx.cs
@@ -1,359 +1,230 @@
using System;
+using System.Threading;
using System.Web;
+using System.Web.Routing;
using System.Web.UI;
using System.IO;
using System.Xml;
using System.Text.RegularExpressions;
-using umbraco.presentation;
+using Umbraco.Web;
using umbraco.cms.businesslogic.web;
using umbraco.cms.businesslogic;
namespace umbraco
{
- ///
- /// Summary description for WebForm1.
- ///
- ///
- public partial class UmbracoDefault : Page
- {
+ ///
+ /// Summary description for WebForm1.
+ ///
+ ///
+ public partial class UmbracoDefault : Page
+ {
+ page _upage = null;
- private Guid m_version = Guid.Empty;
- private string m_tmp = requestHandler.cleanUrl();
- private page m_umbPage = null;
- private requestHandler m_umbRequest = null;
+ bool _validateRequest = true;
- private bool m_validateRequest = true;
+ const string TraceCategory = "UmbracoDefault";
- ///
- /// To turn off request validation set this to false before the PageLoad event. This equelevant to the validateRequest page directive
- /// and has nothing to do with "normal" validation controls. Default value is true.
- ///
- public bool ValidateRequest
- {
- get { return m_validateRequest; }
- set { m_validateRequest = value; }
- }
+ ///
+ /// To turn off request validation set this to false before the PageLoad event. This equivalent to the validateRequest page directive
+ /// and has nothing to do with "normal" validation controls. Default value is true.
+ ///
+ public bool ValidateRequest
+ {
+ get { return _validateRequest; }
+ set { _validateRequest = value; }
+ }
- protected override void Render(HtmlTextWriter output)
- {
+ // fixme - switch over to OnPreInit override
+ void Page_PreInit(Object sender, EventArgs e)
+ {
+ Trace.Write(TraceCategory, "Begin PreInit");
- // Get content
- TextWriter tempWriter = new StringWriter();
- base.Render(new HtmlTextWriter(tempWriter));
- string pageContents = tempWriter.ToString();
+ // moved into LegacyRequestInitializer
+ // initialize the UmbracoContext instance
+ //if (UmbracoContext.Current == null)
+ // UmbracoContext.Current = new UmbracoContext(HttpContext.Current);
- pageContents = template.ParseInternalLinks(pageContents);
+ // get the document request
+ var docreq = UmbracoContext.Current.DocumentRequest;
- // preview
- if (UmbracoContext.Current.InPreviewMode)
- {
- Trace.Write("Runtime Engine", "Umbraco is running in preview mode.");
+ // load request parameters
+ // any reason other than liveEditing why we want to do this?!
+ Guid requestVersion;
+ if (!Guid.TryParse(Request["umbVersion"], out requestVersion))
+ requestVersion = Guid.Empty;
+ int requestId;
+ if (!int.TryParse(Request["umbPageID"], out requestId))
+ requestId = -1;
- int bodyPos = pageContents.ToLower().IndexOf("
Page not found
");
+ UmbracoContext.Current.HttpContext.Response.Write("No umbraco document matches the url '" + HttpUtility.HtmlEncode(Request.Url.ToString()) + "'.
");
- #region Web Form Designer generated code
+ // fixme - should try to get infos from the DocumentRequest?
- protected override void OnInit(EventArgs e)
- {
- //
- // CODEGEN: This call is required by the ASP.NET Web Form Designer.
- //
- InitializeComponent();
-
- if (!UmbracoSettings.UseAspNetMasterPages)
- initUmbracoPage();
- base.OnInit(e);
-
- // Add Umbraco header
- if (!UmbracoSettings.RemoveUmbracoVersionHeader)
- Response.AddHeader("X-Umbraco-Version", string.Format("{0}.{1}", GlobalSettings.VersionMajor, GlobalSettings.VersionMinor));
- }
-
- private void initUmbracoPage()
- {
-
- RequestInitEventArgs e = new RequestInitEventArgs();
- e.Page = m_umbPage;
-
- if(m_umbPage != null)
- e.PageId = m_umbPage.PageID;
-
- e.Context = System.Web.HttpContext.Current;
-
- FireBeforeRequestInit(e);
- if (!e.Cancel)
- {
- if (!UmbracoSettings.EnableSplashWhileLoading || !content.Instance.isInitializing)
- {
-
- if (m_umbPage != null)
- {
- // Add page elements to global items
- try
- {
-
- System.Web.HttpContext.Current.Items.Add("pageElements", m_umbPage.Elements);
-
- }
- catch (ArgumentException)
- {
-
- System.Web.HttpContext.Current.Items.Remove("pageElements");
- System.Web.HttpContext.Current.Items.Add("pageElements", m_umbPage.Elements);
- }
-
- string tempCulture = m_umbPage.GetCulture();
- if (tempCulture != "")
- {
- System.Web.HttpContext.Current.Trace.Write("default.aspx", "Culture changed to " + tempCulture);
- System.Threading.Thread.CurrentThread.CurrentCulture =
- System.Globalization.CultureInfo.CreateSpecificCulture(tempCulture);
- System.Threading.Thread.CurrentThread.CurrentUICulture = System.Threading.Thread.CurrentThread.CurrentCulture;
- }
-
- if (!UmbracoSettings.UseAspNetMasterPages)
- {
- layoutControls.umbracoPageHolder pageHolder = new umbraco.layoutControls.umbracoPageHolder();
- pageHolder.ID = "umbPageHolder";
- Page.Controls.Add(pageHolder);
- m_umbPage.RenderPage(m_umbPage.Template);
- layoutControls.umbracoPageHolder umbPageHolder =
- (layoutControls.umbracoPageHolder)Page.FindControl("umbPageHolder");
- umbPageHolder.Populate(m_umbPage);
- }
-
- }
- else
- {
- // If there's no published content, show friendly error
- if (umbraco.content.Instance.XmlContent.SelectSingleNode("/root/*") == null)
- Response.Redirect(IO.SystemDirectories.Config + "/splashes/noNodes.aspx");
- else
- {
-
- GenerateNotFoundContent();
- }
- }
- }
- else
- {
- Response.Redirect(IO.SystemDirectories.Config + "/splashes/booting.aspx?orgUrl=" + Request.Url);
- }
-
- FireAfterRequestInit(e);
- }
- }
-
- private void GenerateNotFoundContent()
- {
- Response.StatusCode = 404;
- Response.Write("Page not found
");
- if (m_umbRequest != null)
- HttpContext.Current.Response.Write("No umbraco document matches the url '" + HttpUtility.HtmlEncode(Request.Url.ToString()) + "'
umbraco tried this to match it using this xpath query'" + m_umbRequest.PageXPathQuery + "')");
- else
- HttpContext.Current.Response.Write("
No umbraco document matches the url '" + HttpUtility.HtmlEncode(Request.Url.ToString()) + "'
");
- Response.Write("");
- Response.Write("This page can be replaced with a custom 404 page by adding the id of the umbraco document to show as 404 page in the /config/umbracoSettings.config file. Just add the id to the '/settings/content/errors/error404' element.
");
- Response.Write("For more information, visit information about custom 404 on the umbraco website.
");
- Response.Write("This page is intentionally left ugly ;-)
");
- Response.Write("");
- }
-
- ///
- /// Required method for Designer support - do not modify
- /// the contents of this method with the code editor.
- ///
- private void InitializeComponent()
- {
- }
-
- #endregion
-
-
-
- ///
- /// The preinit event handler
- ///
- public delegate void RequestInitEventHandler(object sender, RequestInitEventArgs e);
- ///
- /// occurs before the umbraco page is initialized for rendering.
- ///
- public static event RequestInitEventHandler BeforeRequestInit;
- ///
- /// Raises the event.
- ///
- /// The instance containing the event data.
- protected internal new virtual void FireBeforeRequestInit(RequestInitEventArgs e)
- {
- if (BeforeRequestInit != null)
- BeforeRequestInit(this, e);
- }
-
- ///
- /// Occurs when [after save].
- ///
- public static event RequestInitEventHandler AfterRequestInit;
- ///
- /// Raises the event.
- ///
- /// The instance containing the event data.
- protected virtual void FireAfterRequestInit(RequestInitEventArgs e)
- {
- if (AfterRequestInit != null)
- AfterRequestInit(this, e);
-
- }
- }
-
- //Request Init Events Arguments
- public class RequestInitEventArgs : System.ComponentModel.CancelEventArgs
- {
- public page Page { get; internal set; }
- public HttpContext Context { get; internal set; }
- public string Url { get; internal set; }
- public int PageId { get; internal set; }
- }
+ Response.Write("This page can be replaced with a custom 404. Check the documentation for \"custom 404\".
");
+ Response.Write("This page is intentionally left ugly ;-)
");
+ Response.Write("