[英]There is no ViewData item of type 'IEnumerable<SelectListItem>' that has the key 'Practice' - MVC5
I am very new to MVC and have just added a cascading drop down to my create page so when a Practice is selected the Optician drop down is populated with the names of opticians that work at that practice. 我是MVC的新手,并且刚刚在我的创建页面中添加了一个级联下拉菜单,因此当选择“练习”时,“眼镜师”下拉列表中会填充在该练习中工作的配镜师的姓名。
Model: 模型:
public class Booking
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public Guid BookingId { get; set; }
[ForeignKey("Patient")]
public Guid PatientId { get; set; }
public virtual Patient Patient { get; set; }
public IEnumerable<SelectListItem> PatientList { get; set; }
[ForeignKey("Practice")]
public Guid PracticeId { get; set; }
public virtual Practice Practice { get; set; }
public IEnumerable<SelectListItem> PracticeList { get; set; }
[ForeignKey("Optician")]
public Guid OpticianId { get; set; }
public virtual Optician Optician { get; set; }
public IEnumerable<SelectListItem> OpticiansList { get; set; }
[Display(Name = "Date")]
[DataType(DataType.Date)]
[DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:dd/MM/yyyy}")]
public DateTime Date { get; set; }
[ForeignKey("Time")]
public Guid? TimeId { get; set; }
public virtual Time Time { get; set; }
public IEnumerable<SelectListItem> TimeList { get; set; }
public bool isAvail { get; set; }
}
My Controller: 我的控制器:
// GET: Bookings1/Create
public ActionResult Create()
{
var practices = new SelectList(db.Practices, "PracticeId", "PracticeName");
ViewData["Practice"] = practices;
Booking booking = new Booking();
ConfigureCreateModel(booking);
return View(booking);
}
public void ConfigureCreateModel(Booking booking)
{
booking.PatientList = db.Patients.Select(p => new SelectListItem()
{
Value = p.PatientId.ToString(),
Text = p.User.FirstName
});
booking.TimeList = db.Times.Select(t => new SelectListItem()
{
Value = t.TimeId.ToString(),
Text = t.AppointmentTime
});
}
// POST: Bookings1/Create
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(Booking booking)
{
// to ensure date is in the future
if (ModelState.IsValidField("Date") && DateTime.Now > booking.Date)
{
ModelState.AddModelError("Date", "Please enter a date in the future");
}
// Sets isAvail to false
booking.isAvail = false;
//Checks if model state is not valid
if (!ModelState.IsValid)
{
ConfigureCreateModel(booking);
return View(booking); // returns user to booking page
}
else // if model state is Valid
{
// Generates a new booking Id
booking.BookingId = Guid.NewGuid();
// Adds booking to database
db.Bookings.Add(booking);
// Saves changes to Database
db.SaveChanges();
// Redirects User to Booking Index
return RedirectToAction("Index");
}
}
My View: 我的观点:
<script src="~/Scripts/jquery-1.10.2.js"></script>
<script>
$(document).ready(function () {
$("#Optician").prop("disabled", true);
$("#Practice").change(function () {
$.ajax({
url : "@Url.Action("Opticians","Bookings")",
type : "POST",
data : {Id : $(this).val() }
}).done(function (opticianList) {
$("#Optician").empty();
for (var i = 0; i < opticianList.length; i++) {
$("#Optician").append("<option>" + opticianList[i] + "</option>");
}
$("#Optician").prop("disabled", false);
});
});
});
</script>
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Booking</h4>
<hr />
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
<div class="form-group">
@Html.LabelFor(model => model.PatientId, new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.DropDownListFor(model => model.PatientId, Model.PatientList, "-Please select-", new { @class = "form-control" })
@Html.ValidationMessageFor(model => model.PatientId, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.PracticeId, new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.DropDownList("Practice", ViewData["Practice"] as SelectList,"-Please Select-", new { @class = "form-control" })
@Html.ValidationMessageFor(model => model.PracticeId, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.Label("Select Optician :", new { @class = "col-md-2 control-label" })
<div class="col-md-10">
<select id="Optician"></select>
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.Date, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Date, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Date, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.TimeId, new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.DropDownListFor(model => model.TimeId, Model.TimeList, "-Please select-", new { @class = "form-control" })
@Html.ValidationMessageFor(model => model.TimeId, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
}
<div>
@Html.ActionLink("Back to List", "Index")
</div>
The cascading drop down works as it should how ever when I click the button to create the appointment the following exception is thrown: 当我单击按钮创建约会时,级联下拉菜单的工作方式应该一样,将引发以下异常:
Exception: 例外:
An exception of type 'System.InvalidOperationException' occurred in System.Web.Mvc.dll but was not handled in user code
System.Web.Mvc.dll中发生类型为'System.InvalidOperationException'的异常,但未在用户代码中处理
Additional information: There is no ViewData item of type 'IEnumerable' that has the key 'Practice'.
附加信息:没有类型为“ IEnumerable”的ViewData项目具有键“ Practice”。
Any help would be greatly appreciated. 任何帮助将不胜感激。 Thanks
谢谢
You model already contains a property for the collection of practices 您的模型已经包含用于实践收集的属性
public IEnumerable<SelectListItem> PracticeList { get; set; }
although it should not contain 虽然它不应该包含
public virtual Practice Practice { get; set; }
In the GET method, you create a new SelectList
for practices, but instead of assigning it to the model property, you add it to ViewData
using 在GET方法中,为实践创建一个新的
SelectList
,但没有将其分配给model属性,而是使用以下方法将其添加到ViewData
中:
ViewData["Practice"] = practices;
and then in the view use 然后在视图中使用
@Html.DropDownList("Practice", ViewData["Practice"] as SelectList, ..)
which is not even binding to a property in your model and would never post back to anything. 甚至没有绑定到模型中的属性,也永远不会发回任何东西。 Then when you return the view in the POST method (because your mode will always be invalid), you do not assign a value to
ViewData["Practice"]
so its null, hence the error. 然后,当您在POST方法中返回视图时(因为您的模式将始终无效),则无需为
ViewData["Practice"]
分配一个值,因此它为null,从而导致错误。
Instead, in your ConfigureCreateModel()
method, populate the PracticeList
property (as your doing for PatientList
) and remove the use of ViewData
, and in the view use 相反,在您的
ConfigureCreateModel()
方法中,填充PracticeList
属性(就像对PatientList
所做的PatientList
)并删除对ViewData
的使用,并在视图中使用
@Html.DropDownListFor(model => model.PracticeId, Model.PracticeList, ...)
so your strongly binding to your model and when your submit the form, the value of PracticeId
will be the value of the selected practice. 因此,您对模型具有很强的约束力,并且在提交表单时,
PracticeId
的值将是所选实践的值。
Side note: You will need to change your script to $("#PracticeId").change(function () { ...
旁注:您需要将脚本更改为
$("#PracticeId").change(function () { ...
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.