Routing in Umbraco Part 1: URL segments
Tags: umbraco, dotnet, routing, cms
Published: 2024-05-30 17:19:44

If you have ever paid attention to the URL structure of nodes in Umbraco while going hard at your various Umbraco endeavours, you might have noticed that URLs are generated based on a node's placement in the content tree followed by its name. Usually this poses no issue but what if you wanted to change how the URL is made? 

Say, for example, that you have a blog and you would like the create date (year) of each post shown in the URL. How would you do this?

You _could_ use one of the [built-in property type aliases](https://docs.umbraco.com/umbraco-cms/reference/routing/routing-properties) such as _umbracoUrlName_, as Umbraco will use that property instead of the node's name for the URL segment:

_Textstring_ property with _umbracoUrlName_ as the alias:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d3a4tgzhe4bvxfkjgv82.png)

New URL:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/70ayfvq3sj8enfvebfbp.png)


However, who wants to do this for each blog posts? 

Luckily Umbraco has some tricks up its sleeve and allows you to easily change how URLs behave by using your own URL providers.


## Creating your own URL segment provider

Create a class that implements `IUrlSegmentProvider`. All the magic will take place in `GetUrlSegment()`:

```c#
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.Strings;

namespace Adventures;

public class BlogPostUrlSegmentProvider : IUrlSegmentProvider
{
    private readonly IUrlSegmentProvider _segmentProvider;

    public BlogPostUrlSegmentProvider(IShortStringHelper shortStringHelper)
    {
        _segmentProvider = new DefaultUrlSegmentProvider(shortStringHelper);
    }

    public string? GetUrlSegment(IContentBase content, string? culture = null)
    {
        // Do code
    }
}
```

By using `_segmentProvider.GetUrlSegment(content, culture)` we can get the current URL segment for the given node and its culture. 

In order to prepend the year of the blog post to the URL, all you have to do is make sure `content.CreateDate.Year` is part the string that is returned.

`CreateDate` is used for simplicity's sake. Typically you would want a separate `DateTime` property to assign a _publish_ date. Otherwise, a post that you started in December of a given year but is not published until January will have the previous year in the URL - and you might not want that :-)

```c#
public string? GetUrlSegment(IContentBase content, string? culture = null)
{
    if (content.ContentType.Alias != "blogPost")
        return null;

    var segment = _segmentProvider.GetUrlSegment(content, culture);

    return $"{content.CreateDate.Year}-{segment}";
}
```

With the segment provider in place you can now register it:

```c#
using Umbraco.Cms.Core.Composing;

namespace Adventures;

public class BlogPostUrlComposer : IComposer
{
    public void Compose(IUmbracoBuilder builder)
    {
        builder.UrlSegmentProviders()
            .Insert<BlogPostUrlSegmentProvider>();
    }
}
```

If you have previously worked with custom URLs you might have experience with your own Content Finders. These are not required when only the segment is changed.

Build your solution and republish a relevant node in Umbraco and you will have an updated URL:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1dcgz7omm8dbh0o60q7d.png)

oh.. and if the node has previously been published, Umbraco will automatically created a redirect. Neat :-)