模型空在岗位上

时间:2015-07-01 15:53:03

标签: c# asp.net-mvc razor model

当我提交时,我的模特在帖子上是空的。

模型

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,它会在帖子上重新开始,但模型的其余部分为空。

2 个答案:

答案 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项目。

相关问题