Wird automatisch in eine String-ähnliche Klasse im Web.API-Controller deserialisiert

9

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:

%Vor%

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:

%Vor%     
Nathan Friend 21.12.2015, 16:26
quelle

3 Antworten

3

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:

%Vor%

Hier ist eine schnelle und grundlegende Implementierung von einer, die funktionieren sollte (ungetestet). Es könnte fast sicher verbessert werden:

%Vor%     
Erik 21.12.2015, 16:55
quelle
0

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%     
rlcrews 21.12.2015 16:52
quelle
0

Ich würde vorschlagen, nach mehr Trennung von Sorgen zu streben.

Sie haben hier zwei Bedenken:

  1. Bearbeitung von HTTP-Anfragen und -Antworten.
  2. Domänenlogik ausführen.

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.

Projektmanagement

Ziehen Sie die Verwendung mehrerer Projekte in Betracht, um Probleme klarer zu trennen.

  1. MyNamespace.MyProject - Klassenbibliotheksprojekt, das Ihre Domänenlogik enthält.
  2. 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.

Verschiedene Klassen

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:

  1. MyNamespace.MyProject.Person - Ihre Domain-Layer-Repräsentation einer Person.
  2. 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.

Isolieren Sie die Domänenlogik aus der Servicelogik

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.

%Vor%

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.

Hinweis zur Klassenbenennung

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.

Drittanbieterbibliotheken, auf die verwiesen wird

  1. AutoMapper - Zum Reduzieren von Boilerplate in Mapping-Service-Objekten auf Domain-Objekte und umgekehrt.
  2. Ninject - Um Abhängigkeiten in Controller zu integrieren (denken Sie daran, auch die WebAPI- oder OWIN-Pakete zu erhalten). Jeder IoC kann verwendet werden. Alternativ kann auch ein Singleton- oder Service-Locator-Muster verwendet werden, das jedoch das Testen erschweren kann.

Keine dieser Bibliotheken muss den Ideen dieser Antwort folgen, aber kann das Leben viel einfacher machen.

    
crush 21.12.2015 17:44
quelle