我真的很难在我的创建视图中设置一个下拉列表到相关的模型/表。 My Guest模型以下列方式引用PersonPrefix模型:
嘉宾模特:
public virtual PersonPrefix Prefix { get; set; }
PersonPrefix模型:
public class PersonPrefix
{
[Key]
public int PersonPrefixID { get; set; }
[StringLength(6)]
public string Abbreviation { get; set; }
[StringLength(255)]
public string Name { get; set; }
public virtual ICollection<Guest> Guests { get; set; }
}
我已完成以下操作,以便能够从数据库中获取数据并在下拉列表中显示:
控制器:
public ActionResult Create()
{
ViewBag.PersonPrefixes = new SelectList(db.PersonPrefixes, "PersonPrefixID", "Abbreviation");
return View();
}
我已将前缀对象添加到帖子
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "GuestID,FirstName,MiddleName,Surname,BirthDate,SelectedPrefix")] Guest guest)
{
if (ModelState.IsValid)
{
db.Guests.Add(guest);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(guest);
}
这是目前视图中的相关代码,但它没有将值传递给控制器:
<div class="form-group">
@Html.LabelFor(model => model.Prefix, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10" >
@*@Html.DropDownListFor(m => m.Prefix, new SelectList(ViewBag.PersonPrefixes, "Value", "Text", 1))*@
@Html.DropDownListFor(m => m.Prefix,
new SelectList(ViewBag.PersonPrefixes, "Value", "Text", 1))
</div>
</div>
感谢您的帮助!!
答案 0 :(得分:1)
您无法将before_install:
- sudo apt-get update
- sudo apt-get install python3
元素绑定到复杂对象。所有html表单控件都回发单个值(或者<select>
一个值类型数组)。如果您选择了值为(例如)5的选项,那么<select multiple>
会尝试设置DefaultModelBinder
,这当然会失败。
您需要绑定到值类型(例如guest.Prefix = 5;
,int
等)。在您的情况下,您甚至无法绑定string
的{{1}},因为验证将在PersonPrefixID
的其他属性上失败。与编辑时一样,您应该使用仅包含您需要编辑的属性的视图模型。
PersonPrefix
控制器
PersonPrefix
查看
public class GuestVM
{
[Display(Name = "Prefix")]
[Required(ErrorMessage = "Please select a prefix")]
public int SelectedPrefix { get; set; }
.... // other properties of Guest
public SelectList PrefixList { get; set; }
}
然后在POST方法中,初始化public ActionResult Create()
{
GuestVM model = new GuestVM();
model.PrefixList = new SelectList(db.PersonPrefixes, "PersonPrefixID", "Abbreviation");
.... // set other properties as required
return View(model); // always return an instance of the model
}
数据模型的新实例,并从发布的视图模型中映射其属性,最后保存数据模型。
@Html.LabelFor(m => m.SelectedPrefix)
@Html.DropDownListFor(m => m.SelectedPrefix, Model.PrefixList, "--please select--")
@Html.ValidationMessageFor(m => m.SelectedPrefix)
附注:您不需要在视图中创建另一个Guest
(它已经是public ActionResult Create(GuestVM model)
{
if (!ModelSTate.IsValid)
{
model.PrefixList = new SelectList(db.PersonPrefixes, "PersonPrefixID", "Abbreviation");
return View(model);
}
// Initialize a new instance of the data model and set its properties
Guest guest = new Guest()
{
FirstName = model.FirstName,
MiddleName = model.MiddleName,
.... // other properties
Prefix = db.PersonPrefixes.Find(model.SelectedPrefix)
};
db.Guests.Add(guest);
db.SaveChanges();
return RedirectToAction("Index");
}
),并且您尝试将所选值设置为SelectList
的最后一个参数是忽略(它的绑定属性的值决定选择哪个选项)所以如果你想用SelectList
预先选择一个选项,那么在你之前在控制器中设置1
的值将模型传递给视图。
答案 1 :(得分:1)
虽然最好使用ViewModels,但根据Stephen的回答,你在这里做错的是:
首先,您的DropDownListFor是错误的。您的ViewBag条目已包含SelectList,因此您无需再创建另一个...您只需要转换动态类型。
@Html.DropDownListFor(m => m.Prefix.PersonPrefixID,
(SelectList)ViewBag.PersonPrefixes, "Select...")
第一个参数是PersonPrefixes中对象列表中的选定ID ...因此,当模型发布到控制器时,它将包含ID(但不包含其他数据,因此您必须确保查询数据库以填充它。)
其次,您需要将Post Action更改为:
Create([Bind(Include = "GuestID,FirstName,MiddleName,Surname,BirthDate")] Guest guest)
然后在你的PersonPrefix类上使用Bind语法:
[Bind(Include = "PersonPrefixID")]
public class PersonPrefix
{
[Key]
public int PersonPrefixID { get; set; }
.....
}
现在,当您发布时,PersonPrefix的其余部分将为空,因为帖子中不存在此数据,因此您必须使用发布的PersonPrefixID从数据库中检索它。
但是,正如我所说,最好使用ViewModels。即便如此,我在这里说的一些相同的事情仍然适用。您的DropDownListFor需要正确,并使用选定的id属性。而且,如果您使用的是ViewModel,则没有理由使用Bind属性,因为您只绑定了所需的确切项目。