Copied to clipboard

Flag this post as spam?

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


  • Alex 5 posts 85 karma points
    Nov 20, 2020 @ 23:33
    Alex
    0

    IUrlProvider - Defining custom URL path with query strings

    Hi there,

    I'm hoping someone is able to point me in the right direction here.

    Background I have a bespoke team page on my website where each team member is added in Umbraco as a node under the team section, however, the team members themselves are not a standalone page. Each team member is viewable from the parent Team page and the bios etc for each team member are displayed in a modal.

    In order to give the client the ability to link directly to a particular team member's bio (to load the team page with the correct modal open upon clicking a link) - I have implemented some jQuery which decodes the URL and extracts the URL query strings to then activate the correct modal. This works fine.

    The problem The client also wants to be able to use the RTE in Umbraco to easily create a link to any team member's bio modal, using the in-built 'Insert/edit link' functionality. However, this obviously creates a path to the item as if it was a standalone page. And I don't want the client to have to manually enter query strings into the link picker. I need them to select a team member and the URL + Query strings to be automatically generated for them.

    I have been following this piece of documentation to implement a bespoke Url segment provider. This seems to work to an extend. My URLs for the team member nodes are being converted to use query strings like I want it. However, when using the link picker in the RTE the query strings seem to be added twice.

    In Umbraco it is fine, it's showing the URL with query strings correctly.

    team members link being added in Umbraco

    But when the page is rendered, the link has the two query strings duplicated. I cannot figure our what is causing this. For example:

    <a data-udi="umb://document/db3bb080aa164d1396b7c2c77340e566" href="team?name=test-team-member&amp;tab=team?name=test-team-member&amp;tab=team" title="Test team member" data-anchor="?name=test-team-member&amp;tab=team">Test link</a>
    

    My IUrlProvider implementation code is

    public class TeamUrlProvider : IUrlProvider
    {
        public string GetUrl(UmbracoContext umbracoContext, int id, Uri current, UrlProviderMode mode)
        {
            var content = umbracoContext.ContentCache.GetById(id);           
    
            if (content != null && content.DocumentTypeAlias == "teamMember" && content.Parent != null)
            {                
                var memberName = content.UrlName;
                var tabName = content.Parent.UrlName;
                var teamName = content.Parent.Parent.UrlName;
    
                var url = teamName + "?name=" + memberName + "&tab=" + tabName;
    
                return url;
            }
            return null;
        }
    
        public IEnumerable<string> GetOtherUrls(UmbracoContext umbracoContext, int id, Uri current)
        {
            return Enumerable.Empty<string>();
        }
    

    and

    protected override void ApplicationStarting(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)
        {
            UrlProviderResolver.Current.InsertTypeBefore<DefaultUrlProvider, TeamUrlProvider>();
        }
    

    I'm using Umbraco 7.15.2

    Thank you.

  • Marc Goodson 2128 posts 14220 karma points MVP 8x c-trib
    Nov 25, 2020 @ 15:39
    Marc Goodson
    0

    Hi Alex

    Out of interest

    After picking one of the items in the Rich Text Area, if you select it, and press the link button again in order to edit it - has the querystring part of the URL 'moved' to be in the Anchor / querystring box?

    enter image description here

    I keep reading your post, and thinking I should try this out, but it's almost if it's ignoring the querystring part in the segment, then running the segment provider, and adding the querystring back on, so you are getting double querystring...

    ... I'm not sure it's expecting the segment provided to add the querystring - but I'd need to have a play to be sure.

    one workaround might be to use folder segments, that are then 'rewritten' with a Url rewrite rule to become the querystring, so the links are actually:

    /team/test-team-member/team

    and this gets rewritten to be team?name=test-team-member&tab=team

    regards

    Marc

    /

  • Amir Khan 1282 posts 2739 karma points
    Nov 25, 2020 @ 17:00
    Amir Khan
    0

    @Marc somewhat related do you have a rewrite rule to achieve what you mentioned?

  • Marc Goodson 2128 posts 14220 karma points MVP 8x c-trib
    Nov 25, 2020 @ 18:19
    Marc Goodson
    2

    @Amir It's all done with smoke and mirrors, and regexes and back capture groups:

    https://stackoverflow.com/questions/14367019/url-rewrite-rule-subfolder-to-query-string-value

    @Alex The other way to do this without UrlRewriting - would be to implement an IContentFinder

    https://our.umbraco.com/Documentation/Reference/Routing/Request-Pipeline/IContentFinder

    This would find your team node, based on the /team/team-member-name/tab URL - and you should be able to adjust your client side jquery to read the full URL, and pop open the appropriate modal based on the full URL?

    regards

    marc

  • Alex 5 posts 85 karma points
    Nov 25, 2020 @ 22:13
    Alex
    0

    Hi Marc,

    Thanks for your reply.

    After selecting and pressing edit link the query string box gets the two strings but it is also still in the Link URL box. So what I get is:

    Link /{localLink:umb://document/db3bb080aa164d1396b7c2c77340e566}?name=test-team-member&tab=team

    Anchor / querystring name=test-team-member&tab=team

    I actually tried adding in a re-write rule but had no luck with it so far. I will take a look at that link though and try again.

    The second option sounds interesting. I'll give that a go.

    Thanks

    Alex

  • Alex 5 posts 85 karma points
    Nov 26, 2020 @ 11:59
    Alex
    0

    Hi Marc,

    I implemented the IContentFinder interface which I am using to successfully load the main Team page when a specific team member URL is requested, and I updated my jQuery to open the correct modal accordingly.

    What I am now trying figure out is how to restore the default behaviour for any pages that are not within my team section.

    So what I have so far is this:

    public class TeamContentFinder : IContentFinder
    {
        public bool TryFindContent(PublishedContentRequest contentRequest)
        {
            var path = contentRequest.Uri.GetAbsolutePathDecoded();
            if (path.Contains("team/"))
            {
                // have we got the Team node?
                var contentCache = contentRequest.RoutingContext.UmbracoContext.ContentCache;
                var content = contentCache.GetById(4893);
                if (content == null) return false; // not found
    
                // render that node
                contentRequest.PublishedContent = content;
                return true;
            } 
        }
    }
    

    Which does the trick of returning the team page when I say request /team/team-member-name/tab. But now if it isn't a team page node I want to load, since I had to remove the default IContentFinder for this to work, I will now get a 404 page. I tried to adapt the example default content finder as demonstaretd here but I can't figure out how FindContent() is meant to work?

    Any ideas?

  • David Brendel 792 posts 2970 karma points MVP 3x c-trib
    Nov 28, 2020 @ 14:45
    David Brendel
    1

    Hi Alex,

    you don't have to (and you shouldn't) remove the default ContentFinder. You should instead add yours before the default one.

    Umbraco goes through all the registered content finder to find the correct content.

    public class ContentFinderComposer : IUserComposer
    {
        public void Compose(Composition composition)
        {
            composition.ContentFinders().InsertBefore<ContentFinderByConfigured404, CustomContentFinder>();
        }
    }
    

    With that, yours will get used before the final 404 handler.

    Hope that helps.

  • lucuma 261 posts 563 karma points
    Nov 26, 2020 @ 14:57
    lucuma
    101

    I think you are overcomplicating this. You can create a template for employee and let it be publishable. The user can use this link. On the template just redirect back to the parent with the appropriate hash or however you need to display the right person.

  • Alex 5 posts 85 karma points
    Dec 01, 2020 @ 13:12
    Alex
    0

    Brilliant - I knew there must be a simpler way.

    Thanks for your help!

Please Sign in or register to post replies

Write your reply to:

Draft