Give Document node custom routes but keep default route?

I have a document node that lives at /news/ and I want to keep that route but I always want any /news/YEAR/MONTH/ route to get served up by the same document node. I did some digging but am very confused by a few of the options and they all seem to either do redirects or override the default node url as well.

Is what I am looking to do possible?

So what are the options that you found and why are they confusing?

I’m also curious why you want to keep the existing route? That requirement makes it harder and doesn’t make sense from a SEO perspective. So I’m curious what you want to do :slight_smile:

Hi @Eaglef90

Do you mean that your /news/YEAR/MONTH should show a news listing for that year/month combination? If so, then it won’t be the same as /news/ which presumably shows all news?

You can create a view component or partial if you want to re-use functionality to filter and display a news listing, then just include that view component on those pages - the /news/ page would be unfiltered and the /news/YEAR/MONTH/ page would use the same view component or partial but filtered by month and year.

A few assumptions there but I’m guessing that’s what you are trying to achieve?

Justin

The initial design was that /news/ was going to be a landing page and provide snippets of the last 15 published articles, then /news/YEAR/MONTH/ would be an archive page and show a snippet for all articles published in that month of that year. /news/YEAR/ would be an invalud ULR. Articles would be served up from /news/ARTICLEI am using the invisible node package to make the YEAR and MONTH nodes not render URLs in umbraco and the thought was just to have the news node handle all the traffic and just parse out the YEAR and MONTH from the URL. I have a helper file that would deal with pulling the relevant nodes and process there information for display as snippets.

I did this in the old version of my site but I was not using the invisible node package and instead had a News node then udner that just a YEAR-MONTH node and used the built in custom umbraco URL property to give it the right URL.

Thinking on this now I don’t want /news/ to act as a place for the last 15 nodes. My new navigation layout makes this a bad fit for the site. So I would now just I am thinking that /news/ would just 404 and the news node would just handle /news/YEAR/MONTH/ so still need to figure out how to do that.

I looked at IContentFinder for this and honestly could not follow the page’s information to well, mostly about how to regiser the custom finder. I had looked at IVirtualPageController as well but that seems to be geared for usage on custom controlers and views and not rendering Umbraco conetnt nodes. Thought about URL Rewrites but I don’t want to loose the URL so, as far as my understanding goes, that is not the right solution. I also saw a bit of talk about IUrlProvider in the docs but nothing with examples or a defined usage of that without hitting AI yet so I am confused on how to use it or if it is applicable in this case.

Hi @Eaglef90

I got AI to summarise them for you:

  1. IContentFinder — maps an inbound URL to a content node; runs in collection order until one returns true.
  2. IContentLastChanceFinder — same thing, but for custom 404 handling.
  3. IVirtualPageController — custom MVC route that still runs in the Umbraco pipeline; FindContent supplies the current page.
  4. ForUmbracoPage() — same job, content found at route registration instead; no attribute routing.
  5. IUrlProvider — outbound, decides the URL rendered for a node; v17 adds GetPreviewUrlAsync and Alias.
  6. IUrlSegmentProvider — outbound, decides a single node’s segment rather than the whole URL.
  7. Change a URL outbound and you need a matching IContentFinder inbound, or the page becomes unroutable.

Are you actually creating YEAR/MONTH nodes under News in the CMS or do these not exist as nodes? If they don’t exist, you will need to implement an IVirtualPageController to render content when no route matches a node.

There’s an example here:

This example uses products, which don’t exist in the CMS, so the virtual page controller is used to handle /products/xxx to render a product from a custom store outside the CMS, but could easily be used to render another page.

If you are creating YEAR/MONTH nodes, then just use their templates to render a view component or partial that does what you need it to do.

Justin

Yes, that is the approach. What you actually need is a single page that can display news snippits and the URL should act as filters.

For that approach you need an IContentFinder. An IContentFinder takes a path and maps it to a node. ALL urls you mention /news, /news/month/year all map to the same node. The code for that page parses the path and decides based on that what snippits to show; like I said, the URL acts as filters.

If you also want to reflect the various URLs in the backoffice of Umbraco in the ‘info’ tab and want Umbraco to give you the correct URLs when you request .URL on a node, you need custom IUrlProviders/IUrlSegmentProviders to make that happen. Umbraco’s outbound and inbound URLs are disconnected, so any custom routing usually takes effort to do both.

This is something AI in the context of the Umbraco source can really help you with.

Another maybe simpler option.. which you did mention, you don’t have to redirect, you can rewrite

urlRewrite either native IIS or via asp.net

var rewriteOptions = new RewriteOptions()
            .AddRewrite("^news/(\\d{2})/(\\d{4})$", "/news?month=$1&year=$2", skipRemainingRules: true);
app.UseRewriter(rewriteOptions);

/news/month/year rewritten to /news?month=01&year=2026 (but the browser would still show the oringinal url) and then your news page can show content based on the querystring.. much simpler implementation if you can go that way..

For some reason I had it in my head that rewrite would change the displayed URL. After your suggestion I did dig into it more and found out my memory was wrong. Thanks for pointing that out. I will be evaluating the aproches again and moving forward with my build from there.