Laden...

Dynamische Rückgabewerte über HTTP API

Erstellt von Unfug vor 2 Jahren Letzter Beitrag vor 2 Jahren 421 Views
U
Unfug Themenstarter:in
133 Beiträge seit 2006
vor 2 Jahren
Dynamische Rückgabewerte über HTTP API

Hallo zusammen,

ich hoffe Ihr hattet ein schönes Weihnachtsfest. Ich habe eine Frage die mich derzeit beschäftigt und ich auf keinen grünen Zweig komme. Vielleicht könnt ihr mir hier wieder ein paar Denkanstöße geben.

Gegeben ist eine feste Datenstruktur auf Serverseite, die mit dynamischen Anfragen (Rest?) abgefragt werden soll. Neben dem Filter soll auch mitgegeben werden, was zurückgeliefert werden soll.

Etwas technischer

Client - Server Architektur.

Der Server verwaltet eine Datenstruktur die relativ komplex ist.
Als Beispiel ein Datenmodel:


Mensch
  Kind
      Spielzeug
             Preis
             Farbe
             Hersteller
                     Name
                     Herkunftsort
                     Mitarbeiter

Die Tiefe der Propertys ist enorm. Es sind Listen dabei, einfache Arrays, String, Int etc etc.

Nun ist folgendes geplant:
Der Client sendet eine Anfrage an den Server wie z.B.
"Liefere mir nur den Preis und die Farbe von allen Daten bei denen der Herstellername: Hasbro und Mitarbeiter > 10 ist"
UPDATE: Vermutlich wird es einen Job geben, der abgerufen wird vom Server der diese Anfrage beinhalten soll. Die Jobs werden dann regelmäßig vom Client abgerufen

Ich möchte also als Rückgabewert:


Preis
Farbe

Zusätzlich kann es sein, dass diese Anfrage noch manuell über ein UI erweitert werden muss.


Preis
Farbe
Größe (muss manuell per UI Eingabe hinzugefügt werden)

Worin liegt nun mein Problem: Die Datenstruktur des komplexen Datenmodels bleibt immer gleich, aber die Anfrage muss dynamisch sein. Der Abfragefilter soll vom Endbenutzer angepasst werden aber auch die gewünschten Rückgabewerte
So könnte die Anfrage (siehe oben) die selbe sein, aber diesmal als Rückgabewert nur


Herkunft

sein.

Was ich bisher ausprobiert habe/gelesen habe:
Für die Anfrage:
OData
eigenen Query Parser
GraphQL

Für die Rückgabe:
GraphQL

Mit GraphQL habe ich mich nicht wirklich beschäftigt. Sieht für mich nach viel Hirnschmerz aus, wenn ich mir die Beispiel anschaue.
Doch sollte dies eine Lösung sein eurer Meinung, werde ich das natürlich tun. Was ich dann nur nicht verstehe ist: Wie muss ich meine Datenstruktur aufbauen, z.B. im Client, der die Antwort erhält.
Ein Dictionary?
Wie kann ich denn im Server die Anfrage verarbeiten? Automatisch, dass ich nur bestimmte Propertys dann zurückliefere.

Freu mich über jegliche Denkanstöße.

Allen noch ein guten Rutsch

2.080 Beiträge seit 2012
vor 2 Jahren

JSON - bau das JSON selbst zusammen, dann hast Du maximale Freiheiten

Aber warum eigentlich? Warum muss das Ergebnis so genau spezifiziert werden?
Überleg dir, welche Daten üblicherweise zusammen gehören und liefere die immer als Ganzes zurück, die Client kann sich ja das raus picken, was er braucht. Z.B. zum Hersteller bekommt der Client immer alle Hersteller-Daten und was er nicht braucht, ignoriert er.
Und wenn es zu groß oder komplex wird, pack IDs mit rein, worüber man die restlichen Daten abrufen kann, z.B. eine Hersteller-ID und ein GET-Endpunkt zum Abrufen der Hersteller-Daten.

Und auch die Client-UI sollte 0,nichts mit der Web-API zu tun haben, die liefert die Daten, die vom Server verwaltet oder berechnet werden und mehr nicht.
Wenn zu den Daten eine Größe gespeichert oder anhand der Daten berechnet wurde, ok, aber wenn sie z.B. nur durchgeschleift werden soll (z.B. UI-Eingabe, Client schickt sie mit und bekommt sie zurück), ist das vermutlich Murks.

NuGet Packages im Code auslesen
lock Alternative für async/await

Beim CleanCode zählen nicht die Regeln, sondern dass wir uns mit diesen Regeln befassen, selbst wenn wir sie nicht befolgen - hoffentlich nach reiflichen Überlegungen.

U
Unfug Themenstarter:in
133 Beiträge seit 2006
vor 2 Jahren

JSON - bau das JSON selbst zusammen, dann hast Du maximale Freiheiten

Aber warum eigentlich? Warum muss das Ergebnis so genau spezifiziert werden?
Überleg dir, welche Daten üblicherweise zusammen gehören und liefere die immer als Ganzes zurück, die Client kann sich ja das raus picken, was er braucht.

Danke für deine Antwort. Um deine Fragen zu beantworten: Aus datenschutzrechtlichen Gründen. Jede Anfrage/Job die gestellt wird verlangt bestimmte Daten zurück, die vorerst genehmigt werden. Es ist also nicht erlaubt das komplette Datenmodell zurückzuliefern und dann auf dem Client zu filtern. Client und Server sind unterschiedliche Firmen.

Bzgl. JSON: Wie würdest Du denn beim Server die Daten zusammensuchen und dann setzen, falls man nur ein bestimmtes Property übertragen möchte alle anderen aber nicht?

2.080 Beiträge seit 2012
vor 2 Jahren

Aber kann der Client nicht selber definieren, welche Daten er zurück bekommt?
Dann kann es auch ein potentieller Angreifer machen und die Daten abgreifen.
Aber wenn das wirklich ein Thema ist, sollte die Lösung erst abgesegnet werden.

Und wie Du die Rückgabedaten aufgebaut werden, hängt davon ab, wie ihr Aufbau festgelegt werden soll.
Suchen und zusammensammeln genauso wie sonst auch und beim Zurückgeben lässt Du das JSON nicht automatisch erzeugen, sondern machst es per Reflection selber, aber mit deinen Regeln. Bei Newtonsoft.Json ist das einfach, wie es bei System.Text.Json geht, weiß ich aber nicht.

Vorausgesetzt Du verwendest ein System, was sowas erlaubt, mit ASP.NET Core ist das jedenfalls kein Problem.

NuGet Packages im Code auslesen
lock Alternative für async/await

Beim CleanCode zählen nicht die Regeln, sondern dass wir uns mit diesen Regeln befassen, selbst wenn wir sie nicht befolgen - hoffentlich nach reiflichen Überlegungen.

U
Unfug Themenstarter:in
133 Beiträge seit 2006
vor 2 Jahren

Aber kann der Client nicht selber definieren, welche Daten er zurück bekommt?
Dann kann es auch ein potentieller Angreifer machen und die Daten abgreifen.

Ja das ist korrekt.
Der Kunde soll mit Hilfe einer UI in seiner Client Software angeben welche Daten er benötigt.
Zum Beispiel


Mensch.Kind.Spielzeug.Hersteller.Name
Mensch.Kind.Spielzeug.Farbe

Als Filterkriterium gibt er an


Mensch.Kind.Spielzeug.Hersteller.Mitarbeiter > 10

Der Server soll dann die Anfrage auswerten und erzeugt und dann eine Liste mit den ausschließlich benötigten Daten.


List
 1. Hasbro, Blau
 2. Mattel, Grün
 3. Hasbro, Gelb
 4. Habba, Orange

Bevor die Daten den Server verlassen, muss Kunde 2 den Versand bestätigen.

Theoretisch ist es möglich, dass "versteckt" auch andere Daten abgegriffen werden vom Client, aber dafür gibt es entsprechend Verträge.

Und wie Du die Rückgabedaten aufgebaut werden, hängt davon ab, wie ihr Aufbau festgelegt werden soll.
Suchen und zusammensammeln genauso wie sonst auch und beim Zurückgeben lässt Du das JSON nicht automatisch erzeugen, sondern machst es per Reflection selber, aber mit deinen Regeln. Bei Newtonsoft.Json ist das einfach, wie es bei System.Text.Json geht, weiß ich aber nicht.
Vorausgesetzt Du verwendest ein System, was sowas erlaubt, mit ASP.NET Core ist das jedenfalls kein Problem.

Ja ist alles im C# ASP.NET Core Universum. Du meinst einen eigenen Serializer bauen? Der basierend auf einem Dictionary das korrekte Property raussucht und dann dem JObject hinzufügt?

2.080 Beiträge seit 2012
vor 2 Jahren

Klingt irgendwie unsinnig, die Daten, die übertragen werden, bekommt doch sowieso nur der Client zu Gesicht
Oder gehen die Daten an einen anderen Client? Dann ergäbe das mehr Sinn.

Ja ist alles im C# ASP.NET Core Universum. Du meinst einen eigenen Serializer bauen? Der basierend auf einem Dictionary das korrekte Property raussucht und dann dem JObject hinzufügt?

Kein eigener Serializer, die können das doch alle ^^ Aber ja, zumindest so ungefähr, dein Beispiel sind ja ziemlich leicht analysierbar aus.
Der System.Text.Json.JsonSerializer kann auch zum JsonNode serialisieren, daraus kannst Du dann entfernen, was Du willst und vom Ergebnis den String erzeugen lassen.

Wie Du das in ASP.NET Core integrierst, musst Du dann schauen. Das einfachste wäre, Du gibst das JSON direkt als Content zurück.

NuGet Packages im Code auslesen
lock Alternative für async/await

Beim CleanCode zählen nicht die Regeln, sondern dass wir uns mit diesen Regeln befassen, selbst wenn wir sie nicht befolgen - hoffentlich nach reiflichen Überlegungen.

U
Unfug Themenstarter:in
133 Beiträge seit 2006
vor 2 Jahren

Klingt irgendwie unsinnig, die Daten, die übertragen werden, bekommt doch sowieso nur der Client zu Gesicht
Oder gehen die Daten an einen anderen Client? Dann ergäbe das mehr Sinn.

Ja. Erneut korrekt. Wir hätten auch alles verschlüsselt übertragen, um dann auf dem Client auszuwerten. Aber auch das war/ist nicht gewünscht. Es sind Vorgaben an denen man sich halten muss. Der technologische Blick hat hier überhaupt keinen Einfluß. Es ist einfach die politische Haltung.

Kein eigener Serializer, die können das doch alle ^^ Aber ja, zumindest so ungefähr, dein Beispiel sind ja ziemlich leicht analysierbar aus.
Der System.Text.Json.JsonSerializer kann auch zum **JsonNode serialisieren, daraus kannst Du dann entfernen, was Du willst **und vom Ergebnis den String erzeugen lassen.

Danke. Das probiere ich mal aus.

16.841 Beiträge seit 2008
vor 2 Jahren

Ich bin kein sonderlich großer Freund von solchen Mechanismen (weil sie große Nachteile wie Performance und Caching haben); dennoch gibts berechtigte Anwendungsfälle dafür, wie hier.
Darunter fallen:

  • GraphQL
  • OData

Mit beiden HTTP API Aufsätzen kannst Du Deine Anforderung erfüllen, ohne untypisiert zu werden, dabei Standard-konform zu bleiben und die Dynamik zu ermöglichen.
Bastel das nicht selbst.

Ja, solche Value Pass Systeme sind anfällig(er) für Angreifer.
Die Implementierung ist gegenüber REST sehr aufwändig - aber weit weniger als etwas eigenes zu erfinden.