【问题标题】:MVC Modify List Within ObjectMVC 修改对象内的列表
【发布时间】:2013-03-21 21:40:57
【问题描述】:

我有一个基本的创建/编辑/删除/索引格式,由 MVC 和我的班级 (ClassA) 创建。该类包含一个对象列表 (ClassB)。

当我调用视图来编辑对象时,我可以编辑 ClassA 的所有成员(文本字段等),但是如何编辑对象列表,然后仍然让它们返回到 post 操作?

当我尝试创建和迭代对象并将它们添加到表单时,它不会与对象 (ClassA) 一起返回,并且对象列表为空。

请帮忙。这样做的最佳做法是什么?

下面是一个例子

 public ActionResult Edit(int id)
    {
        ClassA objA = db.ClassAs.Single(a => a.id == id);

        objA.myListOfBs.Add(new ClassB());

        return View(objA);
    }

     [HttpPost]
    public ActionResult Create(ObjectA obj)
    {
        obj.myListOfBs <--- this is empty! :(
        if (ModelState.IsValid)
        {
        }

        return View(obj);
      }

模型类是:

class ClassA {
        int id;
    List<ClassB> myListOfBs;
 }

 class ClassB {
    int id;
    string name;
 }

这是我的观点

@model MyProject.Models.ClassA

@{
    ViewBag.Title = "ClassA Object";
}
@using (Html.BeginForm()) {
    @Html.ValidationSummary(true)

    <fieldset>
        <legend>Objects</legend>

        @Html.EditorFor(model => model.myListOfBs)

        <p>
            <input type="submit" value="Save" />
        </p>
    </fieldset>
}

【问题讨论】:

  • 能否请您发布您的模型类?
  • 您的问题几乎肯定在您看来。请问可以发帖吗?我猜你正在使用 foreach 循环遍历列表,而不尊重 mvc 模型绑定器命名要求'
  • 将其更改为使用 @Html.EditorFor 但它仍然不会将任何内容传递给 Post Action :(

标签: c# .net asp.net-mvc web


【解决方案1】:

找出发生这种情况的原因。这是我的一个错误,但我没有意识到会导致它。

我的主要对象中的对象已声明

class ClassA {
 public ClassB country;
}

而不是

class ClassA {
 public ClassB country {get; set;}
}

所以看来它必须是一个属性才能正确绑定对象。

主要问题在这里解决

我还想补充一点,虽然添加 set/get 标签允许将对象传递到帖子,但它仍然不适用于对象内的列表。

我终于在这里找到了如何做到这一点(ASP.NET MVC 3 Binding to a Collection inside an Object),基本上你需要映射到模型中的特定项目

例子:

 @for (int i = 0; i < Model.myListOfBs.Count; i++)
 {
     <div>
        @Html.LabelFor(m => Model.myListOfBs[i].name )
    </div>
    <div>
        @Html.TextBoxFor(m => Model.myListOfBs[i].name )
    </div>
 }

显式映射到数组位置就可以了。由于您无法使用 foreach 显式映射到列表中的某个项目,因此它失败了。

另外,如果你像我一样使用实体框架,你很可能不得不使用 ViewModel 来访问数组元素。

【讨论】:

    【解决方案2】:

    我以前见过这个。最简单的方法(使用此示例结构)是:

    视图模型:

    public string CompanyName { get; set; }
    public List<ViewModelOfObjects> SubObjects { get; set; }
    

    如您所见,您的子对象应该有自己的 ViewModel,然后您可以在您的视图中执行此操作。

    @model YourMainViewModel
    
    @Html.EditorFor(model => model.CompanyName)
    
    // MVC is clever enough to work this out and list all the sub-Views, even if they are hidden fields and not editable.
    @Html.EditorFor(model => model.SubObjects)
    

    【讨论】:

    • 这个我没完全理解,SubObjects被替换成不同的类型了?我是否必须创建一个不同的模型并将数据从 ClassB 对象复制到 ViewModelOfClassB 对象?
    • 子对象本身就是一个视图模型。假设它是一个 Customer 对象,它将是一个新的 CustomerViewModel,具有与 Customer 对象相同的属性(但作为 ViewModel)。然后 MVC 将能够将这些子对象与您的主对象相关联。
    • 恐怕这仍然行不通。当它触发 post 事件时,它仍然会将列表清空。尽管我尝试创建一个字符串列表,并使用@Html.EditFor 在视图上查看它,但它确实有效!它正确地通过了它,并且回发时列表不是空的。我认为 ViewModel 和 Model 一样,但是结构发生了变化,你不想修改你的基础模型?
    • 附加:我改变了它,所以子对象只是一个不同类型的对象,而不是一个列表,这会被发布(用 fiddler 找到)。但没有附加到主目录。
    【解决方案3】:

    我过去这样做的方式是使用模型绑定器可以识别的命名约定来绑定集合。

    例如,在您的情况下,您的视图中可能有以下内容:

    @model ClassA
    int index = 0;
    @foreach (var classB in Model.myListOfBs)
    {
        //Notice the use of "obj", this matches the name of your model parameter in your post action
        @Html.Hidden("obj.myListOfBs.Index", index)
        @Html.TextBox("obj.myListOfBs[" + index + "].name", classB.name)
        index++;
    }
    

    当将此表单发布到您的操作时,模型绑定器将使用上面详述的索引命名约定将每个字段绑定到模型中的 myListOfBs 集合。

    另外,正如@thedixon 所指出的,MVC 框架可以自动创建字段名称(我不确定这在所有版本的 ASP.NET MVC 中是否可行):

    @Html.EditorFor(model => model.myListOfBs)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-03-14
      • 1970-01-01
      • 2017-02-02
      • 1970-01-01
      • 2023-03-21
      相关资源
      最近更新 更多