domaindrivendev / domaindrivendev/Swashbuckle.AspNetCore
`OrderActionsBy` should take `IComparer<ApiDescription>` or second argument `IComparer<string>`
- 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
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