diff --git a/src/Aspire.Dashboard/Components/Pages/Resources.razor.cs b/src/Aspire.Dashboard/Components/Pages/Resources.razor.cs index 1fb53c32d9e..de87ce666cb 100644 --- a/src/Aspire.Dashboard/Components/Pages/Resources.razor.cs +++ b/src/Aspire.Dashboard/Components/Pages/Resources.razor.cs @@ -363,17 +363,6 @@ private List GetDisplayedEndpoints(ResourceViewModel resource additionalMessage = null; - // Make sure that endpoints have a consistent ordering. Show https first, then everything else. - return [.. GetEndpoints(resource) - .OrderByDescending(e => e.Url?.StartsWith("https") == true) - .ThenBy(e=> e.Url ?? e.Text)]; - } - - /// - /// A resource has services and endpoints. These can overlap. This method attempts to return a single list without duplicates. - /// - private static List GetEndpoints(ResourceViewModel resource) - { return ResourceEndpointHelpers.GetEndpoints(resource, includeInteralUrls: false); } diff --git a/src/Aspire.Dashboard/Model/ResourceEndpointHelpers.cs b/src/Aspire.Dashboard/Model/ResourceEndpointHelpers.cs index 1055ec87ed0..f56934c599b 100644 --- a/src/Aspire.Dashboard/Model/ResourceEndpointHelpers.cs +++ b/src/Aspire.Dashboard/Model/ResourceEndpointHelpers.cs @@ -29,7 +29,18 @@ public static List GetEndpoints(ResourceViewModel resource, b } } - return endpoints; + // Make sure that endpoints have a consistent ordering. + // Order: + // - https + // - other urls + // - endpoint name + var orderedEndpoints = endpoints + .OrderByDescending(e => e.Url?.StartsWith("https") == true) + .ThenByDescending(e => e.Url != null) + .ThenBy(e => e.Name, StringComparers.EndpointAnnotationName) + .ToList(); + + return orderedEndpoints; } } diff --git a/tests/Aspire.Dashboard.Tests/Model/ResourceEndpointHelpersTests.cs b/tests/Aspire.Dashboard.Tests/Model/ResourceEndpointHelpersTests.cs index 52192114d9e..977c00a6b49 100644 --- a/tests/Aspire.Dashboard.Tests/Model/ResourceEndpointHelpersTests.cs +++ b/tests/Aspire.Dashboard.Tests/Model/ResourceEndpointHelpersTests.cs @@ -168,6 +168,25 @@ public void GetEndpoints_IncludesIncludeInternalUrls() }); } + [Fact] + public void GetEndpoints_OrderByName() + { + var endpoints = GetEndpoints(CreateResource([ + new("a", new("http://localhost:8080"), isInternal: false), + new("C", new("http://localhost:8080"), isInternal: false), + new("D", new("tcp://localhost:8080"), isInternal: false), + new("B", new("tcp://localhost:8080"), isInternal: false), + new("Z", new("https://localhost:8080"), isInternal: false) + ])); + + Assert.Collection(endpoints, + e => Assert.Equal("Z", e.Name), + e => Assert.Equal("a", e.Name), + e => Assert.Equal("C", e.Name), + e => Assert.Equal("B", e.Name), + e => Assert.Equal("D", e.Name)); + } + private static ResourceViewModel CreateResource(ImmutableArray urls) { return new ResourceViewModel