【问题标题】:MVC 6 Modelbinding complex dictionariesMVC 6 模型绑定复杂字典
【发布时间】:2016-05-10 14:45:03
【问题描述】:

我正在尝试发布一个包含复杂类型字典的表单。 字典是这样的:

 public Dictionary<Question, List<QuestionAlternative>> Questions { get; set; }

一个问题可以有多种选择。

问题本身是这样的:

public class Question
{
    public Guid Id { get; set; }

    public string Text { get; set; }

    public Guid TestId { get; set; }

    public Test Test { get; set; }

    public ICollection<QuestionAlternative> QuestionAlternatives { get; set; }

    public Guid? QuestionTypeId { get; set; }
    public QuestionType QuestionType { get; set; }
}

然后是 QuestionAlternative:

public class QuestionAlternative
{
    public Guid Id { get; set; }

    public string Alternative { get; set; }

    public Guid QuestionId { get; set; }

    public Question Question { get; set; }
}

我的表单如下所示:

  <form asp-controller="Answer" asp-action="AnswerMe" method="post">
        @foreach (var questionPair in Model.Questions)
        {
            @Html.Hidden("Questions[" + questionIndex + "].Key.Id", questionPair.Key.Id)
            <br />
            foreach (var alternative in questionPair.Value)
            {
              <label for="@alternative.Id">@questionPair.Key.Text</label>
              <textarea id="@alternative.Id" name="@("Questions["+ questionIndex + "].Value["+ index +"]")"></textarea>

               index++;
             }
            }
            questionIndex++;
        }
        <input type="submit" class="button" value="Answer" />
    </form>

我发布到的 ActionResult 如下所示:

  [AllowAnonymous]
  [HttpPost("AnswerMe")]
  public IActionResult AnswerMe([FromBody]AnswerViewModel model)
  {
    foreach(var item in model.Questions) //throws exception 
    ....
  }

和我的视图模型:

public class AnswerViewModel
{
    public ODELDAL.Entities.Test Test { get; set; }

    public Dictionary<Question, List<QuestionAlternative>> Questions { get; set; }

    public Guid SelectedRole { get; set; }
}

当我发布表单时,名为 Questions 的字典为空。

是否可以使用默认的模型绑定器来实现这一点,或者我是否需要构建一个自定义模型绑定器。

如果是这样,该解决方案会是什么样子?

提前致谢

【问题讨论】:

  • 您的 HttpPost 操作看起来如何?
  • @Shyju 编辑了我的问题
  • 所以你有一个包含QuestionAlternatives 集合的字典,每个QuestionAlternative 都有一个Question,它本身有一个QuestionAlternatives 集合。这种嵌套(以及在某种程度上,绑定)可以永远持续下去的意图是什么?
  • @WillRay 这部分只是实体在 EF 中的关联和绑定方式(我首先使用代码),您现在可以忽略它。
  • 在表单发布时检查您的请求(Fiddler 或浏览器开发工具)。虽然表单将发布键值对,但您的场景更为复杂。建议:既然Question 已经拥有ListQuestionAlternative,为什么不在您的视图模型中使用简单的收集(列表、数组...等)。

标签: c# asp.net-mvc dictionary model-binding


【解决方案1】:

既然Question 已经拥有QuestionAlternative 的集合,为什么不在您的视图模型中使用简单的收集(列表、数组...等)...

public class AnswerViewModel {
    public ODELDAL.Entities.Test Test { get; set; }    
    public Question[] Questions { get; set; }    
    public Guid SelectedRole { get; set; }
}

...以及更新的视图...

<form asp-controller="Answer" asp-action="AnswerMe" method="post">
    @for(int i = 0; i < Model.Questions.Length; i++) {
        @Html.HiddenFor(m => m.Questions[i].Id)
        <br />
        for(int j = 0; j < m.Questions[i].QuestionAlternatives.Count; j++) {
            @Html.LabelFor(m => m.Questions[i].QuestionAlternatives[j].Alternative,m.Questions[i].QuestionAlternatives[j].Text)
            @Html.TextAreaFor(m => m.Questions[i].QuestionAlternatives[j].Alternative)
        }
    }

    <input type="submit" class="button" value="Answer" />
</form>

模型绑定器可以更轻松地使用这种方法重建模型,因为它能够使用表达式为 html 标签生成 id。

例如,隐藏的输入在生成时会如下所示

<input data-val="true" id="Questions_0__Id" name="Questions[0].Id" value="{Some-Guid-Value_Here}" type="hidden">

【讨论】:

    猜你喜欢
    • 2016-03-07
    • 2023-03-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-10
    • 1970-01-01
    相关资源
    最近更新 更多