Copied to clipboard

Flag this post as spam?

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


  • organic 100 posts 149 karma points
    Mar 11, 2014 @ 21:28
    organic
    0

    Custom IUrlSegmentProvider not hit

    I'm trying to get a custom implementation of IUrlSegmentProvider to run, but it's not being hit.

    It's basically identical to this example:  http://our.umbraco.org/documentation/Reference/Request-Pipeline/outbound-pipeline

    I also have an IUrlProvider that does run successfully.  Both are registered in ApplicationStarting:

            protected override void ApplicationStarting(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)
            {
                UrlProviderResolver.Current.InsertTypeBefore<DefaultUrlProvider, UrlsWithTagsProvider>();
                UrlSegmentProviderResolver.Current.InsertTypeBefore<DefaultUrlSegmentProvider, AtUrlSegmentProvider>();
    
                base.ApplicationStarting(umbracoApplication, applicationContext);
            }
    

    And then the custom classes are implemented.

        public class UrlsWithTagsProvider : IUrlProvider
        {
            readonly IUrlProvider _provider = new DefaultUrlProvider();
    
            IEnumerable IUrlProvider.GetOtherUrls(Umbraco.Web.UmbracoContext umbracoContext, int id, Uri current)
            {
                return _provider.GetOtherUrls(umbracoContext, id, current);
            }
    
            string IUrlProvider.GetUrl(Umbraco.Web.UmbracoContext umbracoContext, int id, Uri current, UrlProviderMode mode)
            {
                string url = _provider.GetUrl(umbracoContext, id, current, mode);
                string tags = umbracoContext.HttpContext.Request.Params["tags"];
    
                if (string.IsNullOrEmpty(tags))
                    return url;
    
                if (url.Contains('?'))
                {
                    url += "&tags=" + tags;
                }
                else
                {
                    url += "?tags=" + tags;
                }
    
                return url;
            }
        }
    
        public class AtUrlSegmentProvider : IUrlSegmentProvider
        {
            readonly IUrlSegmentProvider _provider = new DefaultUrlSegmentProvider();
    
            string IUrlSegmentProvider.GetUrlSegment(IContentBase content)
            {
                if (content.ContentTypeId != 1085) return null;
                var segment = _provider.GetUrlSegment(content);
                return string.Format("{0}-{1}", content.Id, segment);
            }
    
            string IUrlSegmentProvider.GetUrlSegment(IContentBase content, System.Globalization.CultureInfo culture)
            {
               return _provider.GetUrlSegment(content, culture);
            }
        }
    
  • Stephen 767 posts 2264 karma points c-trib
    Mar 11, 2014 @ 21:44
    Stephen
    0

    Both providers are properly registered... Note that the AtUrlSegmentProvider changes the url only if the content type ID is 1085... I think that was a random value in the example, or does it match an actual content type in your setup? What happens if you remove that line?

  • organic 100 posts 149 karma points
    Mar 11, 2014 @ 22:32
    organic
    0

    Yes, 1085 is my actual ContentTypeId.  I have tried putting a breakpoint on it, as well as, removing that line, but the code is never hit. The debugger looks like the Providers are registering.  I decided to test hitting a breakpoint on the DefaultUrlSegmentProvider in the core Umbraco code, so I downloaded 6.2(because it builds easily in Visual Studio), and I cannot hit any breakpoints in DefaultUrlSegmentProvider.GetUrlSegment() in that code, either, so something is strange...maybe me.  And like I said, my UrlsWithTagsProvider is working.

  • Stephen 767 posts 2264 karma points c-trib
    Mar 12, 2014 @ 08:40
    Stephen
    101

    Was about to ask which version, but if I understand correctly you can reproduce with 6.2. Just tested here on my development code for 6.2 and it works fine. So... it's really strange. If you don't mind a bit of debugging...

    ==> Set a breakpoint in Umbraco.Core.Strings.ContentBaseExtensions.GetUrlSegment methods and check that it is called when you publish a document. Check that UrlSegmentProviderResolver.HasCurrent is true. Check that UrlSegmentProviderResolver.Current.Providers returns the correct list ie contains your own provider in the first position.

    When writing this... I have a doubt: the IUrlSegmentProvider instances are invoked when calculating the content's url segment, ie when the content is published - once the content has been published, you can change the url segment providers config as you want, it won't cause Umbraco to re-compute the content's url segment. Whereas the global url, which is created by assembling the segments, is calculated each time (sort-of) you ask for it. This is because in theory the segment should not change if the content itself does not change, whereas the global url could (eg if a parent's segment changes).

    Making sense?

  • organic 100 posts 149 karma points
    Mar 12, 2014 @ 21:04
    organic
    1

    Yes, thanks so much for the help! 

    I did not realize this code would only run when 'Publishing', and so it does.

  • Stephen 767 posts 2264 karma points c-trib
    Mar 12, 2014 @ 21:12
    Stephen
    0

    Cool.

  • organic 100 posts 149 karma points
    Jun 27, 2014 @ 18:15
    organic
    0

    After using my custom provider for a few months, I've noticed that my implementation had a problem.  Pages with these custom urls respond with a 404 frequently after publishing other site content. If I browsed back to the site root, and then back to the page, it would serve successfully.

    I was appending 'slash node id' because my site allows duplicate node names, this responded with 404 frequently:

            string IUrlSegmentProvider.GetUrlSegment(IContentBase content)

            {...return string.Format("{0}/{1}", segment, content.Id);}

    I simply changed the slash to a hyphen and that solved it.

    I am wondering if you would expect that behavior?  Did it break because I effectively added a new segment?

  • Stephen 767 posts 2264 karma points c-trib
    Jun 27, 2014 @ 18:32
    Stephen
    0

    A url "segment" is defined (not only in Umbraco) as what goes between slashes. Eg, /segment1/segment2/segment3. So if GetUrlSegment returns "something/1234" it is not a segment, since it contains a slash. It will work on the way out (ie Umbraco will generate the url that you expect) but not on the way in, because Umbraco expects each segment in the url to match one node in the tree. So it will look for a node with segment "something" and a child of that node with segment "1234"--not for a node with segment "something/1234".

    So yes, expected behavior. Replacing the slash by an hyphen fixes it. Now I'm wondering whether we should throw an exception if somebody generates a segment containing a slash...

  • organic 100 posts 149 karma points
    Jun 27, 2014 @ 19:27
    organic
    1

    Thanks so much for your help Stephen, #H5YR !

    Throwing an exception sounds like a good idea, as that would've let me know that "You're doing it wrong" originally.  Fortunately, this site is still in development, no 404 were returned in Production.

Please Sign in or register to post replies

Write your reply to:

Draft