domaindrivendev / domaindrivendev/Swashbuckle.AspNetCore

`OrderActionsBy` should take `IComparer<ApiDescription>` or second argument `IComparer<string>`

Open
#2,001 0 comments 0 reactions 0 assignees View on GitHub
help-wanted p2
Dominant language
C#
Stars
5.5k
Forks
1.3k
Avg merge
1d 12h
Merged PRs (30d)
31

Description

Currently it takes `Func`, and it is used with `.OrderBy()`, without StringComparer or CultureInfo. Without them, doc might be rendered in different order between runtime environments, and we can't control it.

I wanted those endpoints to be sorted in this order
```
GET /accounts/{id}
POST /accounts/{id}
DELETE /accounts/{id}
GET /accounts:byAlt/{alt}
```

I had to write this code:
```cs
// README:
// You might think "Isn't '/' comes before ':' in Ascii?", but you are wrong.
// Default string comparer isn't StringComparer.Ordinal. It uses unicode collation, so ':' comes before '/'.
// I've chosen '\t' since it works empherically. '\0' didn't worked.
// Please read the specification of the Unicode Collation Algorithm and teach me if you can : https://unicode.org/reports/tr10/
var path = action.RelativePath.Replace('/', '\t');
// To put POST, PUT before DELETE.
var ordering = new[] { "GET", "HEAD", "POST", "PUT", "DELETE", "PATCH" };
var index = Array.IndexOf(ordering, action.HttpMethod!.ToUpperInvariant());
// Again, "\t\t" is choosen to not collide with /some/endpoint/0. (who writes such endpoint template?)
return string.Format(CultureInfo.InvariantCulture, "{0}\t\t{1}", action.RelativePath, index);
```

If we could provide `StringComparer.Ordinal` to `.OrderBy`, then it would've been
```cs
var ordering = new[] { "GET", "HEAD", "POST", "PUT", "DELETE", "PATCH" };
var index = Array.IndexOf(ordering, action.HttpMethod!.ToUpperInvariant());
return string.Format(CultureInfo.InvariantCulture, "{0}\0{1}", action.RelativePath, index);
```

But I'd like to remove the funky '\0' with IComparer\,
```cs
class ApiDescriptionComparer : IComparer {
readonly string[] ordering = new[] { "GET", "HEAD", "POST", "PUT", "DELETE", "PATCH" };
public int Comapre(ApiDescription a, ApiDescription b) {
var i = a.RelativePath.CompareTo(b.RelativePath, StringComparer.Ordinal);
if (i != 0) return i;

var ia = Array.IndexOf(ordering, a.HttpMethod!.ToUpperInvariant());
var ib = Array.IndexOf(ordering, b.HttpMethod!.ToUpperInvariant());
return ia - ib;
}
}
```

Contributor guide

Open the contributing guide

Research direction

Locate OrderActionsBy and its current OrderBy usage, then inspect how ApiDescription.RelativePath and HttpMethod are currently used for ordering. Compare the proposed comparer-based API options and verify that endpoint ordering is deterministic across runtime environments, including the requested method precedence and ordinal path comparison.

Written by the indexing model from the issue text.

Assessment

Tech stack
csharp
Domain
backend-api-design
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
42/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.