如果我们认为这不是团队应解决的错误,则MSDN应该至少对文档进行改进。令人困惑的是,这确实来自糟糕的文件。在MSDN中,它将参数名称解释 为,
Type: System.String
The name of the form field to return.
这只是意味着它生成的最终html将使用该参数作为选择输入的名称。但是,实际上,这还意味着更多。
我猜设计师假设用户将使用视图模型来显示下拉列表,还将使用回发到相同的视图模型。但是在很多情况下,我们实际上并不遵循这个假设。
使用上面的例子,
public class Person {
public int Id { get; set; }
public string Name { get; set; }
}
如果遵循假设,则应该为此下拉列表相关视图定义视图模型
public class PersonsSelectViewModel{
public string SelectedPersonId,
public List<SelectListItem> Persons;
}
因为在回发时,只有选定的值才会回发,因此假定它应回发到模型的属性SelectedPersonId,这意味着Html.DropDownList的第一个参数名称应为“ SelectedPersonId”。因此,设计人员认为,在视图中显示模型视图时,模型的属性SelectedPersonId应该包含该下拉列表的默认值。即使您的List <SelectListItem>人员已经设置了Selected标志来指示已选择/默认,tml.DropDownList实际上将忽略它并重建它自己的IEnumerable <SelectListItem>并根据名称设置默认/选中的项。
这是来自asp.net mvc的代码
private static MvcHtmlString SelectInternal(this HtmlHelper htmlHelper, ModelMetadata metadata,
string optionLabel, string name, IEnumerable<SelectListItem> selectList, bool allowMultiple,
IDictionary<string, object> htmlAttributes)
{
...
bool usedViewData = false;
// If we got a null selectList, try to use ViewData to get the list of items.
if (selectList == null)
{
selectList = htmlHelper.GetSelectData(name);
usedViewData = true;
}
object defaultValue = (allowMultiple) ? htmlHelper.GetModelStateValue(fullName, typeof(string[])) : htmlHelper.GetModelStateValue(fullName, typeof(string));
// If we haven't already used ViewData to get the entire list of items then we need to
// use the ViewData-supplied value before using the parameter-supplied value.
if (defaultValue == null && !String.IsNullOrEmpty(name))
{
if (!usedViewData)
{
defaultValue = htmlHelper.ViewData.Eval(name);
}
else if (metadata != null)
{
defaultValue = metadata.Model;
}
}
if (defaultValue != null)
{
selectList = GetSelectListWithDefaultValue(selectList, defaultValue, allowMultiple);
}
...
return tagBuilder.ToMvcHtmlString(TagRenderMode.Normal);
}
因此,代码实际上走得更远,它不仅尝试在模型中查找名称,而且还在视图数据中查找名称,一旦找到名称,它将重新构建selectList并忽略原始的Selected。
问题是,在很多情况下,我们并不是真的那样使用它。我们只想抛出一个selectList,其中select / selected项设置为true。
当然,解决方案很简单,使用不在模型或视图数据中的名称。当找不到匹配项时,它将使用原始的selectList,并且原始的Selected将生效。
但是我仍然认为mvc应该通过增加一个条件来改善它
if ((defaultValue != null) && (!selectList.Any(i=>i.Selected)))
{
selectList = GetSelectListWithDefaultValue(selectList, defaultValue, allowMultiple);
}
因为,如果原始的selectList已经有一个Selected,那么为什么要忽略它呢?
只是我的想法。