#Outbound request pipeline The outbound pipeline consists out of the following steps:
To explain things we will use the following content tree:
When the URL is build up, umbraco will convert every node into a segment. Each published Content has a url segment.
In our example "Our Products" will become "our-products" and "Swibble" will become "swibble".
The segments are created by the "Url Segment provider"
On umbraco startup the UrlSegmentProviderResolver
will search for the first IUrlSegmentProvider
and that does not return null
.
If no UrlSegment provider is found, he will fall back to the default Url segment provider.
To create a new Url segment provider, implement the following interface:
public interface IUrlSegmentProvider
{
string GetUrlSegment(IContentBase content);
}
The returned string will be your URL segment for this node. You are free to return whatever string you like.
public class MyProvider : IUrlSegmentProvider
{
readonly IUrlSegmentProvider _provider = new DefaultUrlSegmentProvider();
public string GetUrlSegment(IContentBase content)
{
if (content.ContentTypeId != 1234) return null;
var segment = _provider.GetUrlSegment(content);
return string.Format("{0}-{1}", content.Id, segment);
}
}
The returned string becomes the native Url segment. You don't need any Url rewriting, ...
If we would use MyProvider
, the "swibble" node from our example content tree would have "5678-swibble" as segment.
Default Url builds its segments like this. First it looks (in this order) for:
- the umbracoUrlName property. on the node
content.GetPropertyValue<string>("umbracoUrlName")
- content.Name
Then uses Umbraco string extension ToUrlSegment()
to produce a clean segment. Read more about the IShortStringHelper
// That one is initialized by default
public class DefaultUrlSegmentProvider : IUrlSegmentProvider
{ … }
// Initialized by
public class UrlSegmentProviderResolver
{ … }
To create a path, the pipeline will use the segments to produce the path.
If we look at our example, the "swibble" node will receive the path: "/our-products/swibble". If we take the MyProvider
from above, the path would become: "/our-products/5678-swibble".
But, if you would add another site, the (internal) paths for the nodes of second site will be is prefixed by the NODE ID of the site. Any content node with a hostname defines a “new root” for paths.
Paths can be cached, what comes next cannot (http vs https, current request…).
There are a few more notes to make if you work with hostnames:
- Domain without path e.g. "www.site.com" will become "1234/path/to/page"
- Domain with path e.g. "www.site.com/dk" will produce "1234/dk/path/to/page" as path
- No domain specified: "/path/to/page"
- Unless HideTopLevelNodeFromPath config is true, then the path becomes "/to/page"
The Url of a node consists out of a complete URI: the schema, domainname, (port) and the path.
In our example the "swibble" node could have the following URL: "http://example.com/our-products/swibble.aspx"
This is handled by the Url Provider. The Url provider is every time whenever you write (e.g.):
@Content.Model.url
@Umbraco.Url(1234)
@UmbracoContext.Current.UrlProvider.Geturl(1234)
The UrlProviderResolver
searches for all Url providers and will take the first one that does not return null. If falls back to the default Urls provider if no Url provider has been found.
// That one is initialized by default
public class DefaultUrlProvider : IUrlProvider
{ … }
// But feel free to use your owns
public class UrlProviderResolver
{ … }
To create your own Url provider, implement the IUrlProvider
interface
public interface IUrlProvider
{
string GetUrl(UmbracoContext umbracoContext,
int id,
Uri current,
UrlProviderMode mode);
}
The returned string by GetUrl can return whatever pleases you.
It's tricky to implement your own provider, it is advised use override the default provider. If implementing a custom Url Provider, consider following things:
- cache things,
- be sure to know how to handle schema's (http vs https) and hostnames
- inbound might require rewriting
TODO: "Per-context UrlProvider". Stéphane mentions a "per context Url provider" on page 35 of his document. We need to find out what this is!
- If the current domain matches a root domain of the target content
- Return a relative Url
- Else must return an absolute Url
- If the target content has only one root domain
- Use that domain to build the absolute Url
- If the target content has more that one root domain
- Figure out which one to use
- To build the absolute Url
- Complete the absolute Url with scheme (http vs https)
- If the domain contains a scheme use it
- Else use the current request’s scheme
If "useDirectoryUrls" is false, then add .aspx in the Url. If "addTrailingSlash" is true, then add a slash. Then add the virtual directory.
TODO: CHECK WITH IF THIS IS INTERPRETED CORRECTLY. Copied from page 42 of Stéphane's document.
- The IUrlProvider also has a GetOtherUrls method (For the back-end)
- Another implementation if the IUrlProvider is the
AliasUrlProvider
: this will show the umbracoUrlAlias url in the back-end
###Url Provider Mode Provider "mode" determines absolute vs. relative Urls. You can change the mode of the current provider
These are the different modes:
public enum UrlProviderMode
{
// Produce relative Urls exclusively
Relative,
// Produce absolute Urls exclusively
Absolute,
// Produce relative Urls when possible, else absolute when required
Auto,
// Produce relative Urls when possible, else absolute when required
// If useDomainPrefixes is true, then produce absolute Urls exclusively
AutoLegacy // this is the default mode in v6
}
Auto
is equivalent to AutoLegacy
with useDomainPrefixes set to false
Note: UseDomainPrefixes
is ignored in every mode except AutoLegacy
Default mode can be configured in /umbraco/web.routing/urlProviderMode
The Url provider needs a ISiteDomainHelper
object, this object is provided by the SiteDomainHelperResolver
.
This object gets the current Uri and all eligible domains, and return only one domain which is used by the UrlProvider to create the Url.
// That one is initialized by default
public class SiteDomainHelper : ISiteDomainHelper
{ … }
// But feel free to use your own
public class SiteDomainHelperResolver
{ … }
To create your own Site Domain helper, implement the ISiteDomainHelper and add it to the resolver.
public interface ISiteDomainHelper
{
DomainAndUri MapDomain(Uri current, DomainAndUri[] domainAndUris);
}
You can use the default SiteDomainhelper to add extra domains:
public class MyApplication : ApplicationEventHandler
{
protected override void ApplicationStarting(…)
{
SiteDomainHelper.AddSite("www", "www.alpha.com", "www.bravo.com");
SiteDomainHelper.AddSite("staging", "staging.alpha.com", "staging.bravo.com");
}
}
Then it knows it should pick e.g. “www.bravo.com” when current is “www.alpha.com”.
A more complicated example with the SiteDomainHelper:
public class MyApplication : ApplicationEventHandler
{
protected override void ApplicationStarting(…)
{
SiteDomainHelper.AddSite("www", "www.alpha.com", "www.bravo.com");
SiteDomainHelper.AddSite("mobile", "mobile.alpha.com", " mobile.bravo.com");
SiteDomainHelper.AddSite("staging", "staging.alpha.com", "staging.bravo.com");
SiteDomainHelper.BindSites("www", "mobile");
}
}
Back-end on www.alpha.com/umbraco then link is "www.bravo.com/bravo-2" ; alternate link is "mobile.bravo.com/bravo-2".
If you have good ideas on creating better implementations, please share them on the umbraco dev group.