简体   繁体   English

MVC复杂模型绑定到按索引列出

[英]MVC Complex model binding to list by index

could really use another set of eyes here, what am i doing wrong? 我真的可以在这里使用另一只眼睛,我在做什么错?

Model: 模型:

public class reqView {
    public string Name { get; set; }
    /* Loads of properties */
    private lsAddress _addresses = new lsAddress {
        new Address { id = 1 }, new Address { id = 2 }
    };
    public lsAddress lsAddress {
        get { return _addresses; }
        set { _addresses = value; }
    }
}

View: 视图:

@Html.DropDownListFor(model => model.lsAddress[1].addrCC,
                        new SelectList(CacheConfig.Countries.Where(c => c.dix.Contains(Model.dix)), "id", "text", Model.lsAddress[1].addrCC),
                        new {@class = "form-control"} as object);

Controller: 控制器:

public ActionResult Index() {
        var model = (reqView) TempData["reqView"];

        if (model == null) model = new reqView();

        TempData["reqView"] = model;

        return View(model);
    }

lsAddress: lsAddress:

public class lsAddress : List<Address>, IEnumerable<SqlDataRecord>{
    IEnumerator<SqlDataRecord> IEnumerable<SqlDataRecord>.GetEnumerator()
    {
        var sqlRow = new SqlDataRecord(
            new SqlMetaData("id", System.Data.SqlDbType.TinyInt, false, true, SortOrder.Unspecified, -1),
            new SqlMetaData("nmContact", System.Data.SqlDbType.NVarChar, 80)
            );

        foreach (Address obj in this)
        {
            sqlRow.SetValue(0, obj.id);
            sqlRow.SetValue(1, obj.cName);
            yield return sqlRow;
        }
    }
}  

To Replicate: see the .net fiddle select 1 then 2 -> Index out of range select 2 then 1 -> Object reference not set to an instance of an object. 要复制:请参见.net小提琴,然后选择1然后2->索引超出范围选择2然后1->对象引用未设置为对象实例。

What am i missing here? 我在这里想念什么?

Problem here: how binding model properties on submit. 这里的问题:提交时如何绑定模型属性。

1) you init _addresses in constructor, so if on submit you not pass values for this properties, this would be by default: list with two elements. 1)您在构造函数中初始化_addresses ,因此,如果在提交时您不传递此属性的值,则默认情况下将是:具有两个元素的列表。

that's why all work when you submit from your 0 variant: you set disabled attribute to select, and on submit this value not sended. 这就是为什么当您从0变体提交时所有方法都起作用的原因:您将Disabled属性设置为select,并且在提交时未发送该值。

2) when you do submit from '1': select - enabled, and have name that mapped to first element of _addresses , so MVC see that from request come field, and replace list with to element, that was created in constructor, to list with on element, which come from request. 2)当您确实从'1'提交时:选择-启用,并且其名称映射到_addresses第一个元素,因此MVC看到from请求字段,并将list替换为在构造函数中创建的to元素,以list带有on元素,来自请求。

that's why your 1 work, but if you see what he send on submit - you see that is model where _addresses is list with one element. 这就是您1工作的原因,但是如果您看到他在提交时发送的内容-您会看到模型是_addresses是带有一个元素的列表。 And that's why you have error when go from 1 to 2 - you just send list with one element, but in view try get value from element with index=1 instead 0. 这就是为什么从12出错的原因-您只发送了一个元素的列表,但是在视图中尝试从index = 1而不是0的元素获取值。

3) when you do submit from 2 : select also enabled and have name that mapped to first element of _addresses , but MVC can't create correct list from one element with index that not 0 and if you see what come in post method, you can see that _addresses come null . 3)当您确实从2提交时:也启用了select,并且其名称已映射到_addresses第一个元素,但是MVC无法从索引不为0的一个元素创建正确的列表,并且如果您看到post方法中出现的内容,可以看到_addresses null

for solution you can add hidden field, that would be save value for other list items: 对于解决方案,您可以添加隐藏字段,这将为其他列表项节省价值:

@{var cur = -1;}
@switch (Model.dix)
{
    case 0:
        @Html.DropDownListFor(model => model.lsAddress[0].addrCC,
                new SelectList(mvc.Controllers.CacheConfig.Countries.Where(c => c.dix.Contains(Model.dix)), "id", "text", Model.lsAddress[0].addrCC),
                new { @class = "form-control", disabled = "disabled" } as object)
        break;
    case 1:
    @Html.DropDownListFor(model => model.lsAddress[0].addrCC,
                new SelectList(mvc.Controllers.CacheConfig.Countries.Where(c => c.dix.Contains(Model.dix)), "id", "text", Model.lsAddress[0].addrCC),
                new { @class = "form-control" } as object);
    cur = 0;                    
    break;
    case 2:
    @Html.DropDownListFor(model => model.lsAddress[1].addrCC,
                new SelectList(mvc.Controllers.CacheConfig.Countries.Where(c => c.dix.Contains(Model.dix)), "id", "text", Model.lsAddress[1].addrCC),
                new { @class = "form-control" } as object);
    cur = 1;
        break;
}
@for (int i = 0; i < Model.lsAddress.Count; i++)
{
    if (i == cur) { continue; }
    @Html.HiddenFor(model => model.lsAddress[i].addrCC)
}

DotNetFiddle 点网提琴

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM