Skip to content

URL Info: Fix invariant content URLs missing under non-default language domains (closes #21866)#21883

Merged
AndyButland merged 6 commits intomainfrom
v17/bugfix/21866-fix-backoffice-url-display
Feb 25, 2026
Merged

URL Info: Fix invariant content URLs missing under non-default language domains (closes #21866)#21883
AndyButland merged 6 commits intomainfrom
v17/bugfix/21866-fix-backoffice-url-display

Conversation

@AndyButland
Copy link
Contributor

@AndyButland AndyButland commented Feb 24, 2026

Description

#21866 reports a regression from #21473 where invariant content under a domain assigned to a non-default culture (e.g. test.dkda-DK) showed no URLs in the backoffice Info tab.

Now for invariant content, we iterate all cultures and skip those that return no URL ("#"), as well filtering out fallback URLs (using the request base URL) when domain-based URLs exist. This seems a reasonable approach for invariant content, where we would only expect one language to be defined on a domain setting.

I added further integration tests and did a little test clean-up for this class too.

Testing

See the linked issue for a project that can be used to verify the fix. I pulled out just the database and credentials and set up my local test site to point to that.

With this PR in place I now see expected domains under each root node:

image

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes a regression in the Management API/backoffice URL listing where invariant content under a domain assigned to a non-default culture could end up with missing/incorrect URLs, by changing how PublishedUrlInfoProvider enumerates cultures and filters results.

Changes:

  • Update PublishedUrlInfoProvider.GetAllAsync to iterate all cultures for invariant content, skip missing URLs, and filter out “fallback” base-URL results when domain-based URLs exist.
  • Add an integration test covering invariant content under a non-default language domain, and rename/keep the existing invariant-no-domain coverage.
  • Consolidate the HideTopLevelNodeFromPath = false test into the main PublishedUrlInfoProviderTests using ConfigureBuilder.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 4 comments.

File Description
src/Umbraco.Core/Routing/PublishedUrlInfoProvider.cs Adjusts invariant URL enumeration/filtering logic to surface domain URLs under non-default cultures.
tests/Umbraco.Tests.Integration/Umbraco.Core/Services/PublishedUrlInfoProviderTests.cs Adds/updates integration tests for invariant URL behavior and consolidates HideTopLevel=false coverage.
tests/Umbraco.Tests.Integration/Umbraco.Core/Services/PublishedUrlInfoProvider_hidetoplevel_false.cs Removes the now-redundant separate test fixture after consolidation.

@AndyButland AndyButland changed the title Routing: Fix invariant content URLs missing under non-default language domains (closes #21866) URL Info: Fix invariant content URLs missing under non-default language domains (closes #21866) Feb 24, 2026
@lauraneto
Copy link
Contributor

@AndyButland
I was trying to see if I could approach this in a simpler way, as the code can be a bit hard to follow with all the conditions.
I ended up with the following:

private async Task<IEnumerable<string>> GetCulturesForUrlLookupAsync(IContent content)
{
    if (content.ContentType.VariesByCulture())
    {
        return await _languageService.GetAllIsoCodesAsync();
    }

    IUmbracoContext umbracoContext = _umbracoContextAccessor.GetRequiredUmbracoContext();
    var ancestorOrSelfIds = content.AncestorIds().Append(content.Id).ToHashSet();
    var domainCultures = umbracoContext.Domains.GetAll(true)
        .Where(d => ancestorOrSelfIds.Contains(d.ContentId))
        .Select(d => d.Culture)
        .WhereNotNull()
        .Distinct(StringComparer.OrdinalIgnoreCase)
        .ToList();

    return domainCultures.Count > 0
        ? domainCultures
        : [await _languageService.GetDefaultIsoCodeAsync()];
}

Which could then be assigned to cultures in line 65/68 and the whole if (isInvariant) starting in line 106 could be removed as we would be filtering the cultures before trying to get the urls instead of after, but we would still keep the check you added for isInvariant in url is "#" or "#ex", as that might still be relevant.
While it looks simpler to me, I am unsure whether there is a scenario I might not be considering.
Let me know your thoughts!

@AndyButland
Copy link
Contributor Author

I think this looks OK @lauraneto - and I can see the benefit of getting the cultures up front rather than handling the duplications later. Please go ahead if you'd like to update this.

Instead of querying all cultures and post-processing to remove irrelevant
URLs, determine the relevant cultures before the loop by checking which
domains are assigned to the content's ancestor path.
@AndyButland AndyButland merged commit df952c9 into main Feb 25, 2026
26 checks passed
@AndyButland AndyButland deleted the v17/bugfix/21866-fix-backoffice-url-display branch February 25, 2026 10:27
AndyButland added a commit that referenced this pull request Feb 25, 2026
…ge domains (closes #21866) (#21883)

* Show correct URLs for invariant content under non-default language domains.

* Use configured domain hosts instead of request host for fallback URL filtering.

* Addressed feedback from code review.

* Fixed code warnings.

* Update file references in integration test csproj.

* Simplify invariant URL culture filtering by determining cultures upfront

Instead of querying all cultures and post-processing to remove irrelevant
URLs, determine the relevant cultures before the loop by checking which
domains are assigned to the content's ancestor path.

---------

Co-authored-by: Laura Neto <12862535+lauraneto@users.noreply.github.com>
@AndyButland
Copy link
Contributor Author

Cherry-picked to release/17.2.1.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants