Updated DocumentRequest so that it doesn't actually do the searching, it acts more like a model.

The DocumentSearcher now performs the searching and sets the properties on the DocumentRequest, this
simplifies the dependencies between the contexts. Updated the LookupByNiceUrlTests unit test, now all
initialization is working and the test runs which will be the basis for testing all of the IDocumentLookups.
This commit is contained in:
shannon@ShandemVaio
2012-08-09 04:15:35 +06:00
parent 739de3ef78
commit 2e5db72a09
19 changed files with 587 additions and 454 deletions

View File

@@ -1,5 +1,7 @@
using System;
using System.Linq;
using System.Web;
using System.Xml;
using NUnit.Framework;
using Umbraco.Core;
using Umbraco.Core.Resolving;
@@ -7,40 +9,102 @@ using Umbraco.Tests.Stubs;
using Umbraco.Tests.TestHelpers;
using Umbraco.Web;
using Umbraco.Web.Routing;
using umbraco.BusinessLogic;
using umbraco.cms.businesslogic.cache;
using umbraco.cms.businesslogic.template;
namespace Umbraco.Tests.DocumentLookups
{
[TestFixture]
[TestFixture, RequiresSTA]
public abstract class BaseTest
{
[SetUp]
public virtual void Initialize()
{
TestHelper.SetupLog4NetForTests();
TestHelper.InitializeDatabase();
Resolution.Freeze();
}
[TearDown]
public virtual void TearDown()
{
ActionsResolver.Reset();
//reset the context on global settings
Umbraco.Core.Configuration.GlobalSettings.HttpContext = null;
Resolution.IsFrozen = false;
TestHelper.ClearDatabase();
Cache.ClearAllCache();
}
protected FakeHttpContextFactory GetHttpContextFactory(string url)
{
var factory = new FakeHttpContextFactory(url);
//set the state helper
StateHelper.HttpContext = factory.HttpContext;
return factory;
}
protected UmbracoContext GetUmbracoContext(string url)
private UmbracoContext GetUmbracoContext(string url, Template template)
{
return new UmbracoContext(
var ctx = new UmbracoContext(
GetHttpContextFactory(url).HttpContext,
new ApplicationContext(),
new NullRoutesCache());
new FakeRoutesCache());
SetupUmbracoContextForTest(ctx, template);
return ctx;
}
protected RoutingContext GetRoutingContext(string url, Template template)
{
var umbracoContext = GetUmbracoContext(url, template);
var contentStore = new ContentStore(umbracoContext);
var niceUrls = new NiceUrlProvider(contentStore, umbracoContext);
var routingRequest = new RoutingContext(
umbracoContext,
Enumerable.Empty<IDocumentLookup>(),
new FakeLastChanceLookup(),
contentStore,
niceUrls);
return routingRequest;
}
/// <summary>
/// Initlializes the UmbracoContext with specific XML
/// </summary>
/// <param name="umbracoContext"></param>
/// <param name="template"></param>
protected void SetupUmbracoContextForTest(UmbracoContext umbracoContext, Template template)
{
umbracoContext.GetXmlDelegate = () =>
{
var xDoc = new XmlDocument();
//create a custom xml structure to return
xDoc.LoadXml(@"<?xml version=""1.0"" encoding=""utf-8""?><!DOCTYPE root[
<!ELEMENT Home ANY>
<!ATTLIST Home id ID #REQUIRED>
]>
<root id=""-1"">
<Home id=""1046"" parentID=""-1"" level=""1"" writerID=""0"" creatorID=""0"" nodeType=""1044"" template=""" + template.Id + @""" sortOrder=""2"" createDate=""2012-06-12T14:13:17"" updateDate=""2012-07-20T18:50:43"" nodeName=""Home"" urlName=""home"" writerName=""admin"" creatorName=""admin"" path=""-1,1046"" isDoc=""""><content><![CDATA[]]></content>
<Home id=""1173"" parentID=""1046"" level=""2"" writerID=""0"" creatorID=""0"" nodeType=""1044"" template=""" + template.Id + @""" sortOrder=""1"" createDate=""2012-07-20T18:06:45"" updateDate=""2012-07-20T19:07:31"" nodeName=""Sub1"" urlName=""sub1"" writerName=""admin"" creatorName=""admin"" path=""-1,1046,1173"" isDoc=""""><content><![CDATA[]]></content>
<Home id=""1174"" parentID=""1173"" level=""3"" writerID=""0"" creatorID=""0"" nodeType=""1044"" template=""" + template.Id + @""" sortOrder=""1"" createDate=""2012-07-20T18:07:54"" updateDate=""2012-07-20T19:10:27"" nodeName=""Sub2"" urlName=""sub2"" writerName=""admin"" creatorName=""admin"" path=""-1,1046,1173,1174"" isDoc=""""><content><![CDATA[]]></content>
</Home>
<Home id=""1176"" parentID=""1173"" level=""3"" writerID=""0"" creatorID=""0"" nodeType=""1044"" template=""" + template.Id + @""" sortOrder=""2"" createDate=""2012-07-20T18:08:08"" updateDate=""2012-07-20T19:10:52"" nodeName=""Sub 3"" urlName=""sub-3"" writerName=""admin"" creatorName=""admin"" path=""-1,1046,1173,1176"" isDoc=""""><content><![CDATA[]]></content>
</Home>
</Home>
<Home id=""1175"" parentID=""1046"" level=""2"" writerID=""0"" creatorID=""0"" nodeType=""1044"" template=""" + template.Id + @""" sortOrder=""2"" createDate=""2012-07-20T18:08:01"" updateDate=""2012-07-20T18:49:32"" nodeName=""Sub 2"" urlName=""sub-2"" writerName=""admin"" creatorName=""admin"" path=""-1,1046,1175"" isDoc=""""><content><![CDATA[]]></content>
</Home>
</Home>
<Home id=""1172"" parentID=""-1"" level=""1"" writerID=""0"" creatorID=""0"" nodeType=""1044"" template=""" + template.Id + @""" sortOrder=""3"" createDate=""2012-07-16T15:26:59"" updateDate=""2012-07-18T14:23:35"" nodeName=""Test"" urlName=""test"" writerName=""admin"" creatorName=""admin"" path=""-1,1172"" isDoc="""" />
</root>");
//return the custom x doc
return xDoc;
};
}
}
@@ -52,14 +116,16 @@ namespace Umbraco.Tests.DocumentLookups
[Test]
public void Test_Default_ASPX()
{
var urlAsString = "http://localhost/default.aspx";
var ctx = GetUmbracoContext(urlAsString);
var cleanUrl = new Uri(urlAsString);
var path = ctx.RequestUrl.AbsolutePath.ToLower();
var urlAsString = "/default.aspx";
var template = Template.MakeNew("test", new User(0));
var routingContext = GetRoutingContext(urlAsString, template);
var cleanUrl = routingContext.UmbracoContext.HttpContext.Request.Url;
var path = routingContext.UmbracoContext.RequestUrl.AbsolutePath.ToLower();
UmbracoModule.LegacyCleanUmbPageFromQueryString(ref cleanUrl, ref path);
var docRequest = new DocumentRequest(cleanUrl, ctx);
var lookup = new LookupByNiceUrl();
var docRequest = new DocumentRequest(cleanUrl, routingContext);
var lookup = new LookupByNiceUrl();
var result = lookup.TrySetDocument(docRequest);
}

View File

@@ -0,0 +1,12 @@
using Umbraco.Web.Routing;
namespace Umbraco.Tests.Stubs
{
internal class FakeLastChanceLookup : IDocumentLastChanceLookup
{
public bool TrySetDocument(DocumentRequest docRequest)
{
return false;
}
}
}

View File

@@ -5,7 +5,7 @@ namespace Umbraco.Tests.Stubs
/// <summary>
/// Used for testing, does not cache anything
/// </summary>
public class NullRoutesCache : IRoutesCache
public class FakeRoutesCache : IRoutesCache
{
public void Store(int nodeId, string route)
{

View File

@@ -1,15 +1,48 @@
using System;
using System.Configuration;
using System.IO;
using System.Reflection;
using SqlCE4Umbraco;
using log4net.Config;
using umbraco;
using umbraco.DataLayer;
namespace Umbraco.Tests.TestHelpers
{
{
/// <summary>
/// Common helper properties and methods useful to testing
/// </summary>
public static class TestHelper
{
/// <summary>
/// Clears an initialized database
/// </summary>
public static void ClearDatabase()
{
var dataHelper = DataLayerHelper.CreateSqlHelper(GlobalSettings.DbDSN) as SqlCEHelper;
if (dataHelper == null)
throw new InvalidOperationException("The sql helper for unit tests must be of type SqlCEHelper, check the ensure the connection string used for this test is set to use SQLCE");
dataHelper.ClearDatabase();
}
/// <summary>
/// Initializes a new database
/// </summary>
public static void InitializeDatabase()
{
ConfigurationManager.AppSettings.Set("umbracoDbDSN", @"datalayer=SQLCE4Umbraco.SqlCEHelper,SQLCE4Umbraco;data source=|DataDirectory|\Umbraco.sdf");
ClearDatabase();
var dataHelper = DataLayerHelper.CreateSqlHelper(GlobalSettings.DbDSN);
var installer = dataHelper.Utility.CreateInstaller();
if (installer.CanConnect)
{
installer.Install();
}
}
/// <summary>
/// Gets the current assembly directory.
/// </summary>

View File

@@ -67,7 +67,8 @@
<Compile Include="PackageActionsResolverTests.cs" />
<Compile Include="PluginManagerExtensions.cs" />
<Compile Include="PluginManagerTests.cs" />
<Compile Include="Stubs\NullRoutesCache.cs" />
<Compile Include="Stubs\FakeLastChanceLookup.cs" />
<Compile Include="Stubs\FakeRoutesCache.cs" />
<Compile Include="TestHelpers\TestHelper.cs" />
<Compile Include="EnumerableExtensionsTests.cs" />
<Compile Include="PartialTrust\AbstractPartialTrustFixture.cs" />

View File

@@ -41,7 +41,7 @@ namespace Umbraco.Tests
ConfigurationManager.AppSettings.Set("umbracoReservedPaths", "~/umbraco,~/install/");
ConfigurationManager.AppSettings.Set("umbracoReservedUrls", "~/config/splashes/booting.aspx,~/install/default.aspx,~/config/splashes/noNodes.aspx,~/VSEnterpriseHelper.axd");
Cache.ClearAllCache();
InitializeDatabase();
TestHelper.InitializeDatabase();
//create the not found handlers config
using(var sw = File.CreateText(IOHelper.MapPath(SystemFiles.NotFoundhandlersConfig, false)))
@@ -67,32 +67,10 @@ namespace Umbraco.Tests
ConfigurationManager.AppSettings.Set("umbracoConfigurationStatus", "");
ConfigurationManager.AppSettings.Set("umbracoReservedPaths", "");
ConfigurationManager.AppSettings.Set("umbracoReservedUrls", "");
ClearDatabase();
TestHelper.ClearDatabase();
Cache.ClearAllCache();
}
private void ClearDatabase()
{
var dataHelper = DataLayerHelper.CreateSqlHelper(GlobalSettings.DbDSN) as SqlCEHelper;
if (dataHelper == null)
throw new InvalidOperationException("The sql helper for unit tests must be of type SqlCEHelper, check the ensure the connection string used for this test is set to use SQLCE");
dataHelper.ClearDatabase();
}
private void InitializeDatabase()
{
ConfigurationManager.AppSettings.Set("umbracoDbDSN", @"datalayer=SQLCE4Umbraco.SqlCEHelper,SQLCE4Umbraco;data source=|DataDirectory|\Umbraco.sdf");
ClearDatabase();
var dataHelper = DataLayerHelper.CreateSqlHelper(GlobalSettings.DbDSN);
var installer = dataHelper.Utility.CreateInstaller();
if (installer.CanConnect)
{
installer.Install();
}
}
/// <summary>
/// Initlializes the UmbracoContext with specific XML
/// </summary>

View File

@@ -21,7 +21,7 @@ namespace Umbraco.Web.Mvc
/// </summary>
protected UmbracoContext UmbracoContext
{
get { return DocumentRequest.UmbracoContext; }
get { return DocumentRequest.RoutingContext.UmbracoContext; }
}
//TODO: make this protected once we make DocumentRequest not internal after we figure out what it should actually contain

View File

@@ -0,0 +1,21 @@
using System;
namespace Umbraco.Web.Routing
{
///// <summary>
///// Abstract DocumentLookup class
///// </summary>
//internal abstract class DocumentLookupBase : IDocumentLookup
//{
// public bool TrySetDocument(DocumentRequest docRequest)
// {
// if (docRequest == null) throw new ArgumentNullException("docRequest");
// if (docRequest.RoutingContext == null) throw new ArgumentNullException("docRequest.RoutingContext");
// if (docRequest.RoutingContext.UmbracoContext == null) throw new ArgumentNullException("docRequest.UmbracoContext");
// return TrySetDocument(docRequest, docRequest.RoutingContext, docRequest.UmbracoContext);
// }
// protected abstract bool TrySetDocument(DocumentRequest docRequest, RoutingContext routingContext, UmbracoContext umbracoContext);
//}
}

View File

@@ -13,25 +13,20 @@ using umbraco.NodeFactory;
using umbraco.cms.businesslogic.web;
using umbraco.cms.businesslogic.template;
using umbraco.cms.businesslogic.member;
using umbraco.cms.businesslogic.language;
using umbraco.interfaces;
namespace Umbraco.Web.Routing
{
/// <summary>
/// represents a request for one specified Umbraco document to be rendered
/// by one specified template, using one particular culture.
/// </summary>
internal class DocumentRequest
{
public DocumentRequest(Uri uri, UmbracoContext umbracoContext)
public DocumentRequest(Uri uri, RoutingContext routingContext)
{
this.Uri = uri;
RoutingContext = umbracoContext.RoutingContext;
UmbracoContext = umbracoContext;
RoutingContext = routingContext;
}
/// <summary>
@@ -52,9 +47,7 @@ namespace Umbraco.Web.Routing
/// Returns the current RoutingContext
/// </summary>
public RoutingContext RoutingContext { get; private set; }
public UmbracoContext UmbracoContext { get; private set; }
/// <summary>
/// The cleaned up Uri used for routing
/// </summary>
@@ -63,9 +56,9 @@ namespace Umbraco.Web.Routing
/// <summary>
/// Gets or sets the document request's domain.
/// </summary>
public Domain Domain { get; private set; }
public Domain Domain { get; internal set; }
public Uri DomainUri { get; private set; }
public Uri DomainUri { get; internal set; }
/// <summary>
/// Gets a value indicating whether the document request has a domain.
@@ -158,7 +151,7 @@ namespace Umbraco.Web.Routing
/// <summary>
/// Gets or sets a value indicating whether the requested document could not be found.
/// </summary>
public bool Is404 { get; private set; }
public bool Is404 { get; internal set; }
/// <summary>
/// Gets a value indicating whether the document request triggers a redirect.
@@ -171,326 +164,6 @@ namespace Umbraco.Web.Routing
public string RedirectUrl { get; set; }
#endregion
#region Lookup
/// <summary>
/// Determines the site root (if any) matching the http request.
/// </summary>
/// <returns>A value indicating whether a domain was found.</returns>
internal bool LookupDomain()
{
const string tracePrefix = "LookupDomain: ";
// note - we are not handling schemes nor ports here.
LogHelper.Debug<DocumentRequest>("{0}Uri=\"{1}\"", () => tracePrefix, () => this.Uri);
// try to find a domain matching the current request
var domainAndUri = DomainHelper.DomainMatch(Domain.GetDomains(), UmbracoContext.UmbracoUrl, false);
// handle domain
if (domainAndUri != null)
{
// matching an existing domain
LogHelper.Debug<DocumentRequest>("{0}Matches domain=\"{1}\", rootId={2}, culture=\"{3}\"",
() => tracePrefix,
() => domainAndUri.Domain.Name,
() => domainAndUri.Domain.RootNodeId,
() => domainAndUri.Domain.Language.CultureAlias);
this.Domain = domainAndUri.Domain;
this.DomainUri = domainAndUri.Uri;
this.Culture = new CultureInfo(domainAndUri.Domain.Language.CultureAlias);
// canonical? not implemented at the moment
// if (...)
// {
// this.RedirectUrl = "...";
// return true;
// }
}
else
{
// not matching any existing domain
LogHelper.Debug<DocumentRequest>("{0}Matches no domain", () => tracePrefix);
var defaultLanguage = Language.GetAllAsList().FirstOrDefault();
this.Culture = defaultLanguage == null ? CultureInfo.CurrentUICulture : new CultureInfo(defaultLanguage.CultureAlias);
}
LogHelper.Debug<DocumentRequest>("{0}Culture=\"{1}\"", () => tracePrefix, () => this.Culture.Name);
return this.Domain != null;
}
/// <summary>
/// Determines the Umbraco document (if any) matching the http request.
/// </summary>
/// <returns>A value indicating whether a document and template nave been found.</returns>
internal bool LookupDocument()
{
const string tracePrefix = "LookupDocument: ";
LogHelper.Debug<DocumentRequest>("{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
using (DisposableTimer.DebugDuration<PluginManager>(
string.Format("{0}Begin resolvers", tracePrefix),
string.Format("{0}End resolvers, {1}", tracePrefix, (this.HasNode ? "a document was found" : "no document was found"))))
{
RoutingContext.DocumentLookups.Any(lookup => lookup.TrySetDocument(this));
}
// fixme - not handling umbracoRedirect
// should come after internal redirects
// so after ResolveDocument2() => docreq.IsRedirect => handled by the module!
// handle not-found, redirects, access, template
LookupDocument2();
// handle umbracoRedirect (moved from umbraco.page)
FollowRedirect();
bool resolved = this.HasNode && this.HasTemplate;
return resolved;
}
/// <summary>
/// Performs the document resolution second pass.
/// </summary>
/// <remarks>The second pass consists in handling "not found", internal redirects, access validation, and template.</remarks>
private void LookupDocument2()
{
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
int i = 0, j = 0;
const int maxLoop = 12;
do
{
LogHelper.Debug<DocumentRequest>("{0}{1}", () => tracePrefix, () => (i == 0 ? "Begin" : "Loop"));
// handle not found
if (!this.HasNode)
{
this.Is404 = true;
LogHelper.Debug<DocumentRequest>("{0}No document, try last chance lookup", () => tracePrefix);
// if it fails then give up, there isn't much more that we can do
var lastChance = RoutingContext.DocumentLastChanceLookup;
if (lastChance == null || !lastChance.TrySetDocument(this))
{
LogHelper.Debug<DocumentRequest>("{0}Failed to find a document, give up", () => tracePrefix);
break;
}
else
{
LogHelper.Debug<DocumentRequest>("{0}Found a document", () => tracePrefix);
}
}
// follow internal redirects as long as it's not running out of control ie infinite loop of some sort
j = 0;
while (FollowInternalRedirects() && j++ < maxLoop) ;
if (j == maxLoop) // we're running out of control
break;
// ensure access
if (this.HasNode)
EnsureNodeAccess();
// resolve template
if (this.HasNode)
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
// as long as it's not running out of control ie infinite loop of some sort
} while (!this.HasNode && i++ < maxLoop);
if (i == maxLoop || j == maxLoop)
{
LogHelper.Debug<DocumentRequest>("{0}Looks like we're running into an infinite loop, abort", () => tracePrefix);
this.XmlNode = null;
}
LogHelper.Debug<DocumentRequest>("{0}End", () => tracePrefix);
}
/// <summary>
/// Follows internal redirections through the <c>umbracoInternalRedirectId</c> document property.
/// </summary>
/// <returns>A value indicating whether redirection took place and led to a new published document.</returns>
/// <remarks>Redirecting to a different site root and/or culture will not pick the new site root nor the new culture.</remarks>
private bool FollowInternalRedirects()
{
const string tracePrefix = "FollowInternalRedirects: ";
if (this.XmlNode == null)
throw new InvalidOperationException("There is no node.");
bool redirect = false;
string internalRedirect = RoutingContext.ContentStore.GetNodeProperty(this.XmlNode, "umbracoInternalRedirectId");
if (!string.IsNullOrWhiteSpace(internalRedirect))
{
LogHelper.Debug<DocumentRequest>("{0}Found umbracoInternalRedirectId={1}", () => tracePrefix, () => internalRedirect);
int internalRedirectId;
if (!int.TryParse(internalRedirect, out internalRedirectId))
internalRedirectId = -1;
if (internalRedirectId <= 0)
{
// bad redirect
this.XmlNode = null;
LogHelper.Debug<DocumentRequest>("{0}Failed to redirect to id={1}: invalid value", () => tracePrefix, () => internalRedirect);
}
else if (internalRedirectId == this.NodeId)
{
// redirect to self
LogHelper.Debug<DocumentRequest>("{0}Redirecting to self, ignore", () => tracePrefix);
}
else
{
// redirect to another page
var node = RoutingContext.ContentStore.GetNodeById(internalRedirectId);
this.XmlNode = node;
if (node != null)
{
redirect = true;
LogHelper.Debug<DocumentRequest>("{0}Redirecting to id={1}", () => tracePrefix, () => internalRedirectId);
}
else
{
LogHelper.Debug<DocumentRequest>("{0}Failed to redirect to id={1}: no such published document", () => tracePrefix, () => internalRedirectId);
}
}
}
return redirect;
}
/// <summary>
/// Ensures that access to current node is permitted.
/// </summary>
/// <remarks>Redirecting to a different site root and/or culture will not pick the new site root nor the new culture.</remarks>
private void EnsureNodeAccess()
{
const string tracePrefix = "EnsurePageAccess: ";
if (this.XmlNode == null)
throw new InvalidOperationException("There is no node.");
var path = RoutingContext.ContentStore.GetNodeProperty(this.XmlNode, "@path");
if (Access.IsProtected(this.NodeId, path))
{
LogHelper.Debug<DocumentRequest>("{0}Page is protected, check for access", () => tracePrefix);
var user = System.Web.Security.Membership.GetUser();
if (user == null || !Member.IsLoggedOn())
{
LogHelper.Debug<DocumentRequest>("{0}Not logged in, redirect to login page", () => tracePrefix);
var loginPageId = Access.GetLoginPage(path);
if (loginPageId != this.NodeId)
this.XmlNode = RoutingContext.ContentStore.GetNodeById(loginPageId);
}
else if (!Access.HasAccces(this.NodeId, user.ProviderUserKey))
{
LogHelper.Debug<DocumentRequest>("{0}Current member has not access, redirect to error page", () => tracePrefix);
var errorPageId = Access.GetErrorPage(path);
if (errorPageId != this.NodeId)
this.XmlNode = RoutingContext.ContentStore.GetNodeById(errorPageId);
}
else
{
LogHelper.Debug<DocumentRequest>("{0}Current member has access", () => tracePrefix);
}
}
else
{
LogHelper.Debug<DocumentRequest>("{0}Page is not protected", () => tracePrefix);
}
}
/// <summary>
/// Resolves a template for the current node.
/// </summary>
private void LookupTemplate()
{
const string tracePrefix = "LookupTemplate: ";
if (this.XmlNode == null)
throw new InvalidOperationException("There is no node.");
var templateAlias = UmbracoContext.HttpContext.Request.QueryString["altTemplate"];
if (string.IsNullOrWhiteSpace(templateAlias))
templateAlias = UmbracoContext.HttpContext.Request.Form["altTemplate"];
// fixme - we might want to support cookies?!? NO but provide a hook to change the template
if (!this.HasTemplate || !string.IsNullOrWhiteSpace(templateAlias))
{
if (string.IsNullOrWhiteSpace(templateAlias))
{
templateAlias = RoutingContext.ContentStore.GetNodeProperty(this.XmlNode, "@template");
LogHelper.Debug<DocumentRequest>("{0}Look for template id={1}", () => tracePrefix, () => templateAlias);
int templateId;
if (!int.TryParse(templateAlias, out templateId))
templateId = 0;
this.Template = templateId > 0 ? new Template(templateId) : null;
}
else
{
LogHelper.Debug<DocumentRequest>("{0}Look for template alias=\"{1}\" (altTemplate)", () => tracePrefix, () => templateAlias);
this.Template = Template.GetByAlias(templateAlias);
}
if (!this.HasTemplate)
{
LogHelper.Debug<DocumentRequest>("{0}No template was found", () => tracePrefix);
//TODO: I like the idea of this new setting, but lets get this in to the core at a later time, for now lets just get the basics working.
//if (Settings.HandleMissingTemplateAs404)
//{
// this.Node = null;
// LogHelper.Debug<DocumentRequest>("{0}Assume page not found (404)", tracePrefix);
//}
// else we have no template
// and there isn't much more we can do about it
}
else
{
LogHelper.Debug<DocumentRequest>("{0}Found", () => tracePrefix);
}
}
}
/// <summary>
/// Follows external redirection through <c>umbracoRedirect</c> document property.
/// </summary>
private void FollowRedirect()
{
if (this.HasNode)
{
int redirectId;
if (!int.TryParse(RoutingContext.ContentStore.GetNodeProperty(this.XmlNode, "umbracoRedirect"), out redirectId))
redirectId = -1;
string redirectUrl = "#";
if (redirectId > 0)
redirectUrl = RoutingContext.NiceUrlProvider.GetNiceUrl(redirectId);
if (redirectUrl != "#")
this.RedirectUrl = redirectUrl;
}
}
#endregion
}
}

View File

@@ -0,0 +1,343 @@
using System;
using System.Globalization;
using System.Linq;
using Umbraco.Core;
using Umbraco.Core.Logging;
using umbraco.cms.businesslogic.language;
using umbraco.cms.businesslogic.member;
using umbraco.cms.businesslogic.template;
using umbraco.cms.businesslogic.web;
namespace Umbraco.Web.Routing
{
internal class DocumentSearcher
{
private readonly DocumentRequest _documentRequest;
private readonly UmbracoContext _umbracoContext;
private readonly RoutingContext _routingContext;
public DocumentSearcher(DocumentRequest documentRequest)
{
_documentRequest = documentRequest;
_umbracoContext = documentRequest.RoutingContext.UmbracoContext;
_routingContext = documentRequest.RoutingContext;
}
/// <summary>
/// Determines the site root (if any) matching the http request.
/// </summary>
/// <returns>A value indicating whether a domain was found.</returns>
internal bool LookupDomain()
{
const string tracePrefix = "LookupDomain: ";
// note - we are not handling schemes nor ports here.
LogHelper.Debug<DocumentRequest>("{0}Uri=\"{1}\"", () => tracePrefix, () => _documentRequest.Uri);
// try to find a domain matching the current request
var domainAndUri = DomainHelper.DomainMatch(Domain.GetDomains(), _umbracoContext.UmbracoUrl, false);
// handle domain
if (domainAndUri != null)
{
// matching an existing domain
LogHelper.Debug<DocumentRequest>("{0}Matches domain=\"{1}\", rootId={2}, culture=\"{3}\"",
() => tracePrefix,
() => domainAndUri.Domain.Name,
() => domainAndUri.Domain.RootNodeId,
() => domainAndUri.Domain.Language.CultureAlias);
_documentRequest.Domain = domainAndUri.Domain;
_documentRequest.DomainUri = domainAndUri.Uri;
_documentRequest.Culture = new CultureInfo(domainAndUri.Domain.Language.CultureAlias);
// canonical? not implemented at the moment
// if (...)
// {
// this.RedirectUrl = "...";
// return true;
// }
}
else
{
// not matching any existing domain
LogHelper.Debug<DocumentRequest>("{0}Matches no domain", () => tracePrefix);
var defaultLanguage = Language.GetAllAsList().FirstOrDefault();
_documentRequest.Culture = defaultLanguage == null ? CultureInfo.CurrentUICulture : new CultureInfo(defaultLanguage.CultureAlias);
}
LogHelper.Debug<DocumentRequest>("{0}Culture=\"{1}\"", () => tracePrefix, () => _documentRequest.Culture.Name);
return _documentRequest.Domain != null;
}
/// <summary>
/// Determines the Umbraco document (if any) matching the http request.
/// </summary>
/// <returns>A value indicating whether a document and template nave been found.</returns>
internal bool LookupDocument()
{
const string tracePrefix = "LookupDocument: ";
LogHelper.Debug<DocumentRequest>("{0}Path=\"{1}\"", () => tracePrefix, () => _documentRequest.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
using (DisposableTimer.DebugDuration<PluginManager>(
string.Format("{0}Begin resolvers", tracePrefix),
string.Format("{0}End resolvers, {1}", tracePrefix, (_documentRequest.HasNode ? "a document was found" : "no document was found"))))
{
_routingContext.DocumentLookups.Any(lookup => lookup.TrySetDocument(_documentRequest));
}
// fixme - not handling umbracoRedirect
// should come after internal redirects
// so after ResolveDocument2() => docreq.IsRedirect => handled by the module!
// handle not-found, redirects, access, template
LookupDocument2();
// handle umbracoRedirect (moved from umbraco.page)
FollowRedirect();
bool resolved = _documentRequest.HasNode && _documentRequest.HasTemplate;
return resolved;
}
/// <summary>
/// Performs the document resolution second pass.
/// </summary>
/// <remarks>The second pass consists in handling "not found", internal redirects, access validation, and template.</remarks>
private void LookupDocument2()
{
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
int i = 0, j = 0;
const int maxLoop = 12;
do
{
LogHelper.Debug<DocumentRequest>("{0}{1}", () => tracePrefix, () => (i == 0 ? "Begin" : "Loop"));
// handle not found
if (!_documentRequest.HasNode)
{
_documentRequest.Is404 = true;
LogHelper.Debug<DocumentRequest>("{0}No document, try last chance lookup", () => tracePrefix);
// if it fails then give up, there isn't much more that we can do
var lastChance = _routingContext.DocumentLastChanceLookup;
if (lastChance == null || !lastChance.TrySetDocument(_documentRequest))
{
LogHelper.Debug<DocumentRequest>("{0}Failed to find a document, give up", () => tracePrefix);
break;
}
else
{
LogHelper.Debug<DocumentRequest>("{0}Found a document", () => tracePrefix);
}
}
// follow internal redirects as long as it's not running out of control ie infinite loop of some sort
j = 0;
while (FollowInternalRedirects() && j++ < maxLoop) ;
if (j == maxLoop) // we're running out of control
break;
// ensure access
if (_documentRequest.HasNode)
EnsureNodeAccess();
// resolve template
if (_documentRequest.HasNode)
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
// as long as it's not running out of control ie infinite loop of some sort
} while (!_documentRequest.HasNode && i++ < maxLoop);
if (i == maxLoop || j == maxLoop)
{
LogHelper.Debug<DocumentRequest>("{0}Looks like we're running into an infinite loop, abort", () => tracePrefix);
_documentRequest.XmlNode = null;
}
LogHelper.Debug<DocumentRequest>("{0}End", () => tracePrefix);
}
/// <summary>
/// Follows internal redirections through the <c>umbracoInternalRedirectId</c> document property.
/// </summary>
/// <returns>A value indicating whether redirection took place and led to a new published document.</returns>
/// <remarks>Redirecting to a different site root and/or culture will not pick the new site root nor the new culture.</remarks>
private bool FollowInternalRedirects()
{
const string tracePrefix = "FollowInternalRedirects: ";
if (_documentRequest.XmlNode == null)
throw new InvalidOperationException("There is no node.");
bool redirect = false;
string internalRedirect = _routingContext.ContentStore.GetNodeProperty(_documentRequest.XmlNode, "umbracoInternalRedirectId");
if (!string.IsNullOrWhiteSpace(internalRedirect))
{
LogHelper.Debug<DocumentRequest>("{0}Found umbracoInternalRedirectId={1}", () => tracePrefix, () => internalRedirect);
int internalRedirectId;
if (!int.TryParse(internalRedirect, out internalRedirectId))
internalRedirectId = -1;
if (internalRedirectId <= 0)
{
// bad redirect
_documentRequest.XmlNode = null;
LogHelper.Debug<DocumentRequest>("{0}Failed to redirect to id={1}: invalid value", () => tracePrefix, () => internalRedirect);
}
else if (internalRedirectId == _documentRequest.NodeId)
{
// redirect to self
LogHelper.Debug<DocumentRequest>("{0}Redirecting to self, ignore", () => tracePrefix);
}
else
{
// redirect to another page
var node = _routingContext.ContentStore.GetNodeById(internalRedirectId);
_documentRequest.XmlNode = node;
if (node != null)
{
redirect = true;
LogHelper.Debug<DocumentRequest>("{0}Redirecting to id={1}", () => tracePrefix, () => internalRedirectId);
}
else
{
LogHelper.Debug<DocumentRequest>("{0}Failed to redirect to id={1}: no such published document", () => tracePrefix, () => internalRedirectId);
}
}
}
return redirect;
}
/// <summary>
/// Ensures that access to current node is permitted.
/// </summary>
/// <remarks>Redirecting to a different site root and/or culture will not pick the new site root nor the new culture.</remarks>
private void EnsureNodeAccess()
{
const string tracePrefix = "EnsurePageAccess: ";
if (_documentRequest.XmlNode == null)
throw new InvalidOperationException("There is no node.");
var path = _routingContext.ContentStore.GetNodeProperty(_documentRequest.XmlNode, "@path");
if (Access.IsProtected(_documentRequest.NodeId, path))
{
LogHelper.Debug<DocumentRequest>("{0}Page is protected, check for access", () => tracePrefix);
var user = System.Web.Security.Membership.GetUser();
if (user == null || !Member.IsLoggedOn())
{
LogHelper.Debug<DocumentRequest>("{0}Not logged in, redirect to login page", () => tracePrefix);
var loginPageId = Access.GetLoginPage(path);
if (loginPageId != _documentRequest.NodeId)
_documentRequest.XmlNode = _routingContext.ContentStore.GetNodeById(loginPageId);
}
else if (!Access.HasAccces(_documentRequest.NodeId, user.ProviderUserKey))
{
LogHelper.Debug<DocumentRequest>("{0}Current member has not access, redirect to error page", () => tracePrefix);
var errorPageId = Access.GetErrorPage(path);
if (errorPageId != _documentRequest.NodeId)
_documentRequest.XmlNode = _routingContext.ContentStore.GetNodeById(errorPageId);
}
else
{
LogHelper.Debug<DocumentRequest>("{0}Current member has access", () => tracePrefix);
}
}
else
{
LogHelper.Debug<DocumentRequest>("{0}Page is not protected", () => tracePrefix);
}
}
/// <summary>
/// Resolves a template for the current node.
/// </summary>
private void LookupTemplate()
{
const string tracePrefix = "LookupTemplate: ";
if (_documentRequest.XmlNode == null)
throw new InvalidOperationException("There is no node.");
var templateAlias = _umbracoContext.HttpContext.Request.QueryString["altTemplate"];
if (string.IsNullOrWhiteSpace(templateAlias))
templateAlias = _umbracoContext.HttpContext.Request.Form["altTemplate"];
// fixme - we might want to support cookies?!? NO but provide a hook to change the template
if (!_documentRequest.HasTemplate || !string.IsNullOrWhiteSpace(templateAlias))
{
if (string.IsNullOrWhiteSpace(templateAlias))
{
templateAlias = _routingContext.ContentStore.GetNodeProperty(_documentRequest.XmlNode, "@template");
LogHelper.Debug<DocumentRequest>("{0}Look for template id={1}", () => tracePrefix, () => templateAlias);
int templateId;
if (!int.TryParse(templateAlias, out templateId))
templateId = 0;
_documentRequest.Template = templateId > 0 ? new Template(templateId) : null;
}
else
{
LogHelper.Debug<DocumentRequest>("{0}Look for template alias=\"{1}\" (altTemplate)", () => tracePrefix, () => templateAlias);
_documentRequest.Template = Template.GetByAlias(templateAlias);
}
if (!_documentRequest.HasTemplate)
{
LogHelper.Debug<DocumentRequest>("{0}No template was found", () => tracePrefix);
//TODO: I like the idea of this new setting, but lets get this in to the core at a later time, for now lets just get the basics working.
//if (Settings.HandleMissingTemplateAs404)
//{
// this.Node = null;
// LogHelper.Debug<DocumentRequest>("{0}Assume page not found (404)", tracePrefix);
//}
// else we have no template
// and there isn't much more we can do about it
}
else
{
LogHelper.Debug<DocumentRequest>("{0}Found", () => tracePrefix);
}
}
}
/// <summary>
/// Follows external redirection through <c>umbracoRedirect</c> document property.
/// </summary>
private void FollowRedirect()
{
if (_documentRequest.HasNode)
{
int redirectId;
if (!int.TryParse(_routingContext.ContentStore.GetNodeProperty(_documentRequest.XmlNode, "umbracoRedirect"), out redirectId))
redirectId = -1;
string redirectUrl = "#";
if (redirectId > 0)
redirectUrl = _routingContext.NiceUrlProvider.GetNiceUrl(redirectId);
if (redirectUrl != "#")
_documentRequest.RedirectUrl = redirectUrl;
}
}
}
}

View File

@@ -13,32 +13,31 @@ namespace Umbraco.Web.Routing
/// <para>The alias is the full path to the document. There can be more than one alias, separated by commas.</para>
/// </remarks>
//[ResolutionWeight(50)]
internal class LookupByAlias : IDocumentLookup
internal class LookupByAlias : IDocumentLookup
{
/// <summary>
/// Tries to find and assign an Umbraco document to a <c>DocumentRequest</c>.
/// </summary>
/// <param name="docreq">The <c>DocumentRequest</c>.</param>
/// <param name="docRequest">The <c>DocumentRequest</c>.</param>
/// <returns>A value indicating whether an Umbraco document was found and assigned.</returns>
public bool TrySetDocument(DocumentRequest docreq)
{
XmlNode node = null;
public bool TrySetDocument(DocumentRequest docRequest)
{
XmlNode node = null;
if (docreq.Uri.AbsolutePath != "/") // no alias if "/"
{
node = docreq.RoutingContext.ContentStore.GetNodeByUrlAlias(docreq.HasDomain ? docreq.Domain.RootNodeId : 0, docreq.Uri.AbsolutePath);
if (node != null)
{
LogHelper.Debug<LookupByAlias>("Path \"{0}\" is an alias for id={1}", () => docreq.Uri.AbsolutePath, () => docreq.NodeId);
docreq.XmlNode = node;
}
}
if (docRequest.Uri.AbsolutePath != "/") // no alias if "/"
{
node = docRequest.RoutingContext.ContentStore.GetNodeByUrlAlias(docRequest.HasDomain ? docRequest.Domain.RootNodeId : 0, docRequest.Uri.AbsolutePath);
if (node != null)
{
LogHelper.Debug<LookupByAlias>("Path \"{0}\" is an alias for id={1}", () => docRequest.Uri.AbsolutePath, () => docRequest.NodeId);
docRequest.XmlNode = node;
}
}
if (node == null)
if (node == null)
LogHelper.Debug<LookupByAlias>("Not an alias");
return node != null;
}
return node != null;
}
}
}

View File

@@ -13,21 +13,21 @@ namespace Umbraco.Web.Routing
/// <para>Handles <c>/1234</c> where <c>1234</c> is the identified of a document.</para>
/// </remarks>
//[ResolutionWeight(20)]
internal class LookupById : IDocumentLookup
internal class LookupById : IDocumentLookup
{
/// <summary>
/// Tries to find and assign an Umbraco document to a <c>DocumentRequest</c>.
/// </summary>
/// <param name="docreq">The <c>DocumentRequest</c>.</param>
/// <param name="docRequest">The <c>DocumentRequest</c>.</param>
/// <returns>A value indicating whether an Umbraco document was found and assigned.</returns>
public bool TrySetDocument(DocumentRequest docreq)
public bool TrySetDocument(DocumentRequest docRequest)
{
XmlNode node = null;
int nodeId = -1;
if (docreq.Uri.AbsolutePath != "/") // no id if "/"
if (docRequest.Uri.AbsolutePath != "/") // no id if "/"
{
string noSlashPath = docreq.Uri.AbsolutePath.Substring(1);
string noSlashPath = docRequest.Uri.AbsolutePath.Substring(1);
if (!Int32.TryParse(noSlashPath, out nodeId))
nodeId = -1;
@@ -35,11 +35,11 @@ namespace Umbraco.Web.Routing
if (nodeId > 0)
{
LogHelper.Debug<LookupById>("Id={0}", () => nodeId);
node = docreq.RoutingContext.ContentStore.GetNodeById(nodeId);
node = docRequest.RoutingContext.ContentStore.GetNodeById(nodeId);
if (node != null)
{
docreq.XmlNode = node;
LogHelper.Debug<LookupById>("Found node with id={0}", () => docreq.NodeId);
docRequest.XmlNode = node;
LogHelper.Debug<LookupById>("Found node with id={0}", () => docRequest.NodeId);
}
else
{

View File

@@ -12,21 +12,20 @@ namespace Umbraco.Web.Routing
/// <para>Handles <c>/foo/bar</c> where <c>/foo/bar</c> is the nice url of a document.</para>
/// </remarks>
//[ResolutionWeight(10)]
internal class LookupByNiceUrl : IDocumentLookup
internal class LookupByNiceUrl : IDocumentLookup
{
/// <summary>
/// Tries to find and assign an Umbraco document to a <c>DocumentRequest</c>.
/// </summary>
/// <param name="docreq">The <c>DocumentRequest</c>.</param>
/// <param name="docRequest">The <c>DocumentRequest</c>.</param>
/// <returns>A value indicating whether an Umbraco document was found and assigned.</returns>
public virtual bool TrySetDocument(DocumentRequest docreq)
public virtual bool TrySetDocument(DocumentRequest docRequest)
{
string route;
if (docreq.HasDomain)
route = docreq.Domain.RootNodeId.ToString() + DomainHelper.PathRelativeToDomain(docreq.DomainUri, docreq.Uri.AbsolutePath);
if (docRequest.HasDomain)
route = docRequest.Domain.RootNodeId.ToString() + DomainHelper.PathRelativeToDomain(docRequest.DomainUri, docRequest.Uri.AbsolutePath);
else
route = docreq.Uri.AbsolutePath;
route = docRequest.Uri.AbsolutePath;
//TODO: When this is not IIS 7, this does not work for the root '/' request since it comes through as default.aspx!!
// this needs fixing.
@@ -34,7 +33,7 @@ namespace Umbraco.Web.Routing
//format the path, thsi needs fixing when pre-IIS7
route = route.Replace(".aspx", "");
var node = LookupDocumentNode(docreq, route);
var node = LookupDocumentNode(docRequest, route);
return node != null;
}
@@ -49,8 +48,8 @@ namespace Umbraco.Web.Routing
LogHelper.Debug<LookupByNiceUrl>("Test route \"{0}\"", () => route);
//return '0' if in preview mode!
var nodeId = !docreq.UmbracoContext.InPreviewMode
? docreq.UmbracoContext.RoutesCache.GetNodeId(route)
var nodeId = !docreq.RoutingContext.UmbracoContext.InPreviewMode
? docreq.RoutingContext.UmbracoContext.RoutesCache.GetNodeId(route)
: 0;
@@ -65,7 +64,7 @@ namespace Umbraco.Web.Routing
}
else
{
docreq.UmbracoContext.RoutesCache.ClearNode(nodeId);
docreq.RoutingContext.UmbracoContext.RoutesCache.ClearNode(nodeId);
}
}
@@ -78,9 +77,9 @@ namespace Umbraco.Web.Routing
docreq.XmlNode = node;
LogHelper.Debug<LookupByNiceUrl>("Query matches, id={0}", () => docreq.NodeId);
if (!docreq.UmbracoContext.InPreviewMode)
if (!docreq.RoutingContext.UmbracoContext.InPreviewMode)
{
docreq.UmbracoContext.RoutesCache.Store(docreq.NodeId, route); // will not write if previewing
docreq.RoutingContext.UmbracoContext.RoutesCache.Store(docreq.NodeId, route); // will not write if previewing
}
}

View File

@@ -19,20 +19,20 @@ namespace Umbraco.Web.Routing
/// <summary>
/// Tries to find and assign an Umbraco document to a <c>DocumentRequest</c>.
/// </summary>
/// <param name="docreq">The <c>DocumentRequest</c>.</param>
/// <param name="docRequest">The <c>DocumentRequest</c>.</param>
/// <returns>A value indicating whether an Umbraco document was found and assigned.</returns>
/// <remarks>If successful, also assigns the template.</remarks>
public override bool TrySetDocument(DocumentRequest docreq)
public override bool TrySetDocument(DocumentRequest docRequest)
{
XmlNode node = null;
string path = docreq.Uri.AbsolutePath;
string path = docRequest.Uri.AbsolutePath;
if (docreq.HasDomain)
path = DomainHelper.PathRelativeToDomain(docreq.DomainUri, path);
if (docRequest.HasDomain)
path = DomainHelper.PathRelativeToDomain(docRequest.DomainUri, path);
if (path != "/") // no template if "/"
{
var pos = docreq.Uri.AbsolutePath.LastIndexOf('/');
var templateAlias = docreq.Uri.AbsolutePath.Substring(pos + 1);
var pos = docRequest.Uri.AbsolutePath.LastIndexOf('/');
var templateAlias = docRequest.Uri.AbsolutePath.Substring(pos + 1);
path = path.Substring(0, pos);
var template = Template.GetByAlias(templateAlias);
@@ -40,11 +40,11 @@ namespace Umbraco.Web.Routing
{
LogHelper.Debug<LookupByNiceUrlAndTemplate>("Valid template: \"{0}\"", () => templateAlias);
var route = docreq.HasDomain ? (docreq.Domain.RootNodeId.ToString() + path) : path;
node = LookupDocumentNode(docreq, route);
var route = docRequest.HasDomain ? (docRequest.Domain.RootNodeId.ToString() + path) : path;
node = LookupDocumentNode(docRequest, route);
if (node != null)
docreq.Template = template;
docRequest.Template = template;
}
else
{

View File

@@ -15,37 +15,36 @@ namespace Umbraco.Web.Routing
/// We keep it for backward compatility reasons.</para>
/// </remarks>
//[ResolutionWeight(40)]
internal class LookupByProfile : LookupByNiceUrl, IDocumentLookup
internal class LookupByProfile : LookupByNiceUrl
{
/// <summary>
/// Tries to find and assign an Umbraco document to a <c>DocumentRequest</c>.
/// </summary>
/// <param name="docreq">The <c>DocumentRequest</c>.</param>
/// <param name="docRequest">The <c>DocumentRequest</c>.</param>
/// <returns>A value indicating whether an Umbraco document was found and assigned.</returns>
public override bool TrySetDocument(DocumentRequest docreq)
public override bool TrySetDocument(DocumentRequest docRequest)
{
XmlNode node = null;
bool isProfile = false;
var pos = docreq.Uri.AbsolutePath.LastIndexOf('/');
var pos = docRequest.Uri.AbsolutePath.LastIndexOf('/');
if (pos > 0)
{
var memberLogin = docreq.Uri.AbsolutePath.Substring(pos + 1);
var path = docreq.Uri.AbsolutePath.Substring(0, pos);
var memberLogin = docRequest.Uri.AbsolutePath.Substring(pos + 1);
var path = docRequest.Uri.AbsolutePath.Substring(0, pos);
if (path == GlobalSettings.ProfileUrl)
{
isProfile = true;
LogHelper.Debug<LookupByProfile>("Path \"{0}\" is the profile path", () => path);
LogHelper.Debug<LookupByProfile>("Path \"{0}\" is the profile path", () => path);
var route = docreq.HasDomain ? (docreq.Domain.RootNodeId.ToString() + path) : path;
node = LookupDocumentNode(docreq, route);
var route = docRequest.HasDomain ? (docRequest.Domain.RootNodeId.ToString() + path) : path;
node = LookupDocumentNode(docRequest, route);
if (node != null)
{
//TODO: Should be handled by Context Items class manager (http://issues.umbraco.org/issue/U4-61)
docreq.UmbracoContext.HttpContext.Items["umbMemberLogin"] = memberLogin;
docRequest.RoutingContext.UmbracoContext.HttpContext.Items["umbMemberLogin"] = memberLogin;
}
else
{

View File

@@ -12,29 +12,28 @@ namespace Umbraco.Web.Routing
/// <summary>
/// Initializes a new instance of the <see cref="RoutingContext"/> class.
/// </summary>
/// <param name="umbracoContext">The Umbraco context.</param>
/// <param name="documentLookups">The document lookups resolver.</param>
/// <param name="documentLastChanceLookup"> </param>
/// <param name="contentStore">The content store.</param>
/// <param name="niceUrlResolver">The nice urls resolver.</param>
internal RoutingContext(
//UmbracoContext umbracoContext,
UmbracoContext umbracoContext,
IEnumerable<IDocumentLookup> documentLookups,
IDocumentLastChanceLookup documentLastChanceLookup,
ContentStore contentStore,
NiceUrlProvider niceUrlResolver)
{
//this.UmbracoContext = umbracoContext;
this.UmbracoContext = umbracoContext;
this.DocumentLookups = documentLookups;
DocumentLastChanceLookup = documentLastChanceLookup;
this.ContentStore = contentStore;
this.NiceUrlProvider = niceUrlResolver;
}
///// <summary>
///// Gets the Umbraco context.
///// </summary>
//public UmbracoContext UmbracoContext { get; private set; }
/// <summary>
/// Gets the Umbraco context.
/// </summary>
public UmbracoContext UmbracoContext { get; private set; }
/// <summary>
/// Gets the document lookups resolver.

View File

@@ -254,6 +254,8 @@
<Compile Include="Mvc\RenderViewPage.cs" />
<Compile Include="Mvc\RouteDefinition.cs" />
<Compile Include="RouteValueDictionaryExtensions.cs" />
<Compile Include="Routing\DocumentLookupBase.cs" />
<Compile Include="Routing\DocumentSearcher.cs" />
<Compile Include="WebBootManager.cs" />
<Compile Include="LegacyRequestInitializer.cs" />
<Compile Include="Mvc\ControllerExtensions.cs" />

View File

@@ -193,20 +193,20 @@ namespace Umbraco.Web
/// <summary>
/// Boolean value indicating whether the current request is a front-end umbraco request
/// </summary>
public bool IsFrontEndUmbracoRequest
{
get { return DocumentRequest != null; }
}
public bool IsFrontEndUmbracoRequest
{
get { return DocumentRequest != null; }
}
/// <summary>
/// Gets/sets the RoutingContext object
/// </summary>
internal RoutingContext RoutingContext { get; set; }
/// <summary>
/// Gets/sets the DocumentRequest object
/// </summary>
internal DocumentRequest DocumentRequest { get; set; }
/// <summary>
/// Gets/sets the DocumentRequest object
/// </summary>
internal DocumentRequest DocumentRequest { get; set; }
/// <summary>
/// Exposes the HttpContext for the current request

View File

@@ -64,6 +64,7 @@ namespace Umbraco.Web
var niceUrls = new NiceUrlProvider(contentStore, umbracoContext);
//create the RoutingContext
var routingContext = new RoutingContext(
umbracoContext,
DocumentLookupsResolver.Current.DocumentLookups,
LastChanceLookupResolver.Current.LastChanceLookup,
contentStore,
@@ -83,8 +84,8 @@ namespace Umbraco.Web
//Create a document request since we are rendering a document on the front-end
// create the new document request which will cleanup the uri once and for all
var docreq = new DocumentRequest(uri, umbracoContext);
//assign the routing context to the umbraco context
var docreq = new DocumentRequest(uri, routingContext);
//assign the document request to the umbraco context now that we know its a front end request
umbracoContext.DocumentRequest = docreq;
// note - at that point the original legacy module did something do handle IIS custom 404 errors
@@ -95,14 +96,21 @@ namespace Umbraco.Web
// to trigger Umbraco's not-found, one should configure IIS and/or ASP.NET custom 404 errors
// so that they point to a non-existing page eg /redirect-404.aspx
docreq.LookupDomain();
//create the searcher
var searcher = new DocumentSearcher(docreq);
//find domain
searcher.LookupDomain();
//redirect if it has been flagged
if (docreq.IsRedirect)
httpContext.Response.Redirect(docreq.RedirectUrl, true);
//set the culture on the thread
Thread.CurrentThread.CurrentUICulture = Thread.CurrentThread.CurrentCulture = docreq.Culture;
docreq.LookupDocument();
//find the document
searcher.LookupDocument();
//redirect if it has been flagged
if (docreq.IsRedirect)
httpContext.Response.Redirect(docreq.RedirectUrl, true);
//if no doc is found, send to our not found handler
if (docreq.Is404)
{
httpContext.RemapHandler(new DocumentNotFoundHttpHandler());