至于for
对嵌套转发器行为使用循环,我认为这是在 MVC 中执行此操作的最佳方法。但我建议您使用专用的 ViewModel。
视图模型:
public class RadioQuestionListViewModel
{
public IEnumerable<RadioQuestionViewModel> Questions {get;set;}
}
public class RadioQuestionViewModel
{
public int QuestionNumber {get;set;}
public string InputName {get;set;}
public string QuestionPart1 {get;set;}
public string QuestionPart2 {get;set;}
public IEnumerable<RadioAnswerViewModel> PossibleAnswers {get;set;}
}
public class RadioAnswerViewModel
{
public int AnswerId {get;set;}
public string Text {get;set;}
}
控制器:
public ActionResult Details(int id)
{
var model = GetRadioQuestionListModelById(id);
return View(model);
}
看法:
<% foreach (var question in Model) { %>
<h3>Question <%: question.QuestionNumber %></h3>
<p><%: question.QuestionPart1 %></p>
<p><%: question.QuestionPart2 %></p>
<% foreach (var answer in question.PossibleAnswers) { %>
<%: Html.RadioButton(question.InputName, answer.AnswerId) %>
<%: answer.Text %>
<% } %>
<% } %>
这种方法有几个优点:
- 它可以防止您的视图代码依赖于您的数据访问类。视图代码应该只负责决定如何将所需的视图模型呈现为 HTML。
- 它将与显示无关的逻辑排除在您的视图代码之外。如果您稍后决定分页您的问题,并且现在显示问题 11-20 而不是 1-whatever,您可以使用完全相同的视图,因为控制器负责确定要显示的问题编号。
- 它可以更轻松地避免在循环中
Array.IndexOf(Model.ToArray(), question)
进行数据库往返for
,如果您在页面上有多个问题,这可能会变得非常昂贵。
当然,您的单选按钮需要有一个与之关联的输入名称和值,否则在提交表单时您将无法检索此信息。通过让控制器决定如何生成输入名称,您可以更清楚地了解Details
方法与您的方法的对应SaveAnswers
方式。
这是一个可能的实现GetRadioQuestionListModelById
:
public RadioQuestionListViewModel GetRadioQuestionListModelById(int id)
{
// Make sure my context gets disposed as soon as I'm done with it.
using(var context = new Models.Entities())
{
// Pull all the questions and answers out in a single round-trip
var questions = context.Questions
.Where(r => r.PROMId == id)
.Select(r => new RadioQuestionViewModel
{
QuestionPart1 = r.q.QuestionPart1,
QuestionPart2 = r.q.QuestionPart2,
PossibleAnswers = r.a.Select(
a => new RadioAnswerViewModel
{
AnswerId = a.AnswerId,
Text = a.Text
})
})
.ToList();
}
// Populate question number and name
for(int i = 0; i < questions.Count; i++)
{
var q = questions[i];
q.QuestionNumber = i;
q.InputName = "Question_" + i;
}
return new RadioQuestionListViewModel{Questions = questions};
}