Updated UmbracoModule to support the TransferRequest just like umbraMVCo does using query strings. Added more
unit tests for UmbracoModule, refactored the Umbraco.Web.Routing.Domains to not have static methods and created an interface for it so that we can unit test it. Changed DocumentRequest stuff to internal. Finally got unit test working for the module
This commit is contained in:
@@ -44,3 +44,4 @@ build/UmbracoCms.zip
|
||||
src/Umbraco.Tests/config/applications.config
|
||||
src/Umbraco.Tests/config/trees.config
|
||||
src/Umbraco.Web.UI/web.config
|
||||
src/Umbraco.Tests/config/404handlers.config
|
||||
|
||||
@@ -405,6 +405,11 @@ namespace Umbraco.Core
|
||||
return String.Equals(compare, compareTo, StringComparison.InvariantCultureIgnoreCase);
|
||||
}
|
||||
|
||||
public static bool InvariantStartsWith(this string compare, string compareTo)
|
||||
{
|
||||
return compare.StartsWith(compareTo, StringComparison.InvariantCultureIgnoreCase);
|
||||
}
|
||||
|
||||
public static bool InvariantContains(this string compare, string compareTo)
|
||||
{
|
||||
return compare.IndexOf(compareTo, StringComparison.OrdinalIgnoreCase) >= 0;
|
||||
|
||||
@@ -10,7 +10,7 @@ using GlobalSettings = umbraco.GlobalSettings;
|
||||
|
||||
namespace Umbraco.Tests.BusinessLogic
|
||||
{
|
||||
[TestFixture]
|
||||
[TestFixture, RequiresSTA]
|
||||
public abstract class BaseTest
|
||||
{
|
||||
/// <summary>
|
||||
@@ -47,6 +47,8 @@ namespace Umbraco.Tests.BusinessLogic
|
||||
{
|
||||
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)
|
||||
|
||||
@@ -60,6 +60,9 @@ namespace Umbraco.Tests.TestHelpers
|
||||
request.Stub(x => x.ApplicationPath).Return("/");
|
||||
request.Stub(x => x.Cookies).Return(new HttpCookieCollection());
|
||||
request.Stub(x => x.ServerVariables).Return(new NameValueCollection());
|
||||
var queryStrings = HttpUtility.ParseQueryString(fullUrl.Query);
|
||||
request.Stub(x => x.QueryString).Return(queryStrings);
|
||||
request.Stub(x => x.Form).Return(new NameValueCollection());
|
||||
|
||||
//Cache
|
||||
var cache = MockRepository.GenerateMock<HttpCachePolicyBase>();
|
||||
|
||||
@@ -1,13 +1,28 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Configuration;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Xml;
|
||||
using NUnit.Framework;
|
||||
using SqlCE4Umbraco;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Tests.TestHelpers;
|
||||
using Umbraco.Web;
|
||||
using Umbraco.Web.Media.ThumbnailProviders;
|
||||
using Umbraco.Web.Routing;
|
||||
using umbraco.BusinessLogic;
|
||||
using umbraco.DataLayer;
|
||||
using umbraco.IO;
|
||||
using umbraco.cms.businesslogic.cache;
|
||||
using umbraco.cms.businesslogic.language;
|
||||
using umbraco.cms.businesslogic.template;
|
||||
using umbraco.cms.businesslogic.web;
|
||||
using GlobalSettings = umbraco.GlobalSettings;
|
||||
|
||||
namespace Umbraco.Tests
|
||||
{
|
||||
[TestFixture]
|
||||
[TestFixture, RequiresSTA]
|
||||
public class UmbracoModuleTests
|
||||
{
|
||||
private UmbracoModule _module;
|
||||
@@ -24,6 +39,19 @@ namespace Umbraco.Tests
|
||||
ConfigurationManager.AppSettings.Set("umbracoConfigurationStatus", Umbraco.Core.Configuration.GlobalSettings.CurrentVersion);
|
||||
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();
|
||||
|
||||
//create the not found handlers config
|
||||
using(var sw = File.CreateText(IOHelper.MapPath(SystemFiles.NotFoundhandlersConfig, false)))
|
||||
{
|
||||
sw.Write(@"<NotFoundHandlers>
|
||||
<notFound assembly='umbraco' type='SearchForAlias' />
|
||||
<notFound assembly='umbraco' type='SearchForTemplate'/>
|
||||
<notFound assembly='umbraco' type='SearchForProfile'/>
|
||||
<notFound assembly='umbraco' type='handle404'/>
|
||||
</NotFoundHandlers>");
|
||||
}
|
||||
}
|
||||
|
||||
[TearDown]
|
||||
@@ -38,6 +66,30 @@ namespace Umbraco.Tests
|
||||
ConfigurationManager.AppSettings.Set("umbracoConfigurationStatus", "");
|
||||
ConfigurationManager.AppSettings.Set("umbracoReservedPaths", "");
|
||||
ConfigurationManager.AppSettings.Set("umbracoReservedUrls", "");
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
[TestCase("/umbraco_client/Tree/treeIcons.css", false)]
|
||||
@@ -78,5 +130,65 @@ namespace Umbraco.Tests
|
||||
Assert.AreEqual(assert, result);
|
||||
}
|
||||
|
||||
[TestCase("/default.aspx?path=/", true)]
|
||||
[TestCase("/default.aspx?path=/home.aspx", true)]
|
||||
[TestCase("/default.aspx?path=/home.aspx?altTemplate=blah", true)]
|
||||
public void Process_Front_End_Document_Request(string url, bool assert)
|
||||
{
|
||||
var httpContextFactory = new FakeHttpContextFactory(url);
|
||||
var httpContext = httpContextFactory.HttpContext;
|
||||
var umbracoContext = new UmbracoContext(httpContext, ApplicationContext.Current, new DefaultRoutesCache(false));
|
||||
|
||||
StateHelper.HttpContext = httpContext;
|
||||
|
||||
//because of so much dependency on the db, we need to create som stuff here, i originally abstracted out stuff but
|
||||
//was turning out to be quite a deep hole because ultimately we'd have to abstract the old 'Domain' and 'Language' classes
|
||||
Domain.MakeNew("Test.com", 1000, Language.GetByCultureCode("en-US").id);
|
||||
|
||||
//need to create a template with id 1045
|
||||
var template = Template.MakeNew("test", new User(0));
|
||||
|
||||
SetupUmbracoContextForTest(umbracoContext, template);
|
||||
|
||||
var result = _module.ProcessFrontEndDocumentRequest(
|
||||
httpContext,
|
||||
umbracoContext,
|
||||
new IDocumentLookup[] {new LookupByNiceUrl()},
|
||||
new DefaultLastChanceLookup());
|
||||
|
||||
Assert.AreEqual(assert, result);
|
||||
}
|
||||
|
||||
|
||||
private 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;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,7 @@ namespace Umbraco.Web.Routing
|
||||
/// <summary>
|
||||
/// Provides utilities to handle domains.
|
||||
/// </summary>
|
||||
public class Domains
|
||||
internal class DomainHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents an Umbraco domain and its normalized uri.
|
||||
@@ -20,7 +20,7 @@ namespace Umbraco.Web.Routing
|
||||
/// <para>In Umbraco it is valid to create domains with name such as <c>example.com</c>, <c>https://www.example.com</c>, <c>example.com/foo/</c>.</para>
|
||||
/// <para>The normalized uri of a domain begins with a scheme and ends with no slash, eg <c>http://example.com/</c>, <c>https://www.example.com/</c>, <c>http://example.com/foo/</c>.</para>
|
||||
/// </remarks>
|
||||
public class DomainAndUri
|
||||
internal class DomainAndUri
|
||||
{
|
||||
/// <summary>
|
||||
/// The Umbraco domain.
|
||||
@@ -4,6 +4,7 @@ using System.Diagnostics;
|
||||
using System.Reflection;
|
||||
using System.Web;
|
||||
using System.Xml;
|
||||
using Umbraco.Core.Logging;
|
||||
using umbraco.IO;
|
||||
using umbraco.interfaces;
|
||||
|
||||
@@ -14,7 +15,6 @@ namespace Umbraco.Web.Routing
|
||||
/// </summary>
|
||||
internal class DefaultLastChanceLookup : IDocumentLastChanceLookup
|
||||
{
|
||||
static TraceSource _trace = new TraceSource("DefaultLastChanceLookup");
|
||||
|
||||
/// <summary>
|
||||
/// Tries to find and assign an Umbraco document to a <c>DocumentRequest</c>.
|
||||
@@ -33,7 +33,8 @@ namespace Umbraco.Web.Routing
|
||||
|
||||
XmlNode HandlePageNotFound(DocumentRequest docRequest)
|
||||
{
|
||||
HttpContext.Current.Trace.Write("NotFoundHandler", string.Format("Running for url='{0}'.", docRequest.Uri.AbsolutePath));
|
||||
LogHelper.Debug<DefaultLastChanceLookup>("Running for url='{0}'.", () => docRequest.Uri.AbsolutePath);
|
||||
|
||||
XmlNode currentPage = null;
|
||||
|
||||
foreach (var handler in GetNotFoundHandlers())
|
||||
@@ -45,8 +46,7 @@ namespace Umbraco.Web.Routing
|
||||
|
||||
// FIXME - could it be null?
|
||||
|
||||
HttpContext.Current.Trace.Write("NotFoundHandler",
|
||||
string.Format("Handler '{0}' found node with id={1}.", handler.GetType().FullName, handler.redirectID));
|
||||
LogHelper.Debug<DefaultLastChanceLookup>("Handler '{0}' found node with id={1}.", () => handler.GetType().FullName, () => handler.redirectID);
|
||||
|
||||
//// check for caching
|
||||
//if (handler.CacheUrl)
|
||||
@@ -77,7 +77,7 @@ namespace Umbraco.Web.Routing
|
||||
// initialize handlers
|
||||
// create the definition cache
|
||||
|
||||
HttpContext.Current.Trace.Write("NotFoundHandler", "Registering custom handlers.");
|
||||
LogHelper.Debug<DefaultLastChanceLookup>("Registering custom handlers.");
|
||||
|
||||
_customHandlerTypes = new List<Type>();
|
||||
|
||||
@@ -101,17 +101,19 @@ namespace Umbraco.Web.Routing
|
||||
ns = nsAttr.Value;
|
||||
Type type = null;
|
||||
|
||||
HttpContext.Current.Trace.Write("NotFoundHandler",
|
||||
string.Format("Registering '{0}.{1},{2}'.", ns, typeName, assemblyName));
|
||||
|
||||
LogHelper.Debug<DefaultLastChanceLookup>("Registering '{0}.{1},{2}'.", () => ns, () => typeName, () => assemblyName);
|
||||
|
||||
try
|
||||
{
|
||||
//TODO: This isn't a good way to load the assembly, its already in the Domain so we should be getting the type
|
||||
// this loads the assembly into the wrong assembly load context!!
|
||||
|
||||
var assembly = Assembly.LoadFrom(IOHelper.MapPath(SystemDirectories.Bin + "/" + assemblyName + ".dll"));
|
||||
type = assembly.GetType(ns + "." + typeName);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
HttpContext.Current.Trace.Warn("NotFoundHandler", "Error registering handler, ignoring.", e);
|
||||
LogHelper.Error<DefaultLastChanceLookup>("Error registering handler, ignoring.", e);
|
||||
}
|
||||
|
||||
if (type != null)
|
||||
@@ -142,9 +144,7 @@ namespace Umbraco.Web.Routing
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
HttpContext.Current.Trace.Warn("NotFoundHandler",
|
||||
string.Format("Error instanciating handler {0}, ignoring.", type.FullName),
|
||||
e);
|
||||
LogHelper.Error<DefaultLastChanceLookup>(string.Format("Error instanciating handler {0}, ignoring.", type.FullName), e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -22,9 +22,9 @@ namespace Umbraco.Web.Routing
|
||||
/// represents a request for one specified Umbraco document to be rendered
|
||||
/// by one specified template, using one particular culture.
|
||||
/// </summary>
|
||||
public class DocumentRequest
|
||||
internal class DocumentRequest
|
||||
{
|
||||
public DocumentRequest(Uri uri, RoutingContext routingContext)
|
||||
public DocumentRequest(Uri uri, RoutingContext routingContext)
|
||||
{
|
||||
this.Uri = uri;
|
||||
RoutingContext = routingContext;
|
||||
@@ -159,7 +159,7 @@ namespace Umbraco.Web.Routing
|
||||
LogHelper.Debug<DocumentRequest>("{0}Uri=\"{1}\"", () => tracePrefix, () => this.Uri);
|
||||
|
||||
// try to find a domain matching the current request
|
||||
var domainAndUri = Domains.DomainMatch(Domain.GetDomains(), RoutingContext.UmbracoContext.UmbracoUrl, false);
|
||||
var domainAndUri = DomainHelper.DomainMatch(Domain.GetDomains(), RoutingContext.UmbracoContext.UmbracoUrl, false);
|
||||
|
||||
// handle domain
|
||||
if (domainAndUri != null)
|
||||
|
||||
@@ -3,7 +3,7 @@ namespace Umbraco.Web.Routing
|
||||
/// <summary>
|
||||
/// Provides a method to try to find an assign an Umbraco document to a <c>DocumentRequest</c>.
|
||||
/// </summary>
|
||||
public interface IDocumentLookup
|
||||
internal interface IDocumentLookup
|
||||
{
|
||||
/// <summary>
|
||||
/// Tries to find and assign an Umbraco document to a <c>DocumentRequest</c>.
|
||||
|
||||
@@ -24,7 +24,7 @@ namespace Umbraco.Web.Routing
|
||||
{
|
||||
string route;
|
||||
if (docreq.HasDomain)
|
||||
route = docreq.Domain.RootNodeId.ToString() + Domains.PathRelativeToDomain(docreq.DomainUri, docreq.Uri.AbsolutePath);
|
||||
route = docreq.Domain.RootNodeId.ToString() + DomainHelper.PathRelativeToDomain(docreq.DomainUri, docreq.Uri.AbsolutePath);
|
||||
else
|
||||
route = docreq.Uri.AbsolutePath;
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ namespace Umbraco.Web.Routing
|
||||
string path = docreq.Uri.AbsolutePath;
|
||||
|
||||
if (docreq.HasDomain)
|
||||
path = Domains.PathRelativeToDomain(docreq.DomainUri, path);
|
||||
path = DomainHelper.PathRelativeToDomain(docreq.DomainUri, path);
|
||||
if (path != "/") // no template if "/"
|
||||
{
|
||||
var pos = docreq.Uri.AbsolutePath.LastIndexOf('/');
|
||||
|
||||
@@ -25,11 +25,11 @@ namespace Umbraco.Web.Routing
|
||||
public NiceUrlProvider(ContentStore contentStore, UmbracoContext umbracoContext)
|
||||
{
|
||||
_umbracoContext = umbracoContext;
|
||||
_contentStore = contentStore;
|
||||
_contentStore = contentStore;
|
||||
}
|
||||
|
||||
private readonly UmbracoContext _umbracoContext;
|
||||
private readonly ContentStore _contentStore;
|
||||
private readonly ContentStore _contentStore;
|
||||
|
||||
// note: this could be a parameter...
|
||||
const string UrlNameProperty = "@urlName";
|
||||
@@ -207,7 +207,7 @@ namespace Umbraco.Web.Routing
|
||||
return null;
|
||||
|
||||
// apply filter on domains defined on that node
|
||||
var domainAndUri = Domains.DomainMatch(Domain.GetDomainsById(nodeId), current, true);
|
||||
var domainAndUri = DomainHelper.DomainMatch(Domain.GetDomainsById(nodeId), current, true);
|
||||
return domainAndUri == null ? null : domainAndUri.Uri;
|
||||
}
|
||||
|
||||
@@ -217,7 +217,7 @@ namespace Umbraco.Web.Routing
|
||||
if (nodeId <= 0)
|
||||
return new Uri[] { };
|
||||
|
||||
var domainAndUris = Domains.DomainMatches(Domain.GetDomainsById(nodeId), current);
|
||||
var domainAndUris = DomainHelper.DomainMatches(Domain.GetDomainsById(nodeId), current);
|
||||
return domainAndUris.Select(d => d.Uri);
|
||||
}
|
||||
|
||||
|
||||
@@ -258,7 +258,7 @@
|
||||
<Compile Include="Routing\LookupByProfile.cs" />
|
||||
<Compile Include="Routing\NiceUrlProvider.cs" />
|
||||
<Compile Include="PluginManagerExtensions.cs" />
|
||||
<Compile Include="Routing\Domains.cs" />
|
||||
<Compile Include="Routing\DefaultDomainHelper.cs" />
|
||||
<Compile Include="Routing\DocumentLookupsResolver.cs" />
|
||||
<Compile Include="Routing\DocumentRequest.cs" />
|
||||
<Compile Include="Routing\IDocumentLookup.cs" />
|
||||
|
||||
@@ -189,6 +189,14 @@ namespace Umbraco.Web
|
||||
return GetXmlDelegate();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Boolean value indicating whether the current request is a front-end umbraco request
|
||||
/// </summary>
|
||||
public bool IsFrontEndUmbracoRequest
|
||||
{
|
||||
get { return DocumentRequest != null; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets/sets the DocumentRequest object
|
||||
/// </summary>
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Web;
|
||||
using System.Web.Mvc;
|
||||
using System.Web.UI;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Web.Routing;
|
||||
@@ -22,6 +25,87 @@ namespace Umbraco.Web
|
||||
|
||||
public class UmbracoModule : IHttpModule
|
||||
{
|
||||
/// <summary>
|
||||
/// Checks if the current request should process the request as a front-end umbraco request, if this is tru
|
||||
/// it then creates the DocumentRequest object, finds the document, domain and culture and stores this back
|
||||
/// to the UmbracoContext
|
||||
/// </summary>
|
||||
/// <param name="httpContext"></param>
|
||||
/// <param name="umbracoContext"> </param>
|
||||
/// <param name="docLookups"> </param>
|
||||
/// <param name="lastChanceLookup"> </param>
|
||||
internal bool ProcessFrontEndDocumentRequest(
|
||||
HttpContextBase httpContext,
|
||||
UmbracoContext umbracoContext,
|
||||
IEnumerable<IDocumentLookup> docLookups,
|
||||
IDocumentLastChanceLookup lastChanceLookup)
|
||||
{
|
||||
if (httpContext == null) throw new ArgumentNullException("httpContext");
|
||||
if (umbracoContext == null) throw new ArgumentNullException("umbracoContext");
|
||||
|
||||
if (httpContext.Request.Url.LocalPath.InvariantStartsWith("/default.aspx")
|
||||
&& !string.IsNullOrWhiteSpace(httpContext.Request.QueryString["path"]))
|
||||
{
|
||||
//the path is the original path that the request came in on before we've rewritten it,
|
||||
//this is required because TransferRequest does not maintain the httpcontext
|
||||
var path = httpContext.Request.QueryString["path"];
|
||||
var qry = httpContext.Request.QueryString["qry"];
|
||||
Uri uri;
|
||||
try
|
||||
{
|
||||
uri = UriUtility.ToFullUrl(path + qry, httpContext);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
//if this fails then the path could not be parsed to a Uri which could be something malicious
|
||||
LogHelper.Error<UmbracoModule>(string.Format("Could not parse the path {0} into a full Uri", path), ex);
|
||||
return false;
|
||||
}
|
||||
|
||||
//create request based objects (one per http request)...
|
||||
|
||||
//create a content store
|
||||
var contentStore = new ContentStore(umbracoContext);
|
||||
//create the nice urls
|
||||
var niceUrls = new NiceUrlProvider(contentStore, umbracoContext);
|
||||
//create the RoutingContext
|
||||
var routingContext = new RoutingContext(
|
||||
umbracoContext,
|
||||
docLookups,
|
||||
lastChanceLookup,
|
||||
contentStore,
|
||||
niceUrls);
|
||||
// create the new document request which will cleanup the uri once and for all
|
||||
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;
|
||||
|
||||
// note - at that point the original legacy module did something do handle IIS custom 404 errors
|
||||
// ie pages looking like /anything.aspx?404;/path/to/document - I guess the reason was to support
|
||||
// "directory urls" without having to do wildcard mapping to ASP.NET on old IIS. This is a pain
|
||||
// to maintain and probably not used anymore - removed as of 06/2012. @zpqrtbnk.
|
||||
//
|
||||
// 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();
|
||||
if (docreq.IsRedirect)
|
||||
httpContext.Response.Redirect(docreq.RedirectUrl, true);
|
||||
Thread.CurrentThread.CurrentUICulture = Thread.CurrentThread.CurrentCulture = docreq.Culture;
|
||||
docreq.LookupDocument();
|
||||
if (docreq.IsRedirect)
|
||||
httpContext.Response.Redirect(docreq.RedirectUrl, true);
|
||||
|
||||
if (docreq.Is404)
|
||||
httpContext.Response.StatusCode = 404;
|
||||
|
||||
// it is up to default.aspx to figure out what to display in case
|
||||
// there is no document (ugly 404 page?) or no template (blank page?)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is a performance tweak to check if this is a .css, .js or .ico file request since
|
||||
@@ -32,7 +116,7 @@ namespace Umbraco.Web
|
||||
/// <returns></returns>
|
||||
internal bool IsClientSideRequest(Uri url)
|
||||
{
|
||||
var toIgnore = new[] {".js", ".css", ".ico"};
|
||||
var toIgnore = new[] { ".js", ".css", ".ico" };
|
||||
return toIgnore.Any(x => Path.GetExtension(url.LocalPath).InvariantEquals(x));
|
||||
}
|
||||
|
||||
@@ -69,12 +153,9 @@ namespace Umbraco.Web
|
||||
{
|
||||
LogHelper.Debug<UmbracoModule>("Start processing request");
|
||||
|
||||
var uri = httpContext.Request.Url;
|
||||
var lpath = uri.AbsolutePath.ToLower();
|
||||
|
||||
if (IsClientSideRequest(uri))
|
||||
if (IsClientSideRequest(httpContext.Request.Url))
|
||||
{
|
||||
LogHelper.Debug<UmbracoModule>("End processing request, not transfering to handler, this is a client side file request {0}", () => uri);
|
||||
LogHelper.Debug<UmbracoModule>("End processing request, not transfering to handler, this is a client side file request {0}", () => httpContext.Request.Url);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -83,8 +164,12 @@ namespace Umbraco.Web
|
||||
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(httpContext);
|
||||
global::umbraco.presentation.UmbracoContext.Current = new global::umbraco.presentation.UmbracoContext(httpContext);
|
||||
|
||||
//create the LegacyRequestInitializer
|
||||
var legacyRequestInitializer = new LegacyRequestInitializer(httpContext.Request.Url, httpContext);
|
||||
// legacy - initialize legacy stuff
|
||||
legacyRequestInitializer.InitializeRequest();
|
||||
|
||||
//create the UmbracoContext singleton, one per request!!
|
||||
var umbracoContext = new UmbracoContext(
|
||||
@@ -93,66 +178,32 @@ namespace Umbraco.Web
|
||||
RoutesCacheResolver.Current.RoutesCache);
|
||||
UmbracoContext.Current = umbracoContext;
|
||||
|
||||
//create request based objects (one per http request)...
|
||||
|
||||
//create a content store
|
||||
var contentStore = new ContentStore(umbracoContext);
|
||||
//create the nice urls
|
||||
var niceUrls = new NiceUrlProvider(contentStore, umbracoContext);
|
||||
//create the RoutingContext
|
||||
var routingContext = new RoutingContext(
|
||||
umbracoContext,
|
||||
//Does a check to see if this current request contains the information in order to process the
|
||||
//request as a front-end request. If not, then its because the rewrite hasn't taken place yet.
|
||||
//if we need to rewrite, then we'll cleanup the query strings and rewrite to the front end handler.
|
||||
if (!ProcessFrontEndDocumentRequest(httpContext, umbracoContext,
|
||||
DocumentLookupsResolver.Current.DocumentLookups,
|
||||
LastChanceLookupResolver.Current.LastChanceLookup,
|
||||
contentStore,
|
||||
niceUrls);
|
||||
|
||||
// create the new document request which will cleanup the uri once and for all
|
||||
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
|
||||
var legacyRequestInitializer = new LegacyRequestInitializer(httpContext.Request.Url, httpContext);
|
||||
// legacy - initialize legacy stuff
|
||||
legacyRequestInitializer.InitializeRequest();
|
||||
|
||||
// note - at that point the original legacy module did something do handle IIS custom 404 errors
|
||||
// ie pages looking like /anything.aspx?404;/path/to/document - I guess the reason was to support
|
||||
// "directory urls" without having to do wildcard mapping to ASP.NET on old IIS. This is a pain
|
||||
// to maintain and probably not used anymore - removed as of 06/2012. @zpqrtbnk.
|
||||
//
|
||||
// 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
|
||||
|
||||
//do not continue if this request is not a front-end routable page
|
||||
if (!EnsureUmbracoRoutablePage(uri, lpath, httpContext))
|
||||
LastChanceLookupResolver.Current.LastChanceLookup))
|
||||
{
|
||||
LogHelper.Debug<UmbracoModule>("End processing request, not transfering to handler {0}", () => uri);
|
||||
return;
|
||||
}
|
||||
var uri = httpContext.Request.Url;
|
||||
var lpath = uri.AbsolutePath.ToLower();
|
||||
|
||||
// legacy - no idea what this is
|
||||
LegacyCleanUmbPageFromQueryString(ref uri, ref lpath);
|
||||
// legacy - no idea what this is
|
||||
LegacyCleanUmbPageFromQueryString(ref uri, ref lpath);
|
||||
|
||||
//**THERE** we should create the doc request
|
||||
// before, we're not sure we handling a doc request
|
||||
docreq.LookupDomain();
|
||||
if (docreq.IsRedirect)
|
||||
httpContext.Response.Redirect(docreq.RedirectUrl, true);
|
||||
Thread.CurrentThread.CurrentUICulture = Thread.CurrentThread.CurrentCulture = docreq.Culture;
|
||||
docreq.LookupDocument();
|
||||
if (docreq.IsRedirect)
|
||||
httpContext.Response.Redirect(docreq.RedirectUrl, true);
|
||||
//do not continue if this request is not a front-end routable page
|
||||
if (EnsureUmbracoRoutablePage(uri, lpath, httpContext))
|
||||
{
|
||||
RewriteToPath<Page>(HttpContext.Current, lpath, uri.Query);
|
||||
//RewriteToPath<Page>(HttpContext.Current, "", docreq.Uri.Query);
|
||||
}
|
||||
else
|
||||
{
|
||||
LogHelper.Debug<UmbracoModule>("End processing request, not transfering to handler {0}", () => uri);
|
||||
}
|
||||
}
|
||||
|
||||
if (docreq.Is404)
|
||||
httpContext.Response.StatusCode = 404;
|
||||
|
||||
TransferRequest("~/default.aspx" + docreq.Uri.Query, httpContext);
|
||||
|
||||
// it is up to default.aspx to figure out what to display in case
|
||||
// there is no document (ugly 404 page?) or no template (blank page?)
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -245,7 +296,11 @@ namespace Umbraco.Web
|
||||
// fixme ?orgurl=... ?retry=...
|
||||
}
|
||||
|
||||
TransferRequest(bootUrl, httpContext);
|
||||
//RewriteToPath<Page>(HttpContext.Current, bootUrl, "", "");
|
||||
//TransferRequest(bootUrl, httpContext);
|
||||
|
||||
httpContext.RewritePath(bootUrl);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -291,37 +346,70 @@ namespace Umbraco.Web
|
||||
return true;
|
||||
}
|
||||
|
||||
// transfers the request using the fastest method available on the server
|
||||
void TransferRequest(string path, HttpContextBase httpContext)
|
||||
private static void RewriteToPath<THandler>(HttpContext context, string currentPath, string currentQuery)
|
||||
where THandler : IHttpHandler
|
||||
{
|
||||
LogHelper.Debug<UmbracoModule>("Transfering to " + path);
|
||||
|
||||
var integrated = HttpRuntime.UsingIntegratedPipeline;
|
||||
if ((context.CurrentHandler is THandler)) return;
|
||||
|
||||
// fixme - are we doing this properly?
|
||||
// fixme - handle virtual directory?
|
||||
// fixme - this does not work 'cos it resets the HttpContext
|
||||
// so we should move the DocumentRequest stuff etc back to default.aspx?
|
||||
// but, also, with TransferRequest, auth & co will run on the new (default.aspx) url,
|
||||
// is that really what we want? I need to talk about it with others. @zpqrtbnk
|
||||
var rewritePath = "~/default.aspx?path="
|
||||
+ context.Server.UrlEncode(currentPath)
|
||||
+ "&qry="
|
||||
+ context.Server.UrlEncode(currentQuery);
|
||||
|
||||
// NOTE: SD: Need to look at how umbraMVCo does this. It is true that the TransferRequest initializes a new HttpContext,
|
||||
// what we need to do is when we transfer to the handler we send a query string with the found page Id to be looked up
|
||||
// after we have done our routing check. This however needs some though as we don't want to have to query for this
|
||||
// page twice. Again, I'll check how umbraMVCo is doing it as I had though about that when i created it :)
|
||||
if (currentPath.StartsWith(rewritePath, StringComparison.InvariantCultureIgnoreCase)) return;
|
||||
|
||||
integrated = false;
|
||||
var isMvc = TypeHelper.IsTypeAssignableFrom<THandler>(typeof(MvcHandler));
|
||||
|
||||
// http://msmvps.com/blogs/luisabreu/archive/2007/10/09/are-you-using-the-new-transferrequest.aspx
|
||||
// http://msdn.microsoft.com/en-us/library/aa344903.aspx
|
||||
// http://forums.iis.net/t/1146511.aspx
|
||||
LogHelper.Debug<UmbracoModule>("Transfering to " + rewritePath);
|
||||
|
||||
if (integrated)
|
||||
httpContext.Server.TransferRequest(path);
|
||||
if (HttpRuntime.UsingIntegratedPipeline)
|
||||
{
|
||||
context.Server.TransferRequest(rewritePath, true);
|
||||
}
|
||||
else
|
||||
httpContext.RewritePath(path);
|
||||
{
|
||||
// Pre MVC 3
|
||||
context.RewritePath(rewritePath, false);
|
||||
if (isMvc)
|
||||
{
|
||||
IHttpHandler httpHandler = new MvcHttpHandler();
|
||||
httpHandler.ProcessRequest(context);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//// transfers the request using the fastest method available on the server
|
||||
//void TransferRequest(string path, HttpContextBase httpContext)
|
||||
//{
|
||||
// LogHelper.Debug<UmbracoModule>("Transfering to " + path);
|
||||
|
||||
// var integrated = HttpRuntime.UsingIntegratedPipeline;
|
||||
|
||||
// // fixme - are we doing this properly?
|
||||
// // fixme - handle virtual directory?
|
||||
// // fixme - this does not work 'cos it resets the HttpContext
|
||||
// // so we should move the DocumentRequest stuff etc back to default.aspx?
|
||||
// // but, also, with TransferRequest, auth & co will run on the new (default.aspx) url,
|
||||
// // is that really what we want? I need to talk about it with others. @zpqrtbnk
|
||||
|
||||
// // NOTE: SD: Need to look at how umbraMVCo does this. It is true that the TransferRequest initializes a new HttpContext,
|
||||
// // what we need to do is when we transfer to the handler we send a query string with the found page Id to be looked up
|
||||
// // after we have done our routing check. This however needs some though as we don't want to have to query for this
|
||||
// // page twice. Again, I'll check how umbraMVCo is doing it as I had though about that when i created it :)
|
||||
|
||||
// integrated = false;
|
||||
|
||||
// // http://msmvps.com/blogs/luisabreu/archive/2007/10/09/are-you-using-the-new-transferrequest.aspx
|
||||
// // http://msdn.microsoft.com/en-us/library/aa344903.aspx
|
||||
// // http://forums.iis.net/t/1146511.aspx
|
||||
|
||||
// if (integrated)
|
||||
// httpContext.Server.TransferRequest(path);
|
||||
// else
|
||||
// httpContext.RewritePath(path);
|
||||
//}
|
||||
|
||||
|
||||
|
||||
#region Legacy
|
||||
@@ -380,7 +468,7 @@ namespace Umbraco.Web
|
||||
// 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) =>
|
||||
|
||||
|
||||
//SD: changed to post map request handler so we can know what the handler actually is, this is a better fit for
|
||||
//when we handle the routing
|
||||
app.PostMapRequestHandler += (sender, e) =>
|
||||
|
||||
@@ -157,5 +157,30 @@ namespace Umbraco.Web
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Returns an faull url with the host, port, etc...
|
||||
/// </summary>
|
||||
/// <param name="absolutePath">An absolute path (i.e. starts with a '/' )</param>
|
||||
/// <param name="httpContext"> </param>
|
||||
/// <returns></returns>
|
||||
/// <remarks>
|
||||
/// Based on http://stackoverflow.com/questions/3681052/get-absolute-url-from-relative-path-refactored-method
|
||||
/// </remarks>
|
||||
internal static Uri ToFullUrl(string absolutePath, HttpContextBase httpContext)
|
||||
{
|
||||
if (httpContext == null) throw new ArgumentNullException("httpContext");
|
||||
if (string.IsNullOrEmpty(absolutePath))
|
||||
throw new ArgumentNullException("absolutePath");
|
||||
|
||||
if (!absolutePath.StartsWith("/"))
|
||||
throw new FormatException("The absolutePath specified does not start with a '/'");
|
||||
|
||||
|
||||
var url = httpContext.Request.Url;
|
||||
var port = url.Port != 80 ? (":" + url.Port) : String.Empty;
|
||||
|
||||
return new Uri(string.Format("{0}://{1}{2}{3}", url.Scheme, url.Host, port, absolutePath));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -24,7 +24,8 @@ namespace umbraco.cms.businesslogic.web
|
||||
|
||||
static private Hashtable _checkedPages = new Hashtable();
|
||||
|
||||
static private XmlDocument _accessXmlContent;
|
||||
//must be volatile for double check lock to work
|
||||
static private volatile XmlDocument _accessXmlContent;
|
||||
static private string _accessXmlSource;
|
||||
|
||||
private static void clearCheckPages()
|
||||
@@ -54,6 +55,11 @@ namespace umbraco.cms.businesslogic.web
|
||||
|
||||
if (!System.IO.File.Exists(_accessXmlSource))
|
||||
{
|
||||
var file = new FileInfo(_accessXmlSource);
|
||||
if (!Directory.Exists(file.DirectoryName))
|
||||
{
|
||||
Directory.CreateDirectory(file.Directory.FullName); //ensure the folder exists!
|
||||
}
|
||||
System.IO.FileStream f = System.IO.File.Open(_accessXmlSource, FileMode.Create);
|
||||
System.IO.StreamWriter sw = new StreamWriter(f);
|
||||
sw.WriteLine("<access/>");
|
||||
|
||||
@@ -29,6 +29,14 @@ namespace umbraco.cms.businesslogic.web
|
||||
get { return Application.SqlHelper; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Empty ctor used for unit tests to create a custom domain
|
||||
/// </summary>
|
||||
internal Domain()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public Domain(int Id)
|
||||
{
|
||||
initDomain(Id);
|
||||
|
||||
Reference in New Issue
Block a user