MVC DropDownListFor与ViewBag没有传递值到控制器

时间:2015-05-28 02:01:39

标签: asp.net-mvc entity-framework viewbag dropdownlistfor

我真的很难在我的创建视图中设置一个下拉列表到相关的模型/表。 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>

感谢您的帮助!!

2 个答案:

答案 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属性,因为您只绑定了所需的确切项目。