我有两个模型,问答。我想通过ViewModel向一个问题插入一个答案列表,但似乎在我的post方法中我的列表变为null。这可能是一个糟糕的实现,因为当我发布一些东西时,我正在返回我的问题的模型,我猜我的列表只是变为空。我怎么能解决这个问题?
编辑:我根据你给我的评论重新构建了控制器和视图:这就是它现在的样子,但似乎我的答案列表再次变为空。
ViewModel:
public class ViewModel
{
public IEnumerable<Answer> Answers { get; set; }
public Question Question { get; set; }
}
控制器:
[Authorize]
public ActionResult Create()
{
ViewModel vm = new ViewModel();
ViewBag.BelongToTest = new SelectList(db.Tests, "TestId" , "TestTitle").FirstOrDefault();
vm.Question = new Question { Question_Text = String.Empty };
vm.Answers = new List<Answer> { new Answer { CorrectOrNot = false, AnswerText = "", OpenAnswerText = "" } };
return View(vm);
}
//
// POST: /Question/Create
[HttpPost]
[Authorize]
public ActionResult Create(ViewModel vm)
{
if (ModelState.IsValid)
{
vm.Question.BelongToTest = (from t in db.Tests
join m in db.Members on t.AddedByUser equals m.MemberId
where m.UserID == WebSecurity.CurrentUserId &&
t.AddedByUser == m.MemberId
orderby t.TestId descending
select t.TestId).FirstOrDefault();
db.Questions.Add(vm.Question);
db.SaveChanges();
if (vm.Answers != null)
{
foreach (var i in vm.Answers)
{
i.BelongToQuestion = vm.Question.QuestionId;
db.Answers.Add(i);
}
}
db.SaveChanges();
ViewBag.Message = "Data successfully saved!";
ModelState.Clear();
}
ViewBag.BelongToTest = new SelectList(db.Tests, "TestId", "TestTitle", vm.Question.BelongToTest);
vm.Question = new Question { Question_Text = String.Empty };
vm.Answers = new List<Answer> { new Answer { CorrectOrNot = false, AnswerText = "", OpenAnswerText = "" } };
return View("Create" , vm);
}
查看:
@model MvcTestApplication.Models.ViewModel
@using MvcTestApplication.Models
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
@{
ViewBag.Title = "Create";
}
@using (Html.BeginForm("Create", "Question", FormMethod.Post)) {
<h2>Create</h2>
<table>
<tr>
<th>Question Name</th>
</tr>
<tr>
<td>@Html.EditorFor(model=>model.Question.Question_Text)</td>
</tr>
</table>
<table id="dataTable">
<tr>
<th>Correct?</th>
<th>Answer text</th>
<th>Open Answer</th>
</tr>
@foreach(var i in Model.Answers)
{
<tr>
<td>@Html.CheckBoxFor(model=>i.CorrectOrNot)</td>
<td>@Html.EditorFor(model=>i.AnswerText)</td>
<td>@Html.EditorFor(model=>i.OpenAnswerText)</td>
</tr>
}
</table>
<input type="button" id="addNew" value="Add Answer"/>
<input type="submit" value="Create" />
}
@section Scripts {
@Scripts.Render("~/bundles/jqueryval")
<script lang="javascript">
$(document).ready(function () {
//1. Add new row
$("#addNew").click(function (e) {
e.preventDefault();
var $tableBody = $("#dataTable");
var $trLast = $tableBody.find("tr:last");
var $trNew = $trLast.clone();
var suffix = $trNew.find(':input:first').attr('name').match(/\d+/);
$trNew.find("td:last").html('<a href="#" class="remove">Remove</a>');
$.each($trNew.find(':input'), function (i, val) {
// Replaced Name
var oldN = $(this).attr('name');
var newN = oldN.replace('[' + suffix + ']', '[' + (parseInt(suffix) + 1) + ']');
$(this).attr('name', newN);
//Replaced value
var type = $(this).attr('type');
if (type.toLowerCase() == "text") {
$(this).attr('value', '');
}
// If you have another Type then replace with default value
$(this).removeClass("input-validation-error");
});
$trLast.after($trNew);
// Re-assign Validation
var form = $("form")
.removeData("validator")
.removeData("unobtrusiveValidation");
$.validator.unobtrusive.parse(form);
});
// 2. Remove
$('a.remove').live("click", function (e) {
e.preventDefault();
$(this).parent().parent().remove();
});
});
</script>
}
答案 0 :(得分:3)
要使ModelBinder绑定到List,必须按顺序索引HTML表单。
你的
<td>@Html.CheckBoxFor(model=>a.CorrectOrNot)</td>
<td>@Html.EditorFor(model=>a.AnswerText)</td>
<td>@Html.EditorFor(model=>a.OpenAnswerText)</td>
正在创建一些绑定到单个答案的内容。您需要呈现将绑定到List的HTML,例如
@for (int i = 0; i < ((List<Answer>)ViewData["Answers"]).Count; i++)
{
<tr>
<td>@Html.CheckBoxFor(model=>((List<Answer>)ViewData["Answers"])[i].CorrectOrNot)</td>
<td>@Html.EditorFor(model=>((List<Answer>)ViewData["Answers"])[i].AnswerText)</td>
<td>@Html.EditorFor(model=>((List<Answer>)ViewData["Answers"])[i].OpenAnswerText)</td>
</tr>
}
此外,这看起来非常糟糕,可以在整个地方投射ViewData。如果您计划保持这种方法创建一个真实的视图模型,通常会更好。您可以将该模型传递给视图,它可以包装问题和答案集合。
编辑:
您仍然需要针对列表提供顺序索引,而您的编辑实现不会提供该索引。像
这样的东西@for (int i = 0; i < Model.Answers.Count; i++)
{
<tr>
<td>@Html.CheckBoxFor(model=> Model.Answers[i].CorrectOrNot)</td>
<td>@Html.EditorFor(model=> Model.Answers[i].AnswerText)</td>
<td>@Html.EditorFor(model=> Model.Answers[i].OpenAnswerText)</td>
</tr>
}
答案 1 :(得分:1)
从控制器进入视图时,ViewData是相关的。它不会回复。
你应该转发(模型/参数)绑定,为你传递List<Answer> answerList
答案 2 :(得分:0)
ViewData仅用于在视图和控制器之间传输数据。您可以使用会话在控制器之间传输数据
答案 3 :(得分:0)
感谢您的评论。他们真的帮助了我。你说的一切都是正确的,但有一些东西丢失了。我在ViewModel中的IEnumerable根本不允许我索引我的值,而是使用IList帮助我索引所有内容,因为它应该是,并且一切正常。