[英]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. 这就是为什么从
1
到2
出错的原因-您只发送了一个元素的列表,但是在视图中尝试从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)
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.