在编辑页面上的DropDownListFor将空值传递给POSTBACK上的控制器



我有一个ASP mvc项目,在编辑页面中使用部分视图。它将适当的值加载到DropDownListFor中,但是在POST BACK中,这些项突然变为空。

视图使用视图模型来合并两个SQL表。作为该视图模型的一部分,BankListAgentId类型的List收集对象用于存储与特定客户端相关的所有代理Id。为了正确地POST和编辑集合对象中的项目,我遵循了Steve Sanderson关于ASP MVC中可变长度对象的博客文章。

这个过程对于代理Id非常有效,但是一旦用户点击"保存",状态代码就全部为空。"

下面是视图 的代码
@model Monet.ViewModel.BankListViewModel
@using (Html.BeginForm())
{
    <fieldset>
        <legend>Stat(s) Fixed</legend>
        <table id="fixedRows">
            <tr>
                <th>State Code</th>
                <th>Agent ID</th>
                <th></th>
            </tr>
            @foreach (var item in Model.Fixed)
            {
                if (!String.IsNullOrWhiteSpace(item.AgentId))
                {
                    @Html.Partial("FixedPartialView", item) 
                }
            }
        </table>
        <br />
        @Html.ActionLink("Add another", "BlankFixedRow", null, null, new { id = "addFixed" })
    </fieldset>
}

这是部分

@model Monet.Models.BankListAgentId

@using (Html.BeginCollectionItem("Variable"))
{
    <tr>
        <td>
            @Html.DropDownListFor(model => model.StateCode,
                (SelectList)ViewBag.StateCodeList, Model.StateCode)
        </td>
        <td>
            @Html.EditorFor(model => model.AgentId)
            @Html.ValidationMessageFor(model => model.AgentId)
        </td>
        <td>
        <a href="#" onclick="$(this).parent().remove();" style="float:right;">Delete</a></td>
    </tr>
}
这是视图模型
public class BankListViewModel
{
    public int ID { get; set; }
    public string BankName { get; set; }
    public string LastChangeOperator { get; set; }
    public Nullable<System.DateTime> LastChangeDate { get; set; }
    public List<BankListAgentId> Fixed { get; set; }
    public List<BankListAgentId> Variable { get; set; }
    public List<BankListAttachments> Attachments { get; set; }
    public BankListViewModel()
    {
        //Initialize Fixed and Variable stat Lists
        Fixed = new List<BankListAgentId>();
        Variable = new List<BankListAgentId>();
        Models.BankListAgentId agentId = new BankListAgentId();
        for (int i = 0; i < 5; i++)
        {
            Fixed.Add(agentId);
            Variable.Add(agentId);
        }
        //Initialize attachment Lists
        Attachments = new List<BankListAttachments>();
        Attachments.Add(new BankListAttachments());
    }
}

这是从控制器

到编辑页的原始POST
    public ActionResult Edit(int id)
    {
        BankListMaster banklistmaster = db.BankListMaster.Find(id);
        BankListViewModel viewModel = new BankListViewModel();
        viewModel.BankName = banklistmaster.BankName;
        viewModel.LastChangeDate = banklistmaster.LastChangeDate;
        viewModel.LastChangeOperator = banklistmaster.LastChangeOperator;
        List<BankListAgentId> agentId = (from c in db.BankListAgentId
                                         where c.ID == id
                                         select c).ToList();
        foreach (var bankListAgentId in agentId)
        {
            string value = bankListAgentId.FixedOrVariable.Trim();
            if (value.Equals("Fixed"))
            {
                viewModel.Fixed.Add(bankListAgentId);
            }
            else
            {
                viewModel.Variable.Add(bankListAgentId);
            }
        }
        viewModel.Attachments = (from c in db.BankListAttachments
                                 where c.ID == id
                                 select c).ToList();
        SelectList tmpList = new SelectList(new[] { "AL", "AK", "AS", "AZ", "AR", "CA", "CO", "CT", "DE", "DC", "FM", "FL", "GA", "GU", "HI", "ID", "IL", "IN", "IA", "KS", "KY", "LA", "ME", "MH", "MD", "MA", "MI", "MN", "MS", "MO", "MT", "NE", "NV", "NH", "NJ", "NA", "NM", "NY", "NC", "ND", "MP", "OH", "OK", "OR", "PW", "PA", "PR", "RI", "SC", "SD", "TN", "TX", "UT", "US", "VT", "VI", "VA", "WA", "WV", "WI", "WY" });
        ViewBag.StateCodeList = tmpList;
        ViewBag.ID = new SelectList(db.BankListAgentId, "ID", "FixedOrVariable", banklistmaster.ID);
        return View(viewModel);
    }
public partial class BankListAgentId
{
    public string AgentId { get; set; }
    public int ID { get; set; }
    public string FixedOrVariable { get; set; }
    public string StateCode { get; set; }
    public virtual BankListMaster BankListMaster { get; set; }
}

您可能希望尝试使用编辑器模板,而不是在循环中注入部分。

    @foreach (var item in Model.Fixed)
    {
        if (!String.IsNullOrWhiteSpace(item.AgentId))
        {
            @Html.EditorFor(item => item, "FixedPartialView") 
        }
    }

然后放置FixedPartialView。将cshtml放入适当的EditorTemplates文件夹中。我相信,绑定对于框架来说将更加直观。

问题是您使用的是像EditorTemplate一样的Partial视图。部分视图和编辑模板是不同的。你可以把局部视图看作是一个带有一些额外内容的服务器端include。

所以,这里的问题是,您传递给分部的模型与父类中使用的模型不同。

@foreach (var item in Model.Fixed)
{
    if (!String.IsNullOrWhiteSpace(item.AgentId))
    {
        @Html.Partial("FixedPartialView", item) 
    }
}

当你提交你的模型时,你的局部视图中的助手会呈现代码,就好像模型是固定的一样,所以它会错误地格式化和命名你的局部中的项目。在这种情况下,默认的模型绑定器不知道"item"在一个名为"Fixed"的集合中,因为您已经通过迭代foreach循环删除了该集合的上下文,并且只从包含的项中呈现。

我建议不要使用部分视图,而是使用EditorTemplate,因为这是它们被设计用来处理的(在对象中呈现类型),并且它们会自动处理集合。

或者,如果你想渲染局部,那么不要传递子模型,只让它从父模型中渲染。否则,您将不得不做大量的工作来确保在部分中有正确的命名。

或者,如果您只需要发布这个项目集合,那么您可以确保您的post操作接受IEnumerable<Fixed>而不是您的父模型。

最新更新