Copied to clipboard

Flag this post as spam?

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


  • John Churchley 272 posts 1258 karma points c-trib
    Jul 13, 2014 @ 22:35
    John Churchley
    0

    is routing possible in this way?

    I'm trying to create a blog post in which the URL would be blog/{year}/{month}/{name}. I want the blog items to be the direct children of the blog area node. The year & month value would come from the UpdateDate property of each blog item node.

    Any help in directing my curiousty would be greatly appreciated. I'm guessing it's going to involve refereting back to standard MVC or possiblely adding an event which changes adds new string to the umbracoURLAlias when a blog item is saved, then referencing the umbracoURLAlias for menus

     

     

  • Andy Butland 422 posts 2334 karma points MVP 4x hq c-trib
    Jul 19, 2014 @ 22:22
    Andy Butland
    100

    Can't help you much further than this as haven't yet tried to do something similar, but my understanding is you should look into implementing an IContentFinder and override the default URL provider.  Documentation is rather patchy unfortunately, but it was all explained very well in a talk by Stephane at CodeGarden this year, so I'd suggest starting with that.

    Andy

  • John Churchley 272 posts 1258 karma points c-trib
    Jul 20, 2014 @ 10:37
    John Churchley
    0

    Brillaint thanks Andy.

     

  • John Churchley 272 posts 1258 karma points c-trib
    Jul 28, 2014 @ 11:39
    John Churchley
    0

    Hi Andy,

    Do you have anyideas where you would include the UrlSegmentProvider class?

  • Andy Butland 422 posts 2334 karma points MVP 4x hq c-trib
    Jul 28, 2014 @ 11:47
    Andy Butland
    0

    Not sure exactly I'm afraid, but most things in this area of customising the pipeline require you to create a class that inherits ApplicationEventHandler, and then set up/override the resolution to find your class in the ApplicationStarting event.  So I'd expect it''s there you need to do it.

  • John Churchley 272 posts 1258 karma points c-trib
    Jul 28, 2014 @ 12:26
    John Churchley
    0
    Thanks Andy, I'm getting a complile error
    'JohnChurchley.Web.Extensions.UrlSegmentProvider' does not implement interface member 'Umbraco.Core.Strings.IUrlSegmentProvider.GetUrlSegment(Umbraco.Core.Models.IContentBase, System.Globalization.CultureInfo)'D:\Websites\JohnChurchley\JohnChurchley.Web\Extensions\BlogHelper.cs
     
     
    My code is below (thanks for all the help)
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using Umbraco.Core;
    using Umbraco.Core.Models;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.Optimization;
    using Umbraco.Core;
    using Umbraco.Core.Models;
    namespace JohnChurchley.Web.App_Start
    {
        public class ApplicationEventHandler : IApplicationEventHandler
        {
            public interface IUrlSegmentProvider
            {
                string GetUrlSegment(IContentBase content);
            }
        }
    }
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using Umbraco.Core;
    using Umbraco.Core.Models;
    namespace JohnChurchley.Web.App_Start
    {
        public class UrlSegmentProvider : Umbraco.Core.Strings.IUrlSegmentProvider
        {
            public string GetUrlSegment(IContentBase content)
            {
                var services = ApplicationContext.Current.Services;
                var contentType = services.ContentTypeService.GetContentType(content.ContentTypeId);
                if (contentType.Alias != "BlogItem") return null;
                var date = content.UpdateDate.ToString("yyyy-MM-");
                return date + content.Name.ToUrlSegment();
            }
        }
    }
  • Andy Butland 422 posts 2334 karma points MVP 4x hq c-trib
    Jul 28, 2014 @ 13:11
    Andy Butland
    0

    Not sure I'll be able to help much more I'm afraid John as not actually done this myself, but it looks like the problem is that the compiler is looking for a method with a signature like this:

    GetUrlSegment(IContentBase content, CultureInfo cultureInfo)

    And yours is like this:

    GetUrlSegment(IContentBase content)

    So if you add that extra argument that should resolve this build error.

    Andy

     

  • John Churchley 272 posts 1258 karma points c-trib
    Jul 28, 2014 @ 14:13
    John Churchley
    0

    Thanks Andy gave it ago but unfortunatly created a new compiler error.

    Error1'JohnChurchley.Web.App_Start.UrlSegmentProvider' does not implement interface member 'Umbraco.Core.Strings.IUrlSegmentProvider.GetUrlSegment(Umbraco.Core.Models.IContentBase, System.Globalization.CultureInfo)'D:\Websites\JohnChurchley\JohnChurchley.Web\App_Start\BlogConfig.cs1118JohnChurchley.Web

    New Code:

    using System;

    using System.Collections.Generic;

    using System.Globalization;

    using System.Linq;

    using System.Web;

    using System.Web.Optimization;

    using Umbraco.Core;

    using Umbraco.Core.Models;

     

    namespace JohnChurchley.Web.App_Start

    {

        public class ApplicationEventHandler : IApplicationEventHandler

        {

            public void OnApplicationStarting(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext) { }

     

            public void OnApplicationInitialized(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext) { }

     

            public void OnApplicationStarted(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)

            {

                BundleConfig.RegisterBundles(BundleTable.Bundles);

            }

     

            public interface IUrlSegmentProvider

            {

                string GetUrlSegment(IContentBase content, CultureInfo cultureInfo);

            }

        }

    }

    using System;

    using System.Collections.Generic;

    using System.Linq;

    using System.Web;

    using Umbraco.Core;

    using Umbraco.Core.Models;

    namespace JohnChurchley.Web.App_Start

    {

        public class UrlSegmentProvider : Umbraco.Core.Strings.IUrlSegmentProvider

        {

            public string GetUrlSegment(IContentBase content, System.Globalization.CultureInfo cultureInfo)

            {

                var services = ApplicationContext.Current.Services;

                var contentType = services.ContentTypeService.GetContentType(content.ContentTypeId);

                if (contentType.Alias != "BlogItem") return null;

                var date = content.UpdateDate.ToString("yyyy-MM-");

                return date + content.Name.ToUrlSegment();

            }

        }

    }

     

  • Sebastiaan Janssen 5060 posts 15522 karma points MVP admin hq
    Jul 28, 2014 @ 15:17
    Sebastiaan Janssen
    0

    I think you need to do something like this:

    using Umbraco.Core;
    using Umbraco.Core.Models;
    using Umbraco.Core.Strings;
    
    namespace JohnChurchley.Web.App_Start
    {
        public class Something : ApplicationEventHandler
        {
            protected override void ApplicationStarting(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)
            {
                UrlSegmentProviderResolver.Current.InsertTypeBefore<DefaultUrlSegmentProvider, UrlSegmentProvider>();
            }
        }
    
        public class UrlSegmentProvider : Umbraco.Core.Strings.IUrlSegmentProvider
        {
            public string GetUrlSegment(IContentBase content)
            {
                // Implement me
            }
    
            public string GetUrlSegment(IContentBase content, System.Globalization.CultureInfo cultureInfo)
            {
                var services = ApplicationContext.Current.Services;
                var contentType = services.ContentTypeService.GetContentType(content.ContentTypeId);
    
                if (contentType.Alias != "BlogItem")
                    return null;
    
                var date = content.UpdateDate.ToString("yyyy-MM-");
    
                return date + content.Name.ToUrlSegment();
            }
        }
    }
    

    The error you're getting is because you need to implement both public string GetUrlSegment(IContentBase content) AND public string GetUrlSegment(IContentBase content, System.Globalization.CultureInfo cultureInfo) methods.

    Please do not define your own IUrlSegmentProvider in IApplicationEventHandler, you need to use Umbraco's provider. Also note that IApplicationEventHandler should be avoided, use ApplicationEventHandler instead. As that was the name of your class, I renamed it to "Something".

    I don't know if this code will do anything but it should build (once you implement the other method). Be aware that the URL only changes when you publish the page that matches this scheme.

    Also see: http://our.umbraco.org/forum/developers/api-questions/49059-Custom-IUrlSegmentProvider-not-hit

  • Sebastiaan Janssen 5060 posts 15522 karma points MVP admin hq
    Jul 28, 2014 @ 15:20
    Sebastiaan Janssen
    1

    If you're not doing a multilingual site you might be able to get away with ignoring the culture info like so (not sure how well this would work though):

    using Umbraco.Core;
    using Umbraco.Core.Models;
    using Umbraco.Core.Strings;
    
    namespace JohnChurchley.Web.App_Start
    {
        public class Something : ApplicationEventHandler
        {
            protected override void ApplicationStarting(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)
            {
                UrlSegmentProviderResolver.Current.InsertTypeBefore<DefaultUrlSegmentProvider, UrlSegmentProvider>();
            }
        }
    
        public class UrlSegmentProvider : Umbraco.Core.Strings.IUrlSegmentProvider
        {
            public string GetUrlSegment(IContentBase content)
            {
                var services = ApplicationContext.Current.Services;
                var contentType = services.ContentTypeService.GetContentType(content.ContentTypeId);
    
                if (contentType.Alias != "BlogItem")
                    return null;
    
                var date = content.UpdateDate.ToString("yyyy-MM-");
    
                return date + content.Name.ToUrlSegment();
            }
    
            public string GetUrlSegment(IContentBase content, System.Globalization.CultureInfo cultureInfo)
            {
                return GetUrlSegment(content);
            }
        }
    }
    
  • John Churchley 272 posts 1258 karma points c-trib
    Jul 28, 2014 @ 16:59
    John Churchley
    0

    Thanks Sebastiaan it worked great! I next attempted to add multiple segments i.e. 

                var date = content.UpdateDate.ToString("yyyy-MM-");

    Became

                var date = content.UpdateDate.ToString("yyyy/MMMM/");

    however gave me a 404 error but when I changed it to 

                var date = content.UpdateDate.ToString("yyyy/");

    or 

                var date = content.UpdateDate.ToString("yyyy/MM/");

    It worked! Very close to getting my desired result, thanks for the suggestions and patience. 

  • Sebastiaan Janssen 5060 posts 15522 karma points MVP admin hq
    Jul 28, 2014 @ 18:37
  • John Churchley 272 posts 1258 karma points c-trib
    Jul 29, 2014 @ 10:28
    John Churchley
    0

    Hi Sebastiaan, it appears to work fine for multiple segements contains only numbers. However I'm was getting an error in the media section when I try to create a new folder media section. The work around I used was to check if the object exists before checking if the contentType.Alias = "BlogItem" not sure on whether this conforms to any good practice but might be useful to anyone trying to replicate this in the future.

    if (Object.ReferenceEquals(contentType, null)){return null;}

Please Sign in or register to post replies

Write your reply to:

Draft