Copied to clipboard

Flag this post as spam?

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


  • Sagar 74 posts 275 karma points
    Jun 08, 2016 @ 05:54
    Sagar
    0

    URL Routing

    Hi all...

    I want to chnage my URL name from domain.com/Parent/Child to domain/child

    can any1 suggest how can i do that?

  • Dennis Adolfi 1082 posts 6449 karma points MVP 6x c-trib
    Jun 08, 2016 @ 06:16
    Dennis Adolfi
    3

    Hi Sagar.

    Maybe you could use a umbracourlalias property?

    Just create a textfield property for your doctype with the alias umbracourlalias.

    https://our.umbraco.org/wiki/reference/umbraco-best-practices/umbracourlalias/.

    http://www.mayflymedia.co.uk/blog/umbraco/alternate-page-name-in-umbraco-using-umbracourlalias/

    If what you are looking for is more of a general rule, then you probobly have to create your own UrlProvider and ContentFinder. There is a great tutorial about this here:

    http://24days.in/umbraco/2014/urlprovider-and-contentfinder/

    Best of luck to you Sagar!

  • Sagar 74 posts 275 karma points
    Jun 08, 2016 @ 06:35
    Sagar
    0

    Hi Dennis

    I don't want the alternate URl but want to change it.

  • Dennis Adolfi 1082 posts 6449 karma points MVP 6x c-trib
    Jun 08, 2016 @ 06:41
    Dennis Adolfi
    0

    Oh sorry, use umbracoUrlName instead. It replaces the url instead of making a alternative.

    enter image description here enter image description here

    Otherwise i´d advise u to look in to http://24days.in/umbraco/2014/urlprovider-and-contentfinder/.

  • Dennis Adolfi 1082 posts 6449 karma points MVP 6x c-trib
    Jun 08, 2016 @ 07:26
    Dennis Adolfi
    1

    Let me know if umbracoUrlName does´nt work for you and i can spare a few minutes to create a code example on how the ContentFinder works. Althogh i think umbracoUrlName is kind of what you are looking for.

  • Sagar 74 posts 275 karma points
    Jun 08, 2016 @ 10:47
    Sagar
    1

    umbracoUrlName doesn't remove parent url from child Url

    for e.g overview is child of about its url looks like domain/about/overview

    i want it to be looked like domain/overview

  • Dennis Adolfi 1082 posts 6449 karma points MVP 6x c-trib
    Jun 08, 2016 @ 11:44
    Dennis Adolfi
    103

    Ok. Then you might need a UrlProvider.

    A quick example:

    CustomUrlProvider:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using AutoMapper.Internal;
    using Umbraco.Core;
    using Umbraco.Web;
    using Umbraco.Web.Routing;
    
    namespace MyApplication.App_Code
    {
        public class CustomUrlProvider : 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)
            {
                var content = umbracoContext.ContentCache.GetById(id);
                if (content != null && content.HasProperty("customUrl") && content.HasValue("customUrl"))
                    return content.GetPropertyValue("customUrl").ToNullSafeString();
    
                return null;
            }
        }
    
        public class StartUpApplication : ApplicationEventHandler
        {
            protected override void ApplicationStarting(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)
            {
                UrlProviderResolver.Current.InsertTypeBefore<DefaultUrlProvider, CustomUrlProvider>();
            }
        }
    }
    

    Add a property for your child items called CustomUrl:

    enter image description here

    Which will give you an url like this, even though this item is on level 3:

    enter image description here

    Maybe this could work for you, or help you come up with your own UrlProvider. You might want to create a general rule for all nodes of a specific doctype to get a automated root url. But this will probobly get you started.

    best of luck!!

  • Sagar 74 posts 275 karma points
    Jun 08, 2016 @ 12:24
    Sagar
    0

    :(

  • Dennis Adolfi 1082 posts 6449 karma points MVP 6x c-trib
    Jun 08, 2016 @ 13:10
    Dennis Adolfi
    2

    Did you follow the steps in my post? Does the page you are trying to navigate to have a template?

    Make sure that the alias of the CustomUrl is exacly: customUrl. You might need to restart the app (change something in the web.config).

    What value does the child element get on the generic property "Link to document"?

  • Sagar 74 posts 275 karma points
    Jun 09, 2016 @ 03:57
    Sagar
    1

    Yes the page has a template The alias name too is "customUrl" The Link to document is too removing Parent Url from it. But on running it shows page not found.

    So, i had made use of umbracourlalias and provided the same name to it, Now its working perfectly

    1. customUrl : /overview

    2. umbracourlalias : overview

    Cheers Sagar... Thnxx Dennis

  • Bendik Engebretsen 105 posts 202 karma points
    Jun 27, 2018 @ 11:22
    Bendik Engebretsen
    0

    I can confirm that this is the case: You must provide the custom URL in the umbracoUrlAlias property as well (without the leading slash). Otherwise you'll get the 404

  • Dennis Adolfi 1082 posts 6449 karma points MVP 6x c-trib
    Jun 09, 2016 @ 06:20
    Dennis Adolfi
    1

    Hi Sagar! You shoud´nt need to use both customUrl and umbracourlalias, buy hey, if it works for you thats great.

    Glad it worked out for you! Best of luck with the rest of the site.

    Have a great day!!

    / Dennis

  • Micha Somers 134 posts 597 karma points
    Jun 10, 2016 @ 20:57
    Micha Somers
    0

    About that 404 page ...

    ... implement a custom ContentFinder for this situation.

    Dennis Adolfi already mentioned the ContentFinder; without it, a 404 page will appear.

    @Dennis Adolfi: do you perhaps have a simple way to implement a contentfinder for this situation?

  • Dennis Adolfi 1082 posts 6449 karma points MVP 6x c-trib
    Jun 11, 2016 @ 07:33
    Dennis Adolfi
    3

    Off course, here goes (based on http://24days.in/umbraco/2014/urlprovider-and-contentfinder/):

    Usings:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using AutoMapper.Internal;
    using Umbraco.Core;
    using Umbraco.Web;
    using Umbraco.Web.Routing;
    using System.Web;
    using Umbraco.Core.Models;
    using Umbraco.Core.Services;
    using Umbraco.Core.Events;
    

    CustomUrlProvider:

    public class CustomUrlProvider : 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)
            {
                var content = umbracoContext.ContentCache.GetById(id);
                if (content != null && content.HasProperty("customUrl") && content.HasValue("customUrl"))
                    return content.GetPropertyValue("customUrl").ToNullSafeString();
    
                return null;
            }
        }
    

    CustomUrlPContentFinder:

    public class CustomUrlPContentFinder : IContentFinder
        {
            public bool TryFindContent(PublishedContentRequest contentRequest)
            {
                try
                {
                    if (contentRequest != null)
                    {
                        //Get the current url.
                        var url = contentRequest.Uri.AbsolutePath;
    
                        //Get the page nodes that are already cached.
                        var cachedPageNodes = (Dictionary<string, ContentFinderItem>)HttpContext.Current.Cache["CachedPageNodes"];
                        if (cachedPageNodes != null)
                        {
                            //Check if the current url already has a page item.
                            if (cachedPageNodes.ContainsKey(url))
                            {
                                //If the current url already has a node use that so the rest of the code doesn't need to run again.
                                var contentFinderItem = cachedPageNodes[url];
                                contentRequest.PublishedContent = contentFinderItem.Content;
                                contentRequest.TrySetTemplate(contentFinderItem.Template);
                                return true;
                            }
                        }
    
                        //Split the url segments.
                        var path = contentRequest.Uri.AbsolutePath;
    
                        //Get all the root nodes.
                        var rootNodes = contentRequest.RoutingContext.UmbracoContext.ContentCache.GetAtRoot();
    
                        //Find the item that matches the last segment in the url.
                        var pageItem = rootNodes.DescendantsOrSelf("page").Where(x => x.HasProperty("customUrl") && x.GetPropertyValue("customUrl").ToString() == path).FirstOrDefault();
                        if (pageItem != null)
                        {
                            //Get the page item template.
                            var template = ApplicationContext.Current.Services.FileService.GetTemplate(pageItem.TemplateId);
    
                            if (template != null)
                            {
                                //Store the fields in the ContentFinderItem-object.
                                var contentFinderItem = new ContentFinderItem()
                                {
                                    Template = template.Alias,
                                    Content = pageItem
                                };
    
                                //If the correct node is found display that node.
                                contentRequest.PublishedContent = contentFinderItem.Content;
                                contentRequest.TrySetTemplate(contentFinderItem.Template);
    
                                if (cachedPageNodes != null)
                                {
                                    //Add the new ContentFinderItem-object to the cache.
                                    cachedPageNodes.Add(url, contentFinderItem);
                                }
                                else
                                {
                                    //Create a new dictionary and store it in the cache.
                                    cachedPageNodes = new Dictionary<string, ContentFinderItem>()
                                        {
                                            {
                                                url, contentFinderItem
                                            }
                                        };
                                    HttpContext.Current.Cache.Add("CachedPageNodes",
                                            cachedPageNodes,
                                            null,
                                            DateTime.Now.AddDays(1),
                                            System.Web.Caching.Cache.NoSlidingExpiration,
                                            System.Web.Caching.CacheItemPriority.High,
                                            null);
                                }
                            }
                        }
    
                    }
                }
                catch (Exception)
                {
                }
    
                return contentRequest.PublishedContent != null;
            }
        }
    

    ContentFinderItem:

    public class ContentFinderItem
        {
            public ContentFinderItem()
            {
            }
    
            public IPublishedContent Content { get; set; }
            public string Template { get; set; }
        }
    

    StartUpApplication:

    public class StartUpApplication : ApplicationEventHandler
        {
            protected override void ApplicationStarting(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)
            {
                // After the node is found it's also added in a custom cache layer. 
                // Because of that the ContentFinder doesn't need to look for the node each time the page is requested. 
                // Make sure to clear the cache after save and publish because otherwise you'll get a cached node which is not up to date.
                //Listen for when content is being saved
                ContentService.Saving += ContentService_Saving;
    
                //With the url providers we can change node urls.
                UrlProviderResolver.Current.InsertTypeBefore<DefaultUrlProvider, CustomUrlProvider>();
    
                //With the content finder we can match nodes to urls.
                ContentFinderResolver.Current.InsertTypeBefore<ContentFinderByNotFoundHandlers, CustomUrlPContentFinder>();
            }
    
            private void ContentService_Saving(IContentService sender, SaveEventArgs<IContent> e)
            {
                //Clear the content finder cache.
                HttpContext.Current.Cache.Remove("CachedPageNodes");
            }
        }
    

    Best of luck to you!!

  • Micha Somers 134 posts 597 karma points
    Jun 13, 2016 @ 08:44
    Micha Somers
    1

    Hi Dennis,

    When url routing needs to go beyond what's possible with umbracoUrlAlias, this is a great and flexible solution for a custom url!

    Thanks!

  • Dennis Adolfi 1082 posts 6449 karma points MVP 6x c-trib
    Jun 13, 2016 @ 08:50
    Dennis Adolfi
    0

    Thank you Micha! It should be mentioned that i have´nt tried this in production on an actual website, only locally. I just wipped this together quickly to help Sagar with his problem, based on his criteria. It might need some extra tweaking or testing before relying on completly.

    If anyone do try it in production, please post here if/how it works.

    But thanks again Micha for the kind word.

    All the best! See you at Codegarden?

    / Dennis

  • MuirisOG 382 posts 1284 karma points
    Jun 02, 2017 @ 10:58
    MuirisOG
    0

    Hi Dennis,

    your solution has been a fantastic help.

    I've been working on an IUrlProvider that just outputs the Page.Id (Stéphane Gay briefly mentioned such a scenario in his video http://stream.umbraco.org/video/9921022/core-internals-for-website-development)

    However, in the backoffice, GetById() is generating errors.

    Do I need to implement an IContentFinder even if I am just using the Page Id for the Url?

    Any help you can give me would be really useful.

    Thanks

    Muiris

    EDIT: I've just been looking at the link below and I think I've found my problem. I was outputting the Page Id without a leading slash. I've added the slash now and it seems to have fixed my problem.

    http://www.ucodebase.be/blog/implementing-a-custom-urlprovider-in-umbraco-and-its-pitfalls/

Please Sign in or register to post replies

Write your reply to:

Draft