2010-11-16 11 views
0

Je suis à deux doigts de faire fonctionner mon formulaire de création. Mon problème est que certaines données passées dans le formulaire dans le modèle de vue ne sont pas renvoyées dans la publication.Liaison de modèle MVC2 w/many-to-many: au point de rebroussement

Modèles:

Game: 
    GameID - int (primary key, auto-incr) 
    GameTitle - nvarchar(100) 
    ReviewText - text 
    ReviewScore - smallint 
    Pros - text 
    Cons - text 
    LastModified - Datetime 
    GenreID - int (foreign key from Genres) 

Platform: 
    PlatformID - int (primary key, auto-incr) 
    Name - nvarchar(50) 

GamePlatform (not visible as an EF 4 entity): 
    GameID - int (foreign key from Games) 
    PlatformID - int (foreign key from Platforms) 

Les modèles de vue J'utilise:

public class PlatformListing 
{ 
    public Platform Platform { get; set; } 
    public bool IsSelected { get; set; } 
} 

public class AdminGameReviewViewModel 
{ 
    public Game GameData { get; set; } 
    public List<Genre> AllGenres { get; set; } 
    public List<PlatformListing> AllPlatforms { get; set; } 
} 

Et la forme elle-même:

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<HandiGamer.WebUI.ViewModels.AdminGameReviewViewModel>" %> 

<p> 
    <%: Html.Label("Game Title") %> 
    <%: Html.TextBoxFor(model => Model.GameData.GameTitle) %> 
    <%: Html.ValidationMessageFor(model => Model.GameData.GameTitle) %> 
</p> 
<p> 
    <%: Html.LabelFor(model => Model.GameData.GenreID) %> 
    <%: Html.DropDownListFor(m => Model.GameData.GenreID, new SelectList(Model.AllGenres, "GenreID", "Name", Model.GameData.GenreID)) %> 
</p> 
<p> 
    <%: Html.Label("Platforms") %><br /> 
    <% for(var i = 0; i < Model.AllPlatforms.Count; ++i) 
     { %> 
      <%: Model.AllPlatforms[i].Platform.Name %> <%: Html.CheckBoxFor(p => Model.AllPlatforms[i].IsSelected) %> 
    <% } %> 
</p> 
<p> 
    <%: Html.Label("Review") %> 
    <%: Html.TextAreaFor(model => Model.GameData.ReviewText) %> 
</p> 
<p> 
    <%: Html.Label("Review Score") %> 
    <%: Html.DropDownListFor(m => Model.GameData.ReviewScore, new SelectList(new int[] {1, 2, 3, 4, 5}))%> 
</p> 
<p> 
    <%: Html.LabelFor(model => model.GameData.Pros) %><br /> 
    <%: Html.TextAreaFor(model => model.GameData.Pros) %> 
</p> 
<p> 
    <%: Html.LabelFor(model => model.GameData.Cons) %><br /> 
    <%: Html.TextAreaFor(model => model.GameData.Cons) %> 
</p> 

Et enfin, mon méthode Create (barebone comme J'essaye de faire fonctionner ceci):

[HttpPost] 
    public ActionResult CreateReview([Bind(Prefix = "GameData")]Game newGame, [Bind(Prefix = "AllPlatforms")]List<PlatformListing> PlatformList) 
    { 
     try 
     { 
      foreach(var plat in PlatformList) 
      { 
       if (plat.IsSelected == true) 
       { 
        newGame.Platforms.Add(plat.Platform); 
       } 
      } 

      newGame.LastModified = DateTime.Now; 

      _siteDB.Games.AddObject(newGame); 
      _siteDB.SaveChanges(); 

      // add form data to entities, then save 
      return RedirectToAction("Index"); 
     } 
     catch 
     { 
      return View(); 
     } 
    } 

Le problème est, bien sûr, avec mes cases à cocher. Le boolean isSelected est défini correctement, mais lorsque les données sont en cours de publication, l'objet Platform correspondant est manquant. Je pensais qu'ils seraient automatiquement renvoyés. Donc, des suggestions sur la façon de repasser la partie plate-forme réelle d'un PlatformListing?

Répondre

1

En ce qui concerne l'obtention des valeurs de case à cocher, pourquoi ne pas utiliser la stratégie described here? En ce qui concerne le passage d'objets entité comme arguments, je dirais que vous laissez votre couche de données se mélanger dans votre couche de vue, et vous devez utiliser un ViewModel dédié.

+0

Je ne suis pas sûr de comprendre ce que vous entendez par «utiliser un ViewModel dédié». Je pensais que les modèles de vue étaient censés être à sens unique - dérivé du modèle, et transmis à la vue via le contrôleur. Je ne vois pas pourquoi je ne devrais pas m'attendre à récupérer les données du modèle réel sur le formulaire. Cela n'a pas de sens pour moi de rediriger ces données à travers le modèle de vue pour devoir les désassembler et les stocker dans le modèle. Qu'est-ce que je rate? –

+0

@ kevinmajor1: Vous pouvez également avoir des modèles d'entrée, pour modéliser les données transmises de la vue dans votre action. En séparant vos couches de données, d'entreprise et de vue, vous rendez votre code plus modulaire. Par exemple, comment testez-vous l'action de votre contrôleur? Vous ne pouvez pas (au moins pas facilement) parce que vous faites l'accès à la base de données directement dans votre action. Je pourrais donner à cette action les mêmes entrées et arriver à des résultats complètement différents en fonction des données déjà présentes dans la base de données. – StriplingWarrior

+0

Oui, mais maintenant je veux simplement pouvoir créer correctement un jeu. Je sais que TDD est la bonne voie à suivre, mais je suis toujours un débutant avec tout cela. Les tests unitaires ne sont pas une préoccupation réaliste pour le moment. Le simple fait de pouvoir prendre des données à partir d'un formulaire et de les écrire sur une base de données en utilisant EF est ce dont j'ai besoin pour m'occuper avant d'aborder des sujets plus complexes. Je veux être en mesure de le faire de la bonne façon, mais d'abord je dois avoir une idée de la façon dont fonctionnent les bases de base. –