视图和控制器错误之间的模型绑定

时间:2015-07-16 17:36:25

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

我有一个列表,然后我想传递给它查看。我使用模型绑定方法。 这是我的代码: 型号:

public class Group
{
    public string Name { get; set; }
    public string GroupID { get; set; }
}

控制器:

public ActionResult Index()
{
    return View(ListGroup);
}

[HttpPost]
public ActionResult Index(List<Group> listModel)
{
    @ViewBag.Success = "Update Suceess";
    return View(listModel);
}

[HttpPost]
public ActionResult Search(Group modelSearch)
{
    List<Group> listResult = listGroup.Where(m=>m.GroupID == modelSearch.GroupID).ToList();

    if (modelSearch.GroupID == null)
        return View("Index", listGroup);

    return View("Index", listResult);
}

在视图中,我希望按GroupID

组显示列表
@using (Html.BeginForm("Index", "DisplayTable", FormMethod.Post))
{
    <table>
        <tr>
            <td>Name</td>
            <td>GroupID</td>
        </tr>
        @foreach(var items in Model.GroupBy(m => m.GroupID).Select(g => g.ToList())){
            <tr><td colspan="2">@items.ElementAt(0).GroupID</td></tr>
            for (int i = 0; i < items.Count; i++) { 
            <tr>
                <td>@Html.TextBoxFor(m => items[i].Name)</td>
                <td>@Html.TextBoxFor(m => items[i].GroupID)</td>
            </tr>
            }
        }
    </table>
        <input type="submit" value="SAVE" />
    }

我的问题是:如果我使用上面的代码,视图会正确显示组中的数据,但是当我单击按钮SAVE时,它没有向控制器发送任何数据,ActionResult Index(List<Group> listModel)收到一个空列表

更多解释: 我有这样的清单:

  • NAME | GROUPID 钢笔;一个 墨;乙 Pecil;一个 书; C 统治者;乙 笔记本; ç

我想在视图中显示它:

  • GroupID:A - 笔:A |铅笔:A
  • GroupID:B - 标尺:B |墨水:B
  • GroupID:C - Book:C |笔记本:C

如果我在视图中使用此代码:

<td>@Html.TextBoxFor(m => items[i].Name)</td>
<td>@Html.TextBoxFor(m => items[i].GroupID)</td>

视图中的结果是正确的,但这不能将数据发送回控制器。我发现每个字段Name GroupID的名称与html中的textfield名称不匹配。

我在视野中使用group并且我不知道在这种情况下最好的方法是什么:在控制器或视图中分组。如果我在控制器中分组,列表的结构是什么。

2 个答案:

答案 0 :(得分:2)

从你的编辑中,我看到你有一个这些对象的列表,你必须按照ID对它们进行分组,所以很多对象如钢笔和铅笔都有相同的ID'A',如果我们将它们组合在一起,它们属于组ID为'A'。

您的最佳做法是拥有正确的业务逻辑,并从控制器到视图进行建模。就像在这个答案中一样,实际上在模型中有List'group',如果你想分离业务和UI,那么创建一个视图模型,它保存你的“组”业务对象。 ui部分将包含一个子组列表。然后从viewmodel序列化为业务模型。

如何仅使用子项列表填充正确的模型。见控制器。

首先,您可以检查网页的来源,看看剃刀是否正在构建您期望的正确html。

您的问题是由于列表绑定的工作方式。最后,您的网页来源必须如下所示:

注意隐藏的字段,它们绑定原始对象及其ID。页面上的每个输入都必须具有唯一的名称或ID。

<tr>
				<td colspan="2">
					0 - name - 0
					<input name="[0].GroupID" type="hidden" value="0" />
					<input name="[0].Name" type="hidden" value="0 - name" />
				</td>
			</tr>	  
			<tr>
				<td><input class="text-box single-line" name="[0].ListGroup[0].Name" type="text" value="0 - name0 - subname" /></td>
				<td><input name="[0].ListGroup[0].GroupID" type="text" value="00" /></td>
			</tr>
			<tr>
				<td><input class="text-box single-line" name="[0].ListGroup[1].Name" type="text" value="0 - name1 - subname" /></td>
				<td><input name="[0].ListGroup[1].GroupID" type="text" value="01" /></td>
			</tr>

使用以下代码使解决方案正常运行。请不要让人们编辑groupID,因为一旦保存它将影响行为,ID必须保持唯一。在您的数据库结构中也是如此。

您的控制器

public class homeController : Controller
	{
		//
		// GET: /home/

		[HttpGet]
		public ActionResult Index()
		{
			List<Group> lst = new List<Group>();
			for (var i = 0; i < 5; i++)
			{
				lst.Add(new Group()
				{
					GroupID = i.ToString(),
					Name = i.ToString() + " - name",
					ListGroup = new List<Group>()
				});
			}

			foreach (var g in lst)
			{
				for (var i = 0; i < 3; i++)
				{
					g.ListGroup.Add(new Group()
					{
						GroupID = g.GroupID + i.ToString(),
						Name = g.Name + i.ToString() + " - subname",
						ListGroup = new List<Group>()
					});
				}
			}
			
			return View(lst);
		}

		[HttpPost]
		public ActionResult Save(List<Group> listModel)
		{
			@ViewBag.Success = "Update Suceess";
			return View(listModel);
		}

		public class Group
		{
			public string Name { get; set; }
			public string GroupID { get; set; }
			public List<Group> ListGroup { get; set; }
		}
	}

您的观点

@model List<TestMVC.Controllers.homeController.Group>

@{
	ViewBag.Title = "Index";
}

<h2>Index</h2>

@using (Html.BeginForm("Save", "Home", FormMethod.Post))
{
	<table>
		<tr>
			<td>Name</td>
			<td>GroupID</td>
		</tr>
		@for (var g = 0; g < Model.Count; g++)
  {
			<tr>
				<td colspan="2">
					@Model[g].Name - @Model[g].GroupID
					@Html.HiddenFor(x => Model[g].GroupID)
					@Html.HiddenFor(x => Model[g].Name)
				</td>
			</tr>	  
	  for (var i = 0; i < Model[g].ListGroup.Count; i++)
	  {
			<tr>
				<td>@Html.EditorFor(x => Model[g].ListGroup[i].Name)</td>
				<td>@Html.TextBoxFor(x => Model[g].ListGroup[i].GroupID)</td>
			</tr>
	  }
  }

	</table>
	<input type="submit" value="SAVE" />
}

运行时: enter image description here

请在此处查看此答案,了解使用模型编辑器的不同方法: MVC Form not able to post List of objects

进一步阅读,关于MVC中列表绑定的优秀文章: http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx/

答案 1 :(得分:0)

尝试使用Html.TextBox:

@{ var index = 0; }
@foreach(var items in Model.GroupBy(m=>m.GroupID).Select(g=>g.ToList())){
   Html.TextBox("items[" + index + "].Name", items.Name);
   Html.TextBox("items[" + index + "].GroupID", items.GroupID);
   index++;
}