ASP.NET MVC3和实体框架模型中的Dropdownlist帖子

时间:2012-06-24 15:14:44

标签: asp.net-mvc asp.net-mvc-3 razor

我有3张桌子:

RateProfile

  • RateProfileID
  • 摘要名称

  • RateID
  • RateProfileID
  • PanelID
  • 要更新的其他内容

面板

  • PanelID
  • PanelName

我有每个模型。我有一个使用RateProfile模型的编辑页面。我显示RateProfile的信息以及与之关联的所有费率。这工作正常,我可以更新它。但是,我还添加了一个下拉列表,以便我可以按PanelID过滤费率。我需要它回发更改,以便它可以显示过滤后的费率。

我正在使用

@Html.DropDownList("PanelID", (SelectList)ViewData["PanelDropDown"], new { onchange = "$('#RateForm').submit()" })

我的下拉列表。每当它回发到我的HttpPost Edit方法时,它似乎都缺少关于Rates导航属性的所有信息。这很奇怪,因为我认为它会完全按照我在表单中的输入/提交按钮执行(实际上将整个模型传递回我的HttpPost Edit操作并完成我想要它做的事情)。 panelID正确传递给我的HttpPost Edit方法并传递到下一个视图,但是当我尝试查询Model.Rates导航属性为null时(仅当帖子来自下拉列表时。当帖子来自时,一切正常)我的提交输入)。

获取编辑:

    public ActionResult Edit(int id, int panelID = 1)
    {

        RateProfile rateprofile = db.RateProfiles.Single(r => r.RateProfileID == id);
        var panels = db.Panels;

        ViewData["PanelDropDown"] = new SelectList(panels, "PanelID", "PanelName", panelID);
        ViewBag.PanelID = panelID;

        return View(rateprofile);
    }

HttpPost编辑:

    [HttpPost]
    public ActionResult Edit(RateProfile rateprofile, int panelID)
    {
        var panels = db.Panels;
        ViewData["PanelDropDown"] = new SelectList(panels, "PanelID", "PanelName", panelID);
        ViewBag.PanelID = panelID;
        if (ModelState.IsValid)
        {
            db.Entry(rateprofile).State = EntityState.Modified;

            foreach (Rate dimerate in rateprofile.Rates)
            {
                db.Entry(dimerate).State = EntityState.Modified;
            }
            db.SaveChanges();
            return View(rateprofile);
        }
        return View(rateprofile);
    }

查看:

@model  PDR.Models.RateProfile
@using (Html.BeginForm(null,null,FormMethod.Post, new {id="RateForm"}))
{
    <div>
        @Html.Label("Panel")
        @Html.DropDownList("PanelID", (SelectList)ViewData["PanelDropDown"], new { onchange = "$('#RateForm').submit()" })
    </div>
    @{var rates= Model.Rates.Where(a => a.PanelID == ViewBag.PanelID).OrderBy(a => a.minCount).ToList();}
    @for (int i = 0; i < rates.Count; i++)
        {
            <tr>
                <td>
                    @Html.HiddenFor(modelItem => rates[i].RateProfileID)
                    @Html.HiddenFor(modelItem => rates[i].RateID)
                    @Html.HiddenFor(modelItem => rates[i].PanelID)

                    @Html.EditorFor(modelItem => rates[i].minCount)
                    @Html.ValidationMessageFor(model => rates[i].minCount)
                </td>
                <td>
                    @Html.EditorFor(modelItem => rates[i].maxCount)
                    @Html.ValidationMessageFor(model => rates[i].maxCount)
                </td>
                <td>
                    @Html.EditorFor(modelItem => rates[i].Amount)
                    @Html.ValidationMessageFor(model => rates[i].Amount)
                </td>
            </tr>
        }
     <input type="submit" value="Save" />
}

总结一下我的问题,我的视图中的以下查询仅在帖子来自提交按钮时有效,而不是来自我的下拉列表。

@{var rates= Model.Rates.Where(a => a.PanelID == ViewBag.PanelID).OrderBy(a => a.minCount).ToList();}

3 个答案:

答案 0 :(得分:0)

它在渲染页面中的外观如何?您可能有两个使用相同名称/ ID呈现的元素:

 @Html.DropDownList("PanelID", (SelectList)ViewData["PanelDropDown"], new { onchange = "$('#RateForm').submit()"

@Html.HiddenFor(modelItem => rates[i].PanelID)

答案 1 :(得分:0)

我建议您使用Firefox / Firebug来检查它的实际请求。我无法想象如果通过提交与按钮触发,表单将以不同方式发布,但我认为这是可能的。

更重要的是,我会对你的设计做一些评论。

  1. 我会使用ViewBag属性进行选择,而不是基于对ViewData的基于密钥的访问。这在您的控制器和视图中都更具可读性。

  2. 考虑使用单独的操作填充由下拉列表过滤的信息。在您的视图中基于PanelID渲染该操作,并通过AJAX调用该操作以获取新的HTML而不是完整的表单。

  3. 避免在标记中应用处理程序。而是将可选的“脚本”部分添加到母版页,并在需要时向页面添加脚本,以通过该部分应用您的行为。这允许您通过主控件来控制特定于视图的脚本放置在文档中,并将您的行为与文档结构分开,这是可读性的最佳实践。

答案 2 :(得分:0)

我发现了问题。看起来因为我只是循环浏览导航属性的一个子集(由panelID过滤的速率),从视图返回的模型只有可用的导航属性子集。保存更改后,我刚刚重新定义了我的模型(再次从数据库中调用了记录),现在看起来很好。

IE中。在我的导航属性中应该有140条记录,按panelID == 1将其缩小到28条记录。由于某种原因,实体框架决定它不想维持与其他112条记录的关系,所以当我将下拉列表更改为按panelID == 2过滤时,唯一可用的记录都有panelID == 1并返回null