为什么IList的UpdateModel()绑定不起作用,但作为方法参数却起作用
本文关键字:方法 参数 起作用 不起作用 IList UpdateModel 绑定 为什么 | 更新日期: 2023-09-27 18:20:33
我有一个简单的类:
[Serializable]
public class RatePerPurpose
{
public int ValueId { get; set; }
public double Rate { get; set; }
}
,和简单的数据到POST:
<input type="hidden" name="[0].ValueId" value="1" />
<input type="hidden" name="[0].Rate" value="2.34" />
<input type="hidden" name="[1].ValueId" value="10" />
<input type="hidden" name="[1].Rate" value="20.34" />
这工作没有任何问题:
[HttpPost]
public virtual ActionResult MyActionPost(List<RatePerPurpose> rates)
{
// no problem, this works
}
我的问题是,为什么这些不起作用(我已经测试了ASP.NET MVC 5)?或者如何改变这一点,让它发挥作用?
[HttpPost]
public virtual ActionResult MyActionPost()
{
List<RatePerPurpose> rates = new List<RatePerPurpose>();
this.UpdateModel(rates);
// This DOES NOT work, 'rates' is empty :-(
this.UpdateModel(rates, prefix:"");
// Setting 'none' prefix, also DOES NOT work. 'rates' is still empty
}
PS:我也测试过List<>
和IList<>
,但出现了同样的问题。
问题是在第二个示例中,您有一个空列表。UpdateModel
将更新项目(如果存在),并且它可以找到相关性,但它不会为您填充空列表。如果你做了这样的事情:
var rates = db.RatePerPurposes.ToList();
UpdateModel(rates);
可能会起作用,假设它可以将POST主体中的RatePerPurpose
实例与数据库返回的RatePerPurpose
实例相匹配。
我终于想通了(经过三天的不眠之夜)。实际上有两个问题。
问题1
在我的应用程序的global.asax上调用Application_Start
:时,出现了DoubleModelBinder
漏洞
...
ModelBinders.Binders.Add(typeof(double), new DoubleModelBinder());
...
该粘合剂依赖于UICulture
,因此从作用方法参数进行绑定是有效的。但MyActionPost()
的身体有不同的文化,所以我的DoubleModelBinder
抛出了一些内部异常。有点奇怪的是,这个异常没有从UpdateModel()
传播出去。
问题2
像在我的例子中那样使用UpdateModel()
(或TryUpdateModel()
)是非常好的。我在Adam Freeman的一本书Pro ASP.NET MVC 5(第654页)中也发现了类似的例子,但"正确"的版本应该使用FormCollection
作为操作方法参数。因此,工作示例:
[HttpPost]
public virtual ActionResult MyActionPost(FormCollection form)
{
List<RatePerPurpose> rates = new List<RatePerPurpose>();
this.UpdateModel(rates, "MyList", form);
// This works, 'rates' is binded properly
}
PS:
还有最后一条建议。绑定集合时使用.Index
。(当索引从0开始并且项目之间没有间隙时,这不是必需的,但我现在可以睡得更好了。:)所以数据应该是这样的:
<input type="hidden" name="MyList.Index" value="0" />
<input type="hidden" name="MyList[0].ValueId" value="1" />
<input type="hidden" name="MyList[0].Rate" value="2.34" />
<input type="hidden" name="MyList.Index" value="1" />
<input type="hidden" name="MyList[1].ValueId" value="10" />
<input type="hidden" name="MyList[1].Rate" value="20.34" />