Umbraco-cms: Wrong redirect when renaming page name while using custom URL provider

Created on 6 Oct 2018  路  6Comments  路  Source: umbraco/Umbraco-CMS

I implemented a custom URL provider and a custom content finder to manipulate the URLs of certain pages. When I rename a page which has a manipulated URL, Umbraco creates a redirect from the original (non-manipulated) URL to the new manipulated URL.

Original page URL:
/profile/testauthor2/

Manipulated page URL:
/testauthor2/

Wrong redirect:
/profile/testauthor2/ -> /testauthor5/

Expected redirect:
/testauthor2/ -> /testauthor5/

Umbraco version: 7.12.2

Code to reproduce:

public class DefaultEventHandler : ApplicationEventHandler
    {
        protected override void ApplicationStarting(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)
        {
            UrlProviderResolver.Current.InsertTypeBefore<DefaultUrlProvider, ProfileUrlProvider>();

            ContentFinderResolver.Current.InsertTypeBefore<ContentFinderByNotFoundHandlers, ProfileContentFinder>();
        }

    }

The following class currently uses a base class which contains some umbraco methods which are internal. To compile it you could return a string like "/" + content.UrlName; instead of calling the base class methods.

public class ProfileUrlProvider : UrlProviderBase, IUrlProvider
    {

        public IEnumerable<string> GetOtherUrls(UmbracoContext umbracoContext, int id, Uri current)
        {
            return Enumerable.Empty<string>();
        }

        public string GetUrl(UmbracoContext umbracoContext, int id, Uri current, UrlProviderMode mode)
        {
            // Take curent content item from cache by its id
            var content = umbracoContext.ContentCache.GetById(id);

            // Check if the content exists and it has alias companyItem
            if (content != null && (content.DocumentTypeAlias == Author.ModelTypeAlias))
            {
                var route = umbracoContext.ContentCache.GetRouteById(id);
                var domainHelper = new DomainHelper(umbracoContext.Application.Services.DomainService);

                var pos = route.IndexOf('/');
                var path = "/" + content.UrlName;
                var domainUri = pos == 0
                    ? null
                    : DomainForNode(int.Parse(route.Substring(0, pos)), current);

                var result = AssembleUrl(domainUri, path, current, mode).ToString();
                return result;
            }

            return null;
        }
    }

```
public class ProfileContentFinder : IContentFinder
{
public bool TryFindContent(PublishedContentRequest contentRequest)
{
if (contentRequest == null) return false;

        var absoluteUrl = contentRequest.Uri.AbsoluteUri;
        var cachedProfileNodes = (Dictionary<string, CachedResult>)HttpContext.Current.Cache["CachedProfileNodes"];

        if (cachedProfileNodes == null)
        {
            cachedProfileNodes = new Dictionary<string, CachedResult>();
            HttpContext.Current.Cache.Add("CachedProfileNodes",
                                    cachedProfileNodes,
                                    null,
                                    DateTime.Now.AddDays(1),
                                    System.Web.Caching.Cache.NoSlidingExpiration,
                                    System.Web.Caching.CacheItemPriority.High,
                                    null);
        }

        if (cachedProfileNodes.ContainsKey(absoluteUrl))
        {
            var result = cachedProfileNodes[absoluteUrl];
            contentRequest.PublishedContent = result.Content;
            contentRequest.TrySetTemplate(result.TemplateAlias);
            return true;
        }

        var path = contentRequest.Uri.GetAbsolutePathDecoded();
        var parts = path.Split(new[] { '/' }, System.StringSplitOptions.RemoveEmptyEntries);

        if (parts.Length != 1) return false;

        var domainRootId = contentRequest.UmbracoDomain.RootContentId;
        var node = contentRequest.RoutingContext.UmbracoContext.ContentCache.GetByXPath("//home[@id=" + domainRootId + "]//authors//author[@urlName=\"" + parts[0] + "\"]").FirstOrDefault();
        if (node == null) return false;


        var cachedResult = new CachedResult()
        {
            Content = node,
            TemplateAlias = node.GetTemplateAlias()
        };

        cachedProfileNodes.Add(absoluteUrl, cachedResult);
        contentRequest.PublishedContent = node;
        contentRequest.TrySetTemplate(node.GetTemplateAlias());


        return contentRequest.PublishedContent != null;
    }
}
communitpr typbug

Most helpful comment

I believe it's because of this line

it looks like it's no hitting your custom UrlProvider at all when generating new Redirect rule, instead of this it's using this method

so basically it's always using a method from DefaultUrlProvider

I think I could submit PR for that.

All 6 comments

Hi @bernardmoes and thanks for reporting 馃憤

I think is the same issue as described here: https://github.com/umbraco/Umbraco-CMS/issues/3122

I believe it's because of this line

it looks like it's no hitting your custom UrlProvider at all when generating new Redirect rule, instead of this it's using this method

so basically it's always using a method from DefaultUrlProvider

I think I could submit PR for that.

I believe it's because of this line

it looks like it's no hitting your custom UrlProvider at all when generating new Redirect rule, instead of this it's using this method

so basically it's always using a method from DefaultUrlProvider

I think I could submit PR for that.

Thank you! That would be awesome

@bernardmoes @abjerner

PR submitted #3286

@nul800sebastiaan Can you please look at my pull request? It's been open for almost 2 months. Would be nice to get it fixed.

Was this ever resolved? I don't have this issue, just curious, is it also an issue in 8.x?

Was this page helpful?
0 / 5 - 0 ratings