Identifying pages based on URL parameters

When using the custom routing scheme, you can give content editors control over a part of the page URL by adding parameters into URL patterns. This allows you to include suitable human-readable keywords in URLs, and improve the site’s SEO.

By default, pages in Xperience provide a page alias field for this purpose. The system automatically defines a page alias for every page, typically as a URL-safe version of its name in the content tree. Internally, the page alias is stored in the NodeAlias field (column) of each page and you can retrieve it using the {%NodeAlias%} macro expression (for example when specifying URL patterns of page types).

Since page aliases are controlled by content editors, they can change over time. Also, page aliases are only guaranteed to be unique within a given sub-section level of the content tree (under the same parent page). For example, only pages stored directly in the /Articles section will have a unique page alias among each other. However, if one page is stored under /Articles/March and another page is stored under /Articles/May, they can both have the same page alias. This is why you may not want to use page aliases as the only identifier when displaying pages.

The recommended practice for identifying pages with a page alias value in the URL is to combine it with another unique identifier, such as the NodeGUID . This ensures that conflicts cannot occur and URLs remain valid even if a page’s alias changes.

NodeGUID values provide more stable URLs and links than NodeIDs, which may differ when hosting the same website on multiple instances (for example in environments that use content staging).

Typically, a page alias is inserted into the URL pattern of a page type using a macro expression. For example, a URL pattern could look like the following: /Articles/{%NodeGUID%}/{%NodeAlias%}

Setting page aliases

Usually, the page alias is something that describes the given content. One of the motivations for using page aliases to identify pages is to improve the site’s SEO.

Aliases build the alias path of each page, which contains all parent pages up to the root of the site’s content tree. For example, if you set a page’s alias to Media, then the URL is: <site domain>/<parent page alias path>/Media

To define the page alias for pages:

  1. Open the Pages application.
  2. Select the page for which you want to define a page alias.
  3. Open the Properties -> General tab -> Advanced section.
  4. Enter a page alias into the Page alias field.
  5. Click Save.

The page now uses the defined page alias as its identifier.

Tip: You can also make pages available under any number of alternative URLs. While page aliases can affect the main URL of a page, alternative URLs can give you even more flexibility when it comes to providing short and relevant-looking links. For more information, see Managing page URLs.

Identifying multilingual content when using page aliases

Page aliases remain the same for pages in different cultures. To distinguish pages in different cultures, you can include a language prefix in your URL patterns (for example using the {%DocumentCulture%} macro), or create a custom page type field and use it instead of the page alias.

Displaying pages based on a page alias

The following example shows how you can configure your MVC application to display articles that have a URL containing a page alias parameter, without any additional identifiers. 

  1. In your application’s RouteConfig.cs file, create a route for accessing articles based on a page alias. For example:

    
    
    
     public class RouteConfig
     {
         public static void RegisterRoutes(RouteCollection routes)
         {
         ...
             // Maps a custom route that displays an article based on a provided page alias
             route = routes.MapRoute(
                 name: "ArticleByPageAlias",
                 url: "{culture}/Articles/{pageAlias}",
                 defaults: new { culture = new SiteCultureConstraint(), controller = "Articles", action = "ShowByPageAlias" }
             );
         ...
         }
     };
    
    
     
  2. Create a view model for your page type. For example:

    
    
    
     // Encapsulates data that is sent to associated views
     public class ArticleViewModel
     {
         public string Title { get; set; }
         public string Summary { get; set; }
         public string Text { get; set; }
         public DocumentAttachment Teaser { get; set; }
         public string NodeAlias { get; set; }
         public string Url { get; set; }
    
         // Creates a view model instance for a given Article
         public static ArticleViewModel GetViewModel(Article article, IPageUrlRetriever pageUrlRetriever)
         {
             return new ArticleViewModel
             {
                 PublicationDate = article.PublicationDate,
                 RelatedArticles = article.Fields.RelatedArticles.OfType<Article>().Select(related => GetViewModel(related, pageUrlRetriever)),
                 Summary = article.Fields.Summary,
                 Teaser = article.Fields.Teaser,
                 Text = article.Fields.Text,
                 Title = article.Fields.Title,
                 Url = pageUrlRetriever.Retrieve(article).RelativePath
             };
         }
     }
    
    
     
  3. Retrieve articles based on a page alias. For example using the repository pattern:

    
    
    
     public interface IArticleRepository
     {
     ...
         /// <summary>
         /// Returns the article with the specified page alias.
         /// </summary>
         /// <param name="pageAlias">The article page alias.</param>
         /// <returns>The article with the specified page alias, if found; otherwise, null.</returns>
         Article GetArticle(string pageAlias);
     ...
     }
    
    
     
    
    
    
     public class ArticleRepository : IArticleRepository
     {
     ...
         /// <summary>
         /// Returns the article with the specified page alias. Uses a generated page type provider for the Article page type.
         /// </summary>
         /// <param name="pageAlias">The article page alias.</param>
         /// <returns>The article with the specified page alias, if found. Null otherwise.</returns>
         public Article GetArticle(string pageAlias)
         {
             return new DocumentQuery<Article>()
                 .OnSite(mSiteName)
                 .Culture(mCultureName)
                 .WhereEquals("NodeAlias", pageAlias)
                 .LatestVersion(mLatestVersionEnabled)
                 .FirstOrDefault();
         }
     ...
     }
    
    
     
  4. Add a controller action for retrieving articles based on a page alias.

    
    
    
     public class ArticlesController : Controller
     {
         private readonly IPageUrlRetriever pageUrlRetriever;
    
         public ArticlesController(IPageUrlRetriever pageUrlRetriever)
         {
             this.pageUrlRetriever = pageUrlRetriever;
         }
    
     ...
    
         // GET: Articles/{pageAlias}
         public ActionResult ShowByPageAlias(string pageAlias)
         {
             // Retrieves an article based on the provided page alias
             var article = mArticleRepository.GetArticle(pageAlias);
             if (article == null)
             {
                 return HttpNotFound();
             }
    
             // Constructs a view model and sends it to a related view
             return View("Show", ArticleViewModel.GetViewModel(article, pageUrlRetriever));
         }
     ...
     }
    
    
     
  5. Display links to articles in views:

    
    
    
     <a href="@Url.Content(Model.Url)">@article.Title </a>
    
    
     

Displaying pages based on NodeGUID and a page alias

If you use both a NodeGUID and page alias parameter in your URLs, use the NodeGUID identifier to retrieve specific pages in your code. The generated page type code provides the required method by default.




public static DocumentQuery<Article> GetArticle(Guid nodeGuid, string cultureName, string siteName)
{
    return new DocumentQuery<Article>().OnSite(siteName).Culture(cultureName).WhereEquals("NodeGUID", nodeGuid);
}


For URLs that only contain a page alias parameter (NodeAlias), you need to make sure the page alias is always unique. You can, to a certain degree, ensure this uniqueness by limiting how content editors are allowed to create new pages:

To retrieve pages using only the page alias:




public static DocumentQuery<Article> GetArticle(string pageAlias, string cultureName, string siteName)
{
    return new DocumentQuery<Article>().WhereEquals("NodeAlias", pageAlias).OnSite(siteName).Culture(cultureName).TopN(1);
}


You can also use the full NodeAliasPath to retrieve pages (for example /Articles/March/On-Roasts for an article named On Roasts). This approach can be useful in scenarios where you have a highly structured content tree, and can build the alias path in your code according to other URL parameters.




public static DocumentQuery<Article> GetArticle(string nodeAliasPath, string cultureName, string siteName)
{
    return new DocumentQuery<Article>().OnSite(siteName).Culture(cultureName).Path(nodeAliasPath);
}


See also: Displaying page content