在同一视图中创建多个相同类型的对象

时间:2015-05-31 19:18:11

标签: c# asp.net entity-framework asp.net-mvc-4

在我的创建视图中,我希望为用户提供创建对象列表(相同类型)的可能性。因此,我在视图中创建了一个表,包括每行中的每个输入字段。相应的行数"可创建"对象是固定的数字。

假设有一本包含两个属性标题和作者的课本,用户应该可以创建10本或更少的书。

我该怎么做?

我不知道如何将对象列表(绑定的)传递给控制器​​。我试过了:

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(ICollection<Book> bookList)
    {
        if (ModelState.IsValid)
        {
            foreach(var item in bookList)
                db.Books.Add(item);
            db.SaveChanges();
            return RedirectToAction("Index");
        }
        return View(articlediscounts);
    }

在视图中它是:

<fieldset>
    <legend>Book</legend>

    <table id="tableBooks" class="display" cellspacing="0" width="100%">
            <thead>
                <tr>
                    <th>Title</th>
                    <th>Author</th>
                </tr>
            </thead>
            <tbody>
                @for (int i = 0; i < 10 ;i++ )
                {
                    <tr>
                        <td>
                            <div class="editor-field">
                                @Html.EditorFor(model => model.Title)
                                @Html.ValidationMessageFor(model => model.Title)
                            </div>
                        </td>
                        <td>
                            <div class="editor-field">
                                @Html.EditorFor(model => model.Author)
                                @Html.ValidationMessageFor(model => model.Author)
                            </div>
                        </td>
                    </tr>
                }
            </tbody>
        </table>

    <p>
        <input type="submit" value="Create" />
    </p>
</fieldset>

由于booklist为null,它不起作用,我不知道如何将所有创建的对象放在此列表中。

如果您有任何建议,我将非常感谢。

3 个答案:

答案 0 :(得分:2)

Scott Hanselman提供了有关将数组传递给MVC控件绑定的一些细节:http://www.hanselman.com/blog/ASPNETWireFormatForModelBindingToArraysListsCollectionsDictionaries.aspx

本质上是:确保您的控件具有正确的名称:使用列表索引

将for循环更改为:

@for (int i = 0; i < 10 ; i++)
{
    <tr>
        <td>
            <div class="editor-field">
                <input type="text" name="book[" + i + "].Title" />
            </div>
        </td>
        <td>
            <div class="editor-field">
                <input type="text" name="book[" + i + "].Author" />
            </div>
        </td>
    </tr>
}

这将自动绑定到您的帖子操作。

[HttpPost]
public ActionResult Create(IList<Book> bookList)

然后,您可以根据需要显示/隐藏这些内容,或使用js / jquery动态添加它们

编辑:正如Stephen Muecke正确观察到的那样,上述答案仅涉及从+字段到HttpPost的绑定,这似乎是问题的重点。

原始帖子中的帖子操作与视图不兼容。 OP中有相当多的遗漏代码可能相关或不相关,但值得注意的是,如果您的视图是针对单个模型的,那么ModelState.IsValid上的失败代码需要返回单个模型或您的视图需要为IList(或类似),否则您将无法获得服务器端验证(但如果您手动将其添加到<input>s,您仍然可以获得客户端验证)

答案 1 :(得分:0)

您需要发送一个包含书籍列表的JSON对象。所以首先要创建一个这样的Model类:

public class SavedBooks{
    public List<Book> Books { get; set; }
}

然后Book类必须有这两个道具:

public class Book {
   public string Title { get; set; }
   public string Author { get; set; }
}

接下来,更改您的控制器以使用此模型:

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(SavedBooks model)

然后创建一个javascript方法(使用jQuery)来创建一个匹配控制器SavedBooks类结构的JSON对象:

var json = { Books: [ { Title: $('#title_1').val(), Author: $('#Author_1').val() } ,
                      { as many items as you want }
                    ]
           };
$.ajax(
{
    url: "/Controller/Create",
    type: "POST",
    dataType: "json",
    data: json
});

答案 2 :(得分:0)

您使用@Html.EditorFor(model => model.Title)的事实表明您已在视图中将模型声明为

@model yourAssembly.Book

允许仅回发一个Book,因此POST方法需要

public ActionResult Create(Book model)

请注意,您当前的实现会创建类似于

的输入
<input id="Title" name="Title" ... />

name属性没有索引器(它们需要是name="[0].Title"name="[1].Title"等。)因此无法绑定到集合,并且由于重复而无效的html id属性。

如果您想创建10本书,那么您需要在GET方法中初始化一个集合并将该集合传递给视图

public ActionResult Create()
{
  List<Book> model = new List<Book>();
  for(int i = 0; i < 10;i++)
  {
    model.Add(new Book());
  }
  return View(model);
}

并在视图中

@model yourAssembly.Book
@using (Html.BeginForm())
{
  for(int i = 0; i < Model.Count; i++)
  {
    @Html.TextBoxFor(m => m[i].Title)
    @Html.ValidationMessageFor(m => m[i].Title)
    .... // ditto for other properties of Book
  }
  <input type="submit" .. />
}

现在将在POST到

时绑定到您的集合
public ActionResult Create(List<Book> bookList)

请注意,如果您需要返回视图,该集合应为List<Book>

但是,这可能会强制用户创建所有10本书,否则验证可能会失败(正如您使用@Html.ValidationMessageFor()所建议的那样)。更好的方法是使用BeginCollectionItem辅助方法(refer example)或this answer的客户端模板在视图中动态添加新的Book项。

相关问题