Refer to https://orchard.codeplex.com/workitem/20215 on updates regarding this feature.
Edit 11/11/2013:
Since writing this article I've discovered a better method which allows a full taxonomy term path to be slugified and returned into a token result: http://sheltonial.blogspot.com.au/2013/11/orchard-cms-taxonomy-term-autoroute.html
Recently (as of 17/10/2013) the Orchard CMS team has fixed a bug which was preventing taxonomy tokens from returning a value.
Currently I am working off changeset a62f0281ebdac780a1d3a583dbc5821ca8fbc6ce on version 1.7.1 and can confirm that this is working.
An example of an autoroute pattern that works is {Content.Fields.BlogPost.Category.Terms:0}, where [BlogPost] is the name of your content type, and [Category] is the name of the field within our content type, not the taxonomy or term.
This means we can start injecting taxonomy terms into our autoroute patterns and enjoy structuring a url hierarchy based on taxonomy terms and being able to interact with this new url data within queries and layer rules. This is fine if your taxonomy is a single word containing no spaces or special characters, but once you introduce other characters these are also injected into the URL.
The following code adds a new token called TermSlug which allows a taxonomy term to be slugified:
- File to modify: \src\Orchard.Web\Modules\Orchard.Taxonomies\Tokens\TaxonomyTokens.cs
- Usage: {Content.Fields.BlogPost.Category.TermsSlug:0} (refer to example above)
// Comment using System; using System.Linq; using Orchard.Taxonomies.Fields; using Orchard.Localization; using Orchard.Tokens; using Orchard.Autoroute.Services; namespace Orchard.Taxonomies.Tokens { public class TaxonomyTokens : ITokenProvider { private readonly ISlugService _slugService; public TaxonomyTokens(ISlugService slugService) { T = NullLocalizer.Instance; _slugService = slugService; } public Localizer T { get; set; } public void Describe(DescribeContext context) { // Usage: // Content.Fields.Article.Categories.Terms -> 'Science, Sports, Arts' // Content.Fields.Article.Categories.Terms:0 -> 'Science' // When used with an indexer, it can be chained with Content tokens // Content.Fields.Article.Categories.Terms:0.DisplayUrl -> http://... context.For("TaxonomyField", T("Taxonomy Field"), T("Tokens for Taxonomy Fields")) .Token("Terms", T("Terms"), T("The terms (Content) associated with field.")) .Token("Terms[:*]", T("Terms"), T("A term by its index. Can be chained with Content tokens.")) .Token("TermsSlug[:*]", T("Terms"), T("A term slug by its index. Can be chained with Content tokens.")) ; } public void Evaluate(EvaluateContext context) { context.For("TaxonomyField") .Token("Terms", field => String.Join(", ", field.Terms.Select(t => t.Name).ToArray())) .Token( token => token.StartsWith("Terms:", StringComparison.OrdinalIgnoreCase) ? token.Substring("Terms:".Length) : null, (token, t) => { var index = Convert.ToInt32(token); return index + 1 > t.Terms.Count() ? null : t.Terms.ElementAt(index).Name; }) .Token( token => token.StartsWith("TermsSlug:", StringComparison.OrdinalIgnoreCase) ? token.Substring("TermsSlug:".Length) : null, (token, t) => { var index = Convert.ToInt32(token); return index + 1 > t.Terms.Count() ? null : _slugService.Slugify(t.Terms.ElementAt(index).Name); }) // todo: extend Chain() in order to accept a filter like in Token() so that we can chain on an expression .Chain("Terms:0", "Content", t => t.Terms.ElementAt(0)) .Chain("Terms:1", "Content", t => t.Terms.ElementAt(1)) .Chain("Terms:2", "Content", t => t.Terms.ElementAt(2)) .Chain("Terms:3", "Content", t => t.Terms.ElementAt(3)) ; } } }
Hope this helps!