Модель, встроенная в цикл foreach, равна нулю при передаче контроллеру

#c# #asp.net-core-mvc #razor-pages

Вопрос:

У меня возникла проблема с захватом модели, когда она передается из представления в контроллер. В принципе, у каждого вопроса есть набор ответов на вопросы (думайте об этом как о списке предлагаемых ответов на определенный вопрос в раскрывающемся списке). ClinicalSummaryAnswer-это структура, содержащая один ответ на вопрос для данного пользователя. Таким образом, пользователь получает коллекцию ClinicalSummaryAnswer, где каждый элемент является ответом на ответ.

Когда я отправляю форму ниже, все элементы в модели ClinicalSummaryView (ClinicalSummaryAnswer, Вопросы, ответы на вопросы) со стороны контроллера являются нулевыми. Есть какие-нибудь идеи, почему это может произойти? Я подозреваю, что это может быть связано с foreach? Я не уверен. Пожалуйста, помогите!!

Мой Взгляд

  @model TissueBankApp.Models.View.ClinicalSummaryView
    
    
    
    <div>
        @using (Html.BeginForm("Create", "ClinicalSummary", FormMethod.Post, new { @class = "form-horizontal" }))
        {

<div class="form-group">
            <input type="hidden" asp-for="Person.PersonId" value="Person.PersonId" />
            <input type="submit" value="Create" class="btn btn-outline-primary btn-sm" />
            <a asp-action="Details" asp-controller="Person" asp-route-id="Person.PersonId" class="btn btn-outline-primary btn-sm">Cancel</a>
        </div>
           
            <div class="col-md-12">
                <div class="form-row">
                    <b> @Html.DisplayFor(model => model.ClinicalSummary.Description)  </b>
                </div>
    
                @foreach (var question in Model.Questions) //For every question, generate question, and generate responses
                {                        
            <div class="form-row">
                
                <label class="control-label col-md-4">@question.QuestionText</label>
    
                @if (question.QuestionResponse.Count() != 0) //If count ViewData[QID] != 0, generate select dropdown, otherwise, input.
    
                {            
    
                    @Html.DropDownListFor(n => n.ClinicalSummaryAnswer.FirstOrDefault(m => m.QuestionId == question.QuestionId).AnswerId, new SelectList(question.QuestionResponse, "ResponseId", "ResponseText"), "", new { @class = "form-control col-md-4" })             
                }
                else
                {       
                    @Html.TextBoxFor(n => n.ClinicalSummaryAnswer.FirstOrDefault(m => m.QuestionId == question.QuestionId).OtherText, new { placeholder = "", @class = "form-control col-md-4", @type = "date" });
    
                }
            </div>
                }
    
            </div>
            
        }
        </div>
 

Контроллер

       [HttpPost]
                [ValidateAntiForgeryToken]
                public async Task<IActionResult> Create(ClinicalSummaryView viewModel, string[] AnswerId, string[] OtherText)
                { 
    
    //STUFF
//Ignore the OtherText, and AnswerId. I was testing to see if these are passed from view to controller and they are indeed. I just have no way of identifying which answer belongs to which question.
    }
 

Комментарии:

1. как ваш контроллер переходит model к view ?

2. Ты имеешь в виду наоборот? [HttpPost] [ValidateAntiForgeryToken] публичная асинхронная задача<IActionResult> Создать(ClinicalSummaryView ViewModel, строка[] AnswerId, строка[] Другой текст) { //МАТЕРИАЛ } Интересная вещь заключается в том, что другой текст заполняется списком строк из полей ввода, а идентификатор ответа заполняется списком идентификаторов ответов, выбранных из раскрывающегося списка. Я просто проверял это, потому что, когда я проверял элемент в браузере, все поля ввода/выбора имели одинаковое «имя» (другой текст и идентификатор ответа)

3. ваш вопрос содержит слишком много информации о шуме, можете ли вы удалить их, чтобы они были минимальными?

4. Я отредактировал код в представлении, чтобы он содержал только необходимую информацию. Так лучше? Или вступление было слишком длинным? Я просто пытался объяснить структуру модели, чтобы понять, могу ли я неправильно привязывать элементы @Html.

Ответ №1:

Во-первых,вам нужно знать, что для каждого свойства сложного типа привязка модели просматривает источники для шаблона имени prefix.property_name . Если ничего не найдено, он ищет просто property_name без префикса.Ваш сервер хочет получить ClinicalSummaryView.ClinicalSummaryAnswer модель списка. так что то, что вы проходите, должно быть ClinicalSummaryAnswer[index].PropertyName .

Измените, как показано ниже:

 @using (Html.BeginForm("Create", "Home", FormMethod.Post, new { @class = "form-horizontal" }))
{
    <div class="form-group">
        <input type="hidden" asp-for="Person.PersonId" value="@Model.Person.PersonId"/>
        <input type="submit" value="Create" class="btn btn-outline-primary btn-sm" />
        <a asp-action="Details" asp-controller="Person" asp-route-id="@Model.Person.PersonId" class="btn btn-outline-primary btn-sm">Cancel</a>
    </div>

    <div class="col-md-12">
        <div class="form-row">
            <b> @Html.DisplayFor(model => model.ClinicalSummary.Description)  </b>
        </div>
        @{ var i = 0;}      //add here...
        @foreach (var question in Model.Questions) 
        {               
            <div class="form-row">
                <label class="control-label col-md-4">@question.QuestionText</label>
                @if (question.QuestionResponse.Count() != 0) 

                {
                    //change here....               
                    @Html.DropDownList("ClinicalSummaryAnswer[" i  "].AnswerId", new SelectList(question.QuestionResponse, "ResponseId", "ResponseText"), new { @class = "form-control col-md-4" })
                }
                else
                {
                    //change here....  
                    @Html.TextBox("ClinicalSummaryAnswer[" i "].OtherText",null, new { placeholder = "", @class = "form-control col-md-4", @type = "date" });

                }
            </div>
            i  ;  //add here...
        }
    </div>                    
 }
 

Кроме того, необходимо изменить следующий код:

                                          //change the value     
<input type="hidden" asp-for="Person.PersonId" value="@Model.Person.PersonId"/>   
<input type="submit" value="Create" class="btn btn-outline-primary btn-sm" />
                           //change asp-route-id here..
<a asp-action="Details" asp-controller="Person" asp-route-id="@Model.Person.PersonId" class="btn btn-outline-primary btn-sm">Cancel</a>
 

Комментарии:

1. Мне не нужен текст вопроса (который находится в метке) для передачи. Мне нужны значения выбранных параметров в раскрывающемся списке и значения в разных текстовых полях для передачи (Модель. Клинический ответ на вопрос , который является коллекцией). Я думаю, что ваша модификация не решает эту проблему. Поправьте меня, если я ошибаюсь.

2. Привет @HK1232, похоже, вы не хотите string[] AnswerId, string[] OtherText получать данные, вы хотите получать данные раскрывающегося списка и текстового ClinicalSummaryView viewModel поля . Пожалуйста, проверьте мой обновленный ответ.

3. Привет, Рена, спасибо за помощь. Извините, я забыл проверить поток, я решил проблему, у меня уже был ClinicalSummaryView ViewModel в качестве аргумента изначально, но все это было равно нулю. Мне удалось настроить его (у меня нет кода перед банкоматом). Спасибо за помощь, несмотря ни на что!

4. Привет @HK1232, Если мой ответ поможет вам решить вашу проблему,не могли бы вы принять его в качестве ответа? См.: Как принять в качестве ответа . Спасибо.