2009-09-11 8 views
0

Je voudrais intégrer une instance de l'objet A à l'intérieur de l'objet B. J'ai déjà une action et une vue d'édition qui rend un formulaire pour l'objet B. Je l'ai fait un partiel fortement typé vue acceptant B.asp.net MVC: édition d'objet incorporé

J'ai affaire à l'action Créer maintenant, donc je fais b = new B(); b.A = nouveau A();

Maintenant, je rends le formulaire pour B, puis appelez la vue partielle pour A, en passant b.A.

Mais ce que je récupère est soit une FormCollection, soit mon nouvel objet A avec le champ B défini sur null. Dans le premier cas tout va bien, mais que vais-je faire si le formulaire ne parvient pas à falidate? Ai-je besoin de créer les objets manuellement avec les données erronées et de les transmettre de nouveau avec un ModelState invalide? La deuxième option est-elle possible? Ou dois-je juste éviter d'avoir la vue imbriquée? Je pensais, en alternative, créer un objet modèle spécial juste pour gérer le formulaire avec toutes les valeurs pour A et B, et quand ce formulaire serait validé je remplirais manuellement les objets A et B et les sauvegarderais. est-ce la seule solution?

Répondre

1

Vous devriez pouvoir utiliser A et B comme vous l'avez décrit.

Supposons que nous avons les suivantes:

public class B { 
    public A A {get; set;} 
    public string X {get; set;} 
    public int Y {get;set;} 
} 

public class A { 
    public string Z {get; set;} 
} 

//then in your controller: 

public ActionResult Edit() { 
    return View ( 
     new B { 
      A = new A { Z = "AyyZee" } , 
      X = "BeeEcks", 
      Y = 7 
     }); 
} 

Ainsi, votre modèle est une instance de B.

Votre point de vue et votre vue partielle imbriqué devrait produire du HTML quelque chose comme ceci:

<input type="text" name="A.Z" value="AyyZee" /> 
<input type="text" name="X" value="BeeEcks" /> 
<input type="text" name="Y" value="7" /> 

Maintenant, le classeur de modèle par défaut devrait être en mesure de raccorder ceci:

[AcceptVerbs(HttpVerbs.Post)] 
public ActionResult Edit (B input) { 
    // apply changes 
    //the binder should have populated input.A 
} 

Notez que cela ne fonctionne que si A et B ont un constructeur par défaut et sont des classes relativement simples. Si vous avez quelque chose de plus complexe, vous pouvez utiliser votre propre classeur:

[AcceptVerbs(HttpVerbs.Post)] 
public ActionResult Edit ([ModelBinder(typeof(BBinder))] B input) { 
    //... 
} 

public class BBinder : IModelBinder 
{ 
    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) 
    { 
     return 
      new B { 
       A = new A { Z = Request["A.Z"] } , 
       X = Request["X"], 
       Y = int.Parse(Request["Y"]) 
      }; 
    } 
} 
+0

Je n'arrive pas à faire marcher ça. Peut-être que je viens de faire une simple erreur quelque part. Je vais essayer à nouveau lundi, peut-être que je vais avoir une vue plus fraîche: D Merci beaucoup pour la suggestion. – Palantir

+1

Il y a beaucoup plus de détails sur les classeurs ici: http://weblogs.asp.net/scottgu/archive/2008/10/16/asp-net-mvc-beta-released.aspx – Keith

1

créer votre propre modèle personnalisé qui intègre A et B, puis créer une vue de ce modèle lorsque vous soumettez votre formulaire, vous simplement pouvoir mettez à jour votre modèle personnalisé et mettez à jour/ajoutez vos modèles individuels.

public class CustomViewModel 
{ 
    public ModelA myAModel {get;set;} 
    public ModelB mybModel {get;set;} 
} 

vue pour ce modèle va créer une forme qui intègre A et B et vous permettra de ensuite votre FormCollection posté peut ensuite être utilisé pour définir des valeurs pour chaque modèle indivdual et mise à jour/créer puis séparé.

0

Mes problèmes avec ce code ont été causés par deux choses, aussi bien dans la classe modèle:

  1. Les champs doivent être des propriétés, et non des champs normaux
  2. Le constructeur a qui manquait à initialiser les objets internes

Ainsi, les classes de la solution ci-dessus doit être:

public class B { 
    public A a {get; set;} 
    public string x {get; set;} 
    public int y {get;set;} 
    public B() { 
    a = new A(); 
    } 
} 

public class A {  
    public string z {get; set;} 
    public A() {} 
}