Copied to clipboard

Flag this post as spam?

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


  • Gordon Saxby 1335 posts 1596 karma points
    Nov 06, 2015 @ 11:27
    Gordon Saxby
    0

    umbracoUrlName not checking for duplicates?

    Using the property umbracoUrlName allows editors to alter the Url of a node ... and that works as expected.

    However, Umbraco does not seem to check for duplicates, as it does when creating nodes with the same name (doing that results in numbered versions - e.g. "test page (1)").

    So, we now have the situation where 2 pages have been created with different names but with the same umbracoUrlName value, giving them the same Url.

    E.g. this is possible

    Name = Test Page 1, umbracoUrlName = testpage, Url = /testpage Name = Test Page 2, umbracoUrlName = testpage, Url = /testpage

    I assume this is a bug? Is there an easy work around or code fix?

    We are using v7.2.8

  • Marc Goodson 1154 posts 7677 karma points MVP 4x c-trib
    Nov 08, 2015 @ 22:27
    Marc Goodson
    0

    Hi Gordon

    Yes, it has always been possible to create Urls which clash with umbracoUrlName and also with umbracoUrlAlias. Umbraco picks the first node it finds in umbraco.config cache file which matches the url.

    umbracoUrlName and umbracoUrlAlias give the editor the power to override the default umbraco Url, but with this power comes the responsibility to not muck it up!

    Which I've found catches people out sometimes.

    In code you could work around this, you can could capture the Publishing Event, and check if any siblings of the saved node had a clashing url Name.

    The gist of which is like so:

     public class RegisterDuplicateUrlNameDetector : ApplicationEventHandler
        {
            protected override void ApplicationStarting
                          (UmbracoApplicationBase umbracoApplication,
                           ApplicationContext applicationContext)
            {
                ContentService.Publishing += ContentServicePublishing;
            }
    
            static void ContentServicePublishing(IPublishingStrategy sender,
                                                        PublishEventArgs<IContent> e)
    {
    
        foreach (var content in e.PublishedEntities){
            // get content items UrlName - (more than one content item could be being published, hence the foreach)
            var contentUrlName = content.HasProperty("umbracoUrlName") &&
                                 !String.IsNullOrEmpty(content.GetValue<string>("umbracoUrlName"))
                ? content.GetValue<string>("umbracoUrlName")
                : content.Name;
    
            //get sibling content, eg published nodes at the same level in the tree that could contain a clashing url
            if (content.Parent().Children().Any(f=>f.Id != content.Id && f.Published))
            {
                foreach (var sibling in content.Parent().Children().Where(f => f.Id != content.Id && f.Published))
                {
                // get each sibling UrlName
                  var  siblingUrlName = sibling.HasProperty("umbracoUrlName") &&
                                 !String.IsNullOrEmpty(sibling.GetValue<string>("umbracoUrlName"))
                ? sibling.GetValue<string>("umbracoUrlName")
                : sibling.Name;
                    // check for clash
                  if (siblingUrlName.ToUrlSegment() == contentUrlName.ToUrlSegment())
                    {
                        // cancel publishing
                        e.Cancel = true;
                        // bubble up a message to the UI (umbraco 7.3 only)
                        e.Messages.Add(new EventMessage("Save Cancelled", "Clash of UrlNames: " + sibling.Id + "-" + sibling.Name + " and " + content.Id + "-" + content.Name, EventMessageType.Error));
                    }
                }
            }
    }
    
    }
        }
    

    But you'd have to think this would run on every publish, so there would be an overhead - you'd have to trade that off against how often the problem occurs, and how easy it is to resolve this kind of problem manually.

    with umbracoUrlAlias - which enables clashes to happen anywhere across the site, I have in the past taken a different strategy of building a dashboard report that searched the site for clashing urls. So the editor would only need to run this report if a problem was perceived, rather than actually preventing the problem from occurring.

  • Tito 267 posts 458 karma points
    Mar 01, 2017 @ 09:52
    Tito
    0

    Hi, Marc, thank you for your post, it helped me a lot. I think checking the cache is faster (note that im suscribing the published event because at the moment of publishing Umbraco has not calculated the final name:

    private static void ContentServicePublished(IPublishingStrategy sender, PublishEventArgs<IContent> e)
        {
            var umbracoHelper = new UmbracoHelper(UmbracoContext.Current);
            foreach (var content in e.PublishedEntities)
            {
                // get content items UrlName - (more than one content item could be being published, hence the foreach)
                var contentUrlName = content.HasProperty("umbracoUrlName") &&
                                     !String.IsNullOrEmpty(content.GetValue<string>("umbracoUrlName"))
                    ? content.GetValue<string>("umbracoUrlName")
                    : content.Name;
    
                var urlName = contentUrlName.ToUrlSegment();
    
                var padre = umbracoHelper.TypedContent(content.ParentId);
    
                var hermano = padre.Children.FirstOrDefault(c => c.Id != content.Id && c.UrlName == urlName);
                if (hermano!=null)
                {
                    // cancel publishing
                    //e.Cancel = true;
                    // bubble up a message to the UI (umbraco 7.3 only)
                    e.Messages.Add(new EventMessage("WARNING", "Clash of UrlNames: " + hermano.Id + "-" + hermano.Name + " and " + content.Id + "-" + content.Name, EventMessageType.Error));
                }
    
            }
        }
    

    At published event i cant cancel the event so i have change the message to be a warning. Hope this helps.

Please Sign in or register to post replies

Write your reply to:

Draft