如何在 MVC 中发布项目列表
Posted
技术标签:
【中文标题】如何在 MVC 中发布项目列表【英文标题】:How can I post a list of items in MVC 【发布时间】:2013-04-25 15:54:21 【问题描述】:我有一个包含项目列表的简单表单,我想将它们发布到控制器,但有趣的是我不能。除了列表之外,其他一切都正常进行。我检查了firebug中的ajax调用,帖子值是这样的:
Answers[0].IsMissing False
Answers[0].Text Ja
Answers[0].Value 0
Answers[1].IsMissing False
Answers[1].Text Nein
Answers[1].Value 1
Id 1cd14b08-ce3b-4671-8cf8-1bcf69f12b2d
Name Ja/Nein
我有一个具有以下属性的 AnwserScheme 类:
public string Name get; set;
public bool IsMissing get; set;
public List<AnswerDisplayItem> Answers get; set;
public AnswerScheme()
Answers = new List<AnswerDisplayItem>();
我有这个查看代码:
@for (int i = 0; i < Model.Answers.Count; i++)
<tr>
<td>
@html.HiddenFor(model => Model.Answers[i].IsMissing)
@Html.TextBoxFor(model => Model.Answers[i].Value,
new @class = "inputValue" )
</td>
<td>
@Html.TextBoxFor(model => Model.Answers[i].Text,
new @class = "inputAnswer" )
</td>
<td>
<span class="span-delete"
data-answer-scheme-id="@Model.Id"
data-answer-id="@Model.Answers[i].Id" >x</span>
</td>
</tr>
我有这段负责发布的 ajax 代码:
$.ajax(
url: "/AnswerScheme/AddAnswer",
type: "post",
data: $("#formAnswerScheme").serialize(),
success: function (data)
console.log(data);
$("#divAnswerSchemeContainer").html(data);
);
我的控制器中有一个添加答案操作:
[HttpPost]
public PartialViewResult AddAnswer(AnswerScheme answerScheme)
...some logic comes here
所以最终控制器会收到模型,但只有简单的属性,而不是列表。任何帮助将不胜感激!干杯。
【问题讨论】:
您可以查看这篇文章以获取有关如何将模型绑定到集合的教程:haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx 您使用的是 MVC3 还是 MVC4?因为您的代码在新创建的 MVC4 项目中运行良好...您可以发布完整的#formAnswerScheme
表单代码吗?
请从 BeginForm 向下发布您的整个 AnswerScheme 模型和整个表单(并包括您的 @model 声明)
我可以在您发布的代码中看到视图迭代列表项以显示它们,但我不清楚您如何将列表项添加到视图中。这些列表项在网格中?隐藏标记?。项目的容器在表单内?如果不是,这可能是一个原因。您能否提供更多关于您的观点的详细信息,以便我们更好地为您提供帮助?
nemesv:我使用 MVC4 项目。查尔斯:这真的是一个实验,我想添加一个新行,除了 ajax 调用之外不使用任何 javascript 逻辑。所以我所做的就是发布表单,重新创建它,删除空行,然后在末尾添加一个新行。并将其放回#divAnswerSchemeContainer。 (我知道它可能不是最好的方法,但可能过多地使用服务器,只是为了创建一个新行,但重新索引也是 javascript 的麻烦。)
【参考方案1】:
我希望我能看到更多你的类和代码,因为你没有设置正确的东西。
我根据您提供的内容重新创建了一些东西,这很有效。我为此示例创建了一个 MVC 3 项目。
视图/共享/_Layout.cshtml
<!DOCTYPE html>
<html>
<head>
<title>@ViewBag.Title</title>
<link href="@Url.Content("~/Content/Site.css")" rel="stylesheet" type="text/css" />
<script src="@Url.Content("~/Scripts/jquery-1.7.1.min.js")" type="text/javascript"></script>
</head>
<body>
@RenderBody()
</body>
</html>
视图/共享/_Partial.cshtml
@model RazorListTest.Models.AnswerScheme
<table>
@for (int i = 0; i < Model.Answers.Count; i++)
<tr>
<td>
@Html.HiddenFor(model => Model.Answers[i].IsMissing)
@Html.TextBoxFor(model => Model.Answers[i].Value, new @class = "inputValue" )
</td>
<td>
@Html.TextBoxFor(model => Model.Answers[i].Text, new @class = "inputAnswer" )
</td>
<td><span class="span-delete" data-answer-scheme-id="@Model.Id" data-answer-id="@Model.Answers[i].Id" >x</span></td>
</tr>
</table>
模型/AnswerDisplayItem.cs
using System.Collections.Generic;
namespace RazorListTest.Models
public class AnswerDisplayItem
public bool IsMissing get; set;
public string Text get; set;
public string Value get; set;
public string Id get; set;
public class AnswerScheme
public List<AnswerDisplayItem> Answers get; set;
public string Id get; set;
public AnswerScheme()
Answers = new List<AnswerDisplayItem>();
首页/Index.cshtml
@model RazorListTest.Models.AnswerScheme
@using (Html.BeginForm(null, null, FormMethod.Get, new name="formAnswerScheme", id = "formAnswerScheme"))
Html.RenderPartial("_Partial");
<div>
<input type="button" value="Click me" id="btnClick"/>
</div>
<div id="divAnswerSchemeContainer">
</div>
<script type="text/javascript">
$("#btnClick").click(function ()
$.ajax(
url: 'Home/AddAnswer',
type: 'POST',
dataType: 'json',
data: $("#formAnswerScheme").serialize(),
success: function (data)
console.log(data);
$("#divAnswerSchemeContainer").html(data);
,
error: function (xhr, textStatus, exceptionThrown) alert(JSON.parse(xhr.responseText));
);
);
</script>
控制器/HomeController.cs
using System.Collections.Generic;
using System.Web.Mvc;
using RazorListTest.Models;
namespace RazorListTest.Controllers
public class HomeController : Controller
public ActionResult Index()
AnswerScheme a = new AnswerScheme();
a.Id = "1cd14b08-ce3b-4671-8cf8-1bcf69f12b2d";
List<AnswerDisplayItem> adi = new List<AnswerDisplayItem>();
AnswerDisplayItem a1 = new AnswerDisplayItem();
a1.IsMissing = false;
a1.Text = "Ja";
a1.Value = "0";
a1.Id = "1234";
AnswerDisplayItem a2 = new AnswerDisplayItem();
a2.IsMissing = false;
a2.Text = "Nein";
a2.Value = "1";
a2.Id = "5678";
adi.Add(a1);
adi.Add(a2);
a.Answers = adi;
return View(a);
[HttpPost]
public JsonResult AddAnswer(AnswerScheme answerScheme)
return Json("the list is in the Model.");
【讨论】:
感谢您的所有努力,真的很彻底。顺便说一句,我基本上像你一样做了所有事情,但它仍然只是不想工作。恼人的。我要发布我所有的代码,也许某处有一个我缺少或我不知道的设置。 在一个全新的 MVC4 项目中,您的代码可以完美运行。但是那我做错了什么?! 我不知道。我把你的放到一个新项目中,它也可以工作。我创建了一个 Code、CodeList 和 Category 类,这样我就可以坚持使用您的确切代码。我很困惑。 快速提问,所以这意味着在序列化时,mvc 会识别所有 hiddensFor 和 textBoxFor,并将其 Add() 到 model.List 中?我知道您正在使用 data: $("#formAnswerScheme").serialize() 回复,因为问题是这样说的,但是如果我对执行常规帖子的 执行相同操作会发生什么?会有同样的结果吗?【参考方案2】:它几乎与 TheGeekYouNeed 发布的内容相同,但我想只是缺少一些东西。我不知道那可能是什么。
AnswerScheme 视图:
@using System.Web.Mvc.Html
@using MetaDataPortal.Models
@model AnswerScheme
@
ViewBag.Title = @Model.IsMissing ? "Missing" : "AnswerScheme";
Layout = "~/Views/Shared/_Layout.cshtml";
@section CssContent
<link href="../../Content/CSS/AnswerScheme.css" rel="stylesheet" />
@using (Html.BeginForm("Save", "AnswerScheme", FormMethod.Post, new id = "formAnswerScheme" ))
<div id="divAnswerSchemeContainer">
@Html.RenderPartial("_AnswerScheme", Model);
</div>
<input type="button" class="clear inputButton" id="buttonAddCode" value="Add @(Model.IsMissing ? "Missing" : "Answer")" />
<input type="submit" value="Save" />
@section Javascript
<script type="text/javascript">
$(function ()
$("#buttonAddCode").click(function ()
$.ajax(
url: "/AnswerScheme/AddAnswer",
type: "post",
async: false,
data: $("#formAnswerScheme").serialize(),
success: function (data)
console.log(data);
$("#divAnswerSchemeContainer").html(data);
);
return false;
);
);
</script>
<script type="text/javascript" src="~/Content/JavaScript/AnswerScheme.js"></script>
_AnswerScheme 部分视图
@model MetaDataPortal.Models.AnswerScheme
@Html.HiddenFor(model => model.Id, new Id = "AnswerSchemeId" )
<ul class="ulGeneralForm">
<li>
@Html.LabelFor(model => model.Name, "Name", new @class = "labelGeneral" )
@Html.TextBoxFor(model => model.Name, Model.Name, new @class = "textBoxGeneral" )
</li>
<li>
@Html.Label(@Model.IsMissing ? "Missings" : "Answers", new @class = "labelGeneral" )
<table class="textualData links downloadList">
<thead>
<tr>
<th>Value</th>
<th> @(Model.IsMissing ? "Missing" : "Answer")</th>
<th></th>
</tr>
</thead>
<tbody id="tbodyCodeContainer">
@for (int i = 0; i < Model.Answers.Count; i++)
<tr>
<td>
@Html.HiddenFor(model => Model.Answers[i].IsMissing)
@Html.TextBoxFor(model => Model.Answers[i].Value, new @class = "inputValue" )
</td>
<td>
@Html.TextBoxFor(model => Model.Answers[i].Text, new @class = "inputAnswer" )
</td>
<td><span class="span-delete" data-answer-scheme-id="@Model.Id" data-answer-id="@Model.Answers[i].Id" >x</span></td>
</tr>
</tbody>
</table>
</li>
</ul>
AnswerScheme.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using Opit.Rogatus.DomainObjects;
namespace MetaDataPortal.Models
public class AnswerScheme : BaseModel
public string Name get; set;
public bool IsMissing get; set;
public List<AnswerDisplayItem> Answers get; set;
public AnswerScheme()
Answers = new List<AnswerDisplayItem>();
public AnswerScheme(CodeList codeList, bool isMissing) : this()
Id = codeList.Id;
Name = codeList.Name;
IsMissing = isMissing;
foreach (Code code in codeList.Codes.Where(code => code.Category.IsMissing == isMissing))
Answers.Add(new AnswerDisplayItem(code));
AnswerDisplayItem.cs:
using System;
using Opit.Rogatus.DomainObjects;
namespace MetaDataPortal.Models
public class AnswerDisplayItem
public Guid Id get; private set;
public short Value get; private set;
public string Text get; private set;
public Guid AnswerSchemeId get; set;
public bool IsMissing get; private set;
public AnswerDisplayItem()
public AnswerDisplayItem(Code code)
Id = code.Id;
Value = code.Value;
Text = code.Category.Name;
IsMissing = code.Category.IsMissing;
if (code.CodeList == null) return;
AnswerSchemeId = code.CodeList.Id;
和控制器差不多。
【讨论】:
你能贴出你的 Code、CodeList 和 Category 类吗?【参考方案3】:你可以这样创建模型
public class ApplicationInfo
public List<ApplicationAccessRoles> ApplAccessRoleInfo get; set;
public class ApplicationAccessRoles
public int app_access_role_key get; set;
public int app_key get; set;
public string access_role get; set;
public bool inactive get; set;
把它放在眼里
<div class="step-pane" id="step3">
<div class="form-horizontal" style="vertical-align:central;margin-left:150px">
<table id="RolesDetails" cellpadding="0" cellspacing="0" class="data_table">
<tr class="dataheader">
<td class="width5">
@Html.HiddenFor(m => m.app_access_role_key)
</td>
<td class="width200">
Access Roles Name
</td>
<td class="width10">
Inactive
</td>
</tr>
@if (Model.ApplAccessRoleInfo.Count!= 0)
var chk = Model.ApplAccessRoleInfo.Count;
for (int a = 0; a < Model.ApplAccessRoleInfo.Count; a++)
<tr class="exp_col_header top_border_nil">
@if ((chk - 1) == a)
<td><a href="#" class="gridexpand" rel="1"></a></td>
else
<td></td>
<td>
@Html.HiddenFor(m => m.ApplAccessRoleInfo[a].app_access_role_key)
@Html.EditorFor(m => m.ApplAccessRoleInfo[a].access_role)
</td>
<td>
@Html.CheckBox("ApplTeamAccessInfo[" + a.ToString() + "].inactive", false, new @class = "check-box")
</td>
</tr>
else
<tr class="exp_col_header top_border_nil">
<td>
<a href="#" class="gridexpand" rel="1"></a>
</td>
<td>
@*@Html.EditorFor(model => model.access_role)*@
@*@Html.EditorFor(m => m.ApplAccessRoleInfo[0].access_role)*@
@Html.EditorFor(model=>model.access_role)
</td>
<td>
@Html.CheckBoxFor(model => model.inactive)
</td>
</tr>
</table>
</div>
</div>
在控制器中
var main = (from a in db.mas_app_access_roles
where a.app_key == AppInfo.app_key
select new ApplicationAccessRoles
app_access_role_key = a.app_access_role_key,
access_role = a.access_role,
inactive = a.inactive,
).ToList();
access = main;
AppInfo.ApplAccessRoleInfo = access;
ViewBag.check = access;
return View(AppInfo);
【讨论】:
【参考方案4】:问题在于文本框和其他输入控件的 name/id 属性。您可以使用editor templates 使事情变得无缝且可重复使用。另一个例子here。
但是,如果您仍想循环遍历事物,则您的循环必须在这些示例中查看 here 或 here。
【讨论】:
不,他的命名没有问题。是的,他应该使用编辑器模板,但他的命名方式很好。【参考方案5】:尝试将控制器参数名称更改为“answers”或将属性名称更改为 AnswerScheme,如果您帖子中的部分控制器应该接收列表,则将类型更改为:
List<AnswerScheme> answers
【讨论】:
以上是关于如何在 MVC 中发布项目列表的主要内容,如果未能解决你的问题,请参考以下文章
如何将项目列表从视图传递到控制器(ASP.NET MVC 4)