Verwendung von Datenübertragungsobjekten in ASP.NET Core 3.1

Ein Datenübertragungsobjekt (allgemein als DTO bezeichnet) ist normalerweise eine Instanz einer POCO-Klasse (einfaches altes CLR-Objekt), die als Container verwendet wird, um Daten zu kapseln und von einer Schicht der Anwendung an eine andere zu übergeben. In der Service-Schicht werden normalerweise DTOs verwendet, um Daten an die Präsentationsschicht zurückzugeben. Der größte Vorteil der Verwendung von DTOs besteht darin, Clients von Ihren internen Datenstrukturen zu entkoppeln.

In diesem Artikel wird erläutert, warum wir Datenübertragungsobjekte verwenden sollten und wie wir mit ihnen in ASP.NET Core 3.1 arbeiten können. Um mit den in diesem Artikel bereitgestellten Codebeispielen arbeiten zu können, muss Visual Studio 2019 auf Ihrem System installiert sein. Wenn Sie noch keine Kopie haben, können Sie Visual Studio 2019 hier herunterladen. 

Erstellen Sie ein ASP.NET Core 3.1-API-Projekt

Zunächst erstellen wir ein ASP.NET Core-Projekt in Visual Studio. Angenommen, Visual Studio 2019 ist auf Ihrem System installiert, führen Sie die folgenden Schritte aus, um ein neues ASP.NET Core API-Projekt in Visual Studio zu erstellen.

  1. Starten Sie die Visual Studio-IDE.
  2. Klicken Sie auf "Neues Projekt erstellen".
  3. Wählen Sie im Fenster "Neues Projekt erstellen" aus der Liste der angezeigten Vorlagen "ASP.NET Core-Webanwendung" aus.
  4. Weiter klicken. 
  5. Geben Sie im Fenster "Konfigurieren Sie Ihr neues Projekt" den Namen und den Speicherort für das neue Projekt an.
  6. Klicken Sie auf Erstellen. 
  7. Wählen Sie im nächsten Fenster "Neue ASP.NET Core-Webanwendung erstellen" .NET Core als Laufzeit und ASP.NET Core 3.1 (oder höher) aus der Dropdown-Liste oben aus.
  8. Wählen Sie "API" als Projektvorlage aus, um eine neue ASP.NET Core API-Anwendung zu erstellen. 
  9. Stellen Sie sicher, dass die Kontrollkästchen "Docker-Unterstützung aktivieren" und "Für HTTPS konfigurieren" deaktiviert sind, da diese Funktionen hier nicht verwendet werden.
  10. Stellen Sie sicher, dass die Authentifizierung auf "Keine Authentifizierung" eingestellt ist, da wir auch keine Authentifizierung verwenden.
  11. Klicken Sie auf Erstellen. 

Dadurch wird ein neues ASP.NET Core API-Projekt in Visual Studio erstellt. Wir werden dieses Projekt verwenden, um in den folgenden Abschnitten dieses Artikels mit Datenübertragungsobjekten zu arbeiten.

Warum Datenübertragungsobjekte (DTOs) verwenden?

Wenn Sie beim Entwerfen und Entwickeln einer Anwendung Modelle verwenden, um Daten zwischen den Ebenen zu übertragen und Daten an die Präsentationsebene zurückzusenden, legen Sie die internen Datenstrukturen Ihrer Anwendung offen. Das ist ein großer Konstruktionsfehler in Ihrer Anwendung.

Durch die Entkopplung Ihrer Layer erleichtern DTOs das Leben, wenn Sie APIs, MVC-Anwendungen und auch Messaging-Muster wie Message Broker implementieren. Ein DTO ist eine gute Wahl, wenn Sie ein leichtes Objekt über das Kabel übertragen möchten - insbesondere, wenn Sie Ihr Objekt über ein Medium mit eingeschränkter Bandbreite übertragen möchten.

Verwenden Sie DTOs zur Abstraktion

Sie können DTOs nutzen, um die Domänenobjekte Ihrer Anwendung von der Benutzeroberfläche oder der Präsentationsschicht zu abstrahieren. Dabei wird die Präsentationsschicht Ihrer Anwendung von der Serviceschicht entkoppelt. Wenn Sie also die Präsentationsschicht ändern möchten, können Sie dies problemlos tun, während die Anwendung weiterhin mit der vorhandenen Domänenschicht arbeitet. Ebenso können Sie die Domänenschicht Ihrer Anwendung ändern, ohne die Präsentationsschicht der Anwendung ändern zu müssen.

Verwenden Sie DTOs zum Ausblenden von Daten

Ein weiterer Grund, warum Sie DTOs verwenden möchten, ist das Ausblenden von Daten. Das heißt, mit DTOs können Sie nur die angeforderten Daten zurückgeben. Angenommen, Sie haben eine Methode namens GetAllEmployees (), die alle Daten aller Mitarbeiter zurückgibt. Lassen Sie uns dies veranschaulichen, indem wir Code schreiben.

Erstellen Sie in dem zuvor erstellten Projekt eine neue Datei mit dem Namen Employee.cs. Schreiben Sie den folgenden Code in diese Datei, um eine Modellklasse mit dem Namen Employee zu definieren.

Mitarbeiter der öffentlichen Klasse

    {

        public int Id {get; einstellen; }}

        öffentliche Zeichenfolge Vorname {get; einstellen; }}

        öffentlicher String Nachname {get; einstellen; }}

        öffentliche Zeichenfolge DepartmentName {get; einstellen; }}

        öffentliche Dezimalzahl Basic {get; einstellen; }}

        öffentliche Dezimalstelle DA {get; einstellen; }}

        öffentliche Dezimalstelle HRA {get; einstellen; }}

        öffentliche Dezimalzahl NetSalary {get; einstellen; }}

    }}

Beachten Sie, dass die Employee-Klasse Eigenschaften enthält, einschließlich ID, Vorname, Nachname, Abteilung, Basis, DA, HRA und NetSalary. Die Präsentationsschicht benötigt jedoch möglicherweise nur die ID, den Vornamen, den Nachnamen und den Abteilungsnamen der Mitarbeiter aus der GetAllEmployees () -Methode. Wenn diese Methode eine Liste zurückgibt, kann jeder die Gehaltsdetails eines Mitarbeiters anzeigen. Das willst du nicht. 

Um dieses Problem zu vermeiden, können Sie eine DTO-Klasse mit dem Namen EmployeeDTO entwerfen, die nur die angeforderten Eigenschaften enthält (z. B. ID, Vorname, Nachname und Abteilungsname).

Erstellen Sie eine DTO-Klasse in C #

Erstellen Sie dazu eine Datei mit dem Namen EmployeeDTO.cs und schreiben Sie den folgenden Code hinein.

öffentliche Klasse EmployeeDTO

    {

        public int Id {get; einstellen; }}

        öffentliche Zeichenfolge Vorname {get; einstellen; }}

        öffentlicher String Nachname {get; einstellen; }}

        öffentliche Zeichenfolge DepartmentName {get; einstellen; }}

    }}

Nachdem die Modell- und Datenübertragungsobjektklassen verfügbar sind, möchten Sie möglicherweise eine Konverterklasse erstellen, die zwei Methoden enthält: eine zum Konvertieren einer Instanz der Employee-Modellklasse in eine Instanz von EmployeeDTO und (umgekehrt) eine zum Konvertieren einer Instanz von EmployeeDTO zu einer Instanz der Employee-Modellklasse. Sie können auch AutoMapper nutzen, eine beliebte Objekt-zu-Objekt-Zuordnungsbibliothek, um diese beiden unterschiedlichen Typen abzubilden. Weitere Informationen zu AutoMapper finden Sie hier.

Sie sollten eine Liste in der Service-Schicht Ihrer Anwendung erstellen und die Sammlung an die Präsentationsschicht zurückgeben.

Unveränderlichkeit von DTOs

Ein DTO soll Daten von einer Schicht einer Anwendung zu einer anderen Schicht transportieren. Der Konsument eines DTO kann in .NET / C # / Java oder sogar JavaScript / TypeScript erstellt sein. Ein DTO wird häufig serialisiert, damit es unabhängig von der im Empfänger verwendeten Technologie sein kann. In den meisten Fällen muss der Empfänger der Daten diese Daten nach dem Empfang nicht ändern - im Idealfall sollte dies nicht der Fall sein!

Dies ist ein klassisches Beispiel für die Bedeutung der Unveränderlichkeit. Und genau deshalb sollte ein DTO unveränderlich sein!

Es gibt verschiedene Möglichkeiten, unveränderliche DTOs in C # zu implementieren. Sie können eine ReadOnlyCollection oder die thread-sicheren unveränderlichen Auflistungstypen verwenden, die im Namespace System.Collections.Immutable vorhanden sind. Sie können die Datensatztypen in C # 9 nutzen, um auch unveränderliche DTOs zu implementieren.

Das domänengesteuerte Design erwartet, dass die Domänenobjekte extern unveränderlich sind. Dies ist ein guter Grund, Ihre DTOs unveränderlich zu machen, nicht wahr?

Herausforderungen bei der DTO-Serialisierung

Sie sollten in der Lage sein, ein DTO nahtlos zu serialisieren / zu deserialisieren, damit es über das Kabel übertragen werden kann. In der Praxis müssen Sie jedoch möglicherweise einige Serialisierungsprobleme lösen, wenn Sie mit DTOs arbeiten. Möglicherweise befinden sich in einer realen Anwendung mehrere Entitäten oder Modellklassen, von denen jede möglicherweise Verweise aufeinander enthält.

Angenommen, Sie haben ein Anwesenheitsmanagementsystem für die Mitarbeiter in Ihrer Organisation erstellt. In der Regel befindet sich in Ihrer Anwendung möglicherweise eine Klasse mit dem Namen "Mitarbeiter", die auf die Benutzerklasse verweist (dh ein Mitarbeiter ist ein Benutzer der Anwendung), die wiederum auf die Rollenklasse verweist. Die Role-Klasse verweist möglicherweise auf die Permission-Klasse, die wiederum auf die Klassen PermissionType und PermissionGroup verweist. Wenn Sie nun eine Instanz der Employee-Klasse serialisieren, werden auch diese Objekte serialisiert. Es ist leicht zu erkennen, dass Sie in einigen komplizierten Fällen möglicherweise mehrere Typen serialisieren.

Hier kommt das verzögerte oder asynchrone Laden zum Einsatz. Dies ist eine Funktion, mit der Sie Entitäten nur dann laden können, wenn Sie dazu aufgefordert werden. Weitere Informationen zum verzögerten Laden finden Sie in meinem Artikel zur verzögerten Initialisierung in C #.

Datenübertragungsobjekte enthalten normalerweise keine Geschäftslogik - sie enthalten nur Daten. Unveränderlichkeit ist eine gewünschte Funktion bei der Arbeit mit DTOs. Es gibt verschiedene Möglichkeiten, unveränderliche DTOs zu implementieren. Ich werde in einem späteren Beitrag hier mehr über Unveränderlichkeit in C # diskutieren.

So machen Sie mehr in ASP.NET Core:

  • Behandlung von 404-Fehlern in ASP.NET Core MVC
  • Verwendung der Abhängigkeitsinjektion in Aktionsfiltern in ASP.NET Core 3.1
  • Verwendung des Optionsmusters in ASP.NET Core
  • Verwendung des Endpunktroutings in ASP.NET Core 3.0 MVC
  • Exportieren von Daten nach Excel in ASP.NET Core 3.0
  • Verwendung von LoggerMessage in ASP.NET Core 3.0
  • So senden Sie E-Mails in ASP.NET Core
  • So protokollieren Sie Daten in SQL Server in ASP.NET Core
  • So planen Sie Jobs mit Quartz.NET in ASP.NET Core
  • So geben Sie Daten von der ASP.NET Core Web API zurück
  • So formatieren Sie Antwortdaten in ASP.NET Core
  • So verwenden Sie eine ASP.NET Core-Web-API mit RestSharp
  • So führen Sie asynchrone Vorgänge mit Dapper aus
  • Verwendung von Feature-Flags in ASP.NET Core
  • Verwendung des FromServices-Attributs in ASP.NET Core
  • So arbeiten Sie mit Cookies in ASP.NET Core
  • So arbeiten Sie mit statischen Dateien in ASP.NET Core
  • Verwendung der URL-Rewriting-Middleware in ASP.NET Core
  • Implementieren der Ratenbegrenzung in ASP.NET Core
  • So verwenden Sie Azure Application Insights in ASP.NET Core
  • Verwenden erweiterter NLog-Funktionen in ASP.NET Core
  • Behandlung von Fehlern in der ASP.NET-Web-API
  • Implementieren der globalen Ausnahmebehandlung in ASP.NET Core MVC
  • Umgang mit Nullwerten in ASP.NET Core MVC
  • Erweiterte Versionierung in der ASP.NET Core-Web-API
  • So arbeiten Sie mit Worker Services in ASP.NET Core
  • Verwendung der Datenschutz-API in ASP.NET Core
  • Verwendung der bedingten Middleware in ASP.NET Core
  • So arbeiten Sie mit dem Sitzungsstatus in ASP.NET Core
  • So schreiben Sie effiziente Controller in ASP.NET Core