À l'aide de modèles de vue en ASP.NET MVC 3
Je suis relativement nouveau pour les modèles de vue et je suis en cours d'exécution dans un peu de problèmes avec eux. Voici un exemple de situation où je me demandais quelle est la meilleure pratique est...
Je suis en train de mettre toutes les informations en vue des besoins dans le modèle de vue. Voici un exemple-s'il vous plaît pardonnez les erreurs, le code est sur le dessus de ma tête.
public ActionResult Edit(int id)
{
var project = ProjectService.GetProject(id);
if (project == null)
//Something about not found, possibly a redirect to 404.
var model = new ProjectEdit();
model.MapFrom(project); //Extension method using AutoMapper.
return View(model);
}
Si l'écran qui permet de modifier un ou deux champs, lorsque le modèle est de retour il manque un peu de données (comme il faut).
[HttpPost]
public ActionResult Edit(int id, ProjectEdit model)
{
var project = ProjectService.GetProject(id);
if (project == null)
//Something about not found, possibly a redirect to 404.
try
{
if (!ModelState.IsValid)
return View(model) //Won't work, view model is incomplete.
model.MapTo(project); //Extension method using AutoMapper.
ProjectService.UpdateProject(project);
//Add a message for the user to temp data.
return RedirectToAction("details", new { project.Id });
}
catch (Exception exception)
{
//Add a message for the user to temp data.
return View(model) //Won't work, view model is incomplete.
}
}
Ma solution temporaire est de recréer le modèle de vue à partir de zéro, le repeupler partir du modèle de domaine, appliquez de nouveau les données du formulaire, puis procédez de la manière habituelle. Mais cela rend le point de vue de paramètre de modèle un peu inutile.
[HttpPost]
public ActionResult Edit(int id, ProjectEdit model)
{
var project = ProjectService.GetProject(id);
if (project == null)
//Something about not found, possibly a redirect to 404.
//Recreate the view model from scratch.
model = new ProjectEdit();
model.MapFrom(project); //Extension method using AutoMapper.
try
{
TryUpdateModel(model); //Reapply the form data.
if (!ModelState.IsValid)
return View(model) //View model is complete this time.
model.MapTo(project); //Extension method using AutoMapper.
ProjectService.UpdateProject(project);
//Add a message for the user to temp data.
return RedirectToAction("details", new { project.Id });
}
catch (Exception exception)
{
//Add a message for the user to temp data.
return View(model) //View model is complete this time.
}
}
Est-il un moyen plus élégant?
MODIFIER
Les deux réponses sont correctes, et je voudrais donc prix les deux, si je le pouvais. Le hochement de tête va de MJ mais depuis, après des tâtonnements, j'ai trouver sa solution pour être les plus maigres.
Je suis encore capable d'utiliser les helpers trop, Jimmy. Si j'ajoute ce dont j'ai besoin pour être affiché à la vue du sac (ou afficher les données), comme si...
ViewBag.Project= project;
Je peux procéder de la façon suivante...
@Html.LabelFor(model => ((Project)ViewData["Project"]).Name)
@Html.DisplayFor(model => ((Project)ViewData["Project"]).Name)
Un peu un hack, et il exige que le modèle de domaine à être décorés avec de la System.ComponentModel.DisplayNameAttribute
dans certains cas, mais j'ai déjà le faire.
J'aimerais appeler...
@Html.LabelFor(model => ViewBag.Project.Name)
Mais dynamique causes d'un problème dans les expressions.
- vous pouvez regarder ici : prodinner.codeplex.com pour les meilleures pratiques (y compris les viewmodels) dans asp.net mvc
Vous devez vous connecter pour publier un commentaire.
Après quelques essais et d'erreurs (aka code, puis on déteste) d'apprentissage, actuellement mon approche préférée est:
- Je utiliser la vue-des modèles seulement pour lier les champs de saisie. Donc dans votre cas, si votre vue est le montage en deux champs, puis votre point de vue-modèle n'aura plus que deux propriétés. Les données nécessaires pour remplir la vue (listes déroulantes, des étiquettes, etc), j'utilise la dynamique ViewBag.
Je crois que l'affichage de la vue (c'est à dire le remplissage de rien le point de vue des besoins de l'afficher), et la capture de la publication des valeurs d'un formulaire (de liaison, validation, etc) sont deux préoccupations distinctes. Et je trouve que mélanger les données requises pour remplir la vue avec ce qui est affiché de retour à partir de la vue est en désordre, et crée exactement votre situation le plus souvent. Je n'aime pas partiellement peuplée d'objets étant passé autour.
Je ne suis pas sûr de savoir comment cela se joue avec Automapper (pour la cartographie de l'objet du domaine de la dynamique ViewBag) bien, comme je ne l'ai pas utilisé. Je crois qu'il a un DynamicMap méthode de travail? Vous ne devriez pas avoir de problèmes auto-cartographie de la posté fortement typées ViewModel sur le Domaine de l'objet.
Html.DisplayFor
comme Jimmy dit, mais cela pourrait être remédié avec certainsHtmlHelper
extensions de mon propre. Je ne suis pas en profitant de la vue modèle "impôt" à l'instant-cette approche a l'avantage de réduire quelque peu.Si je comprends bien, votre viewmodel probablement un aspect très similaire à votre entité de domaine. Vous avez mentionné que le viewmodel peut revenir presque vide, car seuls certains champs sont modifiables.
En supposant que vous avez un point de vue où seuls quelques champs sont disponibles pour modifier (ou affichage), ce sont les seulement champs de mettre à disposition, dans votre viewmodel. J'ai l'habitude de créer un viewmodel-per-view, et de laisser le contrôleur ou un service de la poignée de l'entrée de l'utilisateur et de la carte vers le haut avec l'entité de domaine après l'exécution de la validation de certains.
Ici's un thread concernant les meilleures pratiques pour les viewmodels que vous pourriez trouver utiles.
Edit: Vous pouvez également accepter un point de vue différent modèle pour votre montage/POST action de votre Modifier/OBTENIR une action sert. Je crois que cela doit fonctionner aussi longtemps que le modèle de classeur peut le comprendre.