I'm looking for a way to change URLs based on document types. I tried to implement IUrlSegmentProvider as explained here, but GetUrlSegment is never hit. For example if normally the URL to a page is /path-to/some-page, I'd like to be able to change it to something like /[somestr]/[hardcodedstr]/[somepagename] if its document type is of a certain alias.
public class UrlSegmentProvider : IUrlSegmentProvider
{
readonly IUrlSegmentProvider _provider = new DefaultUrlSegmentProvider();
public string GetUrlSegment(IContentBase content, CultureInfo ci)
{
return GetUrlSegment(content);
}
public string GetUrlSegment(IContentBase content)
{
var segment = _provider.GetUrlSegment(content);
return segment;
}
}
Could you please show a full example of what you did to get something like /[somestr]/[hardcodedstr]/[somepagename] if its document type is of a certain alias?
public class MyUrlProvider : DefaultUrlProvider
{
public override string GetUrl(UmbracoContext umbracoContext, int id, Uri current, UrlProviderMode mode)
{
IPublishedContent node = umbracoContext.ContentCache.GetById(id);
if (node.DocumentTypeAlias == "...")
{
return "[calculate a URL for the node]";
}
return base.GetUrl(umbracoContext, id, current, mode);
}
}
To calculate the URL you can do something simple like this:
Please note the difference between the URL segment provider and the URL provider. The segment provider can be used to override only the segment of the URL for which a page is responsible, while the URL provider returns the full URL of that page.
To override the default segment provider, add in ApplicationStarting:
The problem I had that if I change the url to something else for example "/test/28-07-2014/home" and I go to that url I get a 404. Do I also need to write a content finder if I change the url? If you change a url segment do you also get a 404?
I had a talk with Stephane and if you change the url with the url provider you also need a content finder to map the new url to the content. You don't need a content finder if you change a url segment because it still matches the content tree structure.
Thanks for the vague pointer, Jeroen! Because of that I finally got my custom UrlProvider to work! I had a SegmentProvider working fine, but when I tried to put abc/xyz in the URL it just 404'd.
If anyone else comes here looking for how to do this (because the documentation isn't finished) My ContentFinder looks like this (mostly cribbed from another post I found on someone's blog):
public class ContentFinder : IContentFinder
{
public bool TryFindContent(PublishedContentRequest contentRequest)
{
// only care about a subfolder
if (contentRequest.Uri.Segments.Count() > 1 && contentRequest.Uri.Segments[1].ToLower() == "CustomisedFolder/")
{
var allNodes = uQuery.GetNodesByType("CustomisedTypeName").OrderByDescending(n => n.Level);
foreach (var node in allNodes)
{
string fullUri = contentRequest.Uri.AbsolutePath;
string parentUri = node.Url;
// if we're appending / to the URL, then remove it for comparison here:
if (node.Url.EndsWith("/"))
{
parentUri = node.Url.Substring(0, node.Url.Length - 1);
}
bool isMatch = fullUri.Equals(parentUri, StringComparison.InvariantCultureIgnoreCase);
if (isMatch)
{
contentRequest.PublishedContent = new UmbracoHelper(UmbracoContext.Current).TypedContent(node.Id);
return true;
}
}
}
return false;
}
}
Then you need to add the ContentFinderResolver, like with the UrlProviderResolver, above:
public class RegisterEvents : ApplicationEventHandler
{
protected override void ApplicationStarting(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)
{
ContentFinderResolver.Current.InsertType();
UrlProviderResolver.Current.InsertTypeBeforeMyUrlProvider>(); }
}
Now I can finally create completely custom URLs for my Umbraco nodes!
I actually have a question about this - don't know if anyone will see this post so maybe I should make a new one, but here goes:
The solution I posted doesn't deal with absolute URLs, so when we started calling library.NiceUrlWithDomain we were still given relative URLs - the problem is I can't work out how to correctly call the base classes to deal with multiple domains etc. At the moment that won't matter because the domain they request on will always be the correct domain.
I've ended up with this to get relative and absolute URLs - but it's much more fragile than the code in Umbraco, but I can't seem to access some methods I need to - or work out how to call (for e.g.) DomainAndUri correctly.
var relativeUriStr = "/NewUrl/";
var domainUri = new Uri(current.GetLeftPart(UriPartial.Authority));
if (mode == UrlProviderMode.AutoLegacy)
{
mode = UmbracoConfig.For.UmbracoSettings().RequestHandler.UseDomainPrefixes
? UrlProviderMode.Absolute
: UrlProviderMode.Auto;
}
// assume we have a domain - and it'll always match
if (mode == UrlProviderMode.Auto)
{
mode = UrlProviderMode.Relative;
}
var uriStr = "";
switch (mode)
{
case UrlProviderMode.Absolute:
uriStr = new Uri(domainUri, relativeUriStr).ToString();
break;
case UrlProviderMode.Relative:
uriStr = relativeUriStr;
break;
default:
throw new ArgumentOutOfRangeException("mode");
}
return uriStr;
Change URLs according to document type
Hello,
I'm looking for a way to change URLs based on document types. I tried to implement IUrlSegmentProvider as explained here, but GetUrlSegment is never hit. For example if normally the URL to a page is /path-to/some-page, I'd like to be able to change it to something like /[somestr]/[hardcodedstr]/[somepagename] if its document type is of a certain alias.
Thanks!
I've figured out what I was doing wrong. First for what I need I should implement DefaultUrlProvider and also register the provider:
Could you please show a full example of what you did to get something like /[somestr]/[hardcodedstr]/[somepagename] if its document type is of a certain alias?
Jeroen
Hi Jeroen,
Well, MyUrlProvider can be like this:
To calculate the URL you can do something simple like this:
Please note the difference between the URL segment provider and the URL provider. The segment provider can be used to override only the segment of the URL for which a page is responsible, while the URL provider returns the full URL of that page.
To override the default segment provider, add in ApplicationStarting:
MyUrlSegmentProvider can be like in my original post.
Also, don't forget about the built-in properties that can be used to override the URL of a node, umbracoUrlName and umbracoUrlAlias.
Hello,
Thanks for the example. I already tried something like the UrlProvider: https://gist.github.com/jbreuer/5e00f21c70285f448124
The problem I had that if I change the url to something else for example "/test/28-07-2014/home" and I go to that url I get a 404. Do I also need to write a content finder if I change the url? If you change a url segment do you also get a 404?
Jeroen
I had a talk with Stephane and if you change the url with the url provider you also need a content finder to map the new url to the content. You don't need a content finder if you change a url segment because it still matches the content tree structure.
Jeroen
Thanks for the vague pointer, Jeroen! Because of that I finally got my custom UrlProvider to work! I had a SegmentProvider working fine, but when I tried to put abc/xyz in the URL it just 404'd.
If anyone else comes here looking for how to do this (because the documentation isn't finished) My ContentFinder looks like this (mostly cribbed from another post I found on someone's blog):
Then you need to add the ContentFinderResolver, like with the UrlProviderResolver, above:
Now I can finally create completely custom URLs for my Umbraco nodes!
I actually have a question about this - don't know if anyone will see this post so maybe I should make a new one, but here goes:
The solution I posted doesn't deal with absolute URLs, so when we started calling library.NiceUrlWithDomain we were still given relative URLs - the problem is I can't work out how to correctly call the base classes to deal with multiple domains etc. At the moment that won't matter because the domain they request on will always be the correct domain.
I've ended up with this to get relative and absolute URLs - but it's much more fragile than the code in Umbraco, but I can't seem to access some methods I need to - or work out how to call (for e.g.) DomainAndUri correctly.
is working on a reply...