这是我正在上课的课程:
public class appointment
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int appointment_id { get; set; }
[DataType(DataType.MultilineText)]
public string appointment_description { get; set; }
public int student_id { get; set; }
public virtual student student { get; set; }
public int sched_id { get; set; }
public virtual sched schedule { get; set; }
}
正如您所看到的,我的一个外键是" schedule"。
这是我的日程安排课程
public class sched
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int sched_id { get; set; }
public string sched_day { get; set; }
public TimeSpan sched_stime { get; set; }
public TimeSpan sched_etime { get; set; }
public int faculty_id { get; set; }
public virtual faculty faculty { get; set; }
}
我在创建的MVC 5 CRUD中生成了这个,这是我视图中的代码:
<div class="col-md-10">
@Html.DropDownList("sched_id", null, htmlAttributes: new { @class = "form-control" })
@Html.ValidationMessageFor(model => model.sched_id, "", new { @class = "text-danger" })
</div>
这是我的控制器:
public ActionResult Book()
{
return View();
}
[HttpPost]
public ActionResult Book(CS.Models.appointment appoint)
{
if(ModelState.IsValid)
{
db.appointments.Add(appoint);
db.SaveChanges();
}
return RedirectToAction("Booked", "Home");
}
但是出现了错误:
There is no ViewData item of type 'IEnumerable<SelectListItem>'
我想要做的就是在下拉列表中显示sched类(来自数据库)的数据,该数据来自我正在处理的类中的外键。
我有办法吗?我是MVC的新手。
答案 0 :(得分:1)
这里有几个问题:
首先 - @Html.DropDownList("sched_id", null,
这行代码。当您构建选择列表时,如果我理解正确的时间表,那么您必须提供要从中构建DropDownList
的项目列表,而不是null。这是错误中提到的IEnumerable<SelectListItem>
,不能为空。这引出了我们的第二个问题。
您在视图中直接使用您的商业模式,这是不对的。因为,在您的特定情况下,您必须初始化列表,因此您必须拥有可供选择的所有计划的集合。这不是您的业务模式的一部分。您需要使用视图模型而不是CS.Models.appointment
,而是包含您填写的所有属性,以便发布您的appointment
和另外两名成员:
IEnumerable<SelectListItem> ScheduleSelectListItems { get; set; };
int SelectedScheduleId { get; set; }
填写您在获取操作中将拥有的SelectListItems
列表。像这样:
public class AppointmentViewModel
{
public int appointment_id { get; set; }
public string appointment_description { get; set; }
public StudentViewModel student { get; set; }
public IEnumerable<SelectListItem> ScheduleSelectListItems { get; set; };
public int SelectedScheduleId { get; set; }
}
public ActionResult Book()
{
var items = db.schedules.ToList().Select(sched => new SelectListItem { Text = string.Format("{0} - {1}", sched.sched_stime, sched.sched_etime), Value = sched.Id });
var model = new AppointmentViewModel { ScheduleSelectListItems = items };
return View(model);
}
并且不要忘记更新您的观点以将AppointmentViewModel
用作@model
。
<div class="col-md-10">
@Html.DropDownList("SelectedScheduleId", Model.ScheduleSelectListItems, htmlAttributes: new { @class = "form-control" })
@Html.ValidationMessageFor(model => model.SelectedScheduleId, "", new { @class = "text-danger" })
</div>
这引导我们进入第三个问题。由于您没有使用任何视图模型 - 您没有任何映射(将视图模型中的所有字段复制到将保存到数据库的实际业务模型)。为了简化任务并避免使用AutoMapper
等外部工具来实现此目的,您可以手动执行映射。例如,在某些外部类中,使控制器动作代码尽可能干净。
public static class Extensions
{
public static appointment ToAppointment(this AppointmentViewModel appointmentViewModel)
{
var result = new appointment
{
appointment_id = appointmentViewModel.appointment_id;
// Copy all other properties here
...
};
return result;
}
}
[HttpPost]
public ActionResult Book(AppointmentViewModel appoint)
{
if(ModelState.IsValid)
{
// Map you view model to the model
var appointment = appoint.ToAppointment();
// Get you selected schedul from the database using either foreighn key either navigation property
var schedule = db.schedules.FirstOrDefault(sched => sched.Id == appoint.SelectedScheduleId);
appointment.schedule = schedule;
db.appointments.Add(appointment);
db.SaveChanges();
}
return RedirectToAction("Booked", "Home");
}