asp.net MVC:嵌入式对象编辑

时间:2009-09-11 13:42:02

标签: asp.net-mvc partial-views

我想在对象B中嵌入一个对象A的实例。我已经有一个动作和一个编辑视图,它为对象B呈现一个表单。我使它成为一个强类型的局部视图,接受B。

我正在处理Create动作,所以我做b = new B(); b.A =新A();

现在我将为B渲染表单,然后调用A的局部视图,将其传递给b.A。

但我得到的是FormCollection,或者我的新A对象,其中B字段设置为null。 在第一种情况下,一切都很好,但如果表格没有出现错误,我该怎么办?我是否需要使用错误的数据手动创建对象,并使用无效的ModelState再次传递它们? 第二种选择是否可能?

或者我只是需要避免使用嵌套视图?作为替代方案,我认为创建一个特殊的模型对象只是为了处理包含A和B的所有值的表单,然后当这个表单验证时,我会手动填充A和B对象并保存它们。这是唯一的解决方案吗?

3 个答案:

答案 0 :(得分:1)

你应该能够像你所描述的那样使用A和B.

假设我们有以下内容:

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
        } );
}

所以你的模型是B的实例。

您的视图和嵌套的局部视图应该生成如下所示的HTML:

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

现在默认的模型绑定器应该能够解决这个问题:

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

请注意,这仅适用于A和B都具有默认构造函数且相对简单的类。如果你有更复杂的东西,你可以使用自己的活页夹:

[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"])
            };
    }
}

答案 1 :(得分:1)

创建自己的包含A和B的自定义模型,然后从该模型创建视图 当您提交表单时,您只需更新自定义模型并更新/添加单个模型即可。

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

该模型的视图将创建一个包含A和B的表单,然后使您能够使用 然后,您发布的formcollection可用于为每个单独模型设置值,然后更新/创建然后单独使用。

答案 2 :(得分:0)

我对此代码的问题是由模型类中的两件事引起的:

  1. 字段必须是属性,而不是普通字段
  2. 缺少初始化内部对象的构造函数
  3. 所以上面解决方案中的类应该是:

    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() {}
     }