为什么IList的UpdateModel()绑定不起作用,但作为方法参数呢?

时间:2014-09-03 11:59:46

标签: c# asp.net .net asp.net-mvc asp.net-mvc-5

我有一个简单的课程:

[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<>,但也出现了同样的问题。

2 个答案:

答案 0 :(得分:0)

问题是在第二个示例中,您有一个空列表。 UpdateModel会更新项(如果它们存在且可以找到相关性),但它不会为您填充空列表。如果你做了类似的事情:

var rates = db.RatePerPurposes.ToList();
UpdateModel(rates);

那个可能会起作用,假设它可以将POST主体中的RatePerPurpose个实例与数据库返回的RatePerPurpose个实例进行匹配。

答案 1 :(得分:0)

我终于想通了(在三个不眠之日之后)。实际上有两个问题。

问题1

我的应用程序的global.asax在DoubleModelBinder上调用了Application_Start深刻的({注册}}:

...
ModelBinders.Binders.Add(typeof(double), new DoubleModelBinder());
...

此绑定程序依赖于UICulture,因此从action方法参数绑定起作用。但是MyActionPost()的身体有不同的文化,所以我的DoubleModelBinder抛出了一些内部异常。有点奇怪,这个异常没有传播出UpdateModel()

问题2

在我的示例中使用UpdateModel()(或TryUpdateModel())非常好。我在第654页的Adam Freeman的书Pro ASP.NET MVC 5中也找到了类似的示例,但“正确”版本应使用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" />