IContentFinder to handle 404's doc types with no template
Hi all, I've made an implementation of the IContentFinder to pick up on 404's and redirect them to a desired node. Everything work's fine when I set the contentRequest.PublishedContent to the node I want to display when a 404 occurs
However if the path of a URL is set a node of which the document type has no template then I get to see the standard 404 notification (No template exists to render the document at url '/submitted-contact-forms/').
I've tried using contentRequest.SetIsInitialPublishedContent() after I assigned my 404 node to contentRequest.PublishedContent but no luck.
Here's the simplified version of my code;
public class _404iLastChanceFinder : IContentFinder {
public bool TryFindContent(PublishedContentRequest contentRequest) {
if (contentRequest.Is404) {
var home = contentRequest.RoutingContext.UmbracoContext.ContentCache.GetByRoute("/");
var notFoundNode = home.Children.FirstOrDefault(x => x.DocumentTypeAlias == "error_404");
if (notFoundNode != null) {
contentRequest.SetResponseStatus(404, notFoundNode.HasProperty("title") ? notFoundNode.GetPropertyValue("title").ToString() : "404");
contentRequest.PublishedContent = notFoundNode;
}
return contentRequest.PublishedContent != null;
} else {
return false;
}
}
}
Hooked it up via the ApplicationEventHandler
public class UmbracoApplication : ApplicationEventHandler {
protected override void ApplicationStarting(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext) {
ContentLastChanceFinderResolver.Current.SetFinder(new _404iLastChanceFinder());
}
}
This is the code we have for serving a page for 404 requests.
Contentfinder :
using Umbraco.Core.Configuration;
using Umbraco.Web;
using Umbraco.Web.Routing;
/// <summary>
/// The four oh four content finder.
/// </summary>
internal class FourOhFourContentFinder : IContentFinder
{
/// <summary>
/// Tries to find and assign an Umbraco document to a <c>PublishedContentRequest</c>.
/// </summary>
/// <param name="contentRequest">The <c>PublishedContentRequest</c>.</param>
/// <returns>A value indicating whether an Umbraco document was found and assigned.</returns>
/// <remarks>Optionally, can also assign the template or anything else on the document request, although that is not required.</remarks>
public bool TryFindContent(PublishedContentRequest contentRequest)
{
// Check request is a 404
if (contentRequest.Is404)
{
return contentRequest.PublishedContent != null;
}
var errorPage =
UmbracoContext.Current.ContentCache.GetSingleByXPath($"//error_404[@isDoc]");
if (errorPage != null)
{
// set content for the 404 page
contentRequest.PublishedContent = errorPage;
// Set Response Status to be HTTP 404
contentRequest.SetIs404();
}
return false;
}
}
Application start
public class UmbracoApplication : ApplicationEventHandler {
protected override void ApplicationStarting(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext) {
ContentFinderResolver.Current.InsertTypeBefore<ContentFinderByNotFoundHandlers, FourOhFourContentFinder>();
}
}
Thanks for the reply. In the code you provided there is a return contentRequest.PublishedContent != null; before assigning the errorpage node thus you still get redirected to the default 404 page. Remove the return but the problem remains unfortunately.
I overlooked something; I've hooked my implementation of the IContentFinder to the ContentLastChanceFinderResolver on application_start where your solution does so on the ContentFinderResolver.
Tried your solution again but unfortunately, if a page that's based on a document type without a template get's requested the FourOhFourContentFinder doesn't even get called and I still get to see the default 404 page.
My 404 page does have a template. Request to non-existent pages like example.com/foobartest123 get to see this custom 404 page
I've noticed another subtle difference between how the implementation of the IContentFinder is hooked up inside the application_start. I did so by using the ContentLastChanceFinderResolver while yours used the ContentFinderResolver.
Tried it again but unfortunately a page request that has it's document type based on one without a template get's redirected to the default 404 page.
Whereas e.g. the non-existent page example.com/foobar get's to see my custom 404 page (it does have a template).
Whilst debugging i've noticed that the FourOhFourContentFinder doesn't even get called.
I've changed the 404handlers.config and set the trySkipIisCustomErrors to true. PassThrough value was already there. Still no luck.
I'm going to try this out on a clean umbraco installation to see if I've missed something.
IContentFinder to handle 404's doc types with no template
Hi all, I've made an implementation of the IContentFinder to pick up on 404's and redirect them to a desired node. Everything work's fine when I set the
contentRequest.PublishedContent
to the node I want to display when a 404 occurs However if the path of a URL is set a node of which the document type has no template then I get to see the standard 404 notification (No template exists to render the document at url '/submitted-contact-forms/').I've tried using
contentRequest.SetIsInitialPublishedContent()
after I assigned my 404 node tocontentRequest.PublishedContent
but no luck.Here's the simplified version of my code;
Hooked it up via the ApplicationEventHandler
Hi Tom,
This is the code we have for serving a page for 404 requests.
Contentfinder :
Application start
This works perfectly for us.
Dave
Hi Dave,
Thanks for the reply. In the code you provided there is a
return contentRequest.PublishedContent != null;
before assigning the errorpage node thus you still get redirected to the default 404 page. Remove thereturn
but the problem remains unfortunately.Hi Tom,
Does your 404 page have a template assigned ? It needs a template to be rendered.
Dave
I overlooked something; I've hooked my implementation of the IContentFinder to the
ContentLastChanceFinderResolver
onapplication_start
where your solution does so on theContentFinderResolver
.Tried your solution again but unfortunately, if a page that's based on a document type without a template get's requested the
FourOhFourContentFinder
doesn't even get called and I still get to see the default 404 page.My 404 page does have a template. Request to non-existent pages like example.com/foobartest123 get to see this custom 404 page
I've noticed another subtle difference between how the implementation of the
IContentFinder
is hooked up inside theapplication_start
. I did so by using theContentLastChanceFinderResolver
while yours used theContentFinderResolver
.Tried it again but unfortunately a page request that has it's document type based on one without a template get's redirected to the default 404 page. Whereas e.g. the non-existent page example.com/foobar get's to see my custom 404 page (it does have a template). Whilst debugging i've noticed that the
FourOhFourContentFinder
doesn't even get called.Hi Tom,
Maybe it's related to some config :
I notice that we have removed this from config/404handlers.config
In config/umbracoSettings.config we have the following set
trySkipIisCustomErrors
to true in theweb.routing
sectionIn our web.config we have the following tag in our
system.webServer
sectionCan you check your configuration ?
Dave
Hi Dave,
I've changed the
404handlers.config
and set thetrySkipIisCustomErrors
totrue
.PassThrough
value was already there. Still no luck. I'm going to try this out on a clean umbraco installation to see if I've missed something.Hi Tom,
This is for when the request is already marked as 404. So there is no need to set the 404 page again.
Dave
is working on a reply...