Puis-je transmettre un object basé sur une interface à un POST MVA 4 WebApi?

Je veux avoir une API en tant que telle:

public class RelayController : ApiController { // POST api/values public void Post([FromBody]IDataRelayPackage package) { MessageQueue queue = new MessageQueue(".\\private$\\DataRelay"); queue.Send(package); queue.Close(); } } 

Je reçois une valeur nulle pour ‘package’, alors je me demande ce qui pourrait mal se passer. Ma seule pensée est que le sérialiseur JSON par défaut ne peut pas gérer cela, mais je ne sais pas comment le résoudre.

Vous pouvez le faire assez facilement avec un classeur de modèle personnalisé. Voici ce qui a fonctionné pour moi. (Utilisation de Web API 2 et JSON.Net 6)

 public class JsonPolyModelBinder : IModelBinder { readonly JsonSerializerSettings settings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.Auto }; public bool BindModel(HttpActionContext actionContext, ModelBindingContext bindingContext) { var content = actionContext.Request.Content; ssortingng json = content.ReadAsSsortingngAsync().Result; var obj = JsonConvert.DeserializeObject(json, bindingContext.ModelType, settings); bindingContext.Model = obj; return true; } } 

Le contrôleur API Web ressemble à ceci. (Remarque: devrait également fonctionner pour les actions MVC normales – j’ai déjà fait quelque chose comme ça pour elles auparavant.)

 public class TestController : ApiController { // POST api/test public void Post([ModelBinder(typeof(JsonPolyModelBinder))]ICommand command) { ... } } 

Il convient également de noter que lorsque vous sérialisez le JSON, vous devez le sérialiser avec le même paramètre, puis le sérialiser en tant qu’interface pour que le rappel automatique soit intégré et que l’indicateur de type soit inclus. Quelque chose comme ça.

  JsonSerializerSettings settings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.Auto }; ssortingng json = JsonConvert.SerializeObject(command, typeof(ICommand), settings); 

Vous essayez de désérialiser sur une interface. Le sérialiseur ne saura pas quel type instancier sauf si on le lui dit.

Examinez l’option TypeNameHandling Publier une collection de sous-classes

Ou envisagez de créer un convertisseur Json personnalisé. Jetez un coup d’oeil à cette question Comment implémenter JsonConverter personnalisé dans JSON.NET pour désérialiser une liste d’objects de classe de base?

Json.NET (le sérialiseur Json par défaut pour l’API Web ASP.NET) peut gérer cette situation. Tout ce que vous avez à faire est de modifier les parameters du sérialiseur et de définir TypeNameHandling sur Tous (ou sur les objects). Cela appenda une propriété “$ type” -json à votre json, contenant le nom du type de votre instance. De l’autre côté, il tentera à nouveau de se désérialiser vers ce type.

Nous l’avons utilisé pour nous-mêmes, en prenant comme type une classe de base abstraite.

Le sérialiseur a besoin d’un type qu’il peut construire, avec un constructeur vide (par défaut). Puisqu’une interface ne peut pas être construite, la sérialisation échoue et vous obtenez une valeur null.

Deux options:

  1. Utiliser un POCO (Plain Old Clr Object) avec un constructeur par défaut
  2. Implémentez votre propre classeur à l’aide de IActionValueBinder