2008-11-17 8 views
0

Courte: comment modelbinding transmet-il les objets de la vue au contrôleur?Comment passer un objet modifié non-vérifié de la vue au contrôleur sans un formulaire?

Long:
En premier lieu, sur la base des paramètres donnés par l'utilisateur via un formulaire de recherche, certains objets sont extraits de la base de données. Ces objets reçoivent des métadonnées qui sont visibles (mais qui ne définissent pas) pour le client (par exemple, la dénomination et la tarification des objets diffèrent d'une région à l'autre).
Plus tard dans le site, l'utilisateur peut cliquer sur des liens qui devraient montrer les détails de ces objets. Étant donné que ces métadonnées sont importantes pour l'affichage, mais pas pour la définition, je dois récupérer l'objet précédemment modifié dans le contrôleur. Lorsque j'utilise le mappage de modèle asp.net mvc par défaut, la méthode .ToString() est utilisée. Ce cours ne retourne pas une chaîne pertinente pour recréer l'objet complet.
J'aurais pensé que l'interface ISerializable serait impliquée, mais ce n'est pas le cas. Comment dois-je procéder pour obtenir l'effet désiré? Je ne peux pas imaginer que je suis le premier à être confronté à cette question, donc je suppose qu'il me manque quelque chose quelque part ...

Répondre

2

La liaison de modèle par défaut prend les paramètres de forme par nom et les assortit avec les propriétés du type spécifié dans la liste d'arguments. Par exemple, votre modèle a des propriétés "Prix" et "Nom", alors le formulaire devrait contenir des entrées avec des identifiants/noms "Prix" et "Nom" (je suppose qu'il fait une correspondance insensible à la casse). Le classeur utilise la réflexion pour convertir les valeurs de formulaire associées à ces clés dans le type approprié et l'affecte aux propriétés d'un objet nouvellement créé du type spécifié par le paramètre (de nouveau dérivé par réflexion).

Vous pouvez réellement regarder (et télécharger) la source pour cela à http://www.codeplex.com/aspnet, bien que vous deviez explorer la source MVC à partir de là. Je donnerais un lien vers la source DefaultModelBinder, mais la façon dont ils sont construits, je crois que le lien change à mesure que les révisions sont introduites. Donc, pour répondre à votre question, vous devez avoir des paramètres (qui pourraient être cachés) sur votre formulaire qui correspondent aux propriétés de l'objet que vous voulez recréer. Lorsque vous POST le formulaire (dans la vue) au contrôleur, le classeur doit reconstituer un objet du type spécifié en utilisant les paramètres de formulaire. Si vous avez besoin de faire la traduction des valeurs du paramètre form vers les propriétés de l'objet, vous devrez probablement implémenter votre propre classeur de modèle personnalisé.

[EDIT] En réponse à votre deuxième message:

Disons que nous voulons avoir un lien vers une action qui utilise un objet personnalisé. Nous pouvons stocker l'objet personnalisé dans TempData (ou la Session si nous en avons besoin pour durer plus d'une publication) avec une clé particulière. Nous pouvons ensuite construire le lien d'action et fournir la clé de l'objet en tant que valeur à ActionLink dans une classe anonyme. Cela renverra la clé en tant que paramètre Request. Dans notre action, nous pouvons utiliser la clé de ce paramètre pour récupérer l'objet de TempData.

<%= Html.ActionLink(ViewData["CustomObject1", 
        "Select", 
        new { TempDataKey = ViewData["CustomObject1_Key"] } 
        ) %> 
&nbsp; 

public ActionResult Select() 
{ 
    Entity custObj = null; 
    string objKey = Request.Params["TempDataKey"]; 
    if (!string.IsNullOrEmpty(objKey)) 
    { 
     custObj = (Entity)TempData[objKey]; 
    } 

    ... continue processing 
} 
+0

Parfait! Cela a fonctionné comme un charme! Je regarde comment je peux le rendre un peu moins hack-ish, mais pour l'instant cela fonctionne parfaitement :) –

0

@tvanfosson

Merci pour votre explication, mais qu'en est-liens? (pas de formulaire) Actuellement, le Html.ActionLink (c => c.Action (paramètre), "label") prend des objets en paramètre. Ceux-ci doivent être traduits en parties URL. Pour cela, MVC TOUJOURS va à la méthode .ToString(). Je ne veux pas sérialiser mon objet dans la méthode ToString.
Ne devrais-je pas être en mesure d'aider en quelque sorte le cadre sérialiser mon objet? Dites à travers l'interface ISerialize ou quelque chose?

+0

vous ne serez pas en mesure de passer des objets entiers autour de cette façon sans les persister quelque part, si c'est un petit objet il suffit de le coller dans une session, ou vous pouvez passer une chaîne codée en base64 de la sérialisation binaire de l'objet. Mais persister quelque part serait mieux à mon avis – Sekhat

+0

en le persistant, vous risquez des erreurs de liaison. Ne pas? Que faire si un utilisateur enregistre le lien aux détails de l'une de ses couleurs et essaie de l'obtenir le jour suivant (session terminée) –

+0

Vous devriez être en mesure de passer des choses entre les actions en utilisant TempData. Je vais augmenter ma réponse avec ça. En supposant que la session est le fournisseur de données temporaires, cela équivaut à une suggestion @Killersponge pour les petits objets. – tvanfosson