Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 | Suche | FAQ

Hauptmenü
myCSharp.de
» Startseite
» Forum
» Suche
» Regeln
» Wie poste ich richtig?

Mitglieder
» Liste / Suche
» Wer ist online?

Ressourcen
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Microsoft Docs

Team
» Kontakt
» Cookies
» Spenden
» Datenschutz
» Impressum

  • »
  • Community
  • |
  • Diskussionsforum
[erledigt] WebApi Serializing
Diräkt
myCSharp.de - Member



Dabei seit:
Beiträge: 620
Herkunft: Schweiz

Themenstarter:

[erledigt] WebApi Serializing

beantworten | zitieren | melden

Hallo Leute

Ich versuche über die WebApi meine Entities (EF) anzubieten in einem möglichst "cleanen" json.
Das Problem ist unter "circular Reference" bekannt, aber eine Lösung habe ich nicht wirklich gefunden.

Der Json Serializer erlaubt einige Einstellungen:


var jsonSerializerSettings = new JsonSerializerSettings
            {
                ReferenceLoopHandling = ReferenceLoopHandling.Serialize,
                PreserveReferencesHandling = PreserveReferencesHandling.Objects,
                NullValueHandling = NullValueHandling.Ignore,
            };

Meine Test-DB:
=> Category -> Formel (1:N)
Ich frage hier immer die Formeln.Inculde("Category") ab.

Abfrage : http://localhost:50517/api/v1/Formel
Resultat: ( Screenshot 1 )
Bemerkung:
Die Formeln sind in der Flachenliste zwar verfügbar aber unter => Category => Formeln nochmals, teils mit dem "referenz Key".... Wie auch immer, clean ist das nicht.

Abfrage : http://localhost:50517/api/v1/Formel/1
Resultat: ( Screenshot 2 )
Bemerkung:
Wie auch immer, clean ist das nicht.


var jsonSerializerSettings = new JsonSerializerSettings
            {
                ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
                NullValueHandling = NullValueHandling.Ignore,
            };

Abfrage : http://localhost:50517/api/v1/Formel
Resultat: ( Screenshot 3 )
Bemerkung:
Gleich wie Screenshot 1 , einfach das die Daten alle X mal wiederholt werden...

Abfrage : http://localhost:50517/api/v1/Formel/1
Resultat: ( Screenshot 4 )
Bemerkung:
Das wäre, was ich clean nennen würde

Als Test habe ich mal ne Methode geschrieben, so wie ich mit ".../Formel" vorstellen würde:

(Screenshot 5)


public dynamic GetCategoryWithFormel()
        {
            return DataStore.All<Formeln>().Select(data => new
                                                               {
                                                                   data.Id,
                                                                   data.Title,
                                                                   data.PositiveFeedback,
                                                                   data.NegativeFeedback,
                                                                   data.PicUrl,
                                                                   data.CategoryId,
                                                                   data.Category
                                                               });
        }


Muss ich jetzt wirklich alles von Hand umsetzen um einigermassen cleanes JSON zu erhalten? Kann mir jemand ein Tipp geben ?!

Beste Grüsse

Diräkt
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von Diräkt am .
Attachments
private Nachricht | Beiträge des Benutzers
m0rius
myCSharp.de - Member

Avatar #avatar-3125.png


Dabei seit:
Beiträge: 1043

beantworten | zitieren | melden

Hallo Diräkt,

deine localhost-URLs sind zwar nett gemeint, nützen uns hier aber nicht viel ;).

Ich würde dir empfehlen, niemals direkt deine Domänenobjekte zurückzugeben, sondern immer ein Data Transfer Object (kurz DTO). Dieses enthält nur die Eigenschaften, die du zurückgeben möchtest, funktioniert also wie eine Whitelist. Dieses kannst du beispielsweise per Extension Method aus deiner Entity erzeugen und dann als Rückgabewerte der Action zurückgeben.

m0rius
Mein Blog: blog.mariusschulz.com
Hochwertige Malerarbeiten in Magdeburg und Umgebung: M'Decor, Ihr Maler für Magdeburg
private Nachricht | Beiträge des Benutzers
Diräkt
myCSharp.de - Member



Dabei seit:
Beiträge: 620
Herkunft: Schweiz

Themenstarter:

beantworten | zitieren | melden

Hallo m0rius

Danke für Deine Antwort.
Zitat
deine localhost-URLs sind zwar nett gemeint, nützen uns hier aber nicht viel ;).
Dachte der lokale Horst sei überall !
Zitat
Dieses kannst du beispielsweise per Extension Method aus deiner Entity erzeugen
Das stell ich mir nicht ganz so einfach vor, da ich z.B. mehrere Tabellen für ein DTO Object benötige, desweitern kann das original Entity dann ja verschiedene Ansichten haben, was wiederum bedeuten würde pro Ansicht eine DTO Klasse erstellen....

Die Daten werden als Json übermittelt. Da Frage ich mich wirklich ob ich auf das ganze nicht einfach verzichten kann und einfach dynamic verwende ?!


public dynamic GetCategoryWithFormel()
        {
            return DataStore.All<Formeln>().Select(data => new
                                                               {
                                                                   data.Id,
                                                                   data.Title,
                                                                   data.PositiveFeedback,
                                                                   data.NegativeFeedback,
                                                                   data.PicUrl,
                                                                   data.CategoryId,
                                                                   data.Category
                                                               });
        }

Dann versuch ich die Frage mal so zu formulieren, was für ein enormer Vorteil (neben der Typensicherheit) habe ich wenn ich 100 DTO Klassen erstellen muss ?


Beste Grüsse

Diräkt
private Nachricht | Beiträge des Benutzers
Abt
myCSharp.de - Team

Avatar #avatar-4119.png


Dabei seit:
Beiträge: 15980

beantworten | zitieren | melden

Zitat von Diräkt
..., was wiederum bedeuten würde pro Ansicht eine DTO Klasse erstellen....
Korrekt. Und das, und auch nur das, wäre ein sauberer Weg.
Zitat von Diräkt
Die Daten werden als Json übermittelt. Da Frage ich mich wirklich ob ich auf das ganze nicht einfach verzichten kann und einfach dynamic verwende ?!
Verwende JSON.NET und nicht die halbherzige .NET Implementierung.

Zitat von Diräkt
Dann versuch ich die Frage mal so zu formulieren, was für ein enormer Vorteil (neben der Typensicherheit) habe ich wenn ich 100 DTO Klassen erstellen muss ?
- Typersicherheit ist ein Muss und daher gibts keine Alternative.
- Dass Entities per Service bekannt gemacht werden, ist ein Nogo.
- dynamic ist langsam, sehr sehr langsam

PS: ich bringe hier mal wieder die MongoDB ins spiel.
Diese kann diese "gewollten Redundanzen" direkt speichern und das BSON quasi 1:1 dem Service anbieten; ohne irgendwelche Includes.
Hier sind DTOs viel leichter umzusetzen als via EF. Das EF ist einfach nicht für die (anderen) Ansprüche des Webs gemacht.
- performance is a feature -

Microsoft MVP - @Website - @blog - @AzureStuttgart - github.com/BenjaminAbt
private Nachricht | Beiträge des Benutzers
Diräkt
myCSharp.de - Member



Dabei seit:
Beiträge: 620
Herkunft: Schweiz

Themenstarter:

beantworten | zitieren | melden

Hallo Abt

Danke für Deine Antwort.
Zitat
Verwende JSON.NET und nicht die halbherzige .NET Implementierung.
WebApi benutzt doch standardmässig json.net ?!
Zitat
Dass Entities per Service bekannt gemacht werden, ist ein Nogo.
Dann frag ich mich wofür ich ein Repository benutze ?!
=> Oder sollte ich dann gleich bei der Basis-Implementierung von Get,GetAll... eine Transformation zu den DTO's implementieren ?

Edit:
=> Da WebApi ja kein WSDL "bietet", kommen die Daten beim Client ja eh nicht "typsicher" an, sondern da muss ja json / xml deserialisiert werden... Oder gibts da was wie "Generate Client Classes ?!... Sollte der Client .Net sein, scheint mir WCF einiges einfacher zu sein ;)

Beste Grüsse

Diräkt

P.S.
Sollte ich ein neues Projekt in nächster Zeit anfangen, werde ich mir dafür MongoDB mal im Detail anschauen und antesten...
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von Diräkt am .
private Nachricht | Beiträge des Benutzers
Abt
myCSharp.de - Team

Avatar #avatar-4119.png


Dabei seit:
Beiträge: 15980

beantworten | zitieren | melden

Zitat von Diräkt
WebApi benutzt doch standardmässig json.net ?!
Ja natürlich. Habs nur mit JsonSerializerSettings verwechselt; hatte iwie im Kopf, das sei .NET.
Zitat von Diräkt
Dann frag ich mich wofür ich ein Repository benutze ?!
Frag Dich doch lieber, wofür Du es nutzt ;-)
Ein Repository ist dazu da, dass die Anwendung den Datenspeicher bzw. dessen inneres Leben nicht kennen muss. Ergo: Du kannst einfach so von mySQL auf MSSQL oder XYZ wechseln, ohne, dass die Anwendung angefasst werden muss.

DTOs sind aber dazu da, dass der Client abstrakt gehalten wird und er das innere Leben des Entities nicht kennen muss. Es ist einfach eine weitere Schicht.
Und nein, eine Entity kennt sein DTO nicht, und das DTO kennt die Entity nicht. Du musst hier einen Mapper bauen, DTO-> Entity bzw. Entity -> DTO.
Ja keine Schichten vermischen!!

Edit:
Zitat von Diräkt
WebApi ja kein WSDL "bietet", kommen die Daten beim Client ja eh nicht "typsicher" an, sondern da muss ja json / xml deserialisiert werden
Das ist (im Prinzip) richtig; aber auch mit Json kann man "typisiert" arbeiten - nennt sich Bson. Wird aber nur zur konsistenten Datenhaltung verwendet, nicht zum Transfer. Darüber würde ich mir aber keine Gedanken machen. Das ist absolut gängig und OK so.
Nur sowas wieüber return object oder return dynamic auch nur nachzudenken... nix ;-)
- performance is a feature -

Microsoft MVP - @Website - @blog - @AzureStuttgart - github.com/BenjaminAbt
private Nachricht | Beiträge des Benutzers
Diräkt
myCSharp.de - Member



Dabei seit:
Beiträge: 620
Herkunft: Schweiz

Themenstarter:

beantworten | zitieren | melden

Hallo Abt

Danke für Deine Antwort.
Zitat
Und nein, eine Entity kennt sein DTO nicht, und das DTO kennt die Entity nicht. Du musst hier einen Mapper bauen, DTO-> Entity bzw. Entity -> DTO.

Es gibt doch da ein Projekt "AutoMapper", irgendwie ist mir das zwar nicht ganz geheuer ;)... Wenn DTO's soweit vebreitet sind, sollte es doch dafür eine "gängige" Lösung geben ? Oder wie machst du das ? :-)
Zitat
Darüber würde ich mir aber keine Gedanken machen

Kann man die Server-Klassen ( in diesem Falle wären es ja dann die DTO's ) irgendwie vernüfntig anbieten ? (wenns ja kein WSDL gibt..)
Als .Net Entwickler ist ja WCF (auch..) wegen der Definition die "automatisch downloaded" wird so cool zu benutzen ?!

Wenn ich schaue wie die WebApi konsumiert werden, erstellt jeder wieder ein Model von Hand... *grml* (wir sind doch im Jahr 2013 oder hab ich was verpasst ?)


Beste Grüsse

Diräkt
private Nachricht | Beiträge des Benutzers
Abt
myCSharp.de - Team

Avatar #avatar-4119.png


Dabei seit:
Beiträge: 15980

beantworten | zitieren | melden

Zitat von Diräkt
Oder wie machst du das ? :-)
Von Hand.
Zitat von Diräkt

Wenn ich schaue wie die WebApi konsumiert werden, erstellt jeder wieder ein Model von Hand... *grml* (wir sind doch im Jahr 2013 oder hab ich was verpasst ?)
Wir sind im Web; da ist alles Metaoptimiert. Das ist schon richtig so.
Json ist das Mittel der Dinge.
- performance is a feature -

Microsoft MVP - @Website - @blog - @AzureStuttgart - github.com/BenjaminAbt
private Nachricht | Beiträge des Benutzers