我们在DropDownListFor(ASP.NET MVC3版本)中发现了奇怪的行为.它在下拉列表中选择ViewBag属性值而不是Model属性值.
模型:
public class Country { public string Name { get; set; } } public class User { public Country Country { get; set; } }
控制器索引动作:
ViewBag.CountryList = new List<Country> { /* Dropdown collection */ new Country() { Name = "Danmark" },new Country() { Name = "Russia" } }; var user = new User(); user.Country = new Country(){Name = "Russia"}; /* User value */ ViewBag.Country = new Country() { Name = "Danmark" }; /* It affects user */ return View(user);
视图:
@Html.EditorFor(user => user.Country.Name) @Html.DropDownListFor(user => user.Country.Name,new SelectList(ViewBag.CountryList,"Name",Model.Country),"...")
它将显示带有“俄罗斯”值的文本框和带有“Danmark”值的下拉列表,而不是“俄罗斯”.
解决方法
我不太确定为什么做出这个决定,但是之所以发生这种情况是因为MVC框架在使用参数提供的值之前尝试使用ViewData提供的值.这就是ViewBag.Country覆盖参数提供的值Model.Country的原因.
这就是私有方法SelectInternal在MVC框架中的written.
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 (!usedViewData) { if (defaultValue == null) { defaultValue = htmlHelper.ViewData.Eval(fullName); } } if (defaultValue != null) { IEnumerable defaultValues = (allowMultiple) ? defaultValue as IEnumerable : new[] { defaultValue }; IEnumerable<string> values = from object value in defaultValues select Convert.ToString(value,CultureInfo.CurrentCulture); HashSet<string> selectedValues = new HashSet<string>(values,StringComparer.OrdinalIgnoreCase); List<SelectListItem> newSelectList = new List<SelectListItem>(); foreach (SelectListItem item in selectList) { item.Selected = (item.Value != null) ? selectedValues.Contains(item.Value) : selectedValues.Contains(item.Text); newSelectList.Add(item); } selectList = newSelectList; }
此代码defaultValue = htmlHelper.ViewData.Eval(fullName);试图从ViewData获取值,如果它可以获取值,它将覆盖提供的参数selectList with new list.
希望它可以提供帮助.谢谢.
side-node:ViewBag只是ViewData的动态包装类.