列出外键MVC的表值

时间:2015-12-07 15:47:05

标签: c# asp.net-mvc

这是我正在上课的课程:

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的新手。

1 个答案:

答案 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");
}