Navigation widget - make Redirect Pages redirect directly to destination url

by Vesselin Vassilev


Last Updated On May 23, 2021


Here is a scenario - you create a Redirect page that, let's say, you want to redirect to Google.com.

The page appears in the menu, but you notice that when you hover over that page in the menu, the target Url is not actually google.com, but it is the url of the page in Sitefinity, e.g. something like /redirect-to-google

When you click that link, two things are happening:

1. A request to the redirect page's url is sent to Sitefinity
GET /redirect-to-google

2. The response to that request is where the actual redirect is happening:
Status code 301, with a header:
location: https://google.com

To many end users, this is not expected, more often than not they would want the menu to render the Url of the destination page, e.g. google.com

This would also save an unnecessary request to the Sitefinity server.

There is already a KB article on how to change the WebForms navigation widget to achieve that. 

Below is how to do it for the MVC navigation widget.

Note: the NodeViewModel class does not contain info about the type of the Page (i.e. Standard or Redirect), but fortunately it gives us a reference to the PageSiteNode via the OriginalSiteMapNode property. 

From there we can easily get the destination url of any redirect page.

See the below GetUrl function that can be placed in the Navigation view:

@using Telerik.Sitefinity.Pages.Model;
@using Telerik.Sitefinity.Frontend.Mvc.Helpers;
@using Telerik.Sitefinity.Web;
@using Telerik.Sitefinity.Frontend.Navigation.Mvc.Models;
@model Telerik.Sitefinity.Frontend.Navigation.Mvc.Models.INavigationModel
<ul class="navbar-nav mr-auto mt-lg-0 pr-0 @Model.CssClass">
<li class="nav-close"><a href="#"><i class="fa fa-times" aria-hidden="true"></i></a></li>
@foreach (var node in Model.Nodes)
{
var activeCss = node.IsCurrentlyOpened || node.HasChildOpen ? "active" : string.Empty;
if (node.ChildNodes.Count > 0)
{
<li class="nav-item dropdown @node.CustomFields.CssClass">
<a class="nav-link dropdown-toggle @activeCss" href="#"
id='@Html.UniqueId("navbarDropdownMenuLink")' data-toggle="dropdown"
aria-haspopup="true" aria-expanded="false">@node.Title</a>
<ul class="dropdown-menu" aria-labelledby='@Html.UniqueId("navbarDropdownMenuLink")'>
@foreach (var child in node.ChildNodes)
{
var childCss = child.IsCurrentlyOpened ? "active" : string.Empty;
<li>
<a class="dropdown-item nav-link @childCss" href="@GetUrl(child)" target="@child.LinkTarget">@Html.Raw(child.Title)</a>
</li>
}
</ul>
</li>
}
else
{
<li class="nav-item @activeCss @node.CustomFields.CssClass">
<a class="nav-link" href="@GetUrl(node)" target="@node.LinkTarget">@Html.Raw(node.Title)</a>
</li>
}
}
</ul>
@functions {
public string GetUrl(NodeViewModel node)
{
var psnode = node.OriginalSiteMapNode as PageSiteNode;
if (psnode == null)
{
// this is the case where user added a link to the menu using the
// External Url tab of the Nav widget, instead of creating it as a page node in SF
return node.Url;
}
var navigateUrl = node.Url;
if (psnode.NodeType == NodeType.OuterRedirect)
{
navigateUrl = psnode.RedirectUrl;
}
else if (psnode.NodeType == NodeType.InnerRedirect)
{
navigateUrl = App.WorkWith()
.Page(psnode.LinkedNodeId)
.Get()
.GetFullUrl()
.TrimStart("~");
}
return navigateUrl;
}
}



Copyright © Sitefinity Development