2017-07-12 5 views
2

Ich habe Datenverträge geschaffen, wie unten mit Vererbung: -C# REST API polymorpher Rückgabetyp

[DataContract(Name = "Animal")] 
public class Animal { ... } 

[DataContract(Name = "Dog ")] 
public class Dog : Animal { // Has some Dog specific member properties } 

[DataContract(Name = "Cat ")] 
public class Cat : Animal { // Has some Cat specific member properties } 

Und ich bin mit ASP.NET WebAPI einen REST-API zur Verfügung zu stellen wie:

[HttpGet] 
public Task<Animal> Get(string type) 
{ 
    switch(type) 
    { 
     case "dog": 
      Dog dog = GetDogDetails(); 
      return Task.FromResult(dog); 
      break; 

     case "cat": 
      Cat cat = GetCatDetails(); 
      return Task.FromResult(cat); 
      break: 
    } 
} 

Ich kann die jeweiligen Tierarten nicht zurückgeben. Ich erhalte den folgenden Fehler: - "Hund kann nicht implizit in Tier konvertiert werden".

Auch ist diese polymorphe Antwort eine gute Sache wie REST API-Standards.

+1

Was auch immer der Fall ist, das ist eine schreckliche Fehlermeldung. – InBetween

+0

Wenn Sie JSON verwenden, vergessen Sie Datenverträge für den Alptraum, den sie sind, und geben Sie einfach 'dynamic' von Ihrem Controller zurück. Dann können Sie alles zurückgeben und es wird dem Kunden so gut wie möglich serialisiert. – zaitsman

+0

@zaitsman Ich würde nicht empfehlen, dynamische Antwort zu verwenden, falls erforderlich, verwenden Sie IHttpActionResult als VladStryapko in seiner Antwort. –

Antwort

4

Der Grund, warum Sie diesen Fehler erhalten, ist, weil Sie eine Task<T> zurückgeben und Aufgabe ist nicht kovariant. Das heißt, obwohl DogAnimal ist, ist Task<Dog> nicht Task<Animal>.

Was können Sie tun?

  1. Ändern Sie Ihren Code

    case "dog": 
        Animal dog = GetDogDetails(); 
        return Task.FromResult(dog); 
        break; 
    

Sie zu sein, obwohl Hunde spezifischen Eigenschaften verlieren.

  1. Nutzen Sie Task<IHttpActionResult> und geben Sie Ok(yourObject) zurück.

    [HttpGet] 
    public async Task<IHttpActionResult> Get(string type) 
    { 
        switch(type) 
        { 
         case "dog": 
          Dog dog = GetDogDetails(); 
          return Ok(dog); 
          break; 
    
        ... 
        } 
    } 
    

ich glaube, Sie den zweiten Weg gehen sollte.

Auf eine zweite Anmerkung sehe ich keinen Grund, async/await hier zu verwenden. Warum würden Sie Task.FromResult verwenden? Wenn Ihre GetDogDetails Methode async ist, betrachten Sie awaiting es. Ich denke nicht, dass Sie sich in Ihrem aktuellen Code Gedanken um Aufgaben machen sollten.

Also is this polymorphic response a good thing as per REST API standards.

Ich weiß nicht über formale Standards, aber im Allgemeinen ist es in Ordnung, dass einige Objekte bestimmte Eigenschaften haben und andere nicht. Stellen Sie sich zum Beispiel ein Zahlungssystem vor, das ein abstraktes Ereignis zurückgibt, zu dem möglicherweise eine Rechnung gehört.

+0

Sie antworten ist gut Ich möchte nur hinzufügen, dass polymorphe Antwort ein Problem sein kann, wenn Sie irgendeine Art von automatisiertem Code-Build (etwas wie das Erstellen von Dokumentation). Abhängig von der Konfiguration des Serializers können Sie auch die $ type-Eigenschaft in JSON sehen. All dies kann gelöst sein, kann aber ein Problem verursachen. –

+0

@FilipCordas Ja, ich denke, im Fall von optionalen Eigenschaften würde ich es vorziehen, sie in einer Klasse zu haben und "null" zu nichts oder zu etwas, was die API-Kunden bevorzugen (wenn es sich um eine interne API handelt) mit ihnen). –