使用ASP.NET Core MVC编辑Cascade DropDownList

时间:2017-06-28 15:30:01

标签: c# asp.net asp.net-mvc

我无法根据我想要编辑的所选客户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; }
}

SubLocality模型

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; }
}

CustomersController

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

创建视图

&#13;
&#13;
@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>

}
&#13;
&#13;
&#13;

修改视图

&#13;
&#13;
@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>

}
&#13;
&#13;
&#13;

1 个答案:

答案 0 :(得分:0)

可能你在View上错过了这个指令:

@using (Html.BeginForm("ActionName", "ControllerName", FormMethod.Post, new { @class = "form-horizontal", role = "form" }))