当我提交时,我的模特在帖子上是空的。
模型
public QuizModel()
{
Questions = new List<QuizQuestionModel>();
}
public QuizModel(string quizName)
{
QuizName = quizName;
Score = 0;
IntranetEntities db = new IntranetEntities();
Quiz quiz = db.Quizs.Where(x => x.Name.Equals(quizName, StringComparison.InvariantCultureIgnoreCase)).FirstOrDefault();
if (quiz != null)
{
IQueryable<Quiz_Question> questions = db.Quiz_Question.Where(x => x.QuizID.Equals(quiz.ID)).OrderBy(x => x.QuestionNo);
Questions = new List<QuizQuestionModel>();
foreach (Quiz_Question question in questions)
{
QuizQuestionModel q = new QuizQuestionModel();
q.ID = question.ID;
q.Question = question.Question;
q.UserAnswer = null;
q.SystemAnswer = question.Answer;
Questions.Add(q);
}
}
}
public string QuizName { get; set; }
public List<QuizQuestionModel> Questions { get; set; }
public int Score { get; set; }
控制器
[HttpPost]
public ActionResult OSHAQuiz(Models.QuizModel model)
{
if (ModelState.IsValid)
{
bool passed = false;
model.Score = model.Questions.Where(x => x.UserAnswer.Equals(x.SystemAnswer, StringComparison.InvariantCultureIgnoreCase)).Count();
if (!model.Score.Equals(0))
{
double percent = model.Score / model.Questions.Count();
if (percent >= .8)
{
passed = true;
}
}
if (passed)
{
return View("/Views/Quiz/Passed.cshtml");
}
else
{
return View("/Views/Quiz/Failed.cshtml");
}
}
else
{
return View("/Views/Quiz/Quiz.cshtml", model);
}
}
查看
@model PAL.Intranet.Models.QuizModel
<script>
$(document).ready(function () {
$("input:checked").removeAttr("checked");
});
</script>
<div class="grid">
<h2>OSHA Quiz</h2>
<hr />
<div class="align-center">
@using (Html.BeginForm("OSHAQuiz", "Quiz", FormMethod.Post, new { id = "formShowLoading" }))
{
@Html.AntiForgeryToken()
@Html.ValidationSummary(true)
<div class="row cell">
<div class="example bg-grayLighter" data-text="Directions">
<ul class="simple-list">
<li class="align-left">When you have made your selection for all 20 statements, click on the button 'Submit.'</li>
<li class="align-left">Mark 'True' or 'False' for each statement.</li>
<li class="align-left">You must score 80% (16 correct) to pass.</li>
<li class="align-left">You must fill in your full name to receive credit.</li>
</ul>
</div>
</div>
<div class="row cell">
<div class="row cell">
<div class="panel" data-role="panel">
<div class="heading">
<span class="title">Questions</span>
</div>
<div class="content">
<ul class="numeric-list">
@foreach (var question in Model.Questions)
{
<li>
<table class="table hovered" style="width: 100%;">
<tr>
<td align="left">@question</td>
<td align="right" width="150px">
<div class="align-center">
<label class="align-right input-control radio small-check">
@Html.RadioButtonFor(model => question.UserAnswer, true, new { Name = question.GroupName })
<span class="check"></span>
<span class="caption">True</span>
</label>
<label class="align-right input-control radio small-check">
@Html.RadioButtonFor(model => question.UserAnswer, false, new { Name = question.GroupName })
<span class="check"></span>
<span class="caption">False</span>
</label>
</div>
</td>
</tr>
</table>
</li>
}
</ul>
</div>
</div>
</div>
</div>
<div class="row cell">
<input type="submit" value="Submit" class="button info small-button" />
<input type="reset" value="Reset" class="button primary small-button" />
</div>
}
</div>
</div>
更新
如果我在QuizName上使用HiddenFor,它会在帖子上重新开始,但模型的其余部分为空。
答案 0 :(得分:2)
当迭代要回发给模型的集合时,不能使用foreach
;您必须使用带索引的常规for
语句,以便Razor生成正确的字段名称。
@for (var i = 0; i < Model.Questions.Count(); i++)
{
...
@Html.RadioButtonFor(m => m.Questions[i].UserAnswer)
}
然后,您的字段将具有Questions[0].UserAnswer
形式的名称属性,模型绑定器将识别并适当地绑定到您的模型。正如您现在所拥有的那样,使用foreach
,字段名称将生成为question.UserAnswer
,模型绑定器不知道如何处理和丢弃。
此外,FWIW从您的模型实体中访问您的上下文是一个非常糟糕的主意,如果您没有注入它,更糟糕的是。将该逻辑移出您的实体并改为使用实用程序类或服务。另外,请查看依赖注入,因为您的上下文是您想要的内容之一,而仅每个请求的一个实例。如果您开始实例化同一上下文的多个实例,则将出现问题。
答案 1 :(得分:1)
问题是模型绑定会尝试将表单值绑定到模型上的属性。它不会使用模型上的构造函数来获取测验名称,它将使用默认构造函数来实例化QuizModel对象。
我会考虑重构此模型以删除您的EntityFramework依赖项,并找到一种新方法来填充这些值。
当你完成IDisposable对象的使用时,你也应该调用Dispose()方法。
我对如何解决这个问题的建议是使用你目前拥有的QuizModel帮助渲染你的观点(即你的测验问题和每个问题的可能答案)。
为测验提交创建单独的ViewModel
public class QuizSubmission
{
public string QuizName { get;set; }
public List<QuizQuestionResponse> Responses { get;set; }
}
public class QuizQuestionResponse
{
public int QuestionId { get;set; }
public int AnswerId { get;set; }
}
在您的控制器操作中,您应该绑定到QuizSubmission模型。
[HttpPost]
public ActionResult OSHAQuiz(Models.QuizSubmission model)
{
然后,您将能够执行测验提交所需的任何操作(即数据访问,验证)。
您还需要更新视图,以便您的Html输入元素具有正确的名称属性,模型绑定可以将每个问题和响应对正确绑定到“响应”列表中的QuizQuestionResponse项目。