Сообщение формы ASP.Net MVC не может связывать свойство списка модели

asp.net-mvc-5 c# entity-framework-6 model-binding razor

Вопрос

Я пытаюсь создать страницу опроса, которая может иметь текстовые поля и списки переключателей или полей флажков. Независимо от того, что я пытаюсь, я не могу получить свойство model.Questions для привязки при отправке формы; модель создается с использованием свойства null Questions.

Скажите, пожалуйста, у вас есть идея, которая может мне помочь!

Модель вида выглядит следующим образом:

// Survey view model
public class Question
{
    public int Id { set; get; }
    public string QuestionText { set; get; }

    public bool IsHeading { get; set; }
    public bool IsList { get; set; }
    public bool IsCheckBox { get; set; }

    public List<Answer> Answers { set; get; }
    [Required]
    public string SelectedAnswer { set; get; }
    public string GivenAnswer { get; set; }
    public Question()
    {
        Answers = new List<Answer>();
        GivenAnswer = "-1";
        SelectedAnswer = "-1";
        QuestionText = "";
    }
}

public class Answer
{
    public int Id { set; get; }
    public string AnswerText { set; get; }
}

public class Assessment
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int LessonId { get; set; }
    public Module Lesson { get; set; }

    public SurveyType SurveyType { get; set; }

    public virtual List<Question> Questions { set; get; }
    public Assessment()
    {
        Questions = new List<Question>();
    }
}

Метод контроллера выглядит следующим образом:

 [HttpPost]
 public ActionResult Survey(Assessment model)
 {
     if (ModelState.IsValid)
     {
         foreach (var q in model.Questions)
         {
             var qId = q.Id;
             var selectedAnswer = q.SelectedAnswer;
             // Save the data 
         }
         return RedirectToAction("ThankYou", new { id = model.Id }); //PRG Pattern
     }
     //to do : reload questions and answers
     return View(model);
 }

Где Assessment является основной моделью просмотра. Ниже представлены представление (Survey.cshtml) и шаблон редактора (EditorTemplates / Question.cshtml, для каждого Вопроса)

Survey.cshtml:

@model ZTTDD.Models.Assessment
@using ZTTDD.Models

<div class="row">
    <div class="col-md-9">
        @using (Html.BeginForm())
        {
            @Html.HiddenFor(m => m.Id)

            @Html.EditorFor(m => m.Questions)

            <input type="submit" />
        }
    </div>
    <div class="col-md-3">
        <p>
            @Html.ActionLink((string)ViewBag.LessonLinkBackText, "Lesson", "Lessons", new { id = Model.Lesson.Id }, null)
        </p>
        <p>
            @Html.ActionLink(linkName, linkMethod, "Lessons", new { id = Model.Lesson.Id }, null)
        </p>
    </div>
</div>

EditorTemplates / Question.cshtml

@model ZTTDD.Models.Question


@if (Model.IsHeading)
{
    <div class="survey-heading">
        <h4>@Model.QuestionText</h4>
    </div>
    <hr/>
}
@if (!Model.IsHeading)
{
    <div class="form-group">
        @Html.HiddenFor(m => m.Id)

        <p> @Model.QuestionText </p>

        @if (Model.IsList)
        {
            <div class="radio">
                @Html.HiddenFor(m => m.GivenAnswer)
                @foreach (var a in Model.Answers)
                {
                    if (Model.IsCheckBox)
                    {
                    <span class="form-horizontal">
                        @Html.CheckBox(String.Format("Questions_{0}__SelectedAnswer", Model.Id), false, new { value = "", name = String.Format("Questions[{0}].SelectedAnswer", Model.Id) })  @Html.Raw(a.AnswerText) &nbsp;&nbsp;
                    </span>
                    }
                    else
                    {
                        @Html.RadioButtonFor(b => b.SelectedAnswer, a.Id)  @Html.Raw(a.AnswerText) <br />
                    }
                }
            </div>
        }
        @if (!Model.IsList)
        {
            Model.GivenAnswer = "";
            @Html.HiddenFor(m => m.SelectedAnswer)
            @Html.TextAreaFor(m => m.GivenAnswer)
        }
    </div>
}

Вот список ключей, которые публикуются:

    [0] "Id"    string
    [1] "Questions[1].Id"   string
    [2] "Questions[1].GivenAnswer"  string
    [3] "Questions[1].SelectedAnswer"   string
    [4] "Questions[2].Id"   string
    [5] "Questions[2].GivenAnswer"  string
    [6] "Questions[2].SelectedAnswer"   string
    [7] "Questions[3].Id"   string
    [8] "Questions[3].GivenAnswer"  string
    [9] "Questions[3].SelectedAnswer"   string
    [10]    "Questions[5].Id"   string
    [11]    "Questions[5].GivenAnswer"  string
    [12]    "Questions[5].SelectedAnswer"   string
    [13]    "Questions[6].Id"   string
    [14]    "Questions[6].GivenAnswer"  string
    [15]    "Questions[6].SelectedAnswer"   string
    [16]    "Questions[7].Id"   string
    [17]    "Questions[7].GivenAnswer"  string
    [18]    "Questions[7].SelectedAnswer"   string
    [19]    "Questions[9].Id"   string
    [20]    "Questions[9].SelectedAnswer"   string
    [21]    "Questions[9].GivenAnswer"  string
    [22]    "Questions[10].Id"  string
    [23]    "Questions[10].SelectedAnswer"  string
    [24]    "Questions[10].GivenAnswer" string

ОБНОВИТЬ:

Просто небольшое пояснение: объект Question может представлять заголовок (без полей) или ввода (либо переключатели, флажки, либо текстовые поля). Насколько я могу судить, нужные мне значения публикуются правильно. Я попытаюсь схватить их из отладчика и отправить здесь.

ОБНОВИТЬ:

Ниже приведена строка запроса: Request.Form.ToString (), с расширением и форматированием URL для упрощения чтения. Как вы можете видеть, значения публикуются, но по некоторым причинам не привязаны к оценке. Может ли это быть из-за значения xx в Вопросах [xx], потому что это не значение индекса, а фактическое значение Id?

Id=1&
Questions[1].Id=2&
Questions[1].GivenAnswer=-1&
Questions[1].SelectedAnswer=2&
Questions[2].Id=3&
Questions[2].GivenAnswer=-1&
Questions[2].SelectedAnswer=5&
Questions[3].Id=5&
Questions[3].GivenAnswer=-1&
Questions[3].SelectedAnswer=8&
Questions[5].Id=7&
Questions[5].GivenAnswer=-1&
Questions[5].SelectedAnswer=12&
Questions[6].Id=8&
Questions[6].GivenAnswer=-1&
Questions[6].SelectedAnswer=15&
Questions[7].Id=9&
Questions[7].GivenAnswer=-1&
Questions[7].SelectedAnswer=18&
Questions[9].Id=11&
Questions[9].SelectedAnswer=-1&
Questions[9].GivenAnswer=sdfg sdfg dsfg&
Questions[10].Id=12&
Questions[10].SelectedAnswer=-1&
Questions[10].GivenAnswer=sdfg dfsg sdfg

ПОСЛЕДНЕЕ ОБНОВЛЕНИЕ:

Проблема заключалась в том, что я не отправлял ничего на сервер для Вопросов, которые являются заголовками, поэтому индекс «Вопросы» на самом деле был неполным. Добавление скрытого поля идентификатора с каждым заголовком устраняет проблему.

Принятый ответ

Я создал базовый проект, в котором использовались приведенные вами образцы кода, а также некоторые основные фиктивные данные и сборник вопросов.

Я предполагаю, что в данных для конкретного опроса есть что-то, что вы делаете, что вызывает проблему.

Посмотрев на код, я вижу две возможные проблемы:

  • Когда Question.IsHeader истинно, я не думаю, что что-то будет отправлено обратно в форму для этого вопроса. Я бы предположил, что модельное связующее ничего не подбирает для этого вопроса. Который из ваших данных формы выглядел бы так: у него отсутствуют индексы для 0, 4 и 8. На самом деле я не знаю, приведет ли это к повреждению модели, но это может сделать. Вы можете попробовать поставить HiddenFor для идентификатора вопроса в разделе шаблона редактора вопросов, где IsHeading истинно.
  • Код @Html.CheckBox вы используете форматы входных значений с использованием идентификатора вопроса, а не индекса вопроса в списке. Я бы предположил, что это тоже сломает привязку.

Надеемся, что если вы сможете исправить эти проблемы, привязка будет работать. Я предлагаю попробовать его в опросе без каких-либо вопросов с заголовком и без вопросов с помощью галочки или радиокнопки и посмотреть, работает ли привязка.




Лицензировано согласно: CC-BY-SA with attribution
Не связан с Stack Overflow
Является ли этот КБ законным? Да, узнайте, почему
Лицензировано согласно: CC-BY-SA with attribution
Не связан с Stack Overflow
Является ли этот КБ законным? Да, узнайте, почему