c# - MVC ViewModel 包含一个字典,用于将空值返回给 Controller 的字段

标签 c# asp.net-mvc dictionary

尝试为客户制作问卷调查页面。这是一个相当大的问题列表,所以我将它分成了部分和小节,以便用户更容易浏览。问题似乎是为了构建页面,我遍历了部分/小节/问题,而不是答案。答案存储在字典中,键是相关问题的 ID 号。

传递给 View 的 ViewModel 是 UserQuestionnaireViewModel , QuestionnaireViewModel有一个列表 Sections ,每个都有一个列表 SubSections ,每个都有一个列表 Questions . Answers字典获取链接到相关用户的所有答案,由 Question 索引他们链接到。缺少的答案会在此处填充,如果缺少答案, View 会中断。

型号

public class UserQuestionnaireViewModel {
    ClientPortalDbContext db = new ClientPortalDbContext();

    public QuestionnaireViewModel Questionnaire { get; set; }
    public Dictionary<Int32, QuestionnaireAnswer> Answers { get; set; }

    public UserQuestionnaireViewModel() { }
    public UserQuestionnaireViewModel(Int32 userID) {
        Questionnaire = new QuestionnaireViewModel();
        Answers = new Dictionary<Int32, QuestionnaireAnswer>();

        List<QuestionnaireAnswer> answerList = db.QuestionnaireAnswers.Where(a => a.UserID == userID).ToList();
        foreach (QuestionnaireAnswer answer in answerList) {
            Answers.Add(answer.QuestionID, answer);
        }
        foreach (QuestionnaireViewModel_Section section in Questionnaire.Sections) {
            foreach (QuestionnaireViewModel_SubSection subsection in section.SubSections) {
                foreach (QuestionnaireQuestion question in subsection.Questions) {
                    if (!Answers.ContainsKey(question.ID)) {
                        Answers.Add(question.ID, new QuestionnaireAnswer() {
                            QuestionID = question.ID,
                            UserID = userID,
                            AnswerBool = false,
                            AnswerText = ""
                        });
}}}}}}

SectionSubSection类包含一个名称字符串,以及它们下面的任何内容的列表(分别为 SubSectionQuestion)。 Question有一个 id int,用于问题文本的字符串,以及用于显示哪些字段的 bool。

查看

<div class="content-wrapper">
    <% using (Html.BeginForm("Save", "Questionnaire", new { input = Model.Answers })) { %>
    <%: Html.AntiForgeryToken()%>
    <%: Html.ValidationSummary(true)%>
    <fieldset>
        <ul class="questionnaire-tabs">
            <% Int32 tabIndex = 0; %>
            <% foreach (clientportal.Models.QuestionnaireViewModel_Section section in Model.Questionnaire.Sections) { %>
            <% tabIndex++; %>
            <li id="<%: "tab-button-" + tabIndex.ToString()%>" data-tab="<%: "tab-" + tabIndex.ToString()%>">
                <%: section.Name%>
            </li>
            <% } %>
        </ul>
        <div class="clear"></div>
        <% tabIndex = 0; %>
        <% foreach (clientportal.Models.QuestionnaireViewModel_Section section in Model.Questionnaire.Sections) { %>
        <% tabIndex++; %>
        <div class="questionnaire-tab-content" id="<%: "tab-" + tabIndex.ToString()%>">
            <p><%: section.Heading%></p>
            <% foreach (clientportal.Models.QuestionnaireViewModel_SubSection subsection in section.SubSections) { %>
            <h4><%: subsection.Name%></h4>
            <p><%: subsection.Heading%></p>
            <div>
                <table class="questionnaire-table">
                    <% foreach (clientportal.Models.QuestionnaireQuestion question in subsection.Questions) { %>
                    <% clientportal.Models.QuestionnaireAnswer answer = Model.Answers[question.ID]; %>
                    <% if (question.Enabled) { %>
                    <tr>
                        <td class="label-col">
                            <%: Html.Label(question.Text) %>
                            <%: Html.Hidden("Model.Answers.Index", question.ID) %>
                            <%: Html.Hidden("Model.Answers[" + question.ID + "].ID", answer.ID) %>
                            <%: Html.Hidden("Model.Answers[" + question.ID + "].QuestionID", answer.QuestionID) %>
                            <%: Html.Hidden("Model.Answers[" + question.ID + "].UserID", answer.UserID) %>
                        </td>
                        <td class="bool-col">
                            <% if (question.ShowCheckBox) { %>
                            <%: Html.CheckBox("Model.Answers[" + question.ID + "].AnswerBool", answer.AnswerBool) %>
                            <% } else { %>
                            <%: Html.Hidden("Model.Answers[" + question.ID + "].AnswerBool", answer.AnswerBool) %>
                            <% } %>
                        </td>
                        <td class="text-col">
                            <% if (question.ShowTextBox) { %>
                            <%: Html.TextBox("Model.Answers[" + question.ID + "].AnswerText", answer.AnswerText) %>
                            <% } else { %>
                            <%: Html.Hidden("Model.Answers[" + question.ID + "].AnswerText", answer.AnswerText) %>
                            <% } %>
                        </td>
                    </tr>
                    <% } %>
                    <% } %>
                </table>
            </div>
            <% } %>
        </div>
        <% } %>
    </fieldset>
    <h4>Please ensure you have checked all sections of the Questionnaire before saving.</h4>
    <input type="submit" value="Save Answers" />
    <% } %>
</div>

在提交表单时,它会很好地传递给 Controller ​​( Controller 为此操作采用 Dictionary<Int32, QuestionnaireAnswer>),除了发送的模型有 0 行并且失败 ModelState.IsValid

环顾四周让我想到这是 MVC 和字典的一般问题,或者只是无法绑定(bind)字典。数据库中的任何答案都正确显示,只是无法将页面内容返回到阻止我继续前进的 Controller 。

最佳答案

不要使用foreach 循环。使用 for 循环。 还有一件事总是使用 Html.HiddenFor(model.xxxx) 和其他控件。

如果您使用 for 循环和 HiddenFor 这将自动为控件创建适当的名称

如果可以将数据库操作从 MVC 模型中分离出来,那是最好的。

关于c# - MVC ViewModel 包含一个字典,用于将空值返回给 Controller 的字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34149906/

相关文章:

c# - 如何通过 .Net 使用 Azure Databricks 进行身份验证?

c# - Entity Framework ,我可以将一个类映射到一个键/值表吗?

mysql - 空间/全文/哈希索引和显式索引顺序 EF 的使用不正确

python - 在 Pandas 列中拆分字典/列表并转换为新数据框

python - 从字典列表中删除重复项(具有唯一值)

java - 检查 map 中的所有值是否为空

c# - MVC 4 在表单外显示验证摘要?

c# - 从周期中选择一天 - 重复

c# - 服务器发送的事件、AJAX 轮询、WebSocket 通知

javascript - 如何将 View (cshtml) 加载到 iframe 中?