我有下一个模型(简化):
public class CarType
{
public int Id { get; set; }
[Required]
public string Name { get; set; }
}
public class Car
{
[Required]
public string Model { get; set; }
[Required]
public CarType Type { get; set; }
[Required]
public decimal Price { get; set; }
}
我想让用户从创建页面上的下拉列表中选择汽车类型。我试图通过ViewBag传递数据库类型字典及其名称:
ViewBag.Types = _context.CarTypes.ToDictionary(carType => carType.Name);
并在页面中选择它:
@Html.DropDownListFor(model => model.Type, new SelectList(ViewBag.Types, "Value", "Key"))
但是在POST方法中,我总是用Type
属性中的null
构造Car
对象。
[HttpPost]
public ActionResult Create(Car car)
{
if (ModelState.IsValid)
{
_context.Cars.Add(car);
_context.SaveChanges();
return RedirectToAction("Index");
}
return View(car);
}
是否可以选择自定义对象与下拉列表?因为选择像int
, string
这样的值工作得很好。
我有一个想法写ViewModel与int
ID而不是CarType
,并通过ID保存到数据库之前找到类型。但是这样的话,我需要复制所有Car
属性和它们的属性到我的ViewModel,并最终将所有值复制到新的Car
对象。对于小班也许还行,但对于一些更复杂的——不要这样想…
这是一个小例子。解决这类问题的常见方法是什么?如何编写灵活和简单的代码?
以下是我在这些情况下使用的可靠的HtmlHelper扩展方法:
public static MvcHtmlString DropDownListForEnum<TModel, TProperty>(this HtmlHelper<TModel> helper, Expression<Func<TModel, TProperty>> expression, SelectListItem initialItem)
where TProperty : struct
{
if (!typeof(TProperty).IsEnum)
throw new ArgumentException("An Enumeration type is required.", "enum");
IList<SelectListItem> items = Enum.GetValues(typeof(TProperty)).Cast<TProperty>()
.Select(t => new SelectListItem { Text = (t as Enum).GetDescription(), Value = t.ToString() }).ToList();
if (initialItem != null)
items.Insert(0, initialItem);
return SelectExtensions.DropDownListFor<TModel, TProperty>(helper, expression, items, null, null);
}
可以让你写这样的代码:
@Html.DropDownListForEnum(model => model.Type)
并给你一个完全填充的select元素,其中传入的Type
被选中。
上面的方法可以用htmlAttributes
和其他任何方法扩展,但这是一个很好的开始