2010-11-27 4 views
0

Je rencontre des difficultés à suivre une bonne conception orientée objet dans ASP.NET MVC2 et je pense que le problème est une mauvaise compréhension de la façon dont ViewModels et Views doivent interagir lorsque l'utilisateur afficher des informations.ASP.NET MVC2: Vues, ​​Viewmodels et demandes de post

J'ai mis en place un forum qui permet aux utilisateurs de créer des réponses à un fil en utilisant une action de réponse. Mon ReplyViewModel contient un int pour le threadId et une chaîne pour le contenu de la réponse. L'action Reply crée un ReplyViewModel avec ThreadId afin que nous sachions à quel thread l'utilisateur répond. La vue de réponse est fortement typée à ReplyViewModel et a un formulaire permettant à l'utilisateur d'éditer le contenu du modèle. L'utilisateur peut ensuite envoyer à l'action Reply avec l'ID de thread en tant que paramètre.

Cela fonctionne, mais je ne pense pas que je le fais de la bonne façon. Chaque message implique deux ReplyViewModels: l'un avec le threadId mais le contenu nul, et l'autre avec le contenu mais un ThreadId nul. La vue de réponse crée un nouveau ReplyViewModel, et je pense qu'il devrait juste éditer le ReplyViewModel qui a été passé à la vue - mais je ne sais pas comment.

est ici une version allégée de la vue:

<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<mvcForum.ViewModels.ReplyViewModel>" %> 
<%: Html.TextAreaFor(model=> model.content, new{TextMode="multiline", id="postbox"})%> 
<input type="submit" value="Reply" /> 

Dans le cas où cela ne suffit pas à répondre à ma question, voici toute la vue: http://pastebin.com/BFGL4p67

Le ViewModel est littéralement juste une chaîne (contenu) et un int (threadId).

Le contrôleur:

[Authorize] 
public ActionResult Reply(int id) 
{ 
    ReplyViewModel reply = new ReplyViewModel 
    { 
     ThreadId = id 
    }; 
    return View(reply); 
} 
[HttpPost] 
public ActionResult Reply(int id, ReplyViewModel model) 
{ 
    /**TODO: Catch when no user*/ 
    var newPost = new ForumPost 
    { 
     UserId = (Guid)Membership.GetUser(User.Identity.Name).ProviderUserKey, 
     ThreadId = id, 
     postContent = model.content 
    }; 
    db.AddToForumPosts(newPost); 
    db.SaveChanges(); 
    return RedirectToAction("Index"); 
} 

Alors ma question est « Quelle est la meilleure façon de faire ce que je suis en train de faire ce que je peux utiliser une seule instance du ReplyViewModel de passer du contrôleur, à la? vue, et de retour au contrôleur? "

+0

Je pense que vous allez bien ici ... vous ne savez pas exactement quel est le problème que vous essayez de résoudre? – CubanX

+0

Il semble erroné d'utiliser deux instances d'une classe pour faire deux choses complètement séparées, en utilisant un seul champ dans chaque instance. Cela aurait plus de sens si je pouvais utiliser la même instance. – divider

Répondre

1

Je pense que ce que vous faites est bien.

Vous pensez à un problème que vous ne venez pas à travers encore, ce qui est lorsque les données pour alimenter la forme diffère grandement de données qui sera affiché. Ici, le modèle de vue 'Get' est un sous-ensemble du modèle de vue 'Post', donc l'utilisation d'un modèle de vue est correcte, mais si les données du 'Get' et du 'Post' diffèrent grandement, vous pouvez utiliser deux différents modèles de vue tels que:

public class GetReplyFromViewModel //... 
public class PostReplyFromViewModel //... 

Mais je suggère contre ceci à moins que les deux modèles de vue étaient très différents et sufficently complexes à exiger de leurs propres modèles de vue. Rappelez-vous qu'une chose importante à retenir: juste parce que la vue est fortement typée pour taper «A» ne signifie pas que le type du paramètre dans la méthode post ne peut pas être de type «B».

  • Le type de la vue déterminera simplement la compilation/IntelliSense dans la vue ainsi que la vérification du type de la vue à chaque fois que l'on crée.
  • Le type du paramètre post-méthode utilisera simplement MVC Model Binding pour convertir le formulaire HTTP affiché en le type que vous spécifiez.

En d'autres termes, le type de votre point de vue pourrait simplement être

<%@ Page Title="" ... Inherits="System.Web.Mvc.ViewPage<int>" %> 

où toute la variable Model est tout simplement le ThreadId si vous le souhaitez et la méthode post pourrait encore prendre le même paramètre si vos champs html ont été nommés correctement.

mais encore une fois, dans ce cas particulier, je pense que la mise en œuvre actuelle est très bien.

+0

Merci pour votre aide! Le lien vers la documentation Model Binding était particulièrement utile, car je me demandais comment les Views choisiraient le type de paramètre qu'ils transmettraient à un contrôleur Post. Je me demande cependant comment (ou si) je peux transmettre des informations du contrôleur Get au Post Controller en les stockant dans ViewModel. – divider

+1

Eh bien, l'idée est de garder les choses «apatrides» puisque c'est une application web. Fondamentalement, votre modèle de vue de l'obtenir est conservé en tant que html dans votre vue. Si votre vue a un formulaire qui envoie un POST HTTP au serveur, toutes les entrées iront dans le message POST et seront traitées par le classeur de modèle MVC. Ce modelbinder regarde les noms de champ et les mappe à l'objet dans votre méthode de publication. Donc, pour passer des choses entre les méthodes Get/Post, vous pouvez les stocker dans des champs cachés dans le formulaire ou utiliser la session. HTH, T.J. P.S. si vous voulez en savoir plus je suggère la série TekPub MVC http://tekpub.com/view/aspmvc/1 – TJB

+0

Merci encore; Je ne savais pas que les apatrides étaient un but alors je suppose que j'essayais de faire le contraire. Bon à savoir que les champs cachés sont acceptables, car cela semble être une façon très simple de faire tout ce que j'ai pensé jusqu'ici. – divider

Questions connexes