传递给控制器​​时,foreach 循环中内置的模型为空

Posted

技术标签:

【中文标题】传递给控制器​​时,foreach 循环中内置的模型为空【英文标题】:Model built in foreach loop is null when passed to controller 【发布时间】:2021-09-12 18:16:47 【问题描述】:

当模型从视图传递到控制器时,我在捕获模型时遇到问题。 基本上,每个 Question 都有一组 QuestionResponse(可以将其视为下拉列表中某个问题的提供响应列表)。 ClinicalSummaryAnswer 是为给定用户捕获每个问题的一个响应的结构。因此,用户最终会得到一个 ClinicalSummaryAnswer 的集合,其中每个元素都是响应的答案。

当我提交下面的表单时,模型 ClinicalSummaryView (ClinicalSummaryAnswer, Questions, QuestionResponse) 中的所有元素在控制器端都是空的。任何想法为什么会发生这种情况?我怀疑这可能是由于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.
    

【问题讨论】:

您的控制器如何将model 传递给view 你的意思是反过来? [HttpPost] [ValidateAntiForgeryToken] public async Task Create(ClinicalSummaryView viewModel, string[] AnswerId, string[] OtherText) //STUFF 有趣的是,OtherText 填充了输入框中的字符串列表,并且 AnswerId 填充有从下拉列表中选择的答案 id 的列表。我只是在测试它,因为当我在浏览器中检查元素时,所有输入框/选择都具有相同的“名称”(OtherText 和 AnswerId) 你的问题包含太多的噪音信息,你能把它们去掉吗? 我在视图中编辑了代码以仅包含必要的信息。那个更好吗?还是介绍太多了?我只是想解释模型的结构,看看我是否可以在@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>

【讨论】:

我不需要传递 questionText(在标签中)。我需要下拉列表中选定选项的值以及要传递的不同文本框中的值(Model.ClinicalSummaryAnswer,它是一个 ICollection)。我认为你的修改没有解决这个问题。如果我错了,请纠正我。 嗨@HK1232,看来你不想string[] AnswerId, string[] OtherText接收数据,你想接收ClinicalSummaryView viewModel的下拉列表和文本框数据。请检查我的更新答案。 嗨 Rena,感谢您的帮助。抱歉,我忘了检查线程,我解决了这个问题,我最初已经将 ClinicalSummaryView viewModel 作为参数,但它都是空的。我设法对其进行了调整(我的 atm 面前没有代码)。无论如何感谢您的帮助! 您好@HK1232,如果我的回答能帮助您解决问题,您能接受吗?请参考:How to accept as answer。谢谢。

以上是关于传递给控制器​​时,foreach 循环中内置的模型为空的主要内容,如果未能解决你的问题,请参考以下文章

在laravel foreach循环中传递多个变量[重复]

Blade:Foreach 循环内未定义的变量

在foreach循环中声明时的SQLDataReader对象

如何在控制器传递变量(laravel)中使用刀片进行 foreach

Array数组循环全解1

C#中foreach用法