2015-11-06 55 views
0

真的可以使用另一组眼睛在这里,我做错了什么?MVC复杂模型绑定到列表索引

型号:

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; } 
    } 
} 

查看:

@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); 

控制器:

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

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

     TempData["reqView"] = model; 

     return View(model); 
    } 

个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; 
     } 
    } 
} 

复制: 看到.net fiddle 选择1然后2 - >索引超出范围 选择2,则1 - >对象引用不设置为一个对象的一个​​实例。

我在这里失踪了什么?

+0

你告诉“调试完毕后,我看到'lsAddress'为空”,并在那里它是空的吗?我的意思是它在视图或控制器中为空?因为在声明中存在冲突:如果'lsAddress'在视图中或控制器内为空,则'lsAddress [0]'也应该抛出相同的异常。 –

+2

“Request”类的定义在哪里?我看到你将它传递给模型,所以lsAddress就是来自这个模型。我没有看到足够的信息来拼凑答案。 – Grungondola

+1

你能否提供'lsAddress'类的定义? – Grundy

回答

1

问题在于:绑定模型属性如何提交。 1)您在构造函数中初始化为_addresses,因此如果提交时不传递此属性的值,则默认情况下为:带有两个元素的列表。

这就是为什么当你从你的0款式提交的所有工作:您设置禁用属性来选择,并提交不是sended此值。 2)当你从'1'提交时:选择 - 启用,并且名称映射到_addresses的第一个元素,所以MVC看到从请求来的字段,并将元素替换为元素,这是创建在构造函数,用on元素列出,它来自请求。

这就是为什么你1的工作,但如果你看到了他发上提交 - 你看到的是模型,其中_addresses是列表的一个元素。这就是为什么你有错误,从12的时候 - 你只是一个元素发送名单,但鉴于尝试从索引元素获得价值= 1而不是0

3)当你从2提交:选择也启用并具有映射到_addresses的第一个元素的名称,但MVC无法从索引不为0的一个元素创建正确的列表,并且如果您看到后处理方法中的内容,则可以看到_addresses来自null

的解决方案,您可以添加隐藏字段,将其他列表项被保存价值:

@{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

+0

谢谢你的帮助Grundy! – Dementic

+0

@Dementic,欢迎您:-) – Grundy