2016-12-20 7 views
0

Ein kleines IntroASP.NET WebApi - zwei mögliche JSON "Return" -Typen?

Hallo, ich bin eine WebAPI Erholung Service-Entwicklung und ich arbeite derzeit an einem Endpunkt, die verschiedenen Wörterbücher zurückzugibt (Arrays von Entitäten, nicht zu verwechseln mit Dictionary Datentyp) in JSON Format. Wörterbücher können mit dem Namen abgerufen werden: /dictionaries/:dictName. Das Problem ist, dass Elemente in Wörterbücher gehalten kann von zwei Arten sein:

ersten Art von Entitäten

class Item { 
    public long ID { get; set; } 
    public string Name { get; set; } 
} 

Zweite Art von Entitäten - erweiterte Artikel

class ExtendedItem : Item { 
    public string AdditionalProperty { get; set; } // Let's name it this way just for example 
} 

Das Problem

Ich möchte vermeiden, senden AdditionalProperty für Wörterbücher, die es nicht benötigen.


Aktuelle Lösung

ich eine einfache Methode in ApiController entwickelt haben:

public IHttpActionResult GetDict(string name) 
{ 
    try 
    { 
     object outDict = null; 

     switch(name) { 
      case "simpleDict": 
       IList<Item> simpleDict = _dataLayer.GetSimpleDict(); 
       // ... 
       outDict = simpleDict; 
       break; 
      case "extDict": 
       IList<ExtendedItem> extDict = _dataLayer.GetExtDict(); 
       // ... 
       outDict = extDict; 
       break; 

      // ... and a few more dictionaries 
     } 

     SomeLogger.SomeLogging(name, outDict); 
     return Ok(outDict); 
    } 
    catch (Exception ex) 
    { 
     // Just returning error 
     return BadRequest(ex.Message); 
    } 

} 

Fazit und Fragen

Obwohl ich finden verwaltet eine Lösung für das Problem, ich bin nicht ganz zufrieden damit. Persönlich würde ich gerne einen einfachen Weg finden, um object Datentyp zu verwenden, konnte jedoch keine. Und jetzt kommen die Fragen:

  1. Was wäre ein besserer programmatischer Weg zur Implementierung einer solchen Lösung? Für mich besser bedeutet Lösung ohne Verwendung der object Art. Gibt es eine einfache Möglichkeit, IList zu beschränken, um Item oder ExtendedItem und keine anderen Typen zu enthalten?
  2. Oder vielleicht sollte ich den Ansatz für das Problem vollständig ändern?
  3. Oder ... Vielleicht ist dieser Ansatz richtig und ich bin ein wenig überempfindlich? ;-)

Ich werde für jede Hilfe dankbar sein.

+0

Was passiert, wenn Sie '' machen outDict' vom Typ 'IEnumerable geschieht? Sie sollten in der Lage sein, jeden abgeleiteten Typ direkt zuzuweisen. – krillgar

+0

Ich kann nicht glauben, dass es so einfach war! Klappt wunderbar. Wenn Sie können, fügen Sie eine Antwort hinzu, damit ich sie akzeptieren kann. Und danke ;-) – PJDev

Antwort

1

Wenn Sie Ihr outDict Variable als eine Sammlung statt object erklären, dann werden Sie in der Lage sein, direkt zu vergeben.

IEnumerable<Base> outDict = null; 

switch(name) { 
    case "simpleDict": 
     IList<Item> simpleDict = _dataLayer.GetSimpleDict(); 
     // ... 
     outDict = simpleDict; 
     break; 
    case "extDict": 
     IList<ExtendedItem> extDict = _dataLayer.GetExtDict(); 
     // ... 
     outDict = extDict; 
     break; 

    // ... and a few more dictionaries 
} 
+0

Sorry für die Verwirrung. Ihre Antwort in dem Kommentar war korrekt und funktioniert wie ein Zauber. Ich habe gerade einen kleinen Fehler gemacht und es sofort nach der Antwort auf Ihren Kommentar bemerkt. Obwohl dieser auch wirklich nett aussieht, bleibe ich beim ersten :-) Danke! – PJDev

+1

Ich habe meine Antwort an meinen Kommentar angepasst. Die Art, wie ich es hatte, war unnötig. – krillgar

0

Verwenden Sie Interface, um die Implementierung für ExtendedItem freizugeben. Die Verwendung von Object for API return kann nützlich sein, wenn Sie "Dynamisch" benötigen, um die Dinge anders zu verarbeiten, bevor Sie die Callback-Antwort zurücksenden.

interface Item { 
    public long ID { get; set; } 
    public string Name { get; set; } 
} 

class SimpleItem : Item { 
    public long ID { get; set; } 
    public string Name { get; set; } 
} 

class ComplicateItem: Item { 
    public long ID { get; set; } 
    public string Name { get; set; } 
    public string AdditionalProperty { get; set; } 
} 

Dann in den api-Controller,

Item outDict; 

    switch(name) { 
     case "simpleDict": 
      var simpleDict = _dataLayer.GetSimpleDict(); 
      // ... 
      outDict = simpleDict; 
      break; 
     case "extDict": 
      var extDict = _dataLayer.GetExtDict(); 
      // ... 
      outDict = extDict; 
      break; 

     // ... and a few more dictionaries 
    } 
+0

Danke für die Rückmeldung, aber in meinem Fall sind die Objekte 'simpleDict' und' extDict' Listen von Objekten, keine einfachen Objekte. Außerdem habe ich in anderen Posts bereits befriedigende Antworten. – PJDev

0

Sie könnten genauso gut in der switch-Anweisung zurück:

public IHttpActionResult GetDict(string name) 
{ 
    try 
    { 
     switch(name) { 
      case "simpleDict": 
       return Ok(_dataLayer.GetSimpleDict()); 
      case "extDict": 
       return Ok(_dataLayer.GetExtDict()); 
     } 

     SomeLogger.SomeLogging(name, outDict); 
     return Ok(new List<Item>()); 
    } 
    catch (Exception ex) 
    { 
     // Just returning error 
     return BadRequest(ex.Message); 
    } 
} 
+0

Danke für die Antwort. Es wäre in einem einfachen Fall in Ordnung, aber in meinem Code würde ich gezwungen sein, Datenprotokollierung und einige andere Anweisungen wiederholt für jeden Block des Schalters auszuführen. Deshalb habe ich eine lokale Variable erstellt - einmal am Ende und dann zurück zum Client. – PJDev