Ich habe einen Web.API-Endpunkt, der ein Objekt wie diesen als Parameter akzeptiert:
%Vor%Zum Beispiel:
%Vor%(Dies ist nur ein Beispiel - wir akzeptieren keine Benutzernamen über unseren Web.API-Endpunkt)
Unsere UserName
-Klasse ist ein Objekt, das implizite Operatoren zu string
definiert, also behandeln wir es genau so, wie wir es in unserer gesamten Anwendung tun würden: string
.
Leider weiß Web.API nicht automatisch, wie ein entsprechendes JavaScript Person
-Objekt in ein C # Person
-Objekt deserialisiert wird - das deserialisierte C # Person
-Objekt ist immer Null. Zum Beispiel, wie ich diesen Endpunkt von meinem JavaScript-Frontend aus mit jQuery aufrufen könnte:
Wenn ich die Eigenschaft UserName
verlasse, wird der Parameter data
korrekt in ein Objekt C # Person
deserialisiert (mit der Eigenschaft UserName
auf null
gesetzt).
Wie kann ich die UserName
-Eigenschaft des JavaScript-Objekts in unserer benutzerdefinierten UserName
-Klasse durch Web.API richtig deserialisieren?
Hier, wie meine UserName
Klasse aussieht:
Sie müssen einen benutzerdefinierten Json.NET Converter für Ihre UserName
-Klasse schreiben. Nachdem Sie den benutzerdefinierten Konverter erstellt haben, müssen Sie Json.NET darüber informieren. In einem meiner Projekte haben wir der Application_Start
-Methode in Ihrer Global.asax.cs
-Datei die folgenden Codezeilen hinzugefügt, um Json.NET über den Konverter zu informieren:
Hier ist eine schnelle und grundlegende Implementierung von einer, die funktionieren sollte (ungetestet). Es könnte fast sicher verbessert werden:
%Vor%WebAPI kann typisierte Struktur serialisieren und serialisieren. Was Sie jedoch tun müssen, ist dem typisierten Muster zu folgen. Zum Beispiel kann ich in Javacsript ein Objekt wie Person
erstellen %Vor%Übergeben Sie das als Objekt als Teil meiner Anfrage an webAPI
In webAPI haben Sie den Typ definiert als:
%Vor% Wenn Sie den .net-Typ Person
haben und er mit dem übereinstimmt, was Sie in Ihrem JavaScript-Antrag name / property erstellt haben, wird er für das Mapping verfügbar sein.
Hinweis zum Gehäuse. Ich folge dem CamelCasing-Muster, so dass das erste Zeichen immer Kleinbuchstaben ist. In Ihrem Punktnetztyp müssen Sie dies nicht tun. Mit der WebAPI können Sie dies über die Konfiguration berücksichtigen.
Wie ich es geschafft habe, war mit einem benutzerdefinierten Konfigurationsformatierer in meiner webapi.config, der hilft, den Typ während der Serialisierung zu konvertieren
%Vor%Ich würde vorschlagen, nach mehr Trennung von Sorgen zu streben.
Sie haben hier zwei Bedenken:
WebAPI beschäftigt sich mit der Verarbeitung von HTTP-Anfragen und -Antworten. Es bietet den Verbrauchern einen Vertrag, in dem festgelegt wird, wie sie ihre Endpunkte und Aktionen konsumieren können. Es sollte sich nicht darum kümmern, etwas anderes zu tun.
Ziehen Sie die Verwendung mehrerer Projekte in Betracht, um Probleme klarer zu trennen.
MyNamespace.MyProject
- Klassenbibliotheksprojekt, das Ihre Domänenlogik enthält. MyNamespace.MyProject.Service
- WebAPI-Projekt, das nur Ihren Web-Service enthält. Fügen Sie einen Verweis auf MyNamespace.MyProject
auf MyNamespace.MyProject.Service
hinzu. Dies wird Ihnen helfen, eine saubere Trennung von Bedenken aufrechtzuerhalten.
Nun ist es wichtig zu verstehen, dass Sie zwei Klassen mit demselben Namen haben werden, die aber unterschiedlich sind. Voll qualifiziert, wird ihre Unterscheidung deutlich:
MyNamespace.MyProject.Person
- Ihre Domain-Layer-Repräsentation einer Person. MyNamespace.MyProject.Service.Models.Person
- Ihre WebAPI-Vertragsvertretung einer Person. Ihr Domain-Layer-Objekt:
%Vor%Ihr Service-Layer-Objekt:
%Vor%Der Vorteil hierbei ist, dass sich die Darstellung der Domänenebene unabhängig vom WebAPI-Vertrag ändern kann. Somit ändert sich Ihr Verbrauchervertrag nicht.
Ich würde auch vorschlagen, jede Domänenlogik, die auf den eingehenden Person
wirkt, in Ihre Domänenlogik-Klassenbibliothek zu verschieben. Dadurch kann diese Logik auch in anderen Anwendungen und Bibliotheken wiederverwendet werden, die außerhalb des Geltungsbereichs von WebAPI liegen. Außerdem würde ich das Repository-Muster implementieren, um unsere Domänenlogik von unserer Servicelogik zu trennen und erstellen Sie MyNamespace.MyProject.PersonRepository
, um zu definieren, wie Sie mit Ihrem Repository von Person
-Objekten auf Domänenebene umgehen.
Ihr Controller kann nun einfach so aussehen:
%Vor% Die Magie mit Mapper.Map<Person>(person)
kommt von AutoMapper . Sie würden Ihre Mappings zuerst in einer Konfigurationsklasse beim Programmstart einrichten. Diese Zuordnungen sagen AutoMapper, wie MyNamespace.MyProject.Service.Models.Person
in MyNamespace.MyProject.Person
konvertiert werden kann.
Außerdem müssten Sie wahrscheinlich einen Singleton-, Service Locator- oder Inversion of Control (IoC) -Container wie Ninject verwenden, um einen Verweis auf Ihre personRepository
zu erhalten. Ich empfehle dringend, IoC zu verwenden. Ninject hat ein Paket, das die Erstellung von Controllern für WebAPI übernehmen kann, indem es Ihre Abhängigkeiten einfügt, die Sie konfiguriert haben.
Was wir hier erreicht haben, ist, dass wir die gesamte Domänenlogik aus MyNamespace.MyProject.Service
entfernt haben. MyNamespace.MyProject
kann jetzt unabhängig getestet werden oder sogar in anderen Projekten enthalten sein, ohne die WebAPI-Abhängigkeiten mitzubringen. Wir haben eine klare Trennung der Anliegen erreicht.
Die identischen Klassennamen können für einige Teams verwirrend sein. Sie können eine Art Namenskonvention implementieren, um die Namen klarer zu machen, z. B. DTO
oder Model
an die Klassen anhängen in Ihrer Serviceebene. Ich bevorzuge es, sie einfach in verschiedene Namespaces zu platzieren und sie nach Bedarf zu qualifizieren.
Keine dieser Bibliotheken muss den Ideen dieser Antwort folgen, aber kann das Leben viel einfacher machen.
Tags und Links asp.net-web-api c# json deserialization asp.net-web-api2