Skip to content

Commit 9e2733c

Browse files
zpqrtbnknul800sebastiaan
authored andcommitted
U4-2549 - fix issue with last chance content finder
Conflicts: src/Umbraco.Web/Umbraco.Web.csproj Conflicts: src/Umbraco.Web/Umbraco.Web.csproj
1 parent fbfdd8d commit 9e2733c

File tree

8 files changed

+273
-113
lines changed

8 files changed

+273
-113
lines changed

src/Umbraco.Web.UI/config/404handlers.Release.config

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,5 @@
33
<notFound assembly="umbraco" type="SearchForAlias" />
44
<notFound assembly="umbraco" type="SearchForTemplate"/>
55
<notFound assembly="umbraco" type="SearchForProfile"/>
6-
<notFound assembly="umbraco" type="handle404"/>
6+
<notFound assembly="umbraco" type="handle404" last="true"/>
77
</NotFoundHandlers>

src/Umbraco.Web.UI/config/404handlers.config

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,5 @@
33
<notFound assembly="umbraco" type="SearchForAlias" />
44
<notFound assembly="umbraco" type="SearchForTemplate"/>
55
<notFound assembly="umbraco" type="SearchForProfile"/>
6-
<notFound assembly="umbraco" type="handle404"/>
6+
<notFound assembly="umbraco" type="handle404" last="true"/>
77
</NotFoundHandlers>

src/Umbraco.Web/Routing/AliasUrlProvider.cs

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -88,14 +88,25 @@ public IEnumerable<string> GetOtherUrls(UmbracoContext umbracoContext, int id, U
8888

8989
#region Utilities
9090

91-
private bool FindByUrlAliasEnabled
91+
private static bool FindByUrlAliasEnabled
9292
{
9393
get
9494
{
95-
var hasFinder = ContentFinderResolver.Current.ContainsType<ContentFinderByUrlAlias>();
96-
var hasHandler = ContentFinderResolver.Current.ContainsType<ContentFinderByNotFoundHandlers>()
97-
&& NotFoundHandlerHelper.CustomHandlerTypes.Contains(typeof(global::umbraco.SearchForAlias));
98-
return hasFinder || hasHandler;
95+
// finder
96+
if (ContentFinderResolver.Current.ContainsType<ContentFinderByUrlAlias>())
97+
return true;
98+
99+
// handler wrapped into a finder
100+
if (ContentFinderResolver.Current.ContainsType<ContentFinderByNotFoundHandler<global::umbraco.SearchForAlias>>())
101+
return true;
102+
103+
// handler wrapped into special finder
104+
if (ContentFinderResolver.Current.ContainsType<ContentFinderByNotFoundHandlers>()
105+
&& NotFoundHandlerHelper.IsNotFoundHandlerEnabled<global::umbraco.SearchForAlias>())
106+
return true;
107+
108+
// anything else, we can't detect
109+
return false;
99110
}
100111
}
101112

src/Umbraco.Web/Routing/ContentFinderByNotFoundHandlers.cs

Lines changed: 41 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -29,114 +29,76 @@ public bool TryFindContent(PublishedContentRequest docRequest)
2929

3030
#region Copied over and adapted from presentation.requestHandler
3131

32-
void HandlePageNotFound(PublishedContentRequest docRequest)
32+
private static void HandlePageNotFound(PublishedContentRequest docRequest)
3333
{
3434
var url = NotFoundHandlerHelper.GetLegacyUrlForNotFoundHandlers();
3535
LogHelper.Debug<ContentFinderByNotFoundHandlers>("Running for legacy url='{0}'.", () => url);
3636

37-
foreach (var handler in GetNotFoundHandlers())
37+
foreach (var handler in NotFoundHandlerHelper.GetNotFoundHandlers())
3838
{
39-
IContentFinder finder = null;
4039
var handlerName = handler.GetType().FullName;
41-
4240
LogHelper.Debug<ContentFinderByNotFoundHandlers>("Handler '{0}'.", () => handlerName);
4341

44-
// replace with our own implementation
45-
if (handler is global::umbraco.SearchForAlias)
46-
finder = new ContentFinderByUrlAlias();
47-
else if (handler is global::umbraco.SearchForProfile)
48-
finder = new ContentFinderByProfile();
49-
else if (handler is global::umbraco.SearchForTemplate)
50-
finder = new ContentFinderByNiceUrlAndTemplate();
51-
else if (handler is global::umbraco.handle404)
52-
finder = new ContentFinderByLegacy404();
53-
42+
var finder = NotFoundHandlerHelper.SubsituteFinder(handler);
5443
if (finder != null)
5544
{
5645
var finderName = finder.GetType().FullName;
5746
LogHelper.Debug<ContentFinderByNotFoundHandlers>("Replace handler '{0}' by new finder '{1}'.", () => handlerName, () => finderName);
58-
if (finder.TryFindContent(docRequest))
59-
{
60-
// do NOT set docRequest.PublishedContent again here as
61-
// it would clear any template that the finder might have set
62-
LogHelper.Debug<ContentFinderByNotFoundHandlers>("Finder '{0}' found node with id={1}.", () => finderName, () => docRequest.PublishedContent.Id);
63-
if (docRequest.Is404)
64-
LogHelper.Debug<ContentFinderByNotFoundHandlers>("Finder '{0}' set status to 404.", () => finderName);
65-
66-
// if we found a document, break, don't look at more handler -- we're done
67-
break;
68-
}
69-
70-
// if we did not find a document, continue, look at other handlers
71-
continue;
72-
}
73-
74-
// else it's a legacy handler, run
7547

76-
if (handler.Execute(url) && handler.redirectID > 0)
77-
{
78-
var redirectId = handler.redirectID;
79-
docRequest.PublishedContent = docRequest.RoutingContext.UmbracoContext.ContentCache.GetById(redirectId);
48+
// can't find a document => continue with other handlers
49+
if (finder.TryFindContent(docRequest) == false)
50+
continue;
8051

81-
if (!docRequest.HasPublishedContent)
82-
{
83-
LogHelper.Debug<ContentFinderByNotFoundHandlers>("Handler '{0}' found node with id={1} which is not valid.", () => handlerName, () => redirectId);
84-
break;
85-
}
52+
// found a document => break, don't run other handlers, we're done
8653

87-
LogHelper.Debug<ContentFinderByNotFoundHandlers>("Handler '{0}' found valid node with id={1}.", () => handlerName, () => redirectId);
54+
// in theory an IContentFinder can return true yet set no document
55+
// but none of the substitued finders (see SubstituteFinder) do it.
8856

89-
if (docRequest.RoutingContext.UmbracoContext.HttpContext.Response.StatusCode == 404)
90-
{
91-
LogHelper.Debug<ContentFinderByNotFoundHandlers>("Handler '{0}' set status code to 404.", () => handlerName);
92-
docRequest.Is404 = true;
93-
}
57+
// do NOT set docRequest.PublishedContent again here
58+
// as it would clear any template that the finder might have set
9459

95-
//// check for caching
96-
//if (handler.CacheUrl)
97-
//{
98-
// if (url.StartsWith("/"))
99-
// url = "/" + url;
60+
LogHelper.Debug<ContentFinderByNotFoundHandlers>("Finder '{0}' found node with id={1}.", () => finderName, () => docRequest.PublishedContent.Id);
61+
if (docRequest.Is404)
62+
LogHelper.Debug<ContentFinderByNotFoundHandlers>("Finder '{0}' set status to 404.", () => finderName);
10063

101-
// var cacheKey = (currentDomain == null ? "" : currentDomain.Name) + url;
102-
// var culture = currentDomain == null ? null : currentDomain.Language.CultureAlias;
103-
// SetCache(cacheKey, new CacheEntry(handler.redirectID.ToString(), culture));
104-
105-
// HttpContext.Current.Trace.Write("NotFoundHandler",
106-
// string.Format("Added to cache '{0}', {1}.", url, handler.redirectID));
107-
//}
108-
109-
// if we found a document, break, don't look at more handler -- we're done
64+
LogHelper.Debug<ContentFinderByNotFoundHandlers>("Handler '{0}' found valid node with id={1}.", () => handlerName, () => docRequest.PublishedContent.Id);
11065
break;
11166
}
11267

113-
// if we did not find a document, continue, look at other handlers
114-
}
115-
}
68+
// else it's a legacy handler: run
11669

117-
IEnumerable<INotFoundHandler> GetNotFoundHandlers()
118-
{
119-
// instanciate new handlers
120-
// using definition cache
70+
// can't find a document => continue with other handlers
71+
if (handler.Execute(url) == false || handler.redirectID <= 0)
72+
continue;
12173

122-
var handlers = new List<INotFoundHandler>();
74+
// found a document ID => ensure it's a valid document
75+
var redirectId = handler.redirectID;
76+
docRequest.PublishedContent = docRequest.RoutingContext.UmbracoContext.ContentCache.GetById(redirectId);
12377

124-
foreach (var type in NotFoundHandlerHelper.CustomHandlerTypes)
125-
{
126-
try
78+
if (docRequest.HasPublishedContent == false)
12779
{
128-
var handler = Activator.CreateInstance(type) as INotFoundHandler;
129-
if (handler != null)
130-
handlers.Add(handler);
80+
// the handler said it could handle the url, and returned a content ID
81+
// yet that content ID is invalid... should we run the other handlers?
82+
// I don't think so, not here, let the "last chance" finder take care.
83+
// so, break.
84+
85+
LogHelper.Debug<ContentFinderByNotFoundHandlers>("Handler '{0}' found node with id={1} which is not valid.", () => handlerName, () => redirectId);
86+
break;
13187
}
132-
catch (Exception e)
88+
89+
// found a valid document => break, don't run other handlers, we're done
90+
91+
LogHelper.Debug<ContentFinderByNotFoundHandlers>("Handler '{0}' found valid node with id={1}.", () => handlerName, () => redirectId);
92+
93+
if (docRequest.RoutingContext.UmbracoContext.HttpContext.Response.StatusCode == 404)
13394
{
134-
LogHelper.Error<ContentFinderByNotFoundHandlers>(string.Format("Error instanciating handler {0}, ignoring.", type.FullName), e);
95+
LogHelper.Debug<ContentFinderByNotFoundHandlers>("Handler '{0}' set status code to 404.", () => handlerName);
96+
docRequest.Is404 = true;
13597
}
136-
}
13798

138-
return handlers;
139-
}
99+
break;
100+
}
101+
}
140102

141103
#endregion
142104
}
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using Umbraco.Core;
4+
using Umbraco.Core.Logging;
5+
using Umbraco.Core.Models;
6+
using umbraco.interfaces;
7+
8+
namespace Umbraco.Web.Routing
9+
{
10+
/// <summary>
11+
/// Provides an implementation of <see cref="IContentFinder"/> that runs legacy <c>INotFoundHandler</c> in "last chance" situation.
12+
/// </summary>
13+
public class ContentLastChanceFinderByNotFoundHandlers : IContentFinder
14+
{
15+
// notes
16+
//
17+
// at the moment we load the legacy INotFoundHandler
18+
// excluding those that have been replaced by proper finders,
19+
// and run them.
20+
21+
/// <summary>
22+
/// Tries to find and assign an Umbraco document to a <c>PublishedContentRequest</c>.
23+
/// </summary>
24+
/// <param name="docRequest">The <c>PublishedContentRequest</c>.</param>
25+
/// <returns>A value indicating whether an Umbraco document was found and assigned.</returns>
26+
public bool TryFindContent(PublishedContentRequest docRequest)
27+
{
28+
HandlePageNotFound(docRequest);
29+
return docRequest.HasPublishedContent;
30+
}
31+
32+
#region Copied over and adapted from presentation.requestHandler
33+
34+
private static void HandlePageNotFound(PublishedContentRequest docRequest)
35+
{
36+
var url = NotFoundHandlerHelper.GetLegacyUrlForNotFoundHandlers();
37+
LogHelper.Debug<ContentLastChanceFinderByNotFoundHandlers>("Running for legacy url='{0}'.", () => url);
38+
39+
var handler = NotFoundHandlerHelper.GetNotFoundLastChanceHandler();
40+
var handlerName = handler.GetType().FullName;
41+
LogHelper.Debug<ContentLastChanceFinderByNotFoundHandlers>("Handler '{0}'.", () => handlerName);
42+
43+
var finder = NotFoundHandlerHelper.SubsituteFinder(handler);
44+
if (finder != null)
45+
{
46+
var finderName = finder.GetType().FullName;
47+
LogHelper.Debug<ContentLastChanceFinderByNotFoundHandlers>("Replace handler '{0}' by new finder '{1}'.", () => handlerName, () => finderName);
48+
49+
// can't find a document => exit
50+
if (finder.TryFindContent(docRequest) == false)
51+
return;
52+
53+
// found a document => we're done
54+
55+
// in theory an IContentFinder can return true yet set no document
56+
// but none of the substitued finders (see SubstituteFinder) do it.
57+
58+
// do NOT set docRequest.PublishedContent again here
59+
// as it would clear any template that the finder might have set
60+
61+
LogHelper.Debug<ContentLastChanceFinderByNotFoundHandlers>("Finder '{0}' found node with id={1}.", () => finderName, () => docRequest.PublishedContent.Id);
62+
if (docRequest.Is404)
63+
LogHelper.Debug<ContentLastChanceFinderByNotFoundHandlers>("Finder '{0}' set status to 404.", () => finderName);
64+
65+
LogHelper.Debug<ContentLastChanceFinderByNotFoundHandlers>("Handler '{0}' found valid node with id={1}.", () => handlerName, () => docRequest.PublishedContent.Id);
66+
return;
67+
}
68+
69+
// else it's a legacy handler, run
70+
71+
// can't find a document => exit
72+
if (handler.Execute(url) == false || handler.redirectID <= 0)
73+
return;
74+
75+
// found a document ID => ensure it's a valid document
76+
var redirectId = handler.redirectID;
77+
docRequest.PublishedContent = docRequest.RoutingContext.UmbracoContext.ContentCache.GetById(redirectId);
78+
79+
if (docRequest.HasPublishedContent == false)
80+
{
81+
// the handler said it could handle the url, and returned a content ID
82+
// yet that content ID is invalid... exit.
83+
84+
LogHelper.Debug<ContentLastChanceFinderByNotFoundHandlers>("Handler '{0}' found node with id={1} which is not valid.", () => handlerName, () => redirectId);
85+
return;
86+
}
87+
88+
// found a valid document => return
89+
90+
LogHelper.Debug<ContentLastChanceFinderByNotFoundHandlers>("Handler '{0}' found valid node with id={1}.", () => handlerName, () => redirectId);
91+
92+
if (docRequest.RoutingContext.UmbracoContext.HttpContext.Response.StatusCode == 404)
93+
{
94+
LogHelper.Debug<ContentLastChanceFinderByNotFoundHandlers>("Handler '{0}' set status code to 404.", () => handlerName);
95+
docRequest.Is404 = true;
96+
}
97+
}
98+
99+
#endregion
100+
}
101+
}

0 commit comments

Comments
 (0)