I have been scratching my head for a whole night on an issue I can do quickly using ajax/jquery and stored procedures. I want to
1) Populate a drop down list from values obtained from a database table using Entity Framework and view model. I DO NOT WANT TO USE VIEWBAG OR VIEWDATA. Any help appreciated.
2) How can I generate a Create View using the View Model with the all the default fields ? The scaffholding works on a model but not on a view model ?
MY MODELS
public class Employee
{
public int EmployeeID { get; set; }
public string Name { get; set; }
public string Gender { get; set; }
public string City { get; set; }
public string Level { get; set; }
public int DepartmentId { get; set; }
}
public class Grade
{
public int ID { get; set; }
public string Level { get; set; }
}
View Model
public class GradeSelectListViewModel
{
public Employee Employee { get; set; }
public IEnumerable<SelectListItem> Grades { get; set; }
public GradeSelectListViewModel(Employee employee, IEnumerable grades)
{
Employee = employee;
Grades = new SelectList(grades, "Grade", "Name", employee.Level);
}
}
MY CONTEXT CLASS
public class EmployeeContext : DbContext
{
public DbSet<Employee> Employees { get; set; }
public DbSet<Department> Departments { get; set; }
public DbSet<Grade> Grades { get; set; }
}
MY CONTROLLER
public ActionResult Edit (int? id)
{
using (var db = new EmployeeContext())
{
var model = new GradeSelectListViewModel(db.Employees.Find(id), db.Grades);
//model.Employee = db.Employees.Single(x => x.EmployeeID == id);
model.Grades = db.Grades.ToList().Select(x => new SelectListItem
{
Value = x.ID.ToString(),
Text = x.Level
});
return View(model);
}
}
MY RAZOR PAGE CSHTML
@model MVCDemo.ViewModels.GradeSelectListViewModel
....
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
....
@Html.DropDownListFor(x => Model.Employee.Level,
new SelectList(Model.Grades, "ID", "Level"),
"Select Level")
....
<input type="submit" value="Create" class="btn btn-default" />
}
The main issue is that in the view you have new SelectList(Model.Grades, "ID", "Level")
but Grades
is IEnumerable<SelectListItem>
and SelectListItem
does not contain properties named ID
and Level
.
However there are a a few other issues with your code. First a view model should not contain a data model, and instead your view model should be
public class GradeSelectListViewModel
{
public int? ID { get; set; } // make this ID so you do not need an input for it
public string Name { get; set; }
.... // other properties of Employee that your editing
[Required(ErrorMessage = "..")]
public int? Level { get; set; } // make value types nullable to protect against under-posting attacks
public IEnumerable<SelectListItem> Grades { get; set; }
}
and add display and validation attributes as required. Note that I deleted the constructor (you don't seem to be using it, but if you did, then you also need to include a parameter-less constructor, otherwise an exception will be thrown when submitting to the POST method. I also assume that Level
should be typeof int
since you binding to the int ID
property of Grade
.
The the code in your GET method should be
Employee employee = db.Employees.Find(id);
var model = new GradeSelectListViewModel()
{
ID = employee.EmployeeID,
Name = employee.Name,
Level = employee.Level, // convert to int?
....
Grades = db.Grades.Select(x => new SelectListItem
{
Value = x.ID.ToString(),
Text = x.Level
})
};
return View(model);
and in the view
@Html.DropDownListFor(x => Model.Level, Model.Grades, "Select Level")
Note also that in the POST method, your need to reassign the SelectList
if you return the view because ModelState
is invalid.
You can use the following approach that populates three DropDownListFor at the same View:
ViewModel:
public class GroupViewModel
{
public IEnumerable<SelectListItem> Schedules { get; set; }
public int ScheduleId { get; set; }
public IEnumerable<SelectListItem> Labs { get; set; }
public int LabId { get; set; }
public IEnumerable<SelectListItem> Terms { get; set; }
public int TermId { get; set; }
}
Controller:
public ActionResult Create()
{
//Populate DropDownList binding values
var model = new GroupViewModel
{
//Preselect the Lab with id 2
//LabId = 2,
Labs = repository.Labs.Select(c => new SelectListItem
{
Value = c.Id.ToString(),
Text = c.Name
}),
Terms = repository.Terms.Select(c => new SelectListItem
{
Value = c.Id.ToString(),
Text = c.Name
}),
Schedules = repository.Schedules.Select(c => new SelectListItem
{
Value = c.Id.ToString(),
Text = c.Name
})
};
return View("Create", model);
}
View:
@Html.DropDownListFor(m => m.LabId, new SelectList(Model.Labs, "Value", "Text"),
"Select", new { @class = "selectpicker" })
@Html.DropDownListFor(m => m.ScheduleId, new SelectList(Model.Schedules, "Value", "Text"),
"Select", new { @class = "selectpicker" })
@Html.DropDownListFor(m => m.TermId, new SelectList(Model.Terms, "Value", "Text"),
"Select", new { @class = "selectpicker" })
Hope this helps...
来源:https://stackoverflow.com/questions/42549622/populate-dropdownlist-in-asp-net-mvc-from-database-table-using-entity-framework