问题描述
我很新的C#和MVC。我试图创建一个Web应用程序来为您预订的配镜师的做法。我已经用code-一是实体框架我的数据库。在创建预订页面我有一个下拉的地方可以选择配镜。当我创建使用CRUD的创建页面,下拉显示的用户ID,但我想改变这种状况到应用程序的用户(配镜)名字和姓氏的CONCAT(全名)。
I am very new to c# and MVC. I am trying to create a web application to make bookings for an Opticians practice. I have created my database using Code-First Entity Framework. On the create booking page I have a drop down where an Optician can be selected. When I created the create page using CRUD, the drop down showed the UserId, however I am trying to change that to a concat(FullName) of the Application Users(Optician) FirstName and LastName.
预订模型:
public class Booking
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public Guid BookingId { get; set; }
[ForeignKey("Patient")]
public Guid PatientId { get; set; }
public virtual Patient Patient { get; set; }
[ForeignKey("Practice")]
public Guid PracticeId { get; set; }
public virtual Practice Practice { get; set; }
[ForeignKey("Optician")]
public Guid OpticianId { get; set; }
public virtual Optician Optician { 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 bool isAvail { get; set; }
}
身份型号:
public class ApplicationUser : IdentityUser
{
[Display(Name = "First Name")]
public string FirstName { get; set; }
[Display(Name = "Last Name")]
public string LastName { get; set; }
public string FullName
{
get
{
return this.FirstName + " " + this.LastName;
}
}
配镜:
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public Guid OpticianId { get; set; }
[ForeignKey("User")]
public string UserId { get; set; }
public virtual ApplicationUser User { get; set; }
[ForeignKey("Practice")]
public Guid PracticeId { get; set; }
public virtual Practice Practice { get; set; }
public virtual ICollection<Booking> Bookings { get; set; }
public virtual ICollection<Appointment> Appointments { get; set; }
}
预订控制器:
// GET: Bookings/Create
public ActionResult Create()
{
ViewBag.OpticianId = new SelectList(db.Opticans, "OpticianId", "UserId");
ViewBag.PatientId = new SelectList(db.Patients, "PatientId", "HCN");
ViewBag.PracticeId = new SelectList(db.Practices, "PracticeId", "PracticeName");
ViewBag.TimeId = new SelectList(db.Times, "TimeId", "AppointmentTime");
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "BookingId,PatientId,PracticeId,OpticianId,Date,TimeId,isAvail")] 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;
if (ModelState.IsValid)
{
booking.BookingId = Guid.NewGuid();
db.Bookings.Add(booking);
db.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.OpticianId = new SelectList(db.Opticans, "OpticianId", "FullName", booking.Optician.User.FullName);
ViewBag.PatientId = new SelectList(db.Patients, "PatientId", "HCN", booking.PatientId);
ViewBag.PracticeId = new SelectList(db.Practices, "PracticeId", "PracticeName", booking.PracticeId);
ViewBag.TimeId = new SelectList(db.Times, "TimeId", "AppointmentTime", booking.TimeId);
return View(booking);
}
创建视图:
<div class="form-group">
@Html.LabelFor(model => model.Optician.User.FullName, "FullName", htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.DropDownList("FullName", null, htmlAttributes: new { @class = "form-control" })
@Html.ValidationMessageFor(model => model.Optician.User.FullName, "", new { @class = "text-danger" })
</div>
</div>
我收到以下异常:
I am getting the following exception:
'System.InvalidOperationException'类型的异常出现在System.Web.Mvc.dll程序,但在用户code没有处理
更多信息:有型'的IEnumerable具有关键的无ViewData的项目全名
Additional information: There is no ViewData item of type 'IEnumerable' that has the key 'FullName'
任何帮助将大大AP preciated
Any help would be greatly appreciated
推荐答案
您得到这个错误的原因是因为财产全名
是一个字符串,而不是的IEnumerable&LT; T&GT;
,并在您使用视图
The reason you get that error is because property FullName
is a string, not IEnumerable<T>
and in the view you use
@Html.DropDownList("FullName", null, ...)
如果您提供空
作为第二个参数则第一个参数必须是的IEnumerable&LT; T&GT;
,其中 T
是值类型或 SelectListItem
。
If you provide null
as the second parameter then the first parameter must be IEnumerable<T>
where T
is a value type or SelectListItem
.
在任何情况下,全名
是一个只读属性(没有一个二传手),所以它永远不会绑定到你的财产,无论如何,何况你从绑定排除属性通过你使用可怕的 [绑定(包括=...)]
属性(如果你发现自己使用它,然后使用视图模型代替)。
In any case FullName
is a readonly property (does not have a setter) so it would never bind to your property anyway, not to mention you exclude the property from binding by you awful use of the [Bind(include = "...")]
attribute (if you ever find yourself using it, then use a view model instead).
目前还不清楚它实际上你希望做的,因为你的的SelectList
构造函数是没有意义的。 新的SelectList(db.Opticans,OpticianId,用户ID);
意味着你生成&LT;选项&GT;
元素与属性的值等于 OpticianId
属性的值和文本等于用户ID
属性的值。但你甚至不使用它,无论如何视图。
Its unclear what your actually wanting to do since your SelectList
constructors don't make sense. new SelectList(db.Opticans, "OpticianId", "UserId");
means you generating <option>
elements with a value attribute equal to the value of the OpticianId
property, and a text equal to the value of the UserId
property. But then you don't even use it in the view anyway.
通过创建一个视图模型重新presenting要在视图中显示哪些启动
Start by creating a view model representing what you want to display in the view
public class BookingVM
{
[Display(Name = "Optician")]
[Required(ErrorMessage = "Please select an optician")]
public Guid OpticianId { get; set; } // recommend you use int , not Guid
public IEnumerable<SelectListItem> OpticianList { get; set; }
.... // other properties to edit in the view
}
然后在控制器
public ActionResult Create()
{
BookingVM model = new BookingVM();
ConfigureCreateModel(BookingVM model);
return View(model);
}
// common code for initializing select lists etc
public void ConfigureCreateModel(BookingVM model)
{
model.OpticianList = db.Opticans.Select(o => new SelectListItem()
{
Value = o.OpticianId,
Text = o.User.FullName
}
.... // other select lists
}
和视图
@model BookingVM
....
<div class="form-group">
@Html.LabelFor(m => m.OpticianId, new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.DropDownListFor(m => m.OpticianId, Model.OpticianList, "-Please select-", new { @class = "form-control" })
@Html.ValidationMessageFor(m => m.OpticianId, new { @class = "text-danger" })
</div>
</div>
终于在POST方法
and finally in the post method
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(BookingVM model)
{
if (!ModelState.IsValid)
{
ConfigureCreateModel(model);
return View(model);
}
// map you view model properties to a new instance of your data model
// save the data model and redirect.
}
旁注:您查看模型可以包括日期时间为MinDate
财产(包括在视图中隐藏的输入),然后申请一个万无一失的 [ GREATERTHAN]
或相似属性的日期
属性让你得到客户端和服务器端验证开箱。一个jQuery插件,日期选择器限制,可以选择也将改善用户体验的日期。
Side note: You view model could include a DateTime MinDate
property (include as a hidden input in the view), then apply a foolproof [GreaterThan]
or similar attribute to your Date
property so you get both client and server side validation out of the box. A jquery datepicker plugin that limits the dates that can be selected would also improve user experience.
这篇关于无效操作异常MVC C#的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!