使用 ASP.NET Core MVC 编辑 Cascade DropDownList
Posted
技术标签:
【中文标题】使用 ASP.NET Core MVC 编辑 Cascade DropDownList【英文标题】:Edit Cascade DropDownList using ASP.NET Core MVC 【发布时间】:2017-12-02 01:49:59 【问题描述】:我无法根据我希望编辑的所选客户 ID 从数据库中检索/显示 CityId 值到 City 下拉列表。
当我选择要编辑的客户时,它会正确填充数据库中的数据,但城市下拉列表除外。城市下拉列表将显示“选择城市”以及与州下拉列表中的州相关的所有城市。
如果我选择另一个州,那么它会正确加载所选州的所有城市。
问题是它没有像我第一次根据所选客户 ID 加载页面时那样显示城市下拉列表的城市值。
我是 jQuery/AJAX 的新手,有人帮我编写级联下拉列表的 jQuery 代码。
我在下面提供了我现在正在使用的 ViewModel、Controller 和 Edit View:
客户模型
public class Customer
public int CustomerId get; set;
public string FirstName get; set;
public string LastName get; set;
public int CityId get; set;
public City City get; set;
public int LocalityId get; set;
public Locality Locality get; set;
public int SubLocalityId get; set;
public SubLocality SubLocality get; set;
城市模型
public class City
public int ID get; set;
public string Name get; set;
public List<Customer> Customers get; set;
public List<Locality> Localities get; set;
局部模型
public class Locality
public int ID get; set;
public string Name get; set;
public int CityId get; set;
public City City get; set;
public List<Customer> Customers get; set;
public List<SubLocality> SubLocalities get; set;
子区域模型
public class SubLocality
public int ID get; set;
public string Name get; set;
public int LocalityId get; set;
public Locality Locality get; set;
public List<Customer> Customers get; set;
WebAppDbContext
public class WebAppDbContext : DbContext
public WebAppDbContext(DbContextOptions<WebAppDbContext> options) : base(options)
public DbSet<Customer> Customers get; set;
public DbSet<City> Cities get; set;
public DbSet<Locality> Localities get; set;
public DbSet<SubLocality> SubLocalities get; set;
protected override void OnModelCreating(ModelBuilder modelBuilder)
modelBuilder.Entity<Customer>()
.HasKey(c => c.CustomerId);
modelBuilder.Entity<Customer>()
.Property(c => c.FirstName)
.HasColumnType("varchar(50)")
.HasMaxLength(50)
.IsRequired();
modelBuilder.Entity<Customer>()
.Property(c => c.LastName)
.HasColumnType("varchar(50)")
.HasMaxLength(50)
.IsRequired();
modelBuilder.Entity<City>()
.HasKey(ci => ci.ID);
modelBuilder.Entity<City>()
.Property(ci => ci.Name)
.HasColumnType("varchar(50)")
.HasMaxLength(50)
.IsRequired();
modelBuilder.Entity<City>()
.HasMany(ci => ci.Customers)
.WithOne(c => c.City)
.HasForeignKey(c => c.CityId);
modelBuilder.Entity<City>()
.HasMany(l => l.Localities)
.WithOne(ci => ci.City)
.HasForeignKey(ci => ci.CityId);
modelBuilder.Entity<Locality>()
.HasKey(l => l.ID);
modelBuilder.Entity<Locality>()
.Property(l => l.Name)
.HasColumnType("varchar(50)")
.HasMaxLength(50)
.IsRequired();
modelBuilder.Entity<Locality>()
.HasMany(l => l.Customers)
.WithOne(c => c.Locality)
.HasForeignKey(c => c.LocalityId);
modelBuilder.Entity<Locality>()
.HasMany(sl => sl.SubLocalities)
.WithOne(l => l.Locality)
.HasForeignKey(l => l.LocalityId);
modelBuilder.Entity<SubLocality>()
.HasKey(sl => sl.ID);
modelBuilder.Entity<SubLocality>()
.Property(sl => sl.Name)
.HasColumnType("varchar(50)")
.HasMaxLength(50)
.IsRequired();
modelBuilder.Entity<SubLocality>()
.HasMany(sl => sl.Customers)
.WithOne(c => c.SubLocality)
.HasForeignKey(c => c.SubLocalityId);
CustomerFormVM
public class CustomerFormVM
[Required(ErrorMessage = "Please enter a First Name")]
[Display(Name = "First Name")]
public string FirstName get; set;
[Required(ErrorMessage = "Please enter a Last Name")]
[Display(Name = "Last Name")]
public string LastName get; set;
[Required(ErrorMessage = "Please select a city")]
[Display(Name = "City")]
public int? SelectedCity get; set;
[Required(ErrorMessage = "Please select a locality")]
[Display(Name = "Locality")]
public int? SelectedLocality get; set;
[Required(ErrorMessage = "Please select a sub locality")]
[Display(Name = "Sub Locality")]
public int? SelectedSubLocality get; set;
public SelectList CityList get; set;
public SelectList LocalityList get; set;
public SelectList SubLocalityList get; set;
客户控制器
public class CustomersController : Controller
private readonly WebAppDbContext _context;
public CustomersController(WebAppDbContext context)
_context = context;
// GET: Customers
public async Task<IActionResult> Index()
var webAppDbContext = _context.Customers.Include(c => c.City).Include(c => c.Locality).Include(c => c.SubLocality);
return View(await webAppDbContext.ToListAsync());
// GET: Customers/Details/5
public async Task<IActionResult> Details(int? id)
if (id == null)
return NotFound();
var customer = await _context.Customers
.Include(c => c.City)
.Include(c => c.Locality)
.Include(c => c.SubLocality)
.SingleOrDefaultAsync(m => m.CustomerId == id);
if (customer == null)
return NotFound();
return View(customer);
// GET: Customers/Create
[HttpGet]
public ActionResult Create()
CustomerFormVM model = new CustomerFormVM();
ConfigureViewModel(model);
return View(model);
// POST: Customers/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(CustomerFormVM vm)
if (ModelState.IsValid)
var customer = new Customer();
customer.FirstName = vm.FirstName;
customer.LastName = vm.LastName;
customer.CityId = vm.SelectedCity.Value;
customer.LocalityId = vm.SelectedLocality.Value;
customer.SubLocalityId = vm.SelectedSubLocality.Value;
_context.Customers.Add(customer);
_context.SaveChanges();
return RedirectToAction("Index");
else
ConfigureViewModel(vm);
return View(vm);
[HttpGet]
public JsonResult FetchLocalities(int ID)
var data = _context.Localities
.Where(l => l.CityId == ID)
.Select(l => new val = l.ID, text = l.Name );
return Json(data);
[HttpGet]
public JsonResult FetchSubLocalities(int ID)
var data = _context.SubLocalities
.Where(l => l.LocalityId == ID)
.Select(l => new val = l.ID, text = l.Name );
return Json(data);
private void ConfigureViewModel(CustomerFormVM model)
List<City> cities = _context.Cities.ToList();
model.CityList = new SelectList(cities, "ID", "Name");
if (model.SelectedCity.HasValue)
IEnumerable<Locality> localities = _context.Localities.Where(l => l.CityId == model.SelectedCity.Value);
model.LocalityList = new SelectList(localities, "ID", "Name");
else
model.LocalityList = new SelectList(Enumerable.Empty<SelectListItem>());
if (model.SelectedLocality.HasValue)
IEnumerable<SubLocality> subLocalities = _context.SubLocalities.Where(l => l.LocalityId == model.SelectedLocality.Value);
model.SubLocalityList = new SelectList(subLocalities, "ID", "Name");
else
model.SubLocalityList = new SelectList(Enumerable.Empty<SelectListItem>());
public ActionResult Edit(int? id)
if (id == null)
return NotFound();
var customervm = new CustomerFormVM();
Customer customer = _context.Customers.SingleOrDefault(c => c.CustomerId == id);
if (customer == null)
return NotFound();
customervm.CustomerId = customer.CustomerId;
customervm.FirstName = customer.FirstName;
customervm.LastName = customer.LastName;
return View(customervm);
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(CustomerFormVM vmEdit)
if (ModelState.IsValid)
Customer customer = _context.Customers.SingleOrDefault(c => c.CustomerId == vmEdit.CustomerId);
if (customer == null)
return NotFound();
customer.FirstName = vmEdit.FirstName;
customer.LastName = vmEdit.LastName;
_context.Entry(customer).State = EntityState.Modified;
_context.SaveChanges();
return RedirectToAction("Index");
return View(vmEdit);
// GET: Customers/Delete/5
public async Task<IActionResult> Delete(int? id)
if (id == null)
return NotFound();
var customer = await _context.Customers
.Include(c => c.City)
.Include(c => c.Locality)
.Include(c => c.SubLocality)
.SingleOrDefaultAsync(m => m.CustomerId == id);
if (customer == null)
return NotFound();
return View(customer);
// POST: Customers/Delete/5
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public async Task<IActionResult> DeleteConfirmed(int id)
var customer = await _context.Customers.SingleOrDefaultAsync(m => m.CustomerId == id);
_context.Customers.Remove(customer);
await _context.SaveChangesAsync();
return RedirectToAction("Index");
private bool CustomerExists(int id)
return _context.Customers.Any(e => e.CustomerId == id);
创建视图
@using (html.BeginForm("Create", "Customers"))
<div class="form-group">
@Html.LabelFor(c => c.FirstName)
@Html.TextBoxFor(c => c.FirstName, new @class = "form-control" )
</div>
<div class="form-group">
@Html.LabelFor(c => c.LastName)
@Html.TextBoxFor(c => c.LastName, new @class = "form-control" )
</div>
<div class="form-group">
@Html.LabelFor(m => m.SelectedCity)
@Html.DropDownListFor(m => m.SelectedCity, Model.CityList, "Please select", new @class = "form-control" )
@Html.ValidationMessageFor(m => m.SelectedCity)
</div>
<div class="form-group">
@Html.LabelFor(m => m.SelectedLocality)
@Html.DropDownListFor(m => m.SelectedLocality, Model.LocalityList, "", new @class = "form-control" )
@Html.ValidationMessageFor(m => m.SelectedLocality)
</div>
<div class="form-group">
@Html.LabelFor(m => m.SelectedSubLocality)
@Html.DropDownListFor(m => m.SelectedSubLocality, Model.SubLocalityList, "", new @class = "form-control" )
@Html.ValidationMessageFor(m => m.SelectedSubLocality)
</div>
<div class="form-group">
<input type="submit" value="Save" class="btn btn-default" />
</div>
<div>
<a asp-action="Index">Back to List</a>
</div>
@section Scripts
@await Html.RenderPartialAsync("_ValidationScriptsPartial");
<script type="text/javascript">
var localityUrl = '@Url.Action("FetchLocalities")';
var subLocalityUrl = '@Url.Action("FetchSubLocalities")';
var localities = $('#SelectedLocality');
var subLocalities = $('#SelectedSubLocality');
$('#SelectedCity').change(function()
localities.empty();
subLocalities.empty();
$.getJSON(localityUrl, ID: $(this).val() ,function (data)
if (!data)
return;
localities.append($('<option></option>').val('').text('Please select'));
$.each(data, function(index, item)
localities.append($('<option></option>').val(item.val).text(item.text));
);
);
)
$('#SelectedLocality').change(function()
subLocalities.empty();
$.getJSON(subLocalityUrl, ID: $(this).val() ,function (data)
if (!data)
return;
subLocalities.append($('<option></option>').val('').text('Please Select'));
$.each(data, function(index, item)
subLocalities.append($('<option></option>').val(item.val).text(item.text));
);
);
)
</script>
编辑视图
@using (Html.BeginForm("Edit", "Customers"))
<div class="form-group">
@Html.LabelFor(c => c.FirstName)
@Html.TextBoxFor(c => c.FirstName, new @class = "form-control" )
</div>
<div class="form-group">
@Html.LabelFor(c => c.LastName)
@Html.TextBoxFor(c => c.LastName, new @class = "form-control" )
</div>
<div class="form-group">
@Html.LabelFor(m => m.SelectedCity)
@Html.DropDownListFor(m => m.SelectedCity, Model.CityList, "Please select", new @class = "form-control" )
@Html.ValidationMessageFor(m => m.SelectedCity)
</div>
<div class="form-group">
@Html.LabelFor(m => m.SelectedLocality)
@Html.DropDownListFor(m => m.SelectedLocality, Model.LocalityList, "", new @class = "form-control" )
@Html.ValidationMessageFor(m => m.SelectedLocality)
</div>
<div class="form-group">
@Html.LabelFor(m => m.SelectedSubLocality)
@Html.DropDownListFor(m => m.SelectedSubLocality, Model.SubLocalityList, "", new @class = "form-control" )
@Html.ValidationMessageFor(m => m.SelectedSubLocality)
</div>
@Html.HiddenFor(m => m.CustomerId)
<div class="form-group">
<input type="submit" value="Save" class="btn btn-default" />
</div>
<div>
<a asp-action="Index">Back to List</a>
</div>
@section Scripts
@await Html.RenderPartialAsync("_ValidationScriptsPartial");
<script type="text/javascript">
var localityUrl = '@Url.Action("FetchLocalities")';
var subLocalityUrl = '@Url.Action("FetchSubLocalities")';
var localities = $('#SelectedLocality');
var subLocalities = $('#SelectedSubLocality');
$('#SelectedCity').change(function()
localities.empty();
subLocalities.empty();
$.getJSON(localityUrl, ID: $(this).val() ,function (data)
if (!data)
return;
localities.append($('<option></option>').val('').text('Please select'));
$.each(data, function(index, item)
localities.append($('<option></option>').val(item.val).text(item.text));
);
);
)
$('#SelectedLocality').change(function()
subLocalities.empty();
$.getJSON(subLocalityUrl, ID: $(this).val() ,function (data)
if (!data)
return;
subLocalities.append($('<option></option>').val('').text('Please Select'));
$.each(data, function(index, item)
subLocalities.append($('<option></option>').val(item.val).text(item.text));
);
);
)
</script>
【问题讨论】:
您确定 JQUERY 工作正常吗?在视图中,我在部分脚本中放置了这个标记 (更改正确的版本)。 是的,jQuery 代码在我这边工作。 jQuery 2.2.0 我的 Create 方法有相同的 jQuery 代码,它工作正常,唯一的问题是我无法根据为 Edit 方法选择的 CustomerId 检索 CityId。 为什么需要这个`$("#StateId").trigger('change');`?您的页面将使用您拥有的服务器代码在下拉列表中加载所选城市。 建议您参考this answer了解如何正确处理 【参考方案1】:可能你在视图上错过了这个指令:
@using (Html.BeginForm("ActionName", "ControllerName", FormMethod.Post, new @class = "form-horizontal", role = "form" ))
【讨论】:
我用你提供的东西替换了我拥有的东西,但我得到了相同的结果。以上是关于使用 ASP.NET Core MVC 编辑 Cascade DropDownList的主要内容,如果未能解决你的问题,请参考以下文章
为啥我的 SelectListItem 无法编辑 ASP.NET Core MVC
如何在 ASP.NET Core MVC 中使用 select 标签动态编辑数据库表?
ASP.NET Core MVC:在发布编辑方法之前删除多对多条目
ASP.NET Core MVC 2.x 全面教程_ASP.NET Core MVC 17. 基于Claim和Policy的授权 上