ArgumentNullException 的列表框参数名称:source
设置:
我使用 MvcScaffolding 搭建了一个控制器。
对于属性 Model.IdCurrencyFrom,脚手架创建了一个 Html.DropDownListFor:
@Html.DropDownListFor(model => model.IdCurrencyFrom,
((IEnumerable<FlatAdmin.Domain.Entities.Currency>)ViewBag.AllCurrencies).Select(option => new SelectListItem {
Text = (option == null ? "None" : option.CurrencyName),
Value = option.CurrencyId.ToString(),
Selected = (Model != null) && (option.CurrencyId == Model.IdCurrencyFrom)
}), "Choose...")
无论是使用新记录还是编辑现有记录,这都可以正常工作。
问题:
只有 3 种货币,AR$、US$ 和 GB£。因此,我想要一个列表框,而不是下拉列表。
所以我将上面的内容更改为:
@Html.ListBoxFor(model => model.IdCurrencyFrom,
((IEnumerable<FlatAdmin.Domain.Entities.Currency>)ViewBag.AllCurrencies).Select(option => new SelectListItem {
Text = (option == null ? "None" : option.CurrencyName),
Value = option.CurrencyId.ToString(),
Selected = (Model != null) && (option.CurrencyId == Model.IdCurrencyFrom)
}))
我现在得到一个 ArgumentNullException,参数名称:source,但仅在编辑现有记录时。创建新记录,这很好用。
问题:
这是怎么回事?!
一切都没有改变。切换回 DropDownListFor 一切正常。切换到 ListBox(而不是 ListBoxFor),我收到错误。
该模型不为空(就像我说的,它与 DropDownListFor 配合得很好)...而且我已经没有想法了。
Setup:
I have scaffolded a controller using MvcScaffolding.
For a property, Model.IdCurrencyFrom, the scaffolding created an Html.DropDownListFor:
@Html.DropDownListFor(model => model.IdCurrencyFrom,
((IEnumerable<FlatAdmin.Domain.Entities.Currency>)ViewBag.AllCurrencies).Select(option => new SelectListItem {
Text = (option == null ? "None" : option.CurrencyName),
Value = option.CurrencyId.ToString(),
Selected = (Model != null) && (option.CurrencyId == Model.IdCurrencyFrom)
}), "Choose...")
This works fine, both with new records, or editing existing ones.
Problem:
There are only 3 currencies, AR$, US$ and GB£. So, instead of a drop down list, I want a ListBox.
So I changed the above to:
@Html.ListBoxFor(model => model.IdCurrencyFrom,
((IEnumerable<FlatAdmin.Domain.Entities.Currency>)ViewBag.AllCurrencies).Select(option => new SelectListItem {
Text = (option == null ? "None" : option.CurrencyName),
Value = option.CurrencyId.ToString(),
Selected = (Model != null) && (option.CurrencyId == Model.IdCurrencyFrom)
}))
I now get an ArgumentNullException, Parameter name: source, but only when editing an existing record. Creating new records, this works fine.
Questions:
What is happening?!
Nothing has changed. Switching back to DropDownListFor and it all works fine. Switching to ListBox (as opposed to ListBoxFor) and I get the error.
The model is not null (like I said, it works fine with the DropDownListFor)... and I've run out of ideas.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我检查了 HTML 助手的源代码,这是一个有趣的练习。
TL;博士;
问题是 ListBoxFor 用于多项选择,并且它需要一个可枚举的 Model 属性。您的 Model 属性 (
model.IdCurrencyFrom
) 不是可枚举的,这就是您收到异常的原因。以下是我的发现:
ListBoxFor 方法将始终呈现带有
multiple="multiple"
属性的select
元素。它是硬编码在System.Web.Mvc.Html.SelectExtensions
所以也许您不想允许用户使用多种货币...
当此 ListBoxHelper 尝试时,您的问题就开始了从模型属性中获取默认值:
它适用于 DropDownList,因为它在调用
SelectInternal
时将 false 传递给allowMultiple
。因为您的 ViewData.ModelState 为空(因为您的控制器之前没有进行验证),所以 defaultValue 将为 null。然后
defaultValue
使用模型的默认值进行初始化(我猜你的情况model.IdCurrencyFrom
是int
),所以它将是0< /代码>。 :
我们已经接近异常了:)因为正如我提到的ListBoxFor仅支持多项选择,所以它尝试将
defaultValue
处理为IEnumbrable
:第二行出现 ArgumentException,因为
defaultValues
为null
。因为它期望
defaultValue
是可枚举的,并且字符串是可枚举的。如果将model.IdCurrencyFrom
的类型更改为string
它将起作用。但是,当然,您将在 UI 上进行多项选择,但您只能获得模型中的第一个选择。I've checked the source of the HTML helpers, it was a fun exercise.
TL;DR;
The problem is that ListBoxFor is for multiple selection and it expects an enumerable Model property. Your Model property (
model.IdCurrencyFrom
) is not an enumerable that's why you get the exception.Here are my findings:
The ListBoxFor method will render a
select
element withmultiple="multiple"
attribute, always. It is hard coded inSystem.Web.Mvc.Html.SelectExtensions
So maybe you anyway don't want to allow for the user multiple currencies...
Your problem starts when this ListBoxHelper tries to get the default value from your model property:
It works for DropDownList because it passes false to
allowMultiple
when callingSelectInternal
.Because your
ViewData.ModelState
is empty (because there were no validation occurred in your controller before) thedefaultValue
will benull
. ThendefaultValue
gets initialized with your model's default value (your casemodel.IdCurrencyFrom
isint
I guess) so it will be0
. :We are getting close to the exception :) Because as I mentioned ListBoxFor only support multiple selection, so it tries to handle
defaultValue
asIEnumbrable
:And in the second line there is your ArgumentException because
defaultValues
isnull
.Because it expects
defaultValue
to be enumerable and because string is enumerable. If you change the the type ofmodel.IdCurrencyFrom
tostring
it will work. But of course you will have multiple selection on the UI but you will only get the first selection in your model.