Laden...

ASP.NET Core Middleware für REST Links

Erstellt von fluxy vor 6 Jahren Letzter Beitrag vor 6 Jahren 2.794 Views
F
fluxy Themenstarter:in
183 Beiträge seit 2009
vor 6 Jahren
ASP.NET Core Middleware für REST Links

Guten Tag,

ich weiss gar nicht, ob mein Vorgehen richtig ist, aber ich habe gelesen, dass man REST-Services so implementiert, dass nicht nur das Ergebnis der Abfrage übermittelt wird, sondern auch Links, die genutzt werden können, um weiter abzufragen. Dazu habe ich versucht eine kleine Middleware zu schreiben, die es mir erlaubt, die Links hinzuzufügen.

Ich habe also zum Beispiel als Resource Projekte, die ich über einen ProjectsController abfrage:


        [HttpGet]
        public IEnumerable<ProjectWebRepresenation> Get()
        {
            var queryProjects = _queryProjectsBusinessController.QueryProjects();
            if (queryProjects == null)
                return null;

            return queryProjects.Select(project =>new ProjectWebRepresenation { Number = project.Number, Name = project.Name});
        }

Projekte haben neben dem Namen und einer Projektnummer noch andere Daten, zum Beispiel hängen an den Projekten Kategorien. Die Kategorien sollen aber nicht mitgeschickt werden, sondern bei Bedarf abgefragt werden.

Stattdessen soll ein Link in die JSON-Antwort eingefügt werden, über die die abhängigen Objekte nachgeladen werden können. Ich habe dafür einen Artikel gefunden, allerdings ist der nicht für Core.

Anreichern von REST-Nachrichten über Links

Den Handler habe ich versucht, in eine Middleware umzuwandeln. Das Erzeugen der Middleware funktioniert ganz gut, allerdings bekomme ich ein Problem weil die Middleware ein HttpContext erwartet und kein HttpResponseMessage.

Vielleicht bin ich auch auf einem ganz falschen Weg. Es wäre schön, von euch zu hören.

Mfg fluxy

16.834 Beiträge seit 2008
vor 6 Jahren

Das, was Du mit der Location einer Ressource meinst, ist nicht REST, sondern nennt sich Hypermedia.
Les Dich mal in Hypermedia ein; da gibts zB. Siren und OData. Hypermedia baut auf REST auf.

Hypermedia ist auch Teil der Ressource und sollte damit nicht einfach nur in der Middleware angereichert werden.
Dadurch werden übrigens auch andere Probleme einer API wie zB Versionierung gelöst.

2.207 Beiträge seit 2011
vor 6 Jahren

Hallo fluxy,

HATEOAS (Hypermedia ...) heisst das. Jedoch ist es mMn in eine Middleware im ASP.NET Core der falsche Ort das Ganze anzureichern.

Da die Links sich ja nach der Ressource richten, die du zurück schickst, kannst du erst im Controller wirklich sagen, welche Links da wirklich mitsollen. Daher würde ich da ansetzen.

Gruss

Coffeebean

F
fluxy Themenstarter:in
183 Beiträge seit 2009
vor 6 Jahren

Verstehe. Dann ist das ja nicht Rest, sondern wieder etwas neues?
Wie würde man denn mit so einer Situation umgehen, Wenn man einen REST Service ohne hypermedia schreiben will?

Ich bin mir nicht sicher, ob es das richtige ist, sich in hypermedia einzuarbeiten, Wenn man sich gerade mit den Grundlagen von REST beschäftigt.

Viele Grüße und danke für die bisherigen Anmerkungen
Fluxy

16.834 Beiträge seit 2008
vor 6 Jahren

Hypermedia baut auf REST auf.

Doch, Hypermedia macht sinn. Sehe es als Anreicherung von REST.
Ohne Hypermedia hast Du halt keine Links.

REST schreibt ja nur, wie zB die URLS aufgebaut sein sollten, sprich die Endpunkte.
Hypermedia beschreibt quasi, wie der Client durch REST navigiert.

2.207 Beiträge seit 2011
vor 6 Jahren

Hallo fluxy,

schau dir mal das Richardson Maturity Model an. Ich glaube das hilft dir HATEOAS in REST einzuordnen.

Richardson Maturity Model - steps toward the glory of REST

Da gibt es vier Level (0-3). Mit diesen Leveln kann man beschreiben wie "reif" deine API ist - deine API erfüllt also Level 0 (Http als Kommunikation), 1 (Resourcen bekommen eigenen Endpunkt), 2 (Korrekte Verben und Statuscodes auf die versch. Endpunkte und Antworten) oder 3 (HATEOAS).

Erst das dritte Level bringt dann das HATEOAS, also das, wo du hinwillst.

Gruss

Coffeebean

16.834 Beiträge seit 2008
vor 6 Jahren

Der Unterschied von Hypermedia und HATEOAS ist, dass die Rückgabe der Ressourcen sich anhand dem Status der Ressource orientiert.
Auch ist das dritte Level nicht HATEOAS sondern Hypermedia.

Hypermedia besagt, dass eine Ressoure zB. einen Link auf sich oder auf Relationen eingebettet hat.
HATEOAS ist als Erweiterung zu sehen.

Wenn die Ressource zum Beispiel eine Bestellung ist, dann kann diese Bestellung zum Beispiel gecancelt werden.
Mit einfachen Hypermedia Definition würde nun also ein Link zu "Cancel" zu sehen sein.

HATEOAS bindet zB im Gegensatz zu OData nun den Zustand ein - beide sind aber Hypermedia.
Ist die Bestellung noch nicht ausgeliefert, so taucht der Link zu Cancel auf. Ist die Bestellung schon im Versand, dann kann sie nicht mehr gecancelt werden und ergo taucht in der Link-Liste bei HATEOAS kein Cancel mehr auf.

Man muss sich überlegen, ob man wirklich den Zustand mit in die API Logik mit hinein nehmen will.
Hypermedia (das Konzept) und HAL (Hypertext Application Language, quasi der Standard) ist aber die Grundbasis.

Hypermedia kann ohne HATEOAS umgesetzt werden, aber nicht HATEOAS ohne Hypermedia.

F
fluxy Themenstarter:in
183 Beiträge seit 2009
vor 6 Jahren

Hallo,

Vielen Dank für eure Informationen.

Aber eine Frage: so wie ich euch verstanden habe, Ist sowohl Hypermedia als auch HATEOAS als Aufsatz auf REST zu verstehen. Im Internet als auch in dem Link zu dem Artikel von Martin Fowler verstehe ich es eher so, das es dabei eher um die Herbeiführung von Zustandsänderungen geht und somit beides Teil von REST ist, bzw. Genutzt werden sollte um REST zu implementieren.

Ich habe übrigens noch einen anderen Artikel gefunden, der auch für andere hilfreich sein könnte. Es ist zwar ein Artikel aus der Javawelt, Aber da es sich bei REST um ein Protokoll handelt und nicht um eine Implementierung, sollte das egal sein

hateoas Artikel von jaxcenter

Was mir noch nicht klar ist!! Ist wie man so etwas nun mit webapi Core explizit umsetzt. Habt ihr vielleicht diesbezüglich gute Links?

Vg fluxy

16.834 Beiträge seit 2008
vor 6 Jahren

Ja, Hypermedia ist quasi ein Aufsatz auf REST oder ein "Rahmen" und HATEOAS eine Erweiterung dessen. Vereinfacht gesagt.

  • REST sagt Dir wie Endpunkte auszusehen haben, wie Ressourcen ausgeliefert werden und wie der Status Code jeweils sein muss
  • Hypermedia zusätzlich sagt, wie der Client durch eine REST API navigiert
  • HATEOAS zusätzlich macht Hypermedia dynamisch indem der Status der Ressource aktiv auf die Rückgabe Auswirkungen hat.

Wie gesagt:

Hypermedia kann ohne HATEOAS umgesetzt werden, aber nicht HATEOAS ohne Hypermedia.

In ASP.NET Core setzt man die API nicht anders um als in der Vorgängerversion.

F
fluxy Themenstarter:in
183 Beiträge seit 2009
vor 6 Jahren

Gut, dann sind wir jetzt wieder am Anfang, aber das macht nichts, weil diese Ehrenrunde hatte einige gute Lerneffekte -;)

Als Orientierung hatte ich dieses Tutorial verwendet: Hypermedia und WebApi

Grundsätzlich werden die Links im Controller hinzugefügt. Beispiel:


public Post Get(int id) 
{
    var post = Session.Load<Domain.Post>(id);
    var response = Mapper.Map<Post>(post);
    response.AddLink(new EditLink(Url.Link(...)));
    return response;
}

Die Implementierung geht davon aus, das jede Ressource von einer abstrakten Basis erbt, die die Möglichkeit erweitert, der Resource Links hinzuzufügen.

Der Author geht dann noch einen Weg um Duplizierten Code zu vermeiden, nämlich die Resourcen immer wieder hinzuzufügen. Soweit ich das verstehe ich der Mechanismus folgender:

Es gibt für verschiedene Ressourcen verschiedene "Enricher". Enricher sind dann dafür da, die Ressourcen um Links zu erweitern. Die Enricher werden quasi einfach als Service registriert, aber es gibt noch einen Handler.

Ich habe noch nicht viel mit WebApi gemacht, aber ich finde das Vorgehen gar nicht so schlecht. Ich hoffe ihr könnt mir das bestätigen. Meine Idee war es jetzt, den Handler durch eine Middleware abzulösen. Ist das wirklich ein ungünstiges Vorgehen?

Vielleicht habe ich mich auch anfangs nicht konkret genug ausgedrückt?!

Viele Grüße,
fluxy

16.834 Beiträge seit 2008
vor 6 Jahren

Auch in der alten Variante hat man IHttpResponse als Rückgabetyp verwendet und zB mit return Ok(object) die Ressource zurück gegeben.

Tutorials sind nur Beispiele; muss man nicht so machen.

Ich sehe keine Notwendigkeit einer eigenen Middleware hier.
Eine Middleware hat immer einen Zweck der Manipulation eines Requests in der Pipeline. Hier ja gar nicht notwendig.

3.003 Beiträge seit 2006
vor 6 Jahren

Eine Middleware hat immer einen Zweck der Manipulation eines Requests in der Pipeline. Hier ja gar nicht notwendig.

Erm, eigentlich manipuliert die Middleware Requests UND Responses in der Application pipeline. Insofern wäre es ohne weiteres machbar, die Antworten um zusätzliche Informationen anzureichern, und natürlich wird das auch gemacht. Der Punkt ist eher der: um HATEOAS zu implementieren, benötigt man Informationen zum Status der Applikation, die die Middleware nicht hat und auch nicht haben sollte. Wer den Status kennen muss, ist/sind der/die Controller, und aus diesem Grund passiert die Informationsanreicherung eben dort und nicht in der Middleware[1].

Grob fahrlässig verallgemeinert:
Middleware: Form der Anfragen prüfen, Form der Antworten manipulieren
EDIT: Action im [/EDIT]Controller: Inhalt der Anfragen prüfen, Inhalt der Antworten festlegen

Bei uns sieht so eine Anreicherung im Normalfall so aus:


public IActionResult Get(int id)
{
    var resultObject = DoSomething(id);
    return ResultResponse(resultObject).WithResultLink(uri);
}
//ResultResponse() ist analog zu OK() implementiert, liefert aber eine von IActionResult abgeleitete Schnittstelle, auf die die Extension WithResultLink manipulierend zugreifen kann, um den Inhalt anzureichern. Bezeichner sind im realen Leben natürlich anders.

LaTino
[1] habt ihr ja auch nicht anders behauptet, nur kam die Begründung nicht so recht rüber, meine ich.

EDIT: Abt hat natürlich recht, die Action ist, wo die, erm, Action ist. Ergänzt.

"Furlow, is it always about money?"
"Is there anything else? I mean, how much sex can you have?"
"Don't know. I haven't maxed out yet."
(Furlow & Crichton, Farscape)

16.834 Beiträge seit 2008
vor 6 Jahren

Erm, eigentlich manipuliert die Middleware Requests UND Responses in der Application pipeline.

Ist mir bewusst... 😭

Aber um bei en Spitzfindigkeiten zu bleiben:

Ein Controller ist nur ein Rahmen.
Die Action ist der Ort, wo der Standort bekannt ist und die Antwort festgelegt wird.

Eure Umsetzung mit Flunt Response finde ich gut und sinnvoll.