Getting the URL after being routed from custom IContentFinder

I have successfuly built a custom IContentFinder extention that routes /news/YEAR/MONTH/ to my NewsPage Document but when I load up the page and check Model.URL() it always just returns /news/ so I can’t parse out the YEAR and MONTH values even though I still see them in the browser’s URL. How can I pull these values at the template level so I can parse them and act on them as needed?

I should say, I can pull the Razor Page’s Context request but was not sure if there is a better way to do it since it’s umbraco.

Hi @Eaglef90

The model will always refer to the content you found and set in the IContentFinder. You have two options, either read the URL from HttpContest.Request.Path and parse it to get the year and month in your view, or better still do it in your IContentFinder and save it to the HttpContext.Items cache which you can then access in your template.

Here is an AI example:

public class NewsArchiveContentFinder : IContentFinder
{
    private readonly IUmbracoContextAccessor _umbracoContextAccessor;

    public NewsArchiveContentFinder(IUmbracoContextAccessor umbracoContextAccessor)
    {
        _umbracoContextAccessor = umbracoContextAccessor;
    }

    public Task<bool> TryFindContent(IPublishedRequestBuilder contentRequest)
    {
        var path = contentRequest.Uri.AbsolutePath;
        var match = Regex.Match(path, @"^/news/(\d{4})/(\d{2})/?$");

        if (!match.Success)
        {
            return Task.FromResult(false);
        }

        if (!_umbracoContextAccessor.TryGetUmbracoContext(out var umbracoContext))
        {
            return Task.FromResult(false);
        }

        var newsPage = umbracoContext.Content?.GetAtRoot()
            .DescendantsOrSelf<NewsPage>()
            .FirstOrDefault();

        if (newsPage is null)
        {
            return Task.FromResult(false);
        }

        contentRequest.SetPublishedContent(newsPage);
        contentRequest.HttpContext.Items["NewsYear"] = match.Groups[1].Value;
        contentRequest.HttpContext.Items["NewsMonth"] = match.Groups[2].Value;

        return Task.FromResult(true);
    }
}

Justin

Thanks. You say “better still do it in your IContentFinder” why is that better?

Hi @Eaglef90

For separation of concerns - logic like that should go into C# code to keep your presentation code separate from any other logic. Only code for rendering output should go into your templates.

Justin

Serperation of concens makes sense. And just a note on that AI code. IT is broken. IPublishedRequestBuilder does not contain an HttpContext in it and it also seems to no have a GetAtroot() method. If I remember from my digging that method was removed in v15 or 16.

However… :wink:

You’ve not decoupled the concern here.. you’ve tightly coupled the News rendering to the IContentFinder with its HttpContent.items magic strings..

The IContentFinder’s only job is what it was actually built for: identifying the NewsPage node and setting it on the request.

So then, inside your ViewComponent or partial, you simply inspect HttpContext.Request.Path (or split the path segments) directly to grab the year and month. Which you will already be doing in a viewComponent or partial if you want your separation of concerns.. (and you might already have page controls to choose month/year to also pass)

Self-contained components: Your ViewComponent knows how to read the URL it cares about without depending on a pre-processing step upstream.
No hidden state: You aren’t relying on HttpContext.Items to ferry data across the request lifecycle.

I’m still not sure that IContentFinder is the simplest approach when iisrewrite could map before any asp.net overheads are incurred..

Then your ViewComponent or partial doesn’t even need to parse path segments—it just reads standard query string parameters (Context.Request.Query["year"]), which works whether someone hits the clean URL or a traditional query string URL.

:person_shrugging:

My take on IContentFinder over .htaccess/iisrewrite rule/asp.net UseRewriter() for, if you forgive, me simple usecases is…

if you need access to DI, maybe an external service,
if culture might be invovled,
if you want to map to a discovered ContentType of NewsPage.. over the simple /News/ which might break down the line if the url was updated to /Latest-News/… but then we do have umbraco helping with an automatic redirect :thinking:

Hi @mistyn8

I don’t think an IContentFinder is the correct approach here either, but that’s the choice @Eaglef90 has made and as I mentioned in his other thread, a view component would be more suitable.

https://forum.umbraco.com/t/give-document-node-custom-routes-but-keep-default-route/8547

My reply about separation of concerns was about avoiding parsing the URL in a template as that’s not rendering logic. If he wants to use an IContentFinder then the template still needs to know about the original URL if he wants to use those parameters. Obviously without seeing his code or knowing his requirements, we are just trying to give our best advice based on what is asked here.

No doubt we could debate all day about the right or wrong approach, but ultimately I think that is just going to muddy the waters even more for @Eaglef90 and make things even more confusing.

Justin

I appreciate your comments and feedback @mistyn8

Thank you all for the input.

I am not sure where is the best place to put the parsing of the query string and consumption for the template’s usage. At this point it is setup to use the HttpContext.Items and that is working so in order to continue trying to meet my deadline I will be leaving it as is.

I made the call for IcontentFinder as that seemed to be the most robust way for my setup. It is a muti-site install and not ever site has a news secetion. With the IContentFinder I can grab the address according to the strick RegEx and then find the right news page to route it to.

I has thought about using the URL Rewrite but I was not confident in it’s ability to work in a mutisite setup without having to be updated everytime a new site is added or even propertly working in this setup when a called site does not have a news section.

As for the template it is actually wired to a helper class on the backend that takes in the month/year combo and gets a formated snippet listing of all the postings for that month/year. There is no drop down select or anything. It would be either directly URL access from being typed in or clicking a link in the navigation menu.

I am sure I am probibily doing this all wrong. I work as a janitor 6 nights a week 55 hours a week and trying to develop this site and the custom plugins on top of keeping my own few employess working on projects has made keeping this whole design hard for me to follow. But for now things are working as I want them to so it is time for me to move onto the next problems to deal with.

I appreaciate the help and input on all this and feel free to discuss among yourselfs approches and design choices but please keep in mind I will not be around to provide feed back after this. This forums is not an area that is good for me so I will be leaving it. Maybe one day if I become a better developer I will return but for now I will not be attending to anything more here beyond reading threads if my research into the next stupid problem I run into brings me here.

Sorry to hear that you feel the need to leave.. My intention was solely to offer a pragmatic view vs separation of concerns.. All approaches and opinions are equally valid, and I do remember my journey with umbraco started with do everything in a template. :face_with_peeking_eye:
If you do continue with Umbraco you will, if you haven’t already, find that there are countless ways to skin that proverbial cat.. and that’s the beauty for me choose a methodolgy and approach that suits you and not an enforced best practice.

But glad that you have something that works for your requirements! :clap:

Hi @Eaglef90

Sorry to hear that, as @mistyn8 says we are here to offer you help and guidance. Everyone has their own opinions and things can easily end up down rabbit holes. Everyone’s experience and journey differs.

Feel free to ask questions - if the replies go off topic or difficult to follow please feel free to say so (or just stop replying/commenting).

Justin

@mistyn8 Please do not think you did anything wrong, you did not. Your feed back and insight are valued and I apreciate you giving it. Along with the insight and feedback from @justin-nevitech

For a while I have not fealt like this is the right place for me. I have had the same problem with a few other places, Stackoverflow is one. It, for the most part, is more me then anyone here,

I will be continuing with Umbraco, even continueing with the development of my two custom plugins that I do want to release to the marketplace.

I have a hard time explaining things and an even harder type transposing thought to text. So when I saw the emails of your replays I wanted to pop in one last time to assure you as best as I can that it is not because of anything either of you have done that I am steping away. THis is a choice derived from my overall exerpainces on this forum and my choices of how I approche things along with the limitations of my abilites.