Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • Bogdan 250 posts 427 karma points
    Nov 25, 2013 @ 10:53
    Bogdan
    0

    Change URLs according to document type

    Hello,

    I'm looking for a way to change URLs based on document types. I tried to implement IUrlSegmentProvider as explained here, but GetUrlSegment is never hit. For example if normally the URL to a page is /path-to/some-page, I'd like to be able to change it to something like /[somestr]/[hardcodedstr]/[somepagename] if its document type is of a certain alias.

    public class UrlSegmentProvider : IUrlSegmentProvider
        {
            readonly IUrlSegmentProvider _provider = new DefaultUrlSegmentProvider();
    
            public string GetUrlSegment(IContentBase content, CultureInfo ci)
            {
                return GetUrlSegment(content);
            }
    
            public string GetUrlSegment(IContentBase content)
            {
                var segment = _provider.GetUrlSegment(content);
                return segment;
            }
        }
    

    Thanks!

  • Bogdan 250 posts 427 karma points
    Nov 25, 2013 @ 13:04
    Bogdan
    100

    I've figured out what I was doing wrong. First for what I need I should implement DefaultUrlProvider and also register the provider:

    protected override void ApplicationStarting(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)
            {
                UrlProviderResolver.Current.InsertTypeBefore<DefaultUrlProvider, MyUrlProvider>();
            }
    
  • Jeroen Breuer 4908 posts 12265 karma points MVP 4x admin c-trib
    Jul 25, 2014 @ 14:20
    Jeroen Breuer
    0

    Could you please show a full example of what you did to get something like /[somestr]/[hardcodedstr]/[somepagename] if its document type is of a certain alias?

    Jeroen

  • Bogdan 250 posts 427 karma points
    Jul 25, 2014 @ 15:42
    Bogdan
    0

    Hi Jeroen,

    Well, MyUrlProvider can be like this:

    public class MyUrlProvider : DefaultUrlProvider
    {
        public override string GetUrl(UmbracoContext umbracoContext, int id, Uri current, UrlProviderMode mode)
        {
            IPublishedContent node = umbracoContext.ContentCache.GetById(id);
    
            if (node.DocumentTypeAlias == "...")
            {
                return "[calculate a URL for the node]";
            }
    
            return base.GetUrl(umbracoContext, id, current, mode);
        }
    }
    

    To calculate the URL you can do something simple like this:

    List<String> pathToContent = new List<String>();
    
    IPublishedContent content = node;
    
    while (content.Level > 1)
    {
        pathToContent.Add(GetNodeUrlSegment(content, languageName));
    
        content = content.Parent;
    }
    
    pathToContent.Reverse();
    
    return String.Join("/", pathToContent);
    

    Please note the difference between the URL segment provider and the URL provider. The segment provider can be used to override only the segment of the URL for which a page is responsible, while the URL provider returns the full URL of that page.

    To override the default segment provider, add in ApplicationStarting:

    UrlSegmentProviderResolver.Current.InsertTypeBefore<DefaultUrlSegmentProvider, MyUrlSegmentProvider>();
    

    MyUrlSegmentProvider can be like in my original post.

    Also, don't forget about the built-in properties that can be used to override the URL of a node, umbracoUrlName and umbracoUrlAlias.

  • Bogdan 250 posts 427 karma points
    Jul 25, 2014 @ 15:46
    Bogdan
    0
    public class RegisterEvents : ApplicationEventHandler
    {
        protected override void ApplicationStarting(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)
        {
            UrlProviderResolver.Current.InsertTypeBefore<DefaultUrlProvider, MyUrlProvider>();
            //UrlSegmentProviderResolver.Current.InsertTypeBefore<DefaultUrlSegmentProvider, MyUrlSegmentProvider>();
        }
    }
    
  • Jeroen Breuer 4908 posts 12265 karma points MVP 4x admin c-trib
    Jul 28, 2014 @ 09:42
    Jeroen Breuer
    0

    Hello,

    Thanks for the example. I already tried something like the UrlProvider: https://gist.github.com/jbreuer/5e00f21c70285f448124

    The problem I had that if I change the url to something else for example "/test/28-07-2014/home" and I go to that url I get a 404. Do I also need to write a content finder if I change the url? If you change a url segment do you also get a 404?

    Jeroen

  • Jeroen Breuer 4908 posts 12265 karma points MVP 4x admin c-trib
    Jul 29, 2014 @ 11:17
    Jeroen Breuer
    0

    I had a talk with Stephane and if you change the url with the url provider you also need a content finder to map the new url to the content. You don't need a content finder if you change a url segment because it still matches the content tree structure.

    Jeroen

  • Ian Grainger 71 posts 135 karma points
    Oct 09, 2014 @ 12:19
    Ian Grainger
    1

    Thanks for the vague pointer, Jeroen! Because of that I finally got my custom UrlProvider to work! I had a SegmentProvider working fine, but when I tried to put abc/xyz in the URL it just 404'd.

    If anyone else comes here looking for how to do this (because the documentation isn't finished) My ContentFinder looks like this (mostly cribbed from another post I found on someone's blog):

    public class ContentFinder : IContentFinder
    {
        public bool TryFindContent(PublishedContentRequest contentRequest)
        {
            // only care about a subfolder
            if (contentRequest.Uri.Segments.Count() > 1 && contentRequest.Uri.Segments[1].ToLower() == "CustomisedFolder/")
            {
                var allNodes = uQuery.GetNodesByType("CustomisedTypeName").OrderByDescending(n => n.Level);
                foreach (var node in allNodes)
                {
                    string fullUri = contentRequest.Uri.AbsolutePath;
                    string parentUri = node.Url;
    
                    // if we're appending / to the URL, then remove it for comparison here:
                    if (node.Url.EndsWith("/"))
                    {
                        parentUri = node.Url.Substring(0, node.Url.Length - 1);
                    }
    
                    bool isMatch = fullUri.Equals(parentUri, StringComparison.InvariantCultureIgnoreCase);
    
                    if (isMatch)
                    {
                        contentRequest.PublishedContent = new UmbracoHelper(UmbracoContext.Current).TypedContent(node.Id);
                        return true;
                    }
                }
            }
            return false;
        }
    }

    Then you need to add the ContentFinderResolver, like with the UrlProviderResolver, above:

    public class RegisterEvents : ApplicationEventHandler
    {
        protected override void ApplicationStarting(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)
        {
            ContentFinderResolver.Current.InsertType();
            UrlProviderResolver.Current.InsertTypeBeforeMyUrlProvider>();
    } }

    Now I can finally create completely custom URLs for my Umbraco nodes!

  • Ian Grainger 71 posts 135 karma points
    Oct 10, 2014 @ 13:06
    Ian Grainger
    0

    I actually have a question about this - don't know if anyone will see this post so maybe I should make a new one, but here goes:

    The solution I posted doesn't deal with absolute URLs, so when we started calling library.NiceUrlWithDomain we were still given relative URLs - the problem is I can't work out how to correctly call the base classes to deal with multiple domains etc. At the moment that won't matter because the domain they request on will always be the correct domain.

    I've ended up with this to get relative and absolute URLs - but it's much more fragile than the code in Umbraco, but I can't seem to access some methods I need to - or work out how to call (for e.g.) DomainAndUri correctly.

    var relativeUriStr = "/NewUrl/";
    var domainUri = new Uri(current.GetLeftPart(UriPartial.Authority));
    if (mode == UrlProviderMode.AutoLegacy)
    {
        mode = UmbracoConfig.For.UmbracoSettings().RequestHandler.UseDomainPrefixes
            ? UrlProviderMode.Absolute
            : UrlProviderMode.Auto;
    }
    // assume we have a domain - and it'll always match
    if (mode == UrlProviderMode.Auto)
    {
        mode = UrlProviderMode.Relative;
    }
    
    var uriStr = "";
    switch (mode)
    {
        case UrlProviderMode.Absolute:
            uriStr = new Uri(domainUri, relativeUriStr).ToString();
            break;
        case UrlProviderMode.Relative:
            uriStr = relativeUriStr;
            break;
        default:
            throw new ArgumentOutOfRangeException("mode");
    }
    return uriStr;
Please Sign in or register to post replies

Write your reply to:

Draft