Hello, I am porting several modules developed in DNN 7 to DNN 9.11. Former colleagues modified the (sealed) "DotNetNuke.Common.Globals.NavigateURL" class to introduce a collection of parameters to be added and stored in query string. Is there a smart way to do the same thing with DNN 9, possibly without modifying the DNN code base?
Thanks Seek
Posted By Brian Dukes on 7/26/2024 7:02 PM If you can provide an example of the sort of customization that was previously done, we could probably give you an alternative fairly easily. I'm imagining that you could move your customized methods out into another class that takes an INavigationManager (and/or wraps Globals.NavigateURL, depending on how its used).
Sure, here my code based on old DNN 7.4.2
[CODE] public static string NavigateURL(int tabID, bool isSuperTab, PortalSettings settings, string controlKey, string language, string pageName, params string[] additionalParameters) { string url = tabID == Null.NullInteger ? ApplicationURL() : ApplicationURL(tabID); if (!String.IsNullOrEmpty(controlKey)) { url += "&ctl=" + controlKey; } if (isSuperTab) { url += "&portalid=" + settings.PortalId; }
/* Introduction of a collection of query string elements to be preserved during portal page navigation. * A collection of keys is defined, where each key is the name of a query string parameter. For each navigation request, * this class checks the collection and, for each element, verifies its presence in the query string of the current request; * if the element is found, a corresponding entry in the query string will be inserted in the generated URL. * This mechanism allows reproducing the behavior that was present when the information about the current company was part * of the HTTP alias: the "CompanySelector" component will take care of keeping the information updated. * If one of the parameters of the current request is a URL, the list of its parameters is merged with the list of the * request parameters. Consequently, the value retrieved from the QueryString property is a comma-separated list of all * the parameter values. In this case, I assume that the parameter representing a URL is always the last in the list * and consider only the value of the first occurrence of the parameter. */ if (HttpContext.Current != null) { foreach (string parameterName in QueryStringParametersToBePreserved) { int indexOfParameter = HttpContext.Current.Request.Url.Query.ToUpper().IndexOf(parameterName.ToUpper());
/* Must check: * - generated URL does not contain the current parameter * - the current parameter does not in additional parameters (which must prevail) */ if (indexOfParameter != -1 && !url.ToUpper().Contains(parameterName.ToUpper() + "=") && (additionalParameters == null || !additionalParameters.Any(p => p != null && p.ToUpper().StartsWith(parameterName.ToUpper() + "=")))) { string substringAfterParameter = HttpContext.Current.Request.Url.Query.Substring(indexOfParameter); int indexOfAmpersand = substringAfterParameter.IndexOf("&"); string nameAndValue; if (indexOfAmpersand != -1) { nameAndValue = substringAfterParameter.Substring(0, indexOfAmpersand); } else { nameAndValue = substringAfterParameter; }
url += "&" + nameAndValue; } } }
TabInfo tab = null;
if (settings != null) { tab = TabController.Instance.GetTab(tabID, isSuperTab ? Null.NullInteger : settings.PortalId, false); }
//only add language to url if more than one locale is enabled if (settings != null && language != null && LocaleController.Instance.GetLocales(settings.PortalId).Count > 1) { if (settings.ContentLocalizationEnabled) { if (language == "") { if (tab != null && !string.IsNullOrEmpty(tab.CultureCode)) { url += "&language=" + tab.CultureCode; } } else { url += "&language=" + language; } } else if (settings.EnableUrlLanguage) { //legacy pre 5.5 behavior if (language == "") { url += "&language=" + Thread.CurrentThread.CurrentCulture.Name; } else { url += "&language=" + language; } } }
/* * I place additional parameters at the end of the generated URL: in some cases, the last parameter passed to this method is a URL; * if this URL itself has parameters, these are mistakenly interpreted as parameters of the generated URL, not of the parameter itself, * causing interpretation errors. */ if (additionalParameters != null) { url = additionalParameters.Where(parameter => !string.IsNullOrEmpty(parameter)).Aggregate(url, (current, parameter) => current + ("&" + parameter)); }
if (Host.UseFriendlyUrls || Config.GetFriendlyUrlProvider() == "advanced") { if (String.IsNullOrEmpty(pageName)) { pageName = glbDefaultPage; }
url = (settings == null) ? FriendlyUrl(tab, url, pageName) : FriendlyUrl(tab, url, pageName, settings); } else { url = ResolveUrl(url); }
return url; } [CODE]
It looks to me like you should be able to wrap the existing <code>NavigateURL</code> functionality, instead of rewriting it. Something like this:
<code>public class NavigationUtility { private readonly INavigationManager navigationManager; public NavigationUtility(INavigationManager navigationManager) { this.navigationManager = navigationManager; } public string NavigateURL(int tabID, bool isSuperTab, PortalSettings settings, string controlKey, string language, string pageName, params string[] additionalParameters) { var allParameters = new List<string>(additionalParameters ?? Array.Empty<string>()); /* Introduction of a collection of query string elements to be preserved during portal page navigation. * A collection of keys is defined, where each key is the name of a query string parameter. For each navigation request, * this class checks the collection and, for each element, verifies its presence in the query string of the current request; * if the element is found, a corresponding entry in the query string will be inserted in the generated URL. * This mechanism allows reproducing the behavior that was present when the information about the current company was part * of the HTTP alias: the "CompanySelector" component will take care of keeping the information updated. * If one of the parameters of the current request is a URL, the list of its parameters is merged with the list of the * request parameters. Consequently, the value retrieved from the QueryString property is a comma-separated list of all * the parameter values. In this case, I assume that the parameter representing a URL is always the last in the list * and consider only the value of the first occurrence of the parameter. */ if (HttpContext.Current != null) { foreach (string parameterName in QueryStringParametersToBePreserved) { int indexOfParameter = HttpContext.Current.Request.Url.Query.ToUpper().IndexOf(parameterName.ToUpper()); /* Must check: the current parameter does not in additional parameters (which must prevail) */ if (indexOfParameter != -1 && !additionalParameters.Any(p => p != null && p.ToUpper().StartsWith(parameterName.ToUpper() + "="))) { string substringAfterParameter = HttpContext.Current.Request.Url.Query.Substring(indexOfParameter); int indexOfAmpersand = substringAfterParameter.IndexOf("&"); string nameAndValue; if (indexOfAmpersand != -1) { nameAndValue = substringAfterParameter.Substring(0, indexOfAmpersand); } else { nameAndValue = substringAfterParameter; } allParameters.Add(nameAndValue); } } } return this.navigationManager.NavigateURL(tabID, isSuperTab, settings, controlKey, language, pageName, allParameters.ToArray()); } </code>
Thanks! What do you think is better to do? Inherit the class Modify the existing DNN code What else?
Posted By Seek78 on 7/30/2024 8:55 AM Thanks! What do you think is better to do? Inherit the class Modify the existing DNN code What else?
I mean, I want it as default for all URL visited in the portal.
Posted By Brian Dukes on 7/31/2024 3:22 PM create your own friendly URL provider.
Could you provide come examples? Thanks S.
Maybe something like this (and then adjust the <code>friendlyUrl</code> section of the <code>web.config</code> to point to your provider):
using System; using DotNetNuke.Abstractions.Portals; using DotNetNuke.Common; using DotNetNuke.Entities.Tabs; using DotNetNuke.Services.Url.FriendlyUrl; namespace overridednnurls { public class SpecialFriendlyUrlProvider : FriendlyUrlProvider { private static readonly string[] QueryStringParametersToBePreserved = { "CompanySelector", }; public override string FriendlyUrl(TabInfo tab, string path) { return DNNFriendlyUrlProvider.Instance().FriendlyUrl(tab, AdjustParameters(path)); } public override string FriendlyUrl(TabInfo tab, string path, string pageName) { return DNNFriendlyUrlProvider.Instance().FriendlyUrl(tab, AdjustParameters(path), pageName); } public override string FriendlyUrl(TabInfo tab, string path, string pageName, string portalAlias) { return DNNFriendlyUrlProvider.Instance().FriendlyUrl(tab, AdjustParameters(path), pageName, portalAlias); } public override string FriendlyUrl(TabInfo tab, string path, string pageName, IPortalSettings settings) { return DNNFriendlyUrlProvider.Instance().FriendlyUrl(tab, AdjustParameters(path), pageName, settings); } private static string AdjustParameters(string path) { if (!Uri.TryCreate(path, UriKind.Relative, out var url)) { return path; } /* Introduction of a collection of query string elements to be preserved during portal page navigation. * A collection of keys is defined, where each key is the name of a query string parameter. For each navigation request, * this class checks the collection and, for each element, verifies its presence in the query string of the current request; * if the element is found, a corresponding entry in the query string will be inserted in the generated URL. * This mechanism allows reproducing the behavior that was present when the information about the current company was part * of the HTTP alias: the "CompanySelector" component will take care of keeping the information updated. * If one of the parameters of the current request is a URL, the list of its parameters is merged with the list of the * request parameters. Consequently, the value retrieved from the QueryString property is a comma-separated list of all * the parameter values. In this case, I assume that the parameter representing a URL is always the last in the list * and consider only the value of the first occurrence of the parameter. */ if (HttpContextSource.Current != null) { foreach (string parameterName in QueryStringParametersToBePreserved) { int indexOfParameter = HttpContextSource.Current.Request.Url.Query.IndexOf(parameterName, StringComparison.OrdinalIgnoreCase); if (indexOfParameter != -1 && !path.ToUpperInvariant().Contains(parameterName.ToUpperInvariant() + "=")) { string substringAfterParameter = HttpContextSource.Current.Request.Url.Query.Substring(indexOfParameter); int indexOfAmpersand = substringAfterParameter.IndexOf('&'); string nameAndValue; if (indexOfAmpersand != -1) { nameAndValue = substringAfterParameter.Substring(0, indexOfAmpersand); } else { nameAndValue = substringAfterParameter; } path += "&" + nameAndValue; } } } return path; } } }
These Forums are for the discussion of the open source CMS DNN platform and ecosystem.
For the benefit of the community and to protect the integrity of the ecosystem, please observe the following posting guidelines:
Awesome! Simply post in the forums using the link below and we'll get you started.