级联下拉菜单 - 无效值

Cascading Drop Down - Invalid Value

我是 MVC 新手,很难从数据库创建级联下拉列表。选择一个诊所后,从事该诊所工作的配镜师会填充,但它不会保存到 dataView 模型:

public class BookingViewModel
{
    [Display (Name = "Select Patient")]
    public Guid PatientId { get; set; }
    public IEnumerable<SelectListItem> PatientList { get; set; }

    [Display(Name = "Select Practice")]
    public Guid PracticeId { get; set; }
    public IEnumerable<SelectListItem> PracticeList { get; set; }

    [Display(Name = "Select Optician")]
    public Guid OpticianId { get; set; }
    public IEnumerable<SelectListItem> OpticiansList { get; set; }

    [Display(Name = "Select Date")]
    [DataType(DataType.Date)]
    [DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:dd/MM/yyyy}")]
    public DateTime Date { get; set; }

    [Display(Name = "Select Time")]
    public Guid TimeId { get; set; }
    public IEnumerable<SelectListItem> TimeList { get; set; }  
}

}

我的预订控制器:

  public ActionResult Create()
    {
        // Creates a new booking
        BookingViewModel bookingViewModel = new BookingViewModel();
        // Initilises Select List
        ConfigureCreateViewModel(bookingViewModel);

        return View(bookingViewModel);

    }

    // Initilises Select List 
    public void ConfigureCreateViewModel(BookingViewModel bookingViewModel)
    {
        // Displays Opticians Name 
        bookingViewModel.OpticiansList = db.Opticians.Select(o => new SelectListItem()
        {
            Value = o.OpticianId.ToString(),
            Text = o.User.FirstName
        });

        // Displays Patients name 
        bookingViewModel.PatientList = db.Patients.Select(p => new SelectListItem()
        {
            Value = p.PatientId.ToString(),
            Text = p.User.FirstName
        });

        // Displays Practice Name
        bookingViewModel.PracticeList = db.Practices.Select(p => new SelectListItem()
        {
            Value = p.PracticeId.ToString(),
            Text = p.PracticeName
        });

        // Displays Appointment Times 
        bookingViewModel.TimeList = db.Times.Select(t => new SelectListItem()
        {
            Value = t.TimeId.ToString(),
            Text = t.AppointmentTime
        });


    }


    // Allows Admin to create booking for patient 
    // POST: Bookings1/Create
    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Create(BookingViewModel bookingViewModel)
    {
        // to ensure date is in the future
        if (ModelState.IsValidField("Date") && DateTime.Now > bookingViewModel.Date)
        {
            ModelState.AddModelError("Date", "Please enter a date in the future");
        }



        // if model state is not valid
        if (!ModelState.IsValid)
        {
            // Initilises Select lists
            ConfigureCreateViewModel(bookingViewModel);
            return View(bookingViewModel); // returns user to booking page


        }
        else // if model state is Valid
        {
            Booking booking = new Booking();
            // Sets isAvail to false
            booking.isAvail = false;
            booking.PracticeId = bookingViewModel.PracticeId;
            booking.OpticianId = bookingViewModel.OpticianId;
            booking.PatientId = bookingViewModel.PatientId;
            booking.Date = bookingViewModel.Date;
            booking.TimeId = bookingViewModel.TimeId;

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

 // Json for cascading drop down, to allow the user to select an optician from the selected practice.
    [HttpPost]
    public JsonResult Opticians(Guid Id)
    {
        var opticianList = db.Opticians.Where(a => a.PracticeId == Id).Select(a => a.User.FirstName).ToList();

        return Json(opticianList);
    }

我的看法:

<script>
$(document).ready(function () {
    $("#OpticianId").prop("disabled", true);
    $("#PracticeId").change(function () {
        $.ajax({
            url : "@Url.Action("Opticians","Bookings")",
            type : "POST",
            data : {Id : $(this).val() }
        }).done(function (opticianList) {
            $("#OpticianId").empty();
            for (var i = 0; i < opticianList.length; i++) {
                $("#OpticianId").append("<option>" + opticianList[i] + "</option>");
            }
            $("#OpticianId").prop("disabled", false);
        });
    });
});

 <div class="form-group">
        @Html.Label("Select Optician :", new { @class = "col-md-2 control-label" })
        <div class="col-md-10">

            @Html.DropDownListFor(model => model.OpticianId, Model.OpticiansList, "-Please Select-", new { @class = "form-control" })
            @Html.ValidationMessageFor(model => model.OpticianId, "", new { @class = "text-danger" })
        </div>
    </div>

级联下拉列表工作正常,但是当我尝试将其保存到数据库时出现验证错误 -

The value 'Name' is not valid for Select Optician

如有任何帮助,我们将不胜感激。谢谢

因为您的 Opticians(Guid Id) 方法仅 return 从您的 Opticians table 中获取 User.FirstName 属性,因此所选值OpticianId 的下拉列表回传所选的 FirstName 值,该值不能绑定到 Guid 属性。 html 你的生成是

<option>Some Name</option>

但必须

<option value="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx">Some Name</option>

将方法更改为 return ID 和 Name 属性

[HttpPost]
public JsonResult Opticians(Guid Id)
{
    var opticianList = db.Opticians.Where(a => a.PracticeId == Id).Select(a => new
    {
      Value = a.OpticianId,
      Text = a.User.FirstName
    }).ToList();
    return Json(opticianList);
}

然后将脚本更改为

var opticians = $("#OpticianId"); // cache elements you repeatedly refer to
opticians.prop("disabled", true);
$("#PracticeId").change(function () {
    $.ajax({
        url : "@Url.Action("Opticians","Bookings")",
        type : "POST",
        data : {Id : $(this).val() }
    }).done(function (opticianList) {
        opticians.empty();
        $.each(opticianList, function(index, item) {
            opticians.append($('<option></option>').val(item.Value).text(item.Text));
        });
        opticians.prop("disabled", false);
    });
});