Laden...

Wie mache ich Routen im ASP.NET Core 2.2 inkl Swagger dynamisch?

Erstellt von GambaJo vor 4 Jahren Letzter Beitrag vor 4 Jahren 1.685 Views
GambaJo Themenstarter:in
105 Beiträge seit 2006
vor 4 Jahren
Wie mache ich Routen im ASP.NET Core 2.2 inkl Swagger dynamisch?

Ich habe eine REST-API entwickelt, die auch so weit gut funktioniert. Fürs Testen und zur Dokumentationszwecken habe ich Swashbuckle (Swagger) eingebunden.

Nun habe ich die Aufgabe den Mittelteil der URL zu den Endpunkten variabel zu machen. Dafür wird der einzusetzende Wert aus einer Umgebungsvariable ausgelesen.

Derzeit:

https://localhost:44316/System

Dabei wir die Route per Annotation über den Controller definiert:

[Route("[controller]")]

Soll:

https://localhost:44316/DynamischerTeil/System

Dabei ist "System" der Controller und "DynamischerTeil" soll aus der Umgebungsvariable ersetzt werden.

Mein Versuch (Auszug):

app.UseMvc(routes =>
            {
                routes.MapRoute(
                    name: "default",
                    template: !string.IsNullOrEmpty(DynamischerTeil) ? $"{DynamischerTeil}" + "/{controller}" : "{controller}"
                    );
            });

Allerdings funktioniert das so nicht. Und wenn ich die Route-Annotation des Controllers entferne, taucht der Controller nicht mehr in Swagger auf.

Am einfachsten wäre es, wenn ich die Route-Annotation dynamisch gestalten könnte:

[Route("{DynamischerTeil}/[controller]")]

Hat jemand einen Tipp für mich, wie man das am besten lösen könnte? Es geht "nur" um das Routing.

16.835 Beiträge seit 2008
vor 4 Jahren

Dabei ist "System" der Controller und "DynamischerTeil" soll aus der Umgebungsvariable ersetzt werden.

Darf man fragen, wofür das nützlich sein soll? Also was hast Du vor? An für sich _sollte _eine REST URL immer mit einer Ressource beginnen und ist damit nicht dynamisch.
Soll das der Platzhalter für die Sprache sein? Oder Tenant-basiert? Wenn ja, dann gibt es dafür bessere Wege.
Wenn Du verrätst was Du vor hast, dann kann man Dich evtl. in die empfohlene Richtung schubsen, wie man es eigentlich machen würde.

Prinzipiell ist es keine empfohlene Art und Weise, dass Du das dynamische Routing ein mal über Attribute-Routing und ein mal über die Fallback-Route abdecken magst.
Es gibt auch eigentlich fast keinen Fall, der nicht via Attribute Routing abdeckbar ist.

GambaJo Themenstarter:in
105 Beiträge seit 2006
vor 4 Jahren

Danke für deine Antwort.

Meine Applikation ist ein Dienst, der zusammen mit anderen Diensten ausgeliefert wird (Docker, Kubernetes). Im Prinzip eine Microservices-Infrastruktur. Darum kümmert sich allerdings jemand anders.

Diese Dienste laufen alle auf einem Host. Hinzu kommt, dass sie auf diesem Host zwei mal installiert sind, eine Produktiv- und eine Test-Umgebung. Die Idee ist es diese durch unterschiedliche Pfade zu den Endpunkten zu trennen. Man kann das im entferntesten Sinne also als Multi-Tenant bezeichnen.

16.835 Beiträge seit 2008
vor 4 Jahren

Sowas hab ich fast schon befürchtet: und wäre ein riesen Fehler.

In einer Microservice Architektur ist niemals die Instanz für ein solches Versions- oder Stagemapping verantwortlich. Niemals.
Das verletzt jedes Grundprinzip von Microservice-Stuktur-Basics, dass eine Service immer nur eine Aufgabe erfüllt.
Ihr würdet euch damit Abhängigkeiten ins Haus holen, mit denen ihr viele Folgeproblem einhandelt und diese nicht ohne Breaking Changes bzw. Offline-Zeit lösen könnt.

Auf Kuberetes übernimmt der Ingress-Controller ein solches Mapping.
Dabei kann man entweder den Built-In Ingress verwenden, oder komfortablere Varianten wie Traefik.

Dort hinterlegst Du Suffix-Mappings wie die Version.

  • api.mydomomain.com/ => Ingress API Endpoint
  • api.mydomomain.com/users/latest => Alias Route für V2
  • api.mydomomain.com/users/v1 => Instanz(en) von API v1
  • api.mydomomain.com/users/v2 => Instanz(en) von API v2

Diese Endpunkte darf die API selbst nie aus Entwicklersicht kennen.
Die API ist für "api.mydomomain.com/users/v2" nicht verantwortlich.
Alles, was jedoch danach kommt, matched dann auf die Controller.

Prinzipiell ist es so, dass die allgemeine Empfehlung dass Stages in Kubernetes über die Namespaces gelöst werden.
In größeren Umgebungen bzw. Umgebungen mit mehr Anforderung an die Service Isolation kann das auch eine physikalische Trennung von einem eigenen Cluster sein.

Willst Du trotz der Gefahren, diese Richtung weiter gehen, dann lös das ganze über RoutePrefixes.
Dazu gibt es auch ein GitHub Repository, wo Du Dirdas Verhalten abschauen kannst
https://github.com/Microsoft/aspnet-api-versioning
Dort gibts auch noch ein Sample mit der Swagger Integrierung. Prinzipiell bekommst damit Dein Vorhaben geschenkt.

Das Vorhaben an für sich ist sicherlich nützlich bei einer 1-Instanz-Architektur: in einer Kubernetes-Welt sind jedoch andere Bausteine für solch ein Mapping verantwortlich.

PS: bin begeistert von den gebackenen Lebkuchen auf Deinem Blog - könnte fast von mir und Coffeebean gemacht worden sein :>

GambaJo Themenstarter:in
105 Beiträge seit 2006
vor 4 Jahren

Sorry, dass ich mich erst jetzt melde, Weihnachtsfeier und so... 😁

Sowas hab ich fast schon befürchtet: und wäre ein riesen Fehler.

Ja, leider habe ich da nicht die Entscheidungsgewalt. Ist aber auch ein etwas ungewöhnlicheres Problem, weil es um eine Art Hybrid-Cloud geht, also zum Teil bei Azure gehostet, teilweise on-prem.

Willst Du trotz der Gefahren, diese Richtung weiter gehen, dann lös das ganze über RoutePrefixes.
Dazu gibt es auch ein GitHub Repository, wo Du Dirdas Verhalten abschauen kannst

>

Dort gibts auch noch ein Sample mit der Swagger Integrierung. Prinzipiell bekommst damit Dein Vorhaben geschenkt.

Ich habe mir das angeschaut, muss aber ehrlich zugeben, ich steig da nicht wirklich durch bzw. weiß nicht so recht, was davon relevant für mich wäre. Wir grübeln derzeit an verschiedenen Lösungsansätzen, aber so richtig gut gefällt uns noch nichts davon.

Danke. Die machen wir jedes Jahr, teilweise sogar mehrfach. Ist ein altes Rezept von meiner Mutter, die es vermutlich von ihrer Großmutter hat. Für mich immer ein Ausflug in meine Kindheit. Und Junior liebt sie auch.

16.835 Beiträge seit 2008
vor 4 Jahren

Ist aber auch ein etwas ungewöhnlicheres Problem, weil es um eine Art Hybrid-Cloud geht, also zum Teil bei Azure gehostet, teilweise on-prem.

Das ist mittlerweile eine sehr weit verbreitete und übliche Anforderung.
Ich mach in der beruflichen Welt fast nur hybride Projekte basierend Azure und On Prem - vor allem IoT Projekte (Maschinenbau, Agrar, Smart Facility..).

Wir grübeln derzeit an verschiedenen Lösungsansätzen, aber so richtig gut gefällt uns noch nichts davon.

Warum kein standardisierten Weg nehmen?

GambaJo Themenstarter:in
105 Beiträge seit 2006
vor 4 Jahren

Das ist mittlerweile eine sehr weit verbreitete und übliche Anforderung.

Ich vermute, das wird sich in der Zukunft immer mehr Richtung Cloud verlagern, aber bis dahin müssen wir diese zwei Welten versuchen zu vereinen. Fühlt sich alles irgendwie als Notlösung an.

Warum kein standardisierten Weg nehmen?

Ich weiß es auch (noch) nicht, sitze hier sozusagen zwischen den Stühlen. Ich muss mir das nächsten Jahr mal genauer anschauen.
Danke schon mal für deine Hilfe.

16.835 Beiträge seit 2008
vor 4 Jahren

Ich vermute, das wird sich in der Zukunft immer mehr Richtung Cloud verlagern, aber bis dahin müssen wir diese zwei Welten versuchen zu vereinen.

Gründe, die dagegen sprechen (je nach Branche):

  • On-Prem werden so viele Daten erzeugt, die gar nicht in die Cloud geschoben werden können (Agrar, Maschinenbau...)
  • Latenzen
  • Offline Fähigkeiten

Daher wird ein hybrides Szenarie keine Notlösung, sondern für die meisten Alltag sein.
Daraufhin arbeiten auch die meisten Technologien (Container, Kubernetes, OpenShift, Rancher...), und Anbieter im Infrastrukturbereich (Microsoft, AWS, Google, IBM..)