Set domain on root node but skip to next child node for home page
I'm working on a multi-site setup (with multiple domains) and was wondering if something like this is possible:
So I set the domain (e.g. site-1.com) on the root node (Site 1), but that is just a 'virtual node' without any template.
But by default this will now get the home URL as well (site-1.com/) and the actual home page node (Home) will get the site-1.com/home/ URL.
Is there any way I can skip the root node and have the first child node as the home URL?
I'm thinking it might need a custom UrlProvider to achieve this, but not sure how to best implement this.
The reason why I haven't set the domain on the Home node is because I need a handful of pages in the Website Components folder as well (with a template and URL), and assigning site-1.com to Home and site-1.com/website-components to Website Components doesn't seem to work when linking to one of those pages from the home page (plus I'd rather set the domain in single place).
On your Site 1 node, add a property called umbracoInternalRedirectId and make it's type a content picker. Then pick the home node you want to redirect to.
This property is a clever build in property that will perform an internal redirect and show the correct page instead.
Although that would work to 'redirect' to the right home page, in the CMS it would still show site-1.com/home/ as the URL of the Home page. And I would like to get rid of that as well.
Another option is to assign the domain to the home node instead of the root node. Although I'm not quite sure how that will work as it's not something I've tried.
I think I have managed to get it working with a custom UrlProvider and ContentFinder:
public class SiteUrlProvider : DefaultUrlProvider
{
public override IEnumerable<string> GetOtherUrls(UmbracoContext umbracoContext, int id, Uri current)
{
var urls = base.GetOtherUrls(umbracoContext, id, current);
var content = umbracoContext.ContentCache.GetById(id);
if (content?.DocumentTypeAlias == MySite.ModelTypeAlias)
{
// add the node ID to the URL, since this shouldn't be the home page URL
urls = urls.Select(u => $"{u}{id}/");
}
var homeNode = content?.AncestorOrSelf<MyHomePage>();
if (homeNode != null)
{
// remove the home node url name, since this should be the home page URL
urls = urls.Select(url =>
{
string path;
if (Uri.IsWellFormedUriString(url, UriKind.Absolute))
{
var uri = new Uri(url);
path = uri.GetAbsolutePathDecoded();
}
else
{
path = url;
}
var newPath = path.TrimStart($"/{homeNode.UrlName}/").EnsureStartsWith("/");
url = url.Replace(path, newPath);
return url;
});
}
return urls;
}
public override string GetUrl(UmbracoContext umbracoContext, int id, Uri current, UrlProviderMode mode)
{
var url = base.GetUrl(umbracoContext, id, current, mode);
var content = umbracoContext.ContentCache.GetById(id);
if (content?.DocumentTypeAlias == MySite.ModelTypeAlias)
{
// add the node ID to the URL, since this shouldn't be the home page URL
url += $"{id}/";
}
var homeNode = content?.AncestorOrSelf<MyHomePage>();
if (homeNode != null)
{
// remove the home node url name, since this should be the home page URL
string path;
if (Uri.IsWellFormedUriString(url, UriKind.Absolute))
{
var uri = new Uri(url);
path = uri.GetAbsolutePathDecoded();
}
else
{
path = url;
}
var newPath = path.TrimStart($"/{homeNode.UrlName}/").EnsureStartsWith("/");
url = url.Replace(path, newPath);
}
return url;
}
}
And the ContentFinder class:
public class SiteContentFinder : IContentFinder
{
public bool TryFindContent(PublishedContentRequest docRequest)
{
var contentCache = docRequest.RoutingContext.UmbracoContext.ContentCache;
string route;
if (docRequest.HasDomain)
{
var domainNode = contentCache.GetById(docRequest.UmbracoDomain.RootContentId.Value);
// get first child node of domain node, as that will be the home node
var homeNode = domainNode?.Children.FirstOrDefault();
// include url name of the home node in the route path
route = docRequest.UmbracoDomain.RootContentId.ToString() + (homeNode != null ? $"/{homeNode.UrlName}" : null) +
DomainHelper.PathRelativeToDomain(docRequest.DomainUri, docRequest.Uri.GetAbsolutePathDecoded());
}
else
{
route = docRequest.Uri.GetAbsolutePathDecoded();
}
docRequest.PublishedContent = contentCache.GetByRoute(route);
return docRequest.PublishedContent != null;
}
}
Register them in the ApplicationStarting event before the defaults:
Set domain on root node but skip to next child node for home page
I'm working on a multi-site setup (with multiple domains) and was wondering if something like this is possible:
So I set the domain (e.g.
site-1.com
) on the root node (Site 1), but that is just a 'virtual node' without any template.But by default this will now get the home URL as well (
site-1.com/
) and the actual home page node (Home) will get thesite-1.com/home/
URL.Is there any way I can skip the root node and have the first child node as the home URL? I'm thinking it might need a custom UrlProvider to achieve this, but not sure how to best implement this.
The reason why I haven't set the domain on the Home node is because I need a handful of pages in the Website Components folder as well (with a template and URL), and assigning
site-1.com
to Home andsite-1.com/website-components
to Website Components doesn't seem to work when linking to one of those pages from the home page (plus I'd rather set the domain in single place).Hi Tom,
On your Site 1 node, add a property called umbracoInternalRedirectId and make it's type a
content picker
. Then pick the home node you want to redirect to.This property is a clever build in property that will perform an internal redirect and show the correct page instead.
More info:
Thanks,
Nik
Hi Nik,
Thanks for the suggestion.
Although that would work to 'redirect' to the right home page, in the CMS it would still show
site-1.com/home/
as the URL of the Home page. And I would like to get rid of that as well.Hi Tom,
One option is to have a redirect of /home to /
Another option is to assign the domain to the home node instead of the root node. Although I'm not quite sure how that will work as it's not something I've tried.
Nik
I think I have managed to get it working with a custom
UrlProvider
andContentFinder
:And the
ContentFinder
class:Register them in the ApplicationStarting event before the defaults:
is working on a reply...