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.
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&tab=team?name=test-team-member&tab=team" title="Test team member" data-anchor="?name=test-team-member&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>();
}
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?
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
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?
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?
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.
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.
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.
But when the page is rendered, the link has the two query strings duplicated. I cannot figure our what is causing this. For example:
My IUrlProvider implementation code is
and
I'm using Umbraco 7.15.2
Thank you.
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?
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
/
@Marc somewhat related do you have a rewrite rule to achieve what you mentioned?
@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
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
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:
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?
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.
With that, yours will get used before the final 404 handler.
Hope that helps.
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.
Brilliant - I knew there must be a simpler way.
Thanks for your help!
is working on a reply...