Copied to clipboard

Flag this post as spam?

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


  • Bernard Moes 16 posts 118 karma points
    Sep 22, 2018 @ 08:54
    Bernard Moes
    0

    301 redirect module fails when using custom url provider

    I developed a custom URL provider which cuts off the parent UrlName from the URL making the URL appear like it's located on the website root.

    For example : /profile/testnode becomes /testnode

    Now I was testing renaming this node and saw that Umbraco made a redirect from the non-customized URL to the new URL. See the image below.

    enter image description here

    I expected to see a redirect from the customized url to the new url. Is this an error in the way Umbraco handles redirecting URL’s? Umbraco does show the correct url on the properties tab and the url is working correctly too. It’s just not using the right url for the redirect after renaming.

  • Bernard Moes 16 posts 118 karma points
    Sep 23, 2018 @ 20:13
    Bernard Moes
    0

    Still don't have a solution for this issue.

  • Bernard Moes 16 posts 118 karma points
    Sep 24, 2018 @ 22:10
    Bernard Moes
    0

    Still don’t have a good solution. Even manually adding the right redirects via the code API doesn’t work. I would expect there to be some kind of builtin solution.

  • shinsuke nakayama 105 posts 246 karma points
    Sep 25, 2018 @ 07:31
    shinsuke nakayama
    0

    Hey Bernard,

    What I found in my previous project is that built-in redirect only works when you rename the page, and you can't edit those entries.

    However, there are plugin that you can use todo the 301 redirect, and they were quite simple to use.

    Simple 301 https://our.umbraco.com/packages/backoffice-extensions/simple-301/

    301 URL Tracker https://our.umbraco.com/packages/developer-tools/301-url-tracker/

    Both of them will give you another tab in the content section, just like below image

    enter image description here

  • Bernard Moes 16 posts 118 karma points
    Sep 25, 2018 @ 07:37
    Bernard Moes
    0

    Thanks for your post. I knew about that package. But I expected Umbraco to automatically make the right redirects and it doesn't. Even when renaming a node it picks the wrong URL because I use a custom URL provider. So for me it's completely useless.

    I am looking for an automated solution, I don't want to add redirects by hand.

  • Bernard Moes 16 posts 118 karma points
    Oct 05, 2018 @ 20:33
    Bernard Moes
    0

    Waiting

  • Marc Goodson 810 posts 5324 karma points MVP 3x c-trib
    Oct 06, 2018 @ 11:45
    Marc Goodson
    101

    Hi Bernard

    Have you raised this on the Issue Tracker?

    https://github.com/umbraco/Umbraco-CMS/issues

    The Redirect Url Manager is quite a simplistic implementation, that I don't think is designed to handle every scenario 'yet'- and this sounds like an issue in the way the Redirect Url Manager determines what the 'actual' published url of the page was, when a change is made...

    The redirects are created in the RedirectTrackingEventHandler

    https://github.com/umbraco/Umbraco-CMS/blob/2f74720c38e734f359cdd3e9a7556860fb96801f/src/Umbraco.Web/Routing/RedirectTrackingEventHandler.cs

      private static void CreateRedirect(int contentId, Guid contentKey, string oldRoute)
            {
    
                var contentCache = GetPublishedCache();
                if (contentCache == null) return;
    
                var newRoute = contentCache.GetRouteById(contentId);
                if (IsNotRoute(newRoute) || oldRoute == newRoute) return;
                var redirectUrlService = ApplicationContext.Current.Services.RedirectUrlService;
                redirectUrlService.Register(oldRoute, contentKey);
            }
    

    This event is triggered when the cache is updated:

    private void PageCacheRefresher_CacheUpdated(PageCacheRefresher sender, CacheRefresherEventArgs cacheRefresherEventArgs) { // only on master / single, not on replicas! if (IsReplicaServer) return;

        // simply getting OldRoutes will register it in the request cache,
        // so whatever we do with it, try/finally it to ensure it's cleared
    
        try
        {
            foreach (var oldRoute in OldRoutes)
            {
                // assuming we cannot have 'CacheUpdated' for only part of the infos else we'd need
                // to set a flag in 'Published' to indicate which entities have been refreshed ok
                CreateRedirect(oldRoute.Key, oldRoute.Value.Item1, oldRoute.Value.Item2);
            }
        }
        finally
        {
            OldRoutes.Clear();
            RequestCache.ClearCacheItem(ContextKey3);
        }
    }
    

    The OldRoutes property is a dictionary containing the routes of an item through the publishing process,

    var oldRoutes = RequestCache.GetCacheItem<>

    this collection of 'OldRoutes' is populated during the ContentService_Publishing event: (eg before the published urls change, you need to know what they once were!)

    foreach (var entity in entities)
            {
                // for each entity, we want to save the 'old route' of any impacted entity.
                //
                // previously, we'd save the routes of all descendants - super safe but has an
                // impact on perfs - assuming that the descendant routes will NOT change if the
                // entity's segment does not change (else... outside of the scope of the simple,
                // built -in, tracker) then we can compare the entity's old and new segments
                // and avoid processing the descendants
    
                var process = true;
                if (Moving == false) // always process descendants when moving
                {
                    // SD: in 7.5.0 we re-lookup the entity that is published, which gets its
                    // current state in the DB, which we use to get the 'old' segment. In the
                    // future this will certainly cause some problems, to fix this we'd need to
                    // change the IUrlSegmentProvider to support being able to determine if a
                    // segment is going to change for an entity. See notes in IUrlSegmentProvider.
    
                    var oldEntity = ApplicationContext.Current.Services.ContentService.GetById(entity.Id);
                    if (oldEntity == null) continue;
                    var oldSegment = oldEntity.GetUrlSegment();
                    var newSegment = entity.GetUrlSegment();
                    process = oldSegment != newSegment;
                }
    
                // skip if no segment change
                if (process == false) continue;
    
                // else save routes for all descendants
                var entityContent = contentCache.GetById(entity.Id);
                if (entityContent == null) continue;
                foreach (var x in entityContent.DescendantsOrSelf())
                {
                    var route = contentCache.GetRouteById(x.Id);
                    if (IsNotRoute(route)) continue;
                    var wk = UnwrapToKey(x);
                    if (wk == null) continue;
    
                    OldRoutes[x.Id] = Tuple.Create(wk.Key, route);
                }
            }
    

    So it is using the UrlSegmentProvider implementation to detect the change in url segment for a node that would trigger the creation of redirects, and populates the 'OldRoutes' dictionary once publishing is confirmed, (and the cache is updated to avoid creating redirects when publishing fails), it then creates the redirects - but it isn't, I don't think considering any CustomUrlProvider implementation...

    So I would suggest raising it as an issue so it can be discussed as the best way to handle this scenario, or in case I've misunderstood!

    In the meantime, 'you could' perform the same trick / use the same pattern of creating your own handling of the ContentServicePublishing Event, determine if a Url will change based on your CustomUrlProvider logic, and then triggering the creation of the Redirect by your own handling of the PageCacheRefresherCacheUpdated event

    regards

    Marc

  • Bernard Moes 16 posts 118 karma points
    Oct 06, 2018 @ 15:17
    Bernard Moes
    0

    Thank you for your extensive analysis. I considered implementing my own event handler but didn't like having 2 redirects created for the same page. But I don't think there's any other solution for now so that will probably be my approach.

    I did not raise it as an issue on the issue tracker yet. I will do as soon as I can. Would be nice to see this issue fixed.

  • Bernard Moes 16 posts 118 karma points
    Oct 06, 2018 @ 16:16
  • Bernard Moes 16 posts 118 karma points
    Feb 01, 2019 @ 13:18
    Bernard Moes
    0

    It's a shame that this issue is still open and my pull request isn't being looked at.

    https://github.com/umbraco/Umbraco-CMS/pull/3837

    It's been open for almost 2 months. What more can I do

Please Sign in or register to post replies

Write your reply to:

Draft