MVC 6 模型绑定复杂字典
MVC 6 Modelbinding complex dictionaries
我正在尝试 post 一个包含复杂类型字典的表单。
字典看起来像这样:
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; }
}
然后是备选问题:
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>
我post想要的 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; }
}
当我 post 我的表单名为 Questions 的字典为空。
是否可以使用默认模型绑定器实现此目的,或者我是否需要构建自定义模型绑定器。
如果是这样,该解决方案会是什么样子?
提前致谢
既然 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">
我正在尝试 post 一个包含复杂类型字典的表单。 字典看起来像这样:
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; }
}
然后是备选问题:
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>
我post想要的 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; }
}
当我 post 我的表单名为 Questions 的字典为空。
是否可以使用默认模型绑定器实现此目的,或者我是否需要构建自定义模型绑定器。
如果是这样,该解决方案会是什么样子?
提前致谢
既然 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">