2010-01-26 4 views
10

Je souhaite être en mesure d'envoyer du JSON par opposition aux QueryStrings standard lors de la publication d'un message sur mes contrôleurs dans ASP.Net MVC. J'ai les choses Front-End fonctionnant bien (la construction, puis la soumission de mes objets JSON).ASP.Net MVC: Envoi de JSON au contrôleur

Le problème se situe du côté du contrôleur, où les ModelBinders par défaut livrés avec le framework MVC ne le prennent pas en charge.

J'ai vu une combinaison de façons de contourner cela, l'une d'entre elles consiste à appliquer un filtre qui prend l'objet en paramètre, utilise une bibliothèque JSON pour le dé-sérialiser et l'ajoute aux paramètres d'action. Ce n'est pas idéal.

L'autre, mieux, est d'utiliser un classeur personnalisé. Tous ceux que j'ai vus supposent que vous aurez un seul modèle et que ce sera une classe plutôt qu'une variable. Si vous en avez plusieurs, ça tombe en panne.

Est-ce que quelqu'un d'autre a rencontré cela? Une idée que j'avais était si je pouvais simplement contourner la façon dont MVC traite le FormCollection et intercepter là, en ajoutant les valeurs à la collection moi-même et en espérant que MVC peut faire le reste de manière normale. Est-ce que quelqu'un sait si c'est possible? Le problème clé, je pense, est que mon problème n'est pas lié à la liaison car mes modèles de vue ne sont pas différents de ce qu'ils étaient auparavant. Le problème est d'obtenir les valeurs de JSON Post.

Si je suis correct MVC obtient les valeurs de la QueryString et le met dans la collection de formulaire qui est ensuite utilisée pour ModelBinding. Donc, la bonne méthode ne devrait-elle pas changer la manière dont FormCollection est assignée?

Exemple d'une action:

public ActionResult MyFirstAction(Int32 ID, PersonObject Person, ClassObject ClassDetails) 
{ 
//etc 
} 

Les travaux de liaison normale, JSON ne fonctionne pas et tout l'exemple du modèle Liants ne fonctionnera pas non plus. Ma meilleure solution jusqu'à présent est de convertir l'objet en dictionnaire et de boucler chaque paramètre et de le faire correspondre. Cela ne semble pas idéal.

+0

Si vous allez voter en bas, pourriez-vous expliquer pourquoi? – Damien

+0

Désolé, malheureusement, quand je suis allé cliquer sur l'étoile préférée, j'ai cliqué accidentellement sur le vote en baisse, même après que je l'ai déjà surclassé (c'est pourquoi il est passé de 5 à 3). Et maintenant, il a dit immédiatement après avoir essayé de défaire ce que j'ai accidentellement fait, qu'il était trop tard pour changer mon vote, à moins que la question ne soit éditée. Si vous faites une modification à la question, je me ferai un plaisir de corriger mon vote. – jamesaharvey

+0

Pas de problème! Cela m'arrive aussi bien souvent. – Damien

Répondre

8

J'utilise un liant modèle personnalisé pour JSON comme ceci:

public class JsonModelBinder<T> : IModelBinder { 
    private string key; 

    public JsonModelBinder(string requestKey) { 
     this.key = requestKey; 
    } 

    public object BindModel(ControllerContext controllerContext, ...) { 
     var json = controllerContext.HttpContext.Request[key]; 
     return new JsonSerializer().Deserialize<T>(json); 
    } 
} 

et le fil puis dans Global.asax.cs comme ceci:

ModelBinders.Binders.Add(
    typeof(Product), 
    new JsonModelBinder<Product>("ProductJson")); 

Vous pouvez en savoir plus sur ce ici : Inheritance is Evil: The Epic Fail of the DataAnnotationsModelBinder

EDIT

Le JsonModelBinder doit être utilisé sur le paramètre d'action du contrôleur tapé en tant que Produit uniquement. Int32 et ClassObject doivent revenir à DefaultModelBinder. Vivez-vous un résultat différent?

+0

Donc, vous auriez besoin de définir les types pour l'utiliser? – Damien

+0

Oui, vous devez spécifier les types. Pouvez-vous décrire votre situation de façon un peu plus détaillée? Je suis en train de creuser dans la liaison de modèles plus récemment et il y a beaucoup de fonctionnalités non évidentes. –

+0

Eh bien avec les types que puis-je faire à propos des paramètres d'action qui sont des types/piqûres primitifs? Si j'envoie un identifiant Int32, le produit Class crée un problème – Damien

Questions connexes