From 343c14db48babb075b471d551d2b034e5f62f366 Mon Sep 17 00:00:00 2001
From: Stephan
Date: Mon, 24 Sep 2012 11:36:25 -0200
Subject: [PATCH] fixing routing, 404, domains + add NiceUrl and UriUtility
tests
---
.../Configuration/UmbracoSettings.cs | 26 ++
.../Routing/NiceUrlProviderTests.cs | 134 +++++---
.../NiceUrlsProviderWithDomainsTests.cs | 299 ++++++++++++++++++
src/Umbraco.Tests/Umbraco.Tests.csproj | 1 +
src/Umbraco.Tests/UriUtilityTests.cs | 88 +++++-
.../DefaultPublishedContentStore.cs | 25 +-
.../Routing/DefaultLastChanceLookup.cs | 36 ++-
.../Routing/DocumentNotFoundHandler.cs | 27 +-
.../Routing/DocumentRequestBuilder.cs | 12 +
src/Umbraco.Web/Routing/LookupByNiceUrl.cs | 12 +-
src/Umbraco.Web/Routing/NiceUrlProvider.cs | 89 +++---
src/Umbraco.Web/Routing/NoTemplateHandler.cs | 14 +-
src/Umbraco.Web/UmbracoModule.cs | 33 +-
src/Umbraco.Web/UriUtility.cs | 11 +-
14 files changed, 637 insertions(+), 170 deletions(-)
create mode 100644 src/Umbraco.Tests/Routing/NiceUrlsProviderWithDomainsTests.cs
diff --git a/src/Umbraco.Core/Configuration/UmbracoSettings.cs b/src/Umbraco.Core/Configuration/UmbracoSettings.cs
index d7a7d4723c..1304b284de 100644
--- a/src/Umbraco.Core/Configuration/UmbracoSettings.cs
+++ b/src/Umbraco.Core/Configuration/UmbracoSettings.cs
@@ -334,6 +334,8 @@ namespace Umbraco.Core.Configuration
}
}
+ static bool? _addTrailingSlash = null;
+
///
/// This will add a trailing slash (/) to urls when in directory url mode
/// NOTICE: This will always return false if Directory Urls in not active
@@ -346,6 +348,8 @@ namespace Umbraco.Core.Configuration
{
if (GlobalSettings.UseDirectoryUrls)
{
+ if (_addTrailingSlash.HasValue)
+ return _addTrailingSlash.Value;
bool result;
if (bool.TryParse(GetKey("/settings/requestHandler/addTrailingSlash"), out result))
return result;
@@ -361,6 +365,10 @@ namespace Umbraco.Core.Configuration
return false;
}
}
+ internal set
+ {
+ _addTrailingSlash = value;
+ }
}
///
@@ -385,6 +393,24 @@ namespace Umbraco.Core.Configuration
}
}
+ public static bool HandleMissingTemplateAs404
+ {
+ get
+ {
+ try
+ {
+ bool result;
+ if (bool.TryParse(GetKey("/settings/templates/handleMissingTemplateAs404"), out result))
+ return result;
+ return false;
+ }
+ catch
+ {
+ return false;
+ }
+ }
+ }
+
///
/// Gets a value indicating whether umbraco will attempt to load any skins to override default template files
diff --git a/src/Umbraco.Tests/Routing/NiceUrlProviderTests.cs b/src/Umbraco.Tests/Routing/NiceUrlProviderTests.cs
index fd3c20471e..59d9ee3e14 100644
--- a/src/Umbraco.Tests/Routing/NiceUrlProviderTests.cs
+++ b/src/Umbraco.Tests/Routing/NiceUrlProviderTests.cs
@@ -1,5 +1,6 @@
using System;
using System.Configuration;
+using System.Collections.Generic;
using NUnit.Framework;
using Umbraco.Tests.TestHelpers;
using Umbraco.Web.Routing;
@@ -30,46 +31,71 @@ namespace Umbraco.Tests.Routing
[Test]
public void Ensure_Cache_Is_Correct()
{
-
var routingContext = GetRoutingContext("/test", 1111);
ConfigurationManager.AppSettings.Set("umbracoUseDirectoryUrls", "true");
- var ids = new[]
- {
- new Tuple(1046, "/home"),
- new Tuple(1173, "/home/sub1"),
- new Tuple(1174, "/home/sub1/sub2"),
- new Tuple(1176, "/home/sub1/sub-3"),
- new Tuple(1177, "/home/sub1/custom-sub-1"),
- new Tuple(1178, "/home/sub1/custom-sub-2"),
- new Tuple(1175, "/home/sub-2"),
- new Tuple(1172, "/test-page")
- };
- foreach(var i in ids)
+
+ var samples = new Dictionary {
+ { 1046, "/home" },
+ { 1173, "/home/sub1" },
+ { 1174, "/home/sub1/sub2" },
+ { 1176, "/home/sub1/sub-3" },
+ { 1177, "/home/sub1/custom-sub-1" },
+ { 1178, "/home/sub1/custom-sub-2" },
+ { 1175, "/home/sub-2" },
+ { 1172, "/test-page" }
+ };
+
+ foreach (var sample in samples)
{
- var result = routingContext.NiceUrlProvider.GetNiceUrl(i.Item1);
- Assert.AreEqual(i.Item2, result);
+ var result = routingContext.NiceUrlProvider.GetNiceUrl(sample.Key);
+ Assert.AreEqual(sample.Value, result);
+ }
+
+ var randomSample = new KeyValuePair(1177, "/home/sub1/custom-sub-1");
+ for (int i = 0; i < 5; i++)
+ {
+ var result = routingContext.NiceUrlProvider.GetNiceUrl(randomSample.Key);
+ Assert.AreEqual(randomSample.Value, result);
+ }
+
+ var cachedRoutes = ((DefaultRoutesCache)routingContext.UmbracoContext.RoutesCache).GetCachedRoutes();
+ Assert.AreEqual(8, cachedRoutes.Count);
+
+ foreach (var sample in samples)
+ {
+ Assert.IsTrue(cachedRoutes.ContainsKey(sample.Key));
+ Assert.AreEqual(sample.Value, cachedRoutes[sample.Key]);
+ }
+
+ var cachedIds = ((DefaultRoutesCache)routingContext.UmbracoContext.RoutesCache).GetCachedIds();
+ Assert.AreEqual(8, cachedIds.Count);
+
+ foreach (var sample in samples)
+ {
+ var key = sample.Value;
+ Assert.IsTrue(cachedIds.ContainsKey(key));
+ Assert.AreEqual(sample.Key, cachedIds[key]);
}
- Assert.AreEqual(8, ((DefaultRoutesCache)routingContext.UmbracoContext.RoutesCache).GetCachedRoutes().Count);
- Assert.AreEqual(8, ((DefaultRoutesCache)routingContext.UmbracoContext.RoutesCache).GetCachedIds().Count);
}
- [TestCase(1046, "/home.aspx")]
- [TestCase(1173, "/home/sub1.aspx")]
- [TestCase(1174, "/home/sub1/sub2.aspx")]
- [TestCase(1176, "/home/sub1/sub-3.aspx")]
- [TestCase(1177, "/home/sub1/custom-sub-1.aspx")]
- [TestCase(1178, "/home/sub1/custom-sub-2.aspx")]
- [TestCase(1175, "/home/sub-2.aspx")]
- [TestCase(1172, "/test-page.aspx")]
- public void Get_Nice_Url_Not_Hiding_Top_Level_No_Directory_Urls(int nodeId, string niceUrlMatch)
- {
- var routingContext = GetRoutingContext("/test", 1111);
+ //[TestCase(1046, "/home.aspx")]
+ //[TestCase(1173, "/home/sub1.aspx")]
+ //[TestCase(1174, "/home/sub1/sub2.aspx")]
+ //[TestCase(1176, "/home/sub1/sub-3.aspx")]
+ //[TestCase(1177, "/home/sub1/custom-sub-1.aspx")]
+ //[TestCase(1178, "/home/sub1/custom-sub-2.aspx")]
+ //[TestCase(1175, "/home/sub-2.aspx")]
+ //[TestCase(1172, "/test-page.aspx")]
+ //public void Get_Nice_Url_Not_Hiding_Top_Level_No_Directory_Urls(int nodeId, string niceUrlMatch)
+ //{
+ // var routingContext = GetRoutingContext("/test", 1111);
- var result = routingContext.NiceUrlProvider.GetNiceUrl(nodeId);
+ // var result = routingContext.NiceUrlProvider.GetNiceUrl(nodeId);
- Assert.AreEqual(niceUrlMatch, result);
- }
+ // Assert.AreEqual(niceUrlMatch, result);
+ //}
+ // test hideTopLevelNodeFromPath false
[TestCase(1046, "/home")]
[TestCase(1173, "/home/sub1")]
[TestCase(1174, "/home/sub1/sub2")]
@@ -78,36 +104,40 @@ namespace Umbraco.Tests.Routing
[TestCase(1178, "/home/sub1/custom-sub-2")]
[TestCase(1175, "/home/sub-2")]
[TestCase(1172, "/test-page")]
- public void Get_Nice_Url_Not_Hiding_Top_Level_With_Directory_Urls(int nodeId, string niceUrlMatch)
+
+ public void Get_Nice_Url_Not_Hiding_Top_Level(int nodeId, string niceUrlMatch)
{
var routingContext = GetRoutingContext("/test", 1111);
ConfigurationManager.AppSettings.Set("umbracoUseDirectoryUrls", "true");
+ ConfigurationManager.AppSettings.Set("umbracoHideTopLevelNodeFromPath", "false");
var result = routingContext.NiceUrlProvider.GetNiceUrl(nodeId);
-
Assert.AreEqual(niceUrlMatch, result);
}
- [TestCase(1046, "/")]
- [TestCase(1173, "/sub1.aspx")]
- [TestCase(1174, "/sub1/sub2.aspx")]
- [TestCase(1176, "/sub1/sub-3.aspx")]
- [TestCase(1177, "/sub1/custom-sub-1.aspx")]
- [TestCase(1178, "/sub1/custom-sub-2.aspx")]
- [TestCase(1175, "/sub-2.aspx")]
- [TestCase(1172, "/test-page.aspx")]
- public void Get_Nice_Url_Hiding_Top_Level_No_Directory_Urls(int nodeId, string niceUrlMatch)
- {
- var routingContext = GetRoutingContext("/test", 1111);
+ // no need for umbracoUseDirectoryUrls test = should be handled by UriUtilityTests
- ConfigurationManager.AppSettings.Set("umbracoHideTopLevelNodeFromPath", "true");
+ //[TestCase(1046, "/")]
+ //[TestCase(1173, "/sub1.aspx")]
+ //[TestCase(1174, "/sub1/sub2.aspx")]
+ //[TestCase(1176, "/sub1/sub-3.aspx")]
+ //[TestCase(1177, "/sub1/custom-sub-1.aspx")]
+ //[TestCase(1178, "/sub1/custom-sub-2.aspx")]
+ //[TestCase(1175, "/sub-2.aspx")]
+ //[TestCase(1172, "/test-page.aspx")]
+ //public void Get_Nice_Url_Hiding_Top_Level_No_Directory_Urls(int nodeId, string niceUrlMatch)
+ //{
+ // var routingContext = GetRoutingContext("/test", 1111);
- var result = routingContext.NiceUrlProvider.GetNiceUrl(nodeId);
+ // ConfigurationManager.AppSettings.Set("umbracoHideTopLevelNodeFromPath", "true");
- Assert.AreEqual(niceUrlMatch, result);
- }
+ // var result = routingContext.NiceUrlProvider.GetNiceUrl(nodeId);
+ // Assert.AreEqual(niceUrlMatch, result);
+ //}
+
+ // test hideTopLevelNodeFromPath true
[TestCase(1046, "/")]
[TestCase(1173, "/sub1")]
[TestCase(1174, "/sub1/sub2")]
@@ -115,16 +145,16 @@ namespace Umbraco.Tests.Routing
[TestCase(1177, "/sub1/custom-sub-1")]
[TestCase(1178, "/sub1/custom-sub-2")]
[TestCase(1175, "/sub-2")]
- [TestCase(1172, "/test-page")]
- public void Get_Nice_Url_Hiding_Top_Level_With_Directory_Urls(int nodeId, string niceUrlMatch)
+ [TestCase(1172, "/test-page")] // not hidden because not first root
+
+ public void Get_Nice_Url_Hiding_Top_Level(int nodeId, string niceUrlMatch)
{
var routingContext = GetRoutingContext("/test", 1111);
- ConfigurationManager.AppSettings.Set("umbracoHideTopLevelNodeFromPath", "true");
ConfigurationManager.AppSettings.Set("umbracoUseDirectoryUrls", "true");
+ ConfigurationManager.AppSettings.Set("umbracoHideTopLevelNodeFromPath", "true");
var result = routingContext.NiceUrlProvider.GetNiceUrl(nodeId);
-
Assert.AreEqual(niceUrlMatch, result);
}
}
diff --git a/src/Umbraco.Tests/Routing/NiceUrlsProviderWithDomainsTests.cs b/src/Umbraco.Tests/Routing/NiceUrlsProviderWithDomainsTests.cs
new file mode 100644
index 0000000000..f83f040c01
--- /dev/null
+++ b/src/Umbraco.Tests/Routing/NiceUrlsProviderWithDomainsTests.cs
@@ -0,0 +1,299 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Configuration;
+using NUnit.Framework;
+using Umbraco.Tests.TestHelpers;
+using Umbraco.Web.Routing;
+using umbraco.cms.businesslogic.web;
+using umbraco.cms.businesslogic.language;
+
+namespace Umbraco.Tests.Routing
+{
+ [TestFixture]
+ public class NiceUrlsProviderWithDomainsTests : BaseRoutingTest
+ {
+ public override void TearDown()
+ {
+ base.TearDown();
+
+ ConfigurationManager.AppSettings.Set("umbracoUseDirectoryUrls", "");
+ ConfigurationManager.AppSettings.Set("umbracoHideTopLevelNodeFromPath", "");
+
+ ClearLanguagesAndDomains();
+ }
+
+ internal override IRoutesCache GetRoutesCache()
+ {
+ return new DefaultRoutesCache(false);
+ }
+
+ void ClearLanguagesAndDomains()
+ {
+ var domains = Domain.GetDomains();
+ foreach (var d in domains)
+ d.Delete();
+
+ var langs = Language.GetAllAsList();
+ foreach (var l in langs.Skip(1))
+ l.Delete();
+ }
+
+ void InitializeLanguagesAndDomains()
+ {
+ var domains = Domain.GetDomains();
+ foreach (var d in domains)
+ d.Delete();
+
+ var langs = Language.GetAllAsList();
+ foreach (var l in langs.Skip(1))
+ l.Delete();
+
+ Language.MakeNew("fr-FR");
+ }
+
+ void SetDomains1()
+ {
+ var langEn = Language.GetByCultureCode("en-US");
+ var langFr = Language.GetByCultureCode("fr-FR");
+
+ Domain.MakeNew("domain1.com", 1001, langFr.id);
+ }
+
+ void SetDomains2()
+ {
+ var langEn = Language.GetByCultureCode("en-US");
+ var langFr = Language.GetByCultureCode("fr-FR");
+
+ Domain.MakeNew("http://domain1.com/foo", 1001, langFr.id);
+ }
+
+ void SetDomains3()
+ {
+ var langEn = Language.GetByCultureCode("en-US");
+ var langFr = Language.GetByCultureCode("fr-FR");
+
+ Domain.MakeNew("http://domain1.com/", 10011, langFr.id);
+ }
+
+ void SetDomains4()
+ {
+ var langEn = Language.GetByCultureCode("en-US");
+ var langFr = Language.GetByCultureCode("fr-FR");
+
+ Domain.MakeNew("http://domain1.com/", 1001, langFr.id);
+ Domain.MakeNew("http://domain1.com/en", 10011, langEn.id);
+ Domain.MakeNew("http://domain1.com/fr", 10012, langEn.id);
+ }
+
+ protected override string GetXmlContent(int templateId)
+ {
+ return @"
+
+
+]>
+
+
+
+
+ This is some content]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ This is some content]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+";
+ }
+
+ // with one simple domain "domain1.com"
+ // basic tests
+ [TestCase(1001, "http://domain1.com", false, "/")]
+ [TestCase(10011, "http://domain1.com", false, "/1001-1")]
+ [TestCase(1002, "http://domain1.com", false, "/1002")]
+ // absolute tests
+ [TestCase(1001, "http://domain1.com", true, "http://domain1.com/")]
+ [TestCase(10011, "http://domain1.com", true, "http://domain1.com/1001-1")]
+ // different current tests
+ [TestCase(1001, "http://domain2.com", false, "http://domain1.com/")]
+ [TestCase(10011, "http://domain2.com", false, "http://domain1.com/1001-1")]
+ [TestCase(1001, "https://domain1.com", false, "/")]
+ [TestCase(10011, "https://domain1.com", false, "/1001-1")]
+
+ public void Get_Nice_Url_SimpleDomain(int nodeId, string currentUrl, bool absolute, string expected)
+ {
+ var routingContext = GetRoutingContext("/test", 1111);
+
+ ConfigurationManager.AppSettings.Set("umbracoUseDirectoryUrls", "true");
+ ConfigurationManager.AppSettings.Set("umbracoHideTopLevelNodeFromPath", "false"); // ignored w/domains
+
+ InitializeLanguagesAndDomains();
+ SetDomains1();
+
+ var currentUri = new Uri(currentUrl);
+ var result = routingContext.NiceUrlProvider.GetNiceUrl(nodeId, currentUri, absolute);
+ Assert.AreEqual(expected, result);
+ }
+
+ // with one complete domain "http://domain1.com/foo"
+ // basic tests
+ [TestCase(1001, "http://domain1.com", false, "/foo")]
+ [TestCase(10011, "http://domain1.com", false, "/foo/1001-1")]
+ [TestCase(1002, "http://domain1.com", false, "/1002")]
+ // absolute tests
+ [TestCase(1001, "http://domain1.com", true, "http://domain1.com/foo")]
+ [TestCase(10011, "http://domain1.com", true, "http://domain1.com/foo/1001-1")]
+ // different current tests
+ [TestCase(1001, "http://domain2.com", false, "http://domain1.com/foo")]
+ [TestCase(10011, "http://domain2.com", false, "http://domain1.com/foo/1001-1")]
+ [TestCase(1001, "https://domain1.com", false, "http://domain1.com/foo")]
+ [TestCase(10011, "https://domain1.com", false, "http://domain1.com/foo/1001-1")]
+
+ public void Get_Nice_Url_SimpleWithSchemeAndPath(int nodeId, string currentUrl, bool absolute, string expected)
+ {
+ var routingContext = GetRoutingContext("/test", 1111);
+
+ ConfigurationManager.AppSettings.Set("umbracoUseDirectoryUrls", "true");
+ ConfigurationManager.AppSettings.Set("umbracoHideTopLevelNodeFromPath", "false"); // ignored w/domains
+
+ InitializeLanguagesAndDomains();
+ SetDomains2();
+
+ var currentUri = new Uri(currentUrl);
+ var result = routingContext.NiceUrlProvider.GetNiceUrl(nodeId, currentUri, absolute);
+ Assert.AreEqual(expected, result);
+ }
+
+ // with one domain, not at root
+ [TestCase(1001, "http://domain1.com", false, "/1001")]
+ [TestCase(10011, "http://domain1.com", false, "/")]
+ [TestCase(100111, "http://domain1.com", false, "/1001-1-1")]
+ [TestCase(1002, "http://domain1.com", false, "/1002")]
+
+ public void Get_Nice_Url_DeepDomain(int nodeId, string currentUrl, bool absolute, string expected)
+ {
+ var routingContext = GetRoutingContext("/test", 1111);
+
+ ConfigurationManager.AppSettings.Set("umbracoUseDirectoryUrls", "true");
+ ConfigurationManager.AppSettings.Set("umbracoHideTopLevelNodeFromPath", "false"); // ignored w/domains
+
+ InitializeLanguagesAndDomains();
+ SetDomains3();
+
+ var currentUri = new Uri(currentUrl);
+ var result = routingContext.NiceUrlProvider.GetNiceUrl(nodeId, currentUri, absolute);
+ Assert.AreEqual(expected, result);
+ }
+
+ // with nested domains
+ [TestCase(1001, "http://domain1.com", false, "/")]
+ [TestCase(10011, "http://domain1.com", false, "/en")]
+ [TestCase(100111, "http://domain1.com", false, "/en/1001-1-1")]
+ [TestCase(10012, "http://domain1.com", false, "/fr")]
+ [TestCase(100121, "http://domain1.com", false, "/fr/1001-2-1")]
+ [TestCase(10013, "http://domain1.com", false, "/1001-3")]
+ [TestCase(1002, "http://domain1.com", false, "/1002")]
+
+ public void Get_Nice_Url_NestedDomains(int nodeId, string currentUrl, bool absolute, string expected)
+ {
+ var routingContext = GetRoutingContext("/test", 1111);
+
+ ConfigurationManager.AppSettings.Set("umbracoUseDirectoryUrls", "true");
+ ConfigurationManager.AppSettings.Set("umbracoHideTopLevelNodeFromPath", "false"); // ignored w/domains
+
+ InitializeLanguagesAndDomains();
+ SetDomains4();
+
+ var currentUri = new Uri(currentUrl);
+ var result = routingContext.NiceUrlProvider.GetNiceUrl(nodeId, currentUri, absolute);
+ Assert.AreEqual(expected, result);
+ }
+
+ [Test]
+ public void Get_Nice_Url_DomainsAndCache()
+ {
+ var routingContext = GetRoutingContext("/test", 1111);
+
+ ConfigurationManager.AppSettings.Set("umbracoUseDirectoryUrls", "true");
+ ConfigurationManager.AppSettings.Set("umbracoHideTopLevelNodeFromPath", "false"); // ignored w/domains
+
+ InitializeLanguagesAndDomains();
+ SetDomains4();
+
+ string ignore;
+ ignore = routingContext.NiceUrlProvider.GetNiceUrl(1001, new Uri("http://domain1.com"), false);
+ ignore = routingContext.NiceUrlProvider.GetNiceUrl(10011, new Uri("http://domain1.com"), false);
+ ignore = routingContext.NiceUrlProvider.GetNiceUrl(100111, new Uri("http://domain1.com"), false);
+ ignore = routingContext.NiceUrlProvider.GetNiceUrl(10012, new Uri("http://domain1.com"), false);
+ ignore = routingContext.NiceUrlProvider.GetNiceUrl(100121, new Uri("http://domain1.com"), false);
+ ignore = routingContext.NiceUrlProvider.GetNiceUrl(10013, new Uri("http://domain1.com"), false);
+ ignore = routingContext.NiceUrlProvider.GetNiceUrl(1002, new Uri("http://domain1.com"), false);
+ ignore = routingContext.NiceUrlProvider.GetNiceUrl(1001, new Uri("http://domain2.com"), false);
+ ignore = routingContext.NiceUrlProvider.GetNiceUrl(10011, new Uri("http://domain2.com"), false);
+ ignore = routingContext.NiceUrlProvider.GetNiceUrl(100111, new Uri("http://domain2.com"), false);
+ ignore = routingContext.NiceUrlProvider.GetNiceUrl(1002, new Uri("http://domain2.com"), false);
+
+ var cachedRoutes = ((DefaultRoutesCache)routingContext.UmbracoContext.RoutesCache).GetCachedRoutes();
+ Assert.AreEqual(7, cachedRoutes.Count);
+
+ var cachedIds = ((DefaultRoutesCache)routingContext.UmbracoContext.RoutesCache).GetCachedIds();
+ Assert.AreEqual(7, cachedIds.Count);
+
+ CheckRoute(cachedRoutes, cachedIds, 1001, "1001/");
+ CheckRoute(cachedRoutes, cachedIds, 10011, "10011/");
+ CheckRoute(cachedRoutes, cachedIds, 100111, "10011/1001-1-1");
+ CheckRoute(cachedRoutes, cachedIds, 10012, "10012/");
+ CheckRoute(cachedRoutes, cachedIds, 100121, "10012/1001-2-1");
+ CheckRoute(cachedRoutes, cachedIds, 10013, "1001/1001-3");
+ CheckRoute(cachedRoutes, cachedIds, 1002, "/1002");
+
+ // use the cache
+ Assert.AreEqual("/", routingContext.NiceUrlProvider.GetNiceUrl(1001, new Uri("http://domain1.com"), false));
+ Assert.AreEqual("/en", routingContext.NiceUrlProvider.GetNiceUrl(10011, new Uri("http://domain1.com"), false));
+ Assert.AreEqual("/en/1001-1-1", routingContext.NiceUrlProvider.GetNiceUrl(100111, new Uri("http://domain1.com"), false));
+ Assert.AreEqual("/fr", routingContext.NiceUrlProvider.GetNiceUrl(10012, new Uri("http://domain1.com"), false));
+ Assert.AreEqual("/fr/1001-2-1", routingContext.NiceUrlProvider.GetNiceUrl(100121, new Uri("http://domain1.com"), false));
+ Assert.AreEqual("/1001-3", routingContext.NiceUrlProvider.GetNiceUrl(10013, new Uri("http://domain1.com"), false));
+ Assert.AreEqual("/1002", routingContext.NiceUrlProvider.GetNiceUrl(1002, new Uri("http://domain1.com"), false));
+
+ Assert.AreEqual("http://domain1.com/fr/1001-2-1", routingContext.NiceUrlProvider.GetNiceUrl(100121, new Uri("http://domain2.com"), false));
+ }
+
+ void CheckRoute(IDictionary routes, IDictionary ids, int id, string route)
+ {
+ Assert.IsTrue(routes.ContainsKey(id));
+ Assert.AreEqual(route, routes[id]);
+ Assert.IsTrue(ids.ContainsKey(route));
+ Assert.AreEqual(id, ids[route]);
+ }
+ }
+}
diff --git a/src/Umbraco.Tests/Umbraco.Tests.csproj b/src/Umbraco.Tests/Umbraco.Tests.csproj
index f35cdee1e5..81d32c037a 100644
--- a/src/Umbraco.Tests/Umbraco.Tests.csproj
+++ b/src/Umbraco.Tests/Umbraco.Tests.csproj
@@ -68,6 +68,7 @@
+
diff --git a/src/Umbraco.Tests/UriUtilityTests.cs b/src/Umbraco.Tests/UriUtilityTests.cs
index eed7df2baa..f01e065e86 100644
--- a/src/Umbraco.Tests/UriUtilityTests.cs
+++ b/src/Umbraco.Tests/UriUtilityTests.cs
@@ -1,28 +1,90 @@
using System;
+using System.Configuration;
using NUnit.Framework;
using Umbraco.Web;
namespace Umbraco.Tests
{
+ // fixme - not testing virtual directory!
+
[TestFixture]
public class UriUtilityTests
{
+ // test normal urls
+ [TestCase("http://LocalHost/", "http://localhost/")]
+ [TestCase("http://LocalHost/?x=y", "http://localhost/?x=y")]
+ [TestCase("http://LocalHost/Home", "http://localhost/home")]
+ [TestCase("http://LocalHost/Home?x=y", "http://localhost/home?x=y")]
+ [TestCase("http://LocalHost/Home/Sub1", "http://localhost/home/sub1")]
+ [TestCase("http://LocalHost/Home/Sub1?x=y", "http://localhost/home/sub1?x=y")]
- [TestCase("http://Localhost/", "http://localhost/")]
- [TestCase("http://localhost/default.aspx", "http://localhost/")]
- [TestCase("http://localhost/default.aspx?test=blah", "http://localhost/?test=blah")]
- [TestCase("http://localhost/home/Sub1", "http://localhost/home/sub1")]
- [TestCase("http://localhost/home/Sub1.aspx", "http://localhost/home/sub1")]
- [TestCase("http://localhost/home/Sub1.aspx?test=blah", "http://localhost/home/sub1?test=blah")]
- [TestCase("http://Localhost/home/sub1.aspx/blah", "http://localhost/home/sub1/blah")]
- [TestCase("http://Localhost/home/sub1.aspx/blah?test=asdf", "http://localhost/home/sub1/blah?test=asdf")]
- public void Uri_To_Umbraco(string url, string expected)
+ // same with .aspx
+ [TestCase("http://LocalHost/Home.aspx", "http://localhost/home")]
+ [TestCase("http://LocalHost/Home.aspx?x=y", "http://localhost/home?x=y")]
+ [TestCase("http://LocalHost/Home/Sub1.aspx", "http://localhost/home/sub1")]
+ [TestCase("http://LocalHost/Home/Sub1.aspx?x=y", "http://localhost/home/sub1?x=y")]
+
+ // test that the trailing slash goes but not on hostname
+ [TestCase("http://LocalHost/", "http://localhost/")]
+ [TestCase("http://LocalHost/Home/", "http://localhost/home")]
+ [TestCase("http://LocalHost/Home/?x=y", "http://localhost/home?x=y")]
+ [TestCase("http://LocalHost/Home/Sub1/", "http://localhost/home/sub1")]
+ [TestCase("http://LocalHost/Home/Sub1/?x=y", "http://localhost/home/sub1?x=y")]
+
+ // test that default.aspx goes, even with parameters
+ [TestCase("http://LocalHost/deFault.aspx", "http://localhost/")]
+ [TestCase("http://LocalHost/deFault.aspx?x=y", "http://localhost/?x=y")]
+
+ // test with inner .aspx
+ [TestCase("http://Localhost/Home/Sub1.aspx/Sub2", "http://localhost/home/sub1/sub2")]
+ [TestCase("http://Localhost/Home/Sub1.aspx/Sub2?x=y", "http://localhost/home/sub1/sub2?x=y")]
+ [TestCase("http://Localhost/Home.aspx/Sub1.aspx/Sub2?x=y", "http://localhost/home/sub1/sub2?x=y")]
+ [TestCase("http://Localhost/deFault.aspx/Home.aspx/deFault.aspx/Sub1.aspx", "http://localhost/home/default/sub1")]
+
+ public void Uri_To_Umbraco(string sourceUrl, string expectedUrl)
{
- var uri = new Uri(url);
- var expectedUri = new Uri(expected);
- var result = UriUtility.UriToUmbraco(uri);
+ var expectedUri = new Uri(expectedUrl);
+ var sourceUri = new Uri(sourceUrl);
+ var resultUri = UriUtility.UriToUmbraco(sourceUri);
- Assert.AreEqual(expectedUri.ToString(), result.ToString());
+ Assert.AreEqual(expectedUri.ToString(), resultUri.ToString());
+ }
+
+ // test directoryUrl false, trailingSlash false
+ [TestCase("/", "/", false, false)]
+ [TestCase("/home", "/home.aspx", false, false)]
+ [TestCase("/home/sub1", "/home/sub1.aspx", false, false)]
+
+ // test directoryUrl false, trailingSlash true
+ [TestCase("/", "/", false, true)]
+ [TestCase("/home", "/home.aspx", false, true)]
+ [TestCase("/home/sub1", "/home/sub1.aspx", false, true)]
+
+ // test directoryUrl true, trailingSlash false
+ [TestCase("/", "/", true, false)]
+ [TestCase("/home", "/home", true, false)]
+ [TestCase("/home/sub1", "/home/sub1", true, false)]
+
+ // test directoryUrl true, trailingSlash true
+ [TestCase("/", "/", true, true)]
+ [TestCase("/home", "/home/", true, true)]
+ [TestCase("/home/sub1", "/home/sub1/", true, true)]
+
+ public void Uri_From_Umbraco(string sourceUrl, string expectedUrl, bool directoryUrls, bool trailingSlash)
+ {
+ ConfigurationManager.AppSettings.Set("umbracoUseDirectoryUrls", directoryUrls ? "true" : "false");
+ Umbraco.Core.Configuration.UmbracoSettings.AddTrailingSlash = trailingSlash;
+
+ var expectedUri = NewUri(expectedUrl);
+ var sourceUri = NewUri(sourceUrl);
+ var resultUri = UriUtility.UriFromUmbraco(sourceUri);
+
+ Assert.AreEqual(expectedUri.ToString(), resultUri.ToString());
+ }
+
+ Uri NewUri(string url)
+ {
+ return new Uri(url, url.StartsWith("http:") ? UriKind.Absolute : UriKind.Relative);
}
}
}
\ No newline at end of file
diff --git a/src/Umbraco.Web/DefaultPublishedContentStore.cs b/src/Umbraco.Web/DefaultPublishedContentStore.cs
index 82cf091e03..69df99713e 100644
--- a/src/Umbraco.Web/DefaultPublishedContentStore.cs
+++ b/src/Umbraco.Web/DefaultPublishedContentStore.cs
@@ -38,33 +38,24 @@ namespace Umbraco.Web
if (route == null) throw new ArgumentNullException("route");
//set the default to be what is in the settings
- if (hideTopLevelNode == null)
- {
- hideTopLevelNode = GlobalSettings.HideTopLevelNodeFromPath;
- }
+ hideTopLevelNode = hideTopLevelNode ?? GlobalSettings.HideTopLevelNodeFromPath;
//the route always needs to be lower case because we only store the urlName attribute in lower case
route = route.ToLowerInvariant();
- string startNodeIdString = "0";
- string path = route;
- if (!route.StartsWith("/"))
- {
- int pos = route.IndexOf('/');
- startNodeIdString = route.Substring(0, pos);
- path = route.Substring(pos + 1);
- }
- int startNodeId = int.Parse(startNodeIdString);
+ int pos = route.IndexOf('/');
+ string path = pos == 0 ? route : route.Substring(pos);
+ int startNodeId = pos == 0 ? 0 : int.Parse(route.Substring(0, pos));
var xpath = CreateXpathQuery(startNodeId, path, hideTopLevelNode.Value);
//check if we can find the node in our xml cache
var found = GetXml(umbracoContext).SelectSingleNode(xpath);
- //this check is because we allow root nodes that don't have a domain assigned, if
- //the previous check fails, we will check if this is a root node (based purely on it having a path with only 1 '/' which it is prefixed with)
- //if it is a root node, we'll try to find it again without hiding top level nodes
- if (found == null && path.ToCharArray().Count(x => x == '/') == 1)
+ // if hideTopLevelNodePath is true then for url /foo we looked for /*/foo
+ // but maybe that was the url of a non-default top-level node, so we also
+ // have to look for /foo (see note in NiceUrlProvider).
+ if (found == null && hideTopLevelNode.Value && path.Length > 1 && path.IndexOf('/', 1) < 0)
{
xpath = CreateXpathQuery(startNodeId, path, false);
found = GetXml(umbracoContext).SelectSingleNode(xpath);
diff --git a/src/Umbraco.Web/Routing/DefaultLastChanceLookup.cs b/src/Umbraco.Web/Routing/DefaultLastChanceLookup.cs
index 038233f4e6..76c1ee22cb 100644
--- a/src/Umbraco.Web/Routing/DefaultLastChanceLookup.cs
+++ b/src/Umbraco.Web/Routing/DefaultLastChanceLookup.cs
@@ -16,6 +16,20 @@ namespace Umbraco.Web.Routing
///
internal class DefaultLastChanceLookup : IDocumentLastChanceLookup
{
+ // notes
+ //
+ // at the moment we load the legacy INotFoundHandler
+ // excluding those that have been replaced by proper lookups,
+ // and run them.
+ //
+ // when we finaly obsolete INotFoundHandler, we'll have to move
+ // over here code from legacy requestHandler.hande404, which
+ // basically uses umbraco.library.GetCurrentNotFoundPageId();
+ // which also would need to be refactored / migrated here.
+ //
+ // the best way to do this would be to create a DefaultLastChanceLookup2
+ // that would do everything by itself, and let ppl use it if they
+ // want, then make it the default one, then remove this one.
///
/// Tries to find and assign an Umbraco document to a DocumentRequest.
@@ -98,22 +112,24 @@ namespace Umbraco.Web.Routing
{
var assemblyName = n.Attributes.GetNamedItem("assembly").Value;
- // skip those that are in umbraco.dll because we have
- // replaced them with ILookups already -- so we just
- // want to load user-defined NotFound handlers...
- if (assemblyName == "umbraco")
- continue;
-
var typeName = n.Attributes.GetNamedItem("type").Value;
string ns = assemblyName;
var nsAttr = n.Attributes.GetNamedItem("namespace");
if (nsAttr != null && !string.IsNullOrWhiteSpace(nsAttr.Value))
ns = nsAttr.Value;
- Type type = null;
- LogHelper.Debug("Registering '{0}.{1},{2}'.", () => ns, () => typeName, () => assemblyName);
-
- try
+ if (assemblyName == "umbraco" && (ns + "." + typeName) != "umbraco.handle404")
+ {
+ // skip those that are in umbraco.dll because we have replaced them with IDocumentLookups
+ // but do not skip "handle404" as that's the built-in legacy final handler, and for the time
+ // being people will have it in their config.
+ continue;
+ }
+
+ LogHelper.Debug("Registering '{0}.{1},{2}'.", () => ns, () => typeName, () => assemblyName);
+
+ Type type = null;
+ 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!!
diff --git a/src/Umbraco.Web/Routing/DocumentNotFoundHandler.cs b/src/Umbraco.Web/Routing/DocumentNotFoundHandler.cs
index e578e8d5a7..51a508397f 100644
--- a/src/Umbraco.Web/Routing/DocumentNotFoundHandler.cs
+++ b/src/Umbraco.Web/Routing/DocumentNotFoundHandler.cs
@@ -14,21 +14,32 @@ namespace Umbraco.Web.Routing
internal void WriteOutput(HttpContext context)
{
- context.Response.StatusCode = 404;
+ var response = context.Response;
- context.Response.Write("Page not found
");
- UmbracoContext.Current.HttpContext.Response.Write("No umbraco document matches the url '" + HttpUtility.HtmlEncode(UmbracoContext.Current.ClientUrl) + "'.
");
+ response.Clear();
+ response.StatusCode = 404;
- // fixme - should try to get infos from the DocumentRequest?
+ var docreq = UmbracoContext.Current.DocumentRequest;
+ var reason = "Cannot render the page at url '{0}'.";
+ if (!docreq.HasNode)
+ reason = "No umbraco document matches the url '{0}'.";
+ else if (!docreq.HasTemplate)
+ reason = "No template exists to render the document at url '{0}'.";
- context.Response.Write("This page can be replaced with a custom 404. Check the documentation for \"custom 404\".
");
- context.Response.Write("This page is intentionally left ugly ;-)
");
- context.Response.Write("");
+ response.Write("Page not found
");
+ response.Write("");
+ response.Write(string.Format(reason, HttpUtility.HtmlEncode(UmbracoContext.Current.ClientUrl)));
+ 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("");
+
+ response.End();
}
public bool IsReusable
{
- get { return false; }
+ get { return true; }
}
}
}
diff --git a/src/Umbraco.Web/Routing/DocumentRequestBuilder.cs b/src/Umbraco.Web/Routing/DocumentRequestBuilder.cs
index 4c53886d3b..6ab2df3e38 100644
--- a/src/Umbraco.Web/Routing/DocumentRequestBuilder.cs
+++ b/src/Umbraco.Web/Routing/DocumentRequestBuilder.cs
@@ -185,6 +185,7 @@ namespace Umbraco.Web.Routing
// handle not found
if (!_documentRequest.HasNode)
{
+ _documentRequest.Is404 = true;
LogHelper.Debug("{0}No document, try last chance lookup", () => tracePrefix);
// if it fails then give up, there isn't much more that we can do
@@ -370,6 +371,17 @@ namespace Umbraco.Web.Routing
var template = Template.GetByAlias(templateAlias);
_documentRequest.Template = template;
}
+
+ if (!_documentRequest.HasTemplate)
+ {
+ LogHelper.Debug("{0}No template was found.");
+ // do not do it if we're already 404 else it creates an infinite loop
+ if (Umbraco.Core.Configuration.UmbracoSettings.HandleMissingTemplateAs404 && !_documentRequest.Is404)
+ {
+ LogHelper.Debug("{0}Assume page not found (404).");
+ _documentRequest.Document = null;
+ }
+ }
}
///
diff --git a/src/Umbraco.Web/Routing/LookupByNiceUrl.cs b/src/Umbraco.Web/Routing/LookupByNiceUrl.cs
index c5ed09e770..4e584b167c 100644
--- a/src/Umbraco.Web/Routing/LookupByNiceUrl.cs
+++ b/src/Umbraco.Web/Routing/LookupByNiceUrl.cs
@@ -42,12 +42,14 @@ namespace Umbraco.Web.Routing
{
LogHelper.Debug("Test route \"{0}\"", () => route);
- //return '0' if in preview mode!
+ // first ask the cache for a node
+ // return '0' if in preview mode
var nodeId = !docreq.RoutingContext.UmbracoContext.InPreviewMode
? docreq.RoutingContext.UmbracoContext.RoutesCache.GetNodeId(route)
: 0;
-
+ // if a node was found, get it by id and ensure it exists
+ // else clear the cache
IDocument node = null;
if (nodeId > 0)
{
@@ -66,6 +68,7 @@ namespace Umbraco.Web.Routing
}
}
+ // if we still have no node, get it by route
if (node == null)
{
LogHelper.Debug("Cache miss, query");
@@ -78,10 +81,9 @@ namespace Umbraco.Web.Routing
docreq.Document = node;
LogHelper.Debug("Query matches, id={0}", () => docreq.DocumentId);
+ // do not store if previewing
if (!docreq.RoutingContext.UmbracoContext.InPreviewMode)
- {
- docreq.RoutingContext.UmbracoContext.RoutesCache.Store(docreq.DocumentId, route); // will not write if previewing
- }
+ docreq.RoutingContext.UmbracoContext.RoutesCache.Store(docreq.DocumentId, route);
}
else
diff --git a/src/Umbraco.Web/Routing/NiceUrlProvider.cs b/src/Umbraco.Web/Routing/NiceUrlProvider.cs
index 41addb9c5c..21fb08e5bb 100644
--- a/src/Umbraco.Web/Routing/NiceUrlProvider.cs
+++ b/src/Umbraco.Web/Routing/NiceUrlProvider.cs
@@ -4,11 +4,11 @@ using System.Linq;
using System.Web;
using Umbraco.Core;
+using Umbraco.Core.IO;
using Umbraco.Core.Logging;
using Umbraco.Web.Routing;
using umbraco;
-using umbraco.IO;
using umbraco.cms.businesslogic.web;
namespace Umbraco.Web.Routing
@@ -55,63 +55,67 @@ namespace Umbraco.Web.Routing
/// The url is absolute or relative depending on the current url, unless absolute is true, and then it is always absolute.
public string GetNiceUrl(int nodeId, Uri current, bool absolute)
{
- Uri domainUri = null;
+ Uri domainUri;
+ string path;
- // will not read cache if previewing!
+ // do not read cache if previewing
var route = _umbracoContext.InPreviewMode
? null
: _umbracoContext.RoutesCache.GetRoute(nodeId);
if (!string.IsNullOrEmpty(route))
{
- domainUri = nodeId > 0 ? DomainUriAtNode(nodeId, current) : null;
+ // there was a route in the cache - extract domainUri and path
+ // route is / or /
+ int pos = route.IndexOf('/');
+ path = pos == 0 ? route : route.Substring(pos);
+ domainUri = pos == 0 ? null : DomainUriAtNode(int.Parse(route.Substring(0, pos)), current);
}
else
{
- var originalNode = _publishedContentStore.GetDocumentById(_umbracoContext, nodeId);
- if (originalNode == null)
+ // there was no route in the cache - create a route
+ var node = _publishedContentStore.GetDocumentById(_umbracoContext, nodeId);
+ if (node == null)
{
LogHelper.Warn(
- "Couldn't find any page with the nodeId = {0}. This is most likely caused by the page isn't published!",
+ "Couldn't find any page with nodeId={0}. This is most likely caused by the page not being published.",
nodeId);
return "#";
}
-
-
+
+ // walk up from that node until we hit a node with a domain,
+ // or we reach the content root, collecting urls in the way
var pathParts = new List();
- int id = nodeId;
- domainUri = DomainUriAtNode(id, current);
- var recursiveNode = originalNode;
- while (domainUri == null && id > 0)
+ var n = node;
+ domainUri = DomainUriAtNode(n.Id, current);
+ while (domainUri == null && n != null) // n is null at root
{
- var urlName = recursiveNode.UrlName;
+ // get the url
+ var urlName = n.UrlName;
pathParts.Add(urlName);
- recursiveNode = recursiveNode.Parent; // set to parent node
- if (recursiveNode == null)
- {
- id = -1;
- }
- else
- {
- id = recursiveNode.Id;
- }
- domainUri = id > 0 ? DomainUriAtNode(id, current) : null;
+
+ // move to parent node
+ n = n.Parent;
+ domainUri = n == null ? null : DomainUriAtNode(n.Id, current);
}
// no domain, respect HideTopLevelNodeFromPath for legacy purposes
if (domainUri == null && global::umbraco.GlobalSettings.HideTopLevelNodeFromPath)
{
- //here we need to determine if this node is another root node (next sibling(s) to the first) because
- // in that case, we do not remove the path part. In theory, like in v5, this node would require
- // a domain assigned but to maintain compatibility we'll add this check
- if (originalNode.Parent == null)
+ // in theory if hideTopLevelNodeFromPath is true, then there should be only once
+ // top-level node, or else domains should be assigned. but for backward compatibility
+ // we add this check - we look for the document matching "/" and if it's not us, then
+ // we do not hide the top level path
+ // it has to be taken care of in IPublishedContentStore.GetDocumentByRoute too so if
+ // "/foo" fails (looking for "/*/foo") we try also "/foo".
+ // this does not make much sense anyway esp. if both "/foo/" and "/bar/foo" exist, but
+ // that's the way it works pre-4.10 and we try to be backward compat for the time being
+ if (node.Parent == null)
{
var rootNode = _publishedContentStore.GetDocumentByRoute(_umbracoContext, "/", true);
- if (rootNode.Id == originalNode.Id)
- {
+ if (rootNode.Id == node.Id) // remove only if we're the default node
pathParts.RemoveAt(pathParts.Count - 1);
- }
}
else
{
@@ -119,15 +123,18 @@ namespace Umbraco.Web.Routing
}
}
-
+ // assemble the route
pathParts.Reverse();
- route = "/" + string.Join("/", pathParts);
+ path = "/" + string.Join("/", pathParts); // will be "/" or "/foo" or "/foo/bar" etc
+ route = (n == null ? "" : n.Id.ToString()) + path;
+ // do not store if previewing
if (!_umbracoContext.InPreviewMode)
_umbracoContext.RoutesCache.Store(nodeId, route);
}
- return AssembleUrl(domainUri, route, current, absolute).ToString();
+ // assemble the url from domainUri (maybe null) and path
+ return AssembleUrl(domainUri, path, current, absolute).ToString();
}
///
@@ -198,21 +205,27 @@ namespace Umbraco.Web.Routing
if (domainUri == null)
{
// no domain was found : return a relative url, add vdir if any
- uri = new Uri(global::umbraco.IO.SystemDirectories.Root + path, UriKind.Relative);
+ uri = new Uri(SystemDirectories.Root + path, UriKind.Relative);
}
else
{
// a domain was found : return an absolute or relative url
// cannot handle vdir, has to be in domain uri
if (!absolute && current != null && domainUri.GetLeftPart(UriPartial.Authority) == current.GetLeftPart(UriPartial.Authority))
- uri = new Uri(domainUri.AbsolutePath.TrimEnd('/') + path, UriKind.Relative); // relative
+ uri = new Uri(CombinePaths(domainUri.AbsolutePath, path), UriKind.Relative); // relative
else
- uri = new Uri(domainUri.GetLeftPart(UriPartial.Path).TrimEnd('/') + path); // absolute
+ uri = new Uri(CombinePaths(domainUri.GetLeftPart(UriPartial.Path), path)); // absolute
}
return UriUtility.UriFromUmbraco(uri);
}
+ string CombinePaths(string path1, string path2)
+ {
+ string path = path1.TrimEnd('/') + path2;
+ return path == "/" ? path : path.TrimEnd('/');
+ }
+
IEnumerable AssembleUrls(IEnumerable domainUris, string path, Uri current)
{
if (domainUris.Any())
@@ -222,7 +235,7 @@ namespace Umbraco.Web.Routing
else
{
// no domain was found : return a relative url, add vdir if any
- return new Uri[] { new Uri(global::umbraco.IO.SystemDirectories.Root + path, UriKind.Relative) };
+ return new Uri[] { new Uri(SystemDirectories.Root + path, UriKind.Relative) };
}
}
diff --git a/src/Umbraco.Web/Routing/NoTemplateHandler.cs b/src/Umbraco.Web/Routing/NoTemplateHandler.cs
index 43ba2cd6c8..8131d0f195 100644
--- a/src/Umbraco.Web/Routing/NoTemplateHandler.cs
+++ b/src/Umbraco.Web/Routing/NoTemplateHandler.cs
@@ -14,18 +14,16 @@ namespace Umbraco.Web.Routing
internal void WriteOutput(HttpContext context)
{
- context.Response.Clear();
- context.Response.Write("");
- context.Response.End();
+ var response = context.Response;
+
+ response.Clear();
+ response.Write("");
+ response.End();
}
public bool IsReusable
{
- get
- {
- //yes this is reusable since it always returns the same thing
- return true;
- }
+ get { return true; }
}
}
}
\ No newline at end of file
diff --git a/src/Umbraco.Web/UmbracoModule.cs b/src/Umbraco.Web/UmbracoModule.cs
index d5b400e3bd..a351bd4541 100644
--- a/src/Umbraco.Web/UmbracoModule.cs
+++ b/src/Umbraco.Web/UmbracoModule.cs
@@ -103,7 +103,7 @@ namespace Umbraco.Web
var searcher = new DocumentRequestBuilder(docreq);
//find domain
searcher.LookupDomain();
- //redirect if it has been flagged
+ // redirect if it has been flagged
if (docreq.IsRedirect)
httpContext.Response.Redirect(docreq.RedirectUrl, true);
//set the culture on the thread
@@ -116,32 +116,37 @@ namespace Umbraco.Web
//TODO: here we should launch an event so that people can modify the doc request to do whatever they want.
- //redirect if it has been flagged
+ // 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
+ // handle 404
if (docreq.Is404)
{
- httpContext.RemapHandler(new DocumentNotFoundHandler());
+ httpContext.Response.StatusCode = 404;
+
+ if (!docreq.HasNode)
+ httpContext.RemapHandler(new DocumentNotFoundHandler());
+ else if (!docreq.HasTemplate)
+ httpContext.RemapHandler(new NoTemplateHandler());
+
+ // else we have a document to render
}
- else
+
+ if (docreq.HasNode && docreq.HasTemplate)
{
+ // everything is ready to pass off to our handlers (mvc or webforms)
+ // still need to setup a few things to deal with legacy code
- //ok everything is ready to pass off to our handlers (mvc or webforms) but we need to setup a few things
- //mostly to do with legacy code,etc...
-
- //we need to complete the request which assigns the page back to the docrequest to make it available for legacy handlers like default.aspx
+ // assign the legagcy page back to the docrequest
+ // handlers like default.aspx will want it
docreq.UmbracoPage = new page(docreq);
- //this is required for many legacy things in umbraco to work
+ // these two are used by many legacy objects
httpContext.Items["pageID"] = docreq.DocumentId;
-
- //this is again required by many legacy objects
- httpContext.Items.Add("pageElements", docreq.UmbracoPage.Elements);
+ httpContext.Items["pageElements"] = docreq.UmbracoPage.Elements;
RewriteToUmbracoHandler(HttpContext.Current, uri.Query, docreq.RenderingEngine);
-
}
}
}
diff --git a/src/Umbraco.Web/UriUtility.cs b/src/Umbraco.Web/UriUtility.cs
index 596228e10d..34d7cead12 100644
--- a/src/Umbraco.Web/UriUtility.cs
+++ b/src/Umbraco.Web/UriUtility.cs
@@ -78,16 +78,17 @@ namespace Umbraco.Web
//if this is the case we need to change it to '/'
if (path.StartsWith("/default.aspx", StringComparison.InvariantCultureIgnoreCase))
{
- path = "/" + path.Substring("/default.aspx".Length, path.Length - "/default.aspx".Length);
+ string rempath = path.Substring("/default.aspx".Length, path.Length - "/default.aspx".Length);
+ path = rempath.StartsWith("/") ? rempath : "/" + rempath;
+ }
+ if (path != "/")
+ {
+ path = path.TrimEnd('/');
}
- if (path != "/")
- path = path.TrimEnd('/');
//if any part of the path contains .aspx, replace it with nothing.
//sometimes .aspx is not at the end since we might have /home/sub1.aspx/customtemplate
path = path.Replace(".aspx", "");
- //if (path.EndsWith(".aspx"))
- // path = path.Substring(0, path.Length - ".aspx".Length);
return uri.Rewrite(path);
}