Skip to content

Make DDRMenu independent of its host control and the WebForms Page - #7563

Open
donker wants to merge 3 commits into
dnnsoftware:developfrom
donker:2026-10-ddrmenu-pageless
Open

donker wants to merge 3 commits into
dnnsoftware:developfrom
donker:2026-10-ddrmenu-pageless

Conversation

@donker

@donker donker commented Oct 15, 2026

Copy link
Copy Markdown
Contributor

Allows DDRMenu to render without a WebForms host control or System.Web.UI.Page.

Changes

Host control independence

  • DNNContext gets a new DNNContext(string clientID) constructor and a ClientID property.
    • Page returns null instead of throwing when there is no host control.
    • ResolveUrl falls back to Globals.ResolveUrl when there is no host control.
  • RazorTemplateProcessor, TokenTemplateProcessor and XsltTemplateProcessor use DNNContext.Current.ClientID instead of HostControl.ClientID.
  • XsltTemplateProcessor resolves paths with Page.ResolveUrl when a page exists, and with Globals.ResolveUrl otherwise.
  • MenuNode.ApplyContext only converts postback: URLs when a WebForms page is available.

Resource and head registration without a Page

  • TemplateDefinition.PreRender (internal) now receives IClientResourceController and IPageService instead of resolving the controller from the service locator.
  • Fallback scripts (jsObject scripts):
    • On WebForms pages, they still use ClientScript.RegisterClientScriptBlock.
    • Without a page, they are added to the head through IPageService.AddToHead, skipping any script that is already there.
  • Template head content:
    • On WebForms pages, it is still written to Page.Header, because Default.aspx has already consumed the IPageService head tags by the time controls pre-render.
    • Without a page, it goes through IPageService.AddToHead.

Bug fix

  • XsltFunctions.GetUserText read HttpContext.Items["DDRMenuHostControl"], which nothing sets. For anonymous users it therefore returned an exception message instead of the localized "Register" text. It now uses DNNContext.Current.ResolveUrl.

Public API

The new dependencies are passed through MenuBase, MenuView, SkinObject, DDRMenuNavigationProvider and the internal DDRMenuControl. Every public member whose signature changed keeps its old signature as an overload, deprecated in 10.4.0.

Type Added Deprecated (10.4.0)
MenuBase ctor(ILocaliser, IHostSettings, ITabController, IClientResourceController, IPageService)
Instantiate(ILocaliser, IHostSettings, ITabController, IClientResourceController, IPageService, string)
ctor(ILocaliser, IHostSettings, ITabController)
Instantiate(ILocaliser, IHostSettings, ITabController, string)
MenuView ctor(..., IClientResourceController, IPageService) ctor(ILocaliser, IHostSettings, ITabController)
SkinObject ctor(..., IClientResourceController, IPageService) ctor(ILocaliser, IHostSettings, ITabController)
DDRMenuNavigationProvider ctor(..., IClientResourceController, IPageService) ctor(ILocaliser, IHostSettings, ITabController)
DNNContext ctor(string clientID), ClientID —

When the new constructor parameters are null, they are resolved from the current service provider, the same as the existing parameters.

Review feedback from #7526 addressed here

  • DNNContext URL helpers now work when HostControl is null.
  • Fallback ScriptKeys are now registered when there is no page, so MVC rendering keeps the fallback script behavior.
  • The deprecation version is 10.4.0, since this targets develop.

Testing

  • All C# projects in DNN_Platform.sln compile, including DotNetNuke.Modules.DDRMenu and DotNetNuke.Tests.Modules.DDRMenu.
  • No new CS0618 (obsolete member) warnings.
  • TODO: smoke-test DDRMenu skin objects (XSLT, token and Razor templates) on a WebForms page.

Related to #

donker and others added 2 commits October 15, 2026 11:49
- DNNContext can be created from a client ID; ResolveUrl falls back to Globals.ResolveUrl without a host control.
- Template processors use DNNContext.ClientID; XSLT resolves URLs without a Page.
- XsltFunctions.GetUserText resolves through DNNContext instead of the never-set DDRMenuHostControl item.
- MenuNode only converts postback URLs when a WebForms page is available.
- TemplateDefinition.PreRender registers resources through IClientResourceController and writes head content and fallback scripts through IPageService when no Page exists.
- Thread IClientResourceController and IPageService through MenuBase, MenuView, SkinObject, DDRMenuNavigationProvider and DDRMenuControl; previous public signatures are kept and deprecated in 10.4.0.

Co-authored-by: Cursor <cursoragent@cursor.com>
@donker donker added this to the 10.4.1 milestone Oct 15, 2026
@donker
donker requested a review from bdukes October 15, 2026 10:21
@donker donker self-assigned this Oct 15, 2026
@donker donker modified the milestones: 10.4.1, Future: Minor, 10.5.0 Oct 15, 2026

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

1 participant