【问题标题】:Mvc3 IEnumerable<QuestionModel> have a List<QuestionOptionModel> property. When I post, I get null listMvc3 IEnumerable<QuestionModel> 有一个 List<QuestionOptionModel> 属性。当我发布时,我得到空列表
【发布时间】:2012-08-30 09:06:47
【问题描述】:

我正在制作一份调查申请。调查有问题,问题有 QuestionOption。有一个例子here. 我正在尝试在带有列表(List)的大型表单中使用此技术,但是当我回发时,应该包含项目和活动列表的 Viewmodel.Order 返回时列表为空。

我的 QuestionModel.cs 就是这样。

 public int Id { get; set; }       
 public string QuestionText { get; set; }     
 public System.Nullable<bool> OptionType1 { get; set; }
 public System.Nullable<bool> OptionType2 { get; set; }
 public List<QuestionOptionModel> OptionList = new List<QuestionOptionModel>();

当我回发“IEnumerable questions”时,List OptionList 为空。我怎样才能做到这一点?

 public ActionResult CallSurvey()
    {
        IEnumerable<QuestionModel> questionModelList = (IEnumerable<QuestionModel>)SessionHelper.GetSessionObject(SessionKeys.SurveyKey);
       questionModelList = questionSrv.GetQuestionModel();
        return View(questionModelList);

    }

questionModelList 包括我所有的调查问题和问题选项。当我发布它时,回发只会带有 null optionList。

 [HttpPost]
    public ActionResult CallSurvey(IEnumerable<QuestionModel> questions)
    { ..... }

CallSurvey.cshtml

   <body>
    @using ((Html.BeginForm()))
    {
        @ViewBag.Test
        <section class="slides layout-regular template-kendo">
        @foreach (var item in Model)
        {<article>

                @Html.Partial("QuestionEditor", item)
               </article>
        }
   <div class="slide-area" id="prev-slide-area"></div>
        <div class="slide-area" id="next-slide-area"></div>
      </section> 
    }
</body>

QuestionEditor.cshtml

    @model LSMM.Business.Model.Survey.QuestionModel
@using LSMM.Web.Helpers
<div>
    @using (Html.BeginCollectionItem("Questions"))
    {

        <table id="table1">
            <tr>
                <td>
                    <div id="@Model.Id" class="hint">
                        @Html.HiddenFor(m => m.Id)
                        @Html.HiddenFor(m => m.QuestionText)
                        @Html.HiddenFor(m => m.OptionType1)
                        @Html.HiddenFor(m => m.OptionType2)



                        @for (int i = 0; i < Model.OptionList.Count; ++i)
                        {
                        @Html.LabelFor(m => m.OptionList[i].Id)
                        @Html.LabelFor(m => m.OptionList[i].QuestionId)
                        @Html.LabelFor(m => m.OptionList[i].Checked)
                        @Html.LabelFor(m => m.OptionList[i].Description)
                        @Html.LabelFor(m => m.OptionList[i])
                   }
                        <span id="sorular">@Model.Id. @Model.QuestionText</span>
                        <br />
                        <br />
                    </div>
                </td>
            </tr>
            <tr>
                <td>
                    <div class="hint2">
                        @Html.Partial("QuestionOptionEditor", Model)
                    </div>
                </td>
                <td>
                    <div id="@Model.Id-Img">
                        <h2 style="top: 200px; right: 0;">
                            <img src="../../Content/css/img/@Model.Id-Img.png"></h2>
                    </div>
                </td>
            </tr>
        </table>  

和 QuestionOptionEditor.cshtml

   @model LSMM.Business.Model.Survey.QuestionModel

 @using LSMM.Web.Helpers               



@foreach (var option in @Model.OptionList)
{


    <p>
        @if (@Model.OptionType1 == false)
        { 
            @Html.Partial("QuestionOptionModel", option)

        }
        else
        { 
            @Html.Partial("../Shared/DisplayTemplates/QuestionOptionModel", option)

        }
    </p>

}

这里的 QuestionOptionModel 视图是这样的;

@model LSMM.Business.Model.Survey.QuestionOptionModel

      @(Html.RadioButtonFor(m => m.Id, true, new { Id = @Model.Id, Name = @Model.QuestionId })) @Html.Label("Evet")  
      <br /> 
      <br />
      @(Html.RadioButtonFor(m => m.Id, false ,new { Id=@Model.Id, Name = @Model.QuestionId})) @Html.Label("Hayır")

【问题讨论】:

    标签: asp.net-mvc-3 list post ienumerable


    【解决方案1】:

    根据默认 ModelBinder 使用的命名规则,单选按钮上的名称属性不“正确”。这就是为什么您没有看到您期望的值,ModelBinder 找不到它正在寻找的东西。

    这很容易解决,您最终应该使用更少的代码。 充分利用框架,让它为您工作:

    1. MVC 可以为您循环 IEnumerables。让它。如今,几乎没有理由在视图中编写 foreach 循环。
    2. 摆脱那些部分。请改用 MVC 的 Templates 功能。

    那么你的视图可以这么简单:

     <body>
            @using ((Html.BeginForm()))
            {
                @ViewBag.Test
                <section class="slides layout-regular template-kendo">
            <table id="table1">
                @* Table header goes here *@
                @Html.EditorFor(model => model.OptionList)
            </table>
           <div class="slide-area" id="prev-slide-area"></div>
                <div class="slide-area" id="next-slide-area"></div>
              </section> 
            }
    </body>
    

    当您使用 EditorTemplate 或 DisplayTemplate 时,MVC 将自动修复表单字段上的 name 属性。它不会用部分来做到这一点。

    另一个建议,如果你不介意的话。摆脱模型上的那些 nulla-bools 并编写不同的 QuestionOptionModel 类型。 DisplayTemplate/EditorTemplates 对类型系统很明智,MVC 会选择与其呈现的类型匹配的模板。

    所以你可以有另一个派生自 QuestionOptionModel 的类:

    public class ExtendedQuestionOptionModel : QuestionOptionModel
    {
        //Stuff goes here.
    }
    

    你可以有一个List&lt;QuestionOptionModel&gt; 挂在你的模型上,其中包含:

    • 问题选项模型
    • 扩展问题选项模型
    • 问题选项模型

    当你这样做时:

    @Html.EditorFor(model => model.QuestionOptions)
    

    MVC 将遍历选项列表并渲染 QuestionOptionModel 的 Editor Template,然后是 ExtendedQuestionOptionModel 的 Editor Template,然后是 QuestionOptionModel 的 Editor Template。

    你想玩的游戏是尽量减少视图中的 C# 代码,因为视图不能进行单元测试。未经单元测试的代码最终会回来并得到您。

    【讨论】:

      【解决方案2】:

      你的问题有点模棱两可。坦率地说,我希望这是您正在寻找的:
      IEnumerable 可以使用

      转换为列表
       List<foo>listFoo =iEnumerableEntityFoo.toList() 
      

      【讨论】:

      • 点击您的问题下方的编辑标签并将其添加到问题中。
      猜你喜欢
      • 2022-10-19
      • 2021-09-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-08-22
      • 1970-01-01
      • 1970-01-01
      • 2021-10-17
      相关资源
      最近更新 更多