Copied to clipboard

Flag this post as spam?

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


  • Ondřej Kobza 15 posts 96 karma points
    Aug 17, 2019 @ 12:00
    Ondřej Kobza
    0

    Umbraco change default URL

    Hello.

    I would like to change the way Umbraco generates URLs for my posts. I want to make different categories and then subcategories inside of the categories. In the subcategories, there will be articles (blog posts).

    amazing word skills

    Hope that makes sense.

    Now. When I make a blog post under Subcategory A, Umbraco automatically sets its URL to www.domain.com/category-1/subcategory-a/blog-post

    I would like this URL to be simply www.domain.com/blog-post.

    Is there an easy way to achieve this? I know I can use the built-in umbracoUrlName property. But is there a way to do this automatically? Maybe based on a document type? Or based on the document type of the category?

    I want to be able to still have pages like www.domain.com/category and www.domain.com/category/subcategory - I just don't want the posts inside of them to have the "full path". On top of that, I want this only in certain categories, not all of them.

    I was trying to get a solution for the past few days and nothing. Please take it easy on me, I'm a beginner. :-)

  • Shaishav Karnani from digitallymedia.com 354 posts 1638 karma points
    Aug 17, 2019 @ 14:24
    Shaishav Karnani from digitallymedia.com
    100

    We can change using any of below 3 options. Please review and let me know if you need any further assistance.

    1. umbracoUrlAlias as you mentioned.

    2. Virtual Folder Plugin https://our.umbraco.com/packages/website-utilities/virtualnodes/

    3. UrlProvider and ContentFinder https://24days.in/umbraco-cms/2014/urlprovider-and-contentfinder/

    Regards,

    Shaishav

    https://www.digitallymedia.com

  • Ondřej Kobza 15 posts 96 karma points
    Aug 17, 2019 @ 20:35
    Ondřej Kobza
    0

    Hey, thanks for the reply!

    I've checked these options and I tried to go with the virtual folder plugin. I thought it would be the easiest solution. Sadly it's not working for me at all.

    I use Umbraco version 8.1.0. I downloaded the package "Virtual Nodes for Umbraco 8" by Christopher. It's supposed to be a "rewrite of Umbraco-VirtualNodes to make it compatible with Umbraco 8.1+". I added a key into my web.config file under the appSettings section:

    <add key="virtualnode" value="hardware" />
    

    But nothing changed with the node called "Hardware" and the items under it.

  • Shaishav Karnani from digitallymedia.com 354 posts 1638 karma points
    Aug 18, 2019 @ 07:29
    Shaishav Karnani from digitallymedia.com
    0

    Hi,

    I would suggest go for using UrlProvider and ContentFinder. We have already done that way and that worked nicely. I have taken some code for your assistance from our project. It won't exactly match your requirement but will be good guidance for your project.

    If you need any further help then please do let us know.

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using Umbraco.Web;
    using Umbraco.Extensions.Utilities;
    using Umbraco.Web.Routing;
    using Umbraco.Extensions.Models.Generated;
    
    namespace Umbraco.Extensions.UrlProvider
    {
        public class EventsUrlProvider : BaseClass, IUrlProvider
        {
            public string GetUrl(UmbracoContext umbracoContext, int id, Uri current, UrlProviderMode mode)
            {
                var content = umbracoContext.ContentCache.GetById(id);
                if (content != null && content.DocumentTypeAlias == EventDetails.ModelTypeAlias)
                {
                    var url = "/whats-on/"; //manage in web.config
                    if (!(url.EndsWith("/")))
                    {
                        url += "/";
                    }
    
                    return url + content.UrlName;
                }
    
                return null;
            }
    
            public IEnumerable<string> GetOtherUrls(UmbracoContext umbracoContext, int id, Uri current)
            {
                return Enumerable.Empty<string>();
            }
        }
    }
    
    
    
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using Umbraco.Core;
    using Umbraco.Core.Models;
    using Umbraco.Extensions.Models.Custom;
    using Umbraco.Extensions.Models.Generated;
    using Umbraco.Extensions.Utilities;
    using Umbraco.Web;
    using Umbraco.Web.Routing;
    
    namespace Umbraco.Extensions.ContentFinder
    {
        public class EventContentFinder : BaseClass, IContentFinder
        {
            public bool TryFindContent(PublishedContentRequest contentRequest)
            {
                try
                {
                    if (contentRequest != null)
                    {
                        //Get the current url.
                        var url = contentRequest.Uri.AbsoluteUri;
    
                        //Get the events nodes that are already cached.
                        var cachedEventsNodes = (Dictionary<string, ContentFinderItem>)HttpContext.Current.Cache["CachedEventsNodes"];
                        if (cachedEventsNodes != null)
                        {
                            //Check if the current url already has a news item.
                            if (cachedEventsNodes.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 = cachedEventsNodes[url];
                                contentRequest.PublishedContent = contentFinderItem.Content;
                                contentRequest.TrySetTemplate(contentFinderItem.Template);
                                return true;
                            }
                        }
    
                        //Split the url segments.
                        var path = contentRequest.Uri.GetAbsolutePathDecoded().ToLower();
                        var parts = path.Split(new[] { '/' }, System.StringSplitOptions.RemoveEmptyEntries);
    
                        //The news items should contain 3 segments.
                        if (parts.Length >= 1)
                        {
                            //Get all the root nodes.
                            var rootNodes = contentRequest.RoutingContext.UmbracoContext.ContentCache.GetByXPath("//eventsTool").FirstOrDefault();
    
                            IEnumerable<IPublishedContent> Items = null;
                            IPublishedContent Item = null;
                            if (Settings.WhatsOnUrl.Contains(parts.First().ToLower()))
                            {
                                Items = rootNodes.DescendantsOrSelf().Where(x => x.UrlName == parts.Last() && x.DocumentTypeAlias == EventDetails.ModelTypeAlias);
                                if (Items != null)
                                {
                                    Item = Items.FirstOrDefault();
                                }
                            }
                            else if (parts.First().ToLower() == "venues")
                            {
                                Items = rootNodes.DescendantsOrSelf().Where(x => x.UrlName == parts.Last() && (x.DocumentTypeAlias == VenueDetails.ModelTypeAlias || x.DocumentTypeAlias == VenueLanding.ModelTypeAlias));
                                if (Items != null)
                                {
                                    Item = Items.FirstOrDefault();
                                }
                            }
                            /*
                            else if (parts.First().ToLower() == "attractions")
                            {
                                Items = rootNodes.DescendantsOrSelf().Where(x => x.UrlName == parts.Last() && (x.DocumentTypeAlias == VenueType.ModelTypeAlias || x.DocumentTypeAlias == VenueTypes.ModelTypeAlias));
                                if (Items != null)
                                {
                                    Item = Items.FirstOrDefault();
                                }
                            }
                            */
                            else if (parts.First().ToLower() == "host")
                            {
                                Items = rootNodes.DescendantsOrSelf().Where(x => x.UrlName == parts.Last() && x.DocumentTypeAlias == HostDetails.ModelTypeAlias);
                                if (Items != null)
                                {
                                    Item = Items.FirstOrDefault();
                                }
                            }
    
                            if (Item != null)
                            {
                                foreach (var i in Items)
                                {
                                    if (i.Url.Contains(path) || path.Contains(i.Url))
                                    {
                                        Item = i;
                                    }
                                }
    
                                if (Item.DocumentTypeAlias == EventDetails.ModelTypeAlias || Item.DocumentTypeAlias == VenueDetails.ModelTypeAlias || Item.DocumentTypeAlias == HostDetails.ModelTypeAlias || Item.DocumentTypeAlias == SectorPage.ModelTypeAlias || Item.DocumentTypeAlias == VenueLanding.ModelTypeAlias || Item.DocumentTypeAlias == Location.ModelTypeAlias || Item.DocumentTypeAlias == VenueTypes.ModelTypeAlias || Item.DocumentTypeAlias == VenueType.ModelTypeAlias || Item.DocumentTypeAlias==HostLanding.ModelTypeAlias || Item.DocumentTypeAlias == EventTags.ModelTypeAlias)
                                {
                                    //Get the news item template.
                                    var template = Services.FileService.GetTemplate(Item.TemplateId);
    
                                    if (template != null)
                                    {
                                        //Store the fields in the ContentFinderItem-object.
                                        var contentFinderItem = new ContentFinderItem()
                                        {
                                            Template = template.Alias,
                                            Content = Item
                                        };
    
                                        //If the correct node is found display that node.
                                        contentRequest.PublishedContent = contentFinderItem.Content;
                                        contentRequest.TrySetTemplate(contentFinderItem.Template);
    
                                        if (cachedEventsNodes != null)
                                        {
                                            //Add the new ContentFinderItem-object to the cache.
                                            cachedEventsNodes.Add(url, contentFinderItem);
                                        }
                                        else
                                        {
                                            //Create a new dictionary and store it in the cache.
                                            cachedEventsNodes = new Dictionary<string, ContentFinderItem>()
                                            {
                                                {
                                                    url, contentFinderItem
                                                }
                                            };
    
                                            HttpContext.Current.Cache.Add("CachedEventsNodes",
                                                  cachedEventsNodes,
                                                  null,
                                                  DateTime.Now.AddDays(1),
                                                  System.Web.Caching.Cache.NoSlidingExpiration,
                                                  System.Web.Caching.CacheItemPriority.High,
                                                  null);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    Umbraco.LogException<EventContentFinder>(ex);
                }
    
                return contentRequest.PublishedContent != null;
            }
    
        }
    }
    
    
    
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using Umbraco.Core;
    using Umbraco.Core.Models;
    using Umbraco.Extensions.Models.Custom;
    using Umbraco.Extensions.Models.Generated;
    using Umbraco.Extensions.Utilities;
    using Umbraco.Web;
    using Umbraco.Web.Routing;
    
    namespace Umbraco.Extensions.ContentFinder
    {
        public class EventContentFinder : BaseClass, IContentFinder
        {
            public bool TryFindContent(PublishedContentRequest contentRequest)
            {
                try
                {
                    if (contentRequest != null)
                    {
                        //Get the current url.
                        var url = contentRequest.Uri.AbsoluteUri;
    
                        //Get the events nodes that are already cached.
                        var cachedEventsNodes = (Dictionary<string, ContentFinderItem>)HttpContext.Current.Cache["CachedEventsNodes"];
                        if (cachedEventsNodes != null)
                        {
                            //Check if the current url already has a news item.
                            if (cachedEventsNodes.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 = cachedEventsNodes[url];
                                contentRequest.PublishedContent = contentFinderItem.Content;
                                contentRequest.TrySetTemplate(contentFinderItem.Template);
                                return true;
                            }
                        }
    
                        //Split the url segments.
                        var path = contentRequest.Uri.GetAbsolutePathDecoded().ToLower();
                        var parts = path.Split(new[] { '/' }, System.StringSplitOptions.RemoveEmptyEntries);
    
                        //The news items should contain 3 segments.
                        if (parts.Length >= 1)
                        {
                            //Get all the root nodes.
                            var rootNodes = contentRequest.RoutingContext.UmbracoContext.ContentCache.GetByXPath("//eventsTool").FirstOrDefault();
    
                            IEnumerable<IPublishedContent> Items = null;
                            IPublishedContent Item = null;
                            if ("/whats-on".Contains(parts.First().ToLower())) //manage in web.config
                            {
                                Items = rootNodes.DescendantsOrSelf().Where(x => x.UrlName == parts.Last() && x.DocumentTypeAlias == EventDetails.ModelTypeAlias);
                                if (Items != null)
                                {
                                    Item = Items.FirstOrDefault();
                                }
                            }
    
                            if (Item != null)
                            {
                                foreach (var i in Items)
                                {
                                    if (i.Url.Contains(path) || path.Contains(i.Url))
                                    {
                                        Item = i;
                                    }
                                }
    
                                if (Item.DocumentTypeAlias == EventDetails.ModelTypeAlias)
                                {
                                    //Get the news item template.
                                    var template = Services.FileService.GetTemplate(Item.TemplateId);
    
                                    if (template != null)
                                    {
                                        //Store the fields in the ContentFinderItem-object.
                                        var contentFinderItem = new ContentFinderItem()
                                        {
                                            Template = template.Alias,
                                            Content = Item
                                        };
    
                                        //If the correct node is found display that node.
                                        contentRequest.PublishedContent = contentFinderItem.Content;
                                        contentRequest.TrySetTemplate(contentFinderItem.Template);
    
                                        if (cachedEventsNodes != null)
                                        {
                                            //Add the new ContentFinderItem-object to the cache.
                                            cachedEventsNodes.Add(url, contentFinderItem);
                                        }
                                        else
                                        {
                                            //Create a new dictionary and store it in the cache.
                                            cachedEventsNodes = new Dictionary<string, ContentFinderItem>()
                                            {
                                                {
                                                    url, contentFinderItem
                                                }
                                            };
    
                                            HttpContext.Current.Cache.Add("CachedEventsNodes",
                                                  cachedEventsNodes,
                                                  null,
                                                  DateTime.Now.AddDays(1),
                                                  System.Web.Caching.Cache.NoSlidingExpiration,
                                                  System.Web.Caching.CacheItemPriority.High,
                                                  null);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    Umbraco.LogException<EventContentFinder>(ex);
                }
    
                return contentRequest.PublishedContent != null;
            }
    
        }
    }
    
  • Ondřej Kobza 15 posts 96 karma points
    Sep 17, 2019 @ 21:09
    Ondřej Kobza
    0

    Thanks a lot for all the help! This code you provided is a little bit too much for me at the moment (I'm probably too stupid to understand it :-D )

    But I managed to figure out how to run Virtual Nodes on Umbraco v8.

    Surprisingly I found out that on the live server everything works. Only on my local computer there are problems - I'm getting YSOD on several pages when I unpublish any item.

    Anyway, this will do for now. Thanks!

Please Sign in or register to post replies

Write your reply to:

Draft