I'm used to using uComponents for my 404 management. But with version 7.1+ how do we get this setup?
I have this content tree:
Site - FR - Some pages... - I would like my 404 page to be here so I can edit the text with RTE - EN - Some pages... - I would like my 404 page to be here so I can edit the text with RTE
Has anyone got this setup with version 7.1+ ? Should I look into writing my own handler?
You might want to check out SEO Checker that does this and a lot of SEO related things for you out of the box. You can specify the 404 page using a picker for every configured domain/language. Free trial works on localhost.
Thanks Richard, that blog post looks like it's exactly what I'm looking for, I'll get that in my solution, will be useful forall my projects! Thanks! I'll post back if it worked!
Ok I think I have the basics in, but my problem is this, I have a Manage Hostnames set to my FR node. basically like this:
MySite - FR (Hostname: mysite.local)
My english node for this version of the website is not ready yet so I default to the french site and this way I don't see mysite.local/fr/[...].
Problem is that in my code, I run this:
var node = contentRequest.RoutingContext.UmbracoContext.ContentCache.GetByRoute(pathToNextNode);
I'm running this test with this "mysite.local/pageThatDoesNotExist", my pathToNextNode is then set to "/". Basically, I'm using the path to move up the content tree to find a node that will have a property "404Page" set, so that I can use that. My problem is that this GetByRoute, does not give me my FR node, but rather my Site node... It's like it's bypassing my hostname settings.
Ever seen this?
Bellow is the full code I'm running!
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Umbraco.Core;
using Umbraco.Web;
using Umbraco.Web.Routing;
// Needs interfaces and cms references
namespace PrixModeMtlCms.Code
{
public class Umbraco404Handler : IContentFinder
{
public bool TryFindContent(PublishedContentRequest contentRequest)
{
// Safety check, this should never occur
if (contentRequest != null)
{
// Check request is a 404
if (contentRequest.Is404)
{
var path = contentRequest.Uri.GetAbsolutePathDecoded();
// Reversed parts of the path
var parts = path.Split(new[] { '/' }, System.StringSplitOptions.RemoveEmptyEntries).Reverse();
// Loop up the parts, until you find a node
foreach (var part in parts)
{
// Remove the last part since it's not found
parts = parts.Where(x => x != part).ToArray();
var pathToNextNode = "/" + String.Join("/", parts);
// Try to find that node
var node = contentRequest.RoutingContext.UmbracoContext.ContentCache.GetByRoute(pathToNextNode);
// If we can't find that node either we'll let the loop continue
if (node == null)
{
continue;
}
// We've found a node, let's find our root nodes to find our 404 page
var site = node.AncestorOrSelf("Site");
var lang = node.AncestorOrSelf("AccueilLangage");
// Use lang or site
var nodeToUse = lang;
if (lang == null)
{
nodeToUse = site;
}
int notFoundNodeId = 0;
if (nodeToUse != null)
{
notFoundNodeId = nodeToUse.AsDynamic().page404; // Unset content picker, cast to int, will be 0
if (notFoundNodeId == 0)
{
notFoundNodeId = site.AsDynamic().page404;
}
}
// Get the 404 node
if (notFoundNodeId != 0)
{
var notFoundNode = contentRequest.RoutingContext.UmbracoContext.ContentCache.GetById(notFoundNodeId);
if (notFoundNode == null)
{
// The specified 404 node can't be found, break here and let resolve normally
break;
}
// Set Response Status to be HTTP 404
contentRequest.SetResponseStatus(404, "404 Page Not Found");
// Set the node to be the not found node
contentRequest.PublishedContent = notFoundNode;
}
}
}
}
// Finally, we return weather we have found a node to use for this request
return contentRequest.PublishedContent != null;
}
}
}
Edit: Fixed a bug that was in there. This runs good, but does not give me multilingual support, coming from the hostnames.
Ok! Strike that! I guess I had towrite the long version to figure out the short version. This works the way I want! (Well the minimum, I can scope creep later on :))
Turns out using contentRequest.Domain.RootNodeId was really smooth!
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Umbraco.Core;
using Umbraco.Web;
using Umbraco.Web.Routing;
// Needs interfaces and cms references
namespace MyNamespace.Code
{
public class Umbraco404Handler : IContentFinder
{
public bool TryFindContent(PublishedContentRequest contentRequest)
{
// Safety check, this should never occur
if (contentRequest != null)
{
// Check request is a 404
if (contentRequest.Is404)
{
var domainNode = contentRequest.RoutingContext.UmbracoContext.ContentCache.GetById(contentRequest.Domain.RootNodeId);
if (domainNode != null)
{
int notFoundNodeId = domainNode.AsDynamic().page404; // Unset content picker, cast to int, will be 0
if (notFoundNodeId != 0)
{
// Get the 404 node
var notFoundNode = contentRequest.RoutingContext.UmbracoContext.ContentCache.GetById(notFoundNodeId);
if (notFoundNode != null)
{
// Set Response Status to be HTTP 404
contentRequest.SetResponseStatus(404, "404 Page Not Found");
// Set the node to be the not found node
contentRequest.PublishedContent = notFoundNode;
}
}
}
}
}
// Finally, we return weather we have found a node to use for this request
return contentRequest.PublishedContent != null;
}
}
}
Looking to get 404 setup in a multi-lingual site
Hi!
I'm used to using uComponents for my 404 management. But with version 7.1+ how do we get this setup?
I have this content tree:
Site
- FR
- Some pages...
- I would like my 404 page to be here so I can edit the text with RTE
- EN
- Some pages...
- I would like my 404 page to be here so I can edit the text with RTE
Has anyone got this setup with version 7.1+ ? Should I look into writing my own handler?
Thanks much!
Hi,
You might want to check out SEO Checker that does this and a lot of SEO related things for you out of the box. You can specify the 404 page using a picker for every configured domain/language. Free trial works on localhost.
If you want to code it yourself you might want to check out this blogpost
Best,
Richard
+1 for SEO checker.
Thanks Richard, that blog post looks like it's exactly what I'm looking for, I'll get that in my solution, will be useful forall my projects! Thanks! I'll post back if it worked!
Hey Richard,
Ok I think I have the basics in, but my problem is this, I have a Manage Hostnames set to my FR node. basically like this:
MySite
- FR (Hostname: mysite.local)
My english node for this version of the website is not ready yet so I default to the french site and this way I don't see mysite.local/fr/[...].
Problem is that in my code, I run this:
I'm running this test with this "mysite.local/pageThatDoesNotExist", my pathToNextNode is then set to "/". Basically, I'm using the path to move up the content tree to find a node that will have a property "404Page" set, so that I can use that. My problem is that this GetByRoute, does not give me my FR node, but rather my Site node... It's like it's bypassing my hostname settings.
Ever seen this?
Bellow is the full code I'm running!
Edit: Fixed a bug that was in there. This runs good, but does not give me multilingual support, coming from the hostnames.
Ok! Strike that! I guess I had towrite the long version to figure out the short version. This works the way I want! (Well the minimum, I can scope creep later on :))
Turns out using contentRequest.Domain.RootNodeId was really smooth!
is working on a reply...