ASP.NET MVC 核心级联 DropDownList [英] ASP.NET MVC Core Cascading DropDownList

查看:25
本文介绍了ASP.NET MVC 核心级联 DropDownList的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我无法找到展示如何使用 EntityFramework 从数据库实现级联 DropDownList 的教程/视频.我正在使用 ASP.NET MVC Core、EntityFramework Core 和 C#.

截至目前,我可以将数据库中的数据检索到我的 3 DropDownList 中.

我希望能够完成的是让用户首先选择一个州,然后显示与该州相关的所有城市.然后在用户选择一个城市后,它会显示与该城市相关的邮政编码.

任何帮助将不胜感激.

模型

 公共类客户{公共 int CustomerId { 获取;放;}公共字符串名字{获取;放;}公共字符串姓氏 { 获取;放;}公共 int StateId { 获取;放;}公共 int CityId { 获取;放;}公共 int ZipId { 获取;放;}公共状态状态 { 获取;放;}公共城市城市{得到;放;}公共邮编邮编{得到;放;}}公共类状态{公共 int StateId { 获取;放;}公共字符串缩写 { 获取;放;}公共列表<客户>客户{得到;放;}}公开课城市{公共 int CityId { 获取;放;}公共字符串名称 { 获取;放;}公共 int StateId { 获取;放;}公共状态状态 { 获取;放;}公共列表<客户>客户{得到;放;}}公开课邮编{公共 int ZipId { 获取;放;}公共字符串邮政编码 { 获取;放;}公共 int CityId { 获取;放;}公共城市城市{得到;放;}公共列表<客户>客户{得到;放;}}

视图模型

 公共类 CustomerFormVM{公共 int CustomerId { 获取;放;}[显示(名称=名字")][字符串长度(50)]公共字符串名字{获取;放;}[显示(名称 =姓氏")][字符串长度(50)]公共字符串姓氏 { 获取;放;}[必需(ErrorMessage =选择状态")][显示(名称=状态")]公共 int StateId { 获取;放;}//公共IEnumerable<状态>状态 { 得到;放;}公共 IEnumerable状态 { 得到;放;}[必填(ErrorMessage =选择城市")][显示(名称=城市")]公共 int CityId { 获取;放;}//公共IEnumerable城市 { 得到;放;}公共 IEnumerable城市 { 得到;放;}[必需(ErrorMessage =选择邮编")][显示(名称=邮编")]公共 int ZipId { 获取;放;}//公共IEnumerable邮编{得到;放;}公共 IEnumerable邮编{得到;放;}}

客户控制器

public class CustomerController : Controller{私有 MultiDbContext 数据库;公共客户控制器(MultiDbContext 上下文){db = 上下文;}//获取:/<控制器>/公共 IActionResult 索引(){返回视图(db.Customers.ToList());}公共 IActionResult getCititesFromDatabaseByStateId(int id){返回视图(db.Citys.Where(c => c.StateId == id).ToList());}公共 IActionResult getCities(int id){var city = new List();城市 = getCititesFromDatabaseByStateId(id);//调用存储库返回 Json(城市);}公共 ActionResult 创建(){var 状态 = db.States.ToList();var citys = db.Citys.ToList();var zips = db.Zips.ToList();var viewModel = 新的 CustomerFormVM{状态 = 状态,城市 = 城市,拉链 = 拉链};返回视图(视图模型);}[HttpPost][验证AntiForgeryToken]公共 ActionResult 创建(CustomerFormVM vm){如果(模型状态.IsValid){var customer = new Customer();{customer.FirstName = vm.FirstName;customer.LastName = vm.LastName;客户.StateId = vm.StateId;客户.CityId = vm.CityId;客户.ZipId = vm.ZipId;}db.Customers.Add(客户);db.SaveChanges();return RedirectToAction("索引");}别的{vm.States = db.States.ToList();vm.Citys = db.Citys.ToList();vm.Zips = db.Zips.ToList();返回视图(vm);}}公共操作结果编辑(int?id){如果(id == null){返回 NotFound();}var customervm = new CustomerFormVM();{客户客户 = db.Customers.SingleOrDefault(c => c.CustomerId == id);如果(客户 == 空){返回 NotFound();}customervm.CustomerId = customer.CustomerId;customervm.FirstName = customer.FirstName;customervm.LastName = customer.LastName;//检索状态列表var 状态 = db.States.ToList();customervm.States = 状态;//检索城市列表var citys = db.Citys.ToList();customervm.Citys = 城市;//检索城市列表var zips = db.Zips.ToList();customervm.Zips = zips;//设置选中状态customervm.StateId = customer.StateId;//设置选中的城市customervm.CityId = customer.CityId;//设置选中的zipcustomervm.ZipId = customer.ZipId;}返回视图(客户虚拟机);}[HttpPost][验证AntiForgeryToken]公共操作结果编辑(CustomerFormVM vmEdit){如果(模型状态.IsValid){客户客户 = db.Customers.SingleOrDefault(c => c.CustomerId == vmEdit.CustomerId);如果(客户 == 空){返回 NotFound();}customer.FirstName = vmEdit.FirstName;customer.LastName = vmEdit.LastName;customer.StateId = vmEdit.StateId;customer.CityId = vmEdit.CityId;customer.ZipId = vmEdit.ZipId;db.Entry(customer).State = EntityState.Modified;db.SaveChanges();return RedirectToAction("索引");}返回视图(vmEdit);}}

创建视图

 

@Html.LabelFor(c => c.FirstName)@Html.TextBoxFor(c => c.FirstName, new { @class = "form-control" })

<div class="form-group">@Html.LabelFor(c => c.LastName)@Html.TextBoxFor(c => c.LastName, new { @class = "form-control" })

<div class="form-group">@*@Html.LabelFor(s => s.StateId)@Html.DropDownListFor(s => s.StateId, new SelectList(Model.States, "StateId", "Abbr"), "", new { @class = "form-control" })@Html.ValidationMessageFor(s => s.StateId)*@<label asp-for="StateId "></label><select asp-for="StateId" asp-items="Model.States" class="form-control" id="state-target"></select><span asp-validation-for="StateId" class="text-danger"></span>

<div class="form-group">@*@Html.LabelFor(ct => ct.CityId)@Html.DropDownListFor(ct => ct.CityId, new SelectList(Model.Citys, "CityId", "Name"), "", new { @class = "form-control" })@Html.ValidationMessageFor(ct =>ct.CityId)*@<label asp-for="CityId"></label><select asp-for="CityId" asp-items="Model.Citys" class="form-control" id="city-target"></select><span asp-validation-for="CityId" class="text-danger"></span>

<div class="form-group">@Html.LabelFor(z => z.ZipId)@Html.DropDownListFor(z => z.ZipId, new SelectList(Model.Zips, "ZipId", "PostalCode"), "", new { @class = "form-control" })@Html.ValidationMessageFor(z => z.ZipId)

<div class="form-group"><button type="submit" class="btn btn-primary">提交</button>

}@section 脚本 {<script src="~/lib/jquery-validation/dist/jquery.validate.js"></script><script src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js"></script><script src="~/lib/js/example.js"></script>,}

解决方案

我有类似的情况,但在我的示例中,我有一个根文件夹,根据我使用的根文件夹,下一个下拉列表将显示相应的子-文件夹.

不确定是否有纯粹的 asp.net 解决方案,但是我为此使用了 Jquery/Ajax.

您的代码应如下所示:

html 列表:

<select asp-for="StateId" asp-items="Model.States" class="form-control" id="state-target"></select><span asp-validation-for="StateId" class="text-danger"></span><label asp-for="CityId"></label><select asp-for="CityId" asp-items="Model.Citys" class="form-control" id="city-target"></select><span asp-validation-for="CityId" class="text-danger"></span>

Jquery 代码,你把它写在 .js 文件中,然后用这个语句把它添加到一个特定的视图中<script src="~/js/example.js"></script>,不要忘记你需要在任何其他 javascript 之前向你的项目添加一个 jquery 库,并且你的 example.js 将包含:

$(document).ready(function () {$("#state-target").on("change", function () {$list = $("#city-target");$.ajax({url: "/getCities",类型:获取",data: { id: $("#state-target").val() },//用于提取城市的州的id传统:真实,成功:功能(结果){$list.empty();$.each(result, function (i, item) {$list.append('<option value="' + item["CityId"] + '"> ' + item["Name"] + ' </option>');});},错误:函数(){alert("出了点问题报警");}});});});

Ajax 请求将在 Controller 中调用此操作,该操作将从数据库中检索城市列表(使用类似 return dbContext.CityTable.Where(c => c.StateId == id).ToList()getCititesFromDatabaseByStateId(id) 方法中)然后返回 Json 对象,success 函数将创建一个选项列表并应用它:

public IActionResult getCities(int id){var city = new List();城市 = getCititesFromDatabaseByStateId(id);//调用存储库返回 Json(citites);}

在您的 ViewModel 中,考虑将 IEnumerable (IEnumerable) 更改为 IEnumerable;.我也可以说你的模型很乱(但如果你能从数据库中获取数据专注于让列表第一次工作),请考虑稍后改进它们.

修复评论中提到的 2 个错误:

公共列表<城市>getCititesFromDatabaseByStateId(int id){返回 db.Citys.Where(c => c.StateId == id).ToList();}公共 ActionResult 创建(){var states = new SelectList(db.States.ToList(), "StateId", "Abbr");var citys = new SelectList(db.Citys.ToList(), "CityId", "Name");var zips = new SelectList(db.Zips.ToList(), "ZipId", "Code");var viewModel = 新的 CustomerFormVM{状态 = 状态,城市 = 城市,拉链 = 拉链};返回视图(视图模型);}

I'm having trouble finding a tutorial / video that shows how to implement Cascading DropDownList from a Database using EntityFramework. I'm using ASP.NET MVC Core, EntityFramework Core with C#.

As of now, I'm able to retrieve the data from my database to my 3 DropDownList fine.

What I would like to be able to accomplish is to have the user select a State first which would then display all Cities related to that State. Then after user has selected a City it would display the Zip Code(s) related to the City.

Any help would be greatly appreciated.

Models

    public class Customer
{
    public int CustomerId { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }

    public int StateId { get; set; }
    public int CityId { get; set; }
    public int ZipId { get; set; }

    public State State { get; set; }
    public City City { get; set; }
    public Zip Zip { get; set; }
}

    public class State
{
    public int StateId { get; set; }
    public string Abbr { get; set; }

    public List<Customer> Customers { get; set; }
}

    public class City
{
    public int CityId { get; set; }
    public string Name { get; set; }

    public int StateId { get; set; }
    public State State { get; set; }

    public List<Customer> Customers { get; set; }
}

    public class Zip
{
    public int ZipId { get; set; }
    public string PostalCode { get; set; }

    public int CityId { get; set; }
    public City City { get; set; }

    public List<Customer> Customers { get; set; }
}

ViewModels

    public class CustomerFormVM
{
    public int CustomerId { get; set; }

    [Display(Name = "First Name")]
    [StringLength(50)]
    public string FirstName { get; set; }

    [Display(Name = "Last Name")]
    [StringLength(50)]
    public string LastName { get; set; }

    [Required(ErrorMessage = "Select State")]
    [Display(Name = "State")]
    public int StateId { get; set; }

    //public IEnumerable<State> States { get; set; }
    public IEnumerable<SelectListItem> States { get; set; }

    [Required(ErrorMessage = "Select City")]
    [Display(Name = "City")]
    public int CityId { get; set; }

    //public IEnumerable<City> Citys { get; set; }
    public IEnumerable<SelectListItem> Citys { get; set; }

    [Required(ErrorMessage = "Select Zip")]
    [Display(Name = "Zip")]
    public int ZipId { get; set; }

    //public IEnumerable<Zip> Zips { get; set; }
    public IEnumerable<SelectListItem> Zips { get; set; }
}

CustomerController

public class CustomerController : Controller
{
    private MultiDbContext db;

    public CustomerController(MultiDbContext context)
    {
        db = context;
    }

    // GET: /<controller>/
    public IActionResult Index()
    {
        return View(db.Customers.ToList());
    }

    public IActionResult getCititesFromDatabaseByStateId(int id)
    {
        return View(db.Citys.Where(c => c.StateId == id).ToList());
    }

    public IActionResult getCities(int id)
    {
        var cities = new List<City>();
        cities = getCititesFromDatabaseByStateId(id); //call repository
        return Json(cities);
    }

    public ActionResult Create()
    {
        var states = db.States.ToList();
        var citys = db.Citys.ToList();
        var zips = db.Zips.ToList();

        var viewModel = new CustomerFormVM
        {
            States = states,
            Citys = citys,
            Zips = zips
        };

        return View(viewModel);
    }


    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Create(CustomerFormVM vm)
    {
        if (ModelState.IsValid)
        {
            var customer = new Customer();
            {
                customer.FirstName = vm.FirstName;
                customer.LastName = vm.LastName;
                customer.StateId = vm.StateId;
                customer.CityId = vm.CityId;
                customer.ZipId = vm.ZipId;
            }
            db.Customers.Add(customer);
            db.SaveChanges();
            return RedirectToAction("Index");
        }

        else
        {
            vm.States = db.States.ToList();
            vm.Citys = db.Citys.ToList();
            vm.Zips = db.Zips.ToList();
            return View(vm);
        }
    }


    public ActionResult Edit(int? id)
    {
        if (id == null)
        {
            return NotFound();
        }

        var customervm = new CustomerFormVM();
        {
            Customer customer = db.Customers.SingleOrDefault(c => c.CustomerId == id);

            if (customer == null)
            {
                return NotFound();
            }

            customervm.CustomerId = customer.CustomerId;
            customervm.FirstName = customer.FirstName;
            customervm.LastName = customer.LastName;

            // Retrieve list of States
            var states = db.States.ToList();
            customervm.States = states;

            // Retrieve list of Citys
            var citys = db.Citys.ToList();
            customervm.Citys = citys;

            // Retrieve list of Citys
            var zips = db.Zips.ToList();
            customervm.Zips = zips;

            // Set the selected state
            customervm.StateId = customer.StateId;

            // Set the selected city
            customervm.CityId = customer.CityId;

            // Set the selected zip
            customervm.ZipId = customer.ZipId;
        }
        return View(customervm);
    }


    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Edit(CustomerFormVM vmEdit)
    {
        if (ModelState.IsValid)
        {
            Customer customer = db.Customers.SingleOrDefault(c => c.CustomerId == vmEdit.CustomerId);

            if (customer == null)
            {
                return NotFound();
            }

            customer.FirstName = vmEdit.FirstName;
            customer.LastName = vmEdit.LastName;
            customer.StateId = vmEdit.StateId;
            customer.CityId = vmEdit.CityId;
            customer.ZipId = vmEdit.ZipId;

            db.Entry(customer).State = EntityState.Modified;
            db.SaveChanges();
            return RedirectToAction("Index");
        }
        return View(vmEdit);
    }
}

Create View

        <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(s => s.StateId)
            @Html.DropDownListFor(s => s.StateId, new SelectList(Model.States, "StateId", "Abbr"), "", new { @class = "form-control" })
            @Html.ValidationMessageFor(s => s.StateId)*@

        <label asp-for="StateId "></label>
        <select asp-for="StateId " asp-items="Model.States" class="form-control" id="state-target"></select>
        <span asp-validation-for="StateId " class="text-danger"></span>
    </div>

    <div class="form-group">
        @*@Html.LabelFor(ct => ct.CityId)
            @Html.DropDownListFor(ct => ct.CityId, new SelectList(Model.Citys, "CityId", "Name"), "", new { @class = "form-control" })
            @Html.ValidationMessageFor(ct => ct.CityId)*@

        <label asp-for="CityId"></label>
        <select asp-for="CityId" asp-items="Model.Citys" class="form-control" id="city-target"></select>
        <span asp-validation-for="CityId" class="text-danger"></span>
    </div>

    <div class="form-group">
        @Html.LabelFor(z => z.ZipId)
        @Html.DropDownListFor(z => z.ZipId, new SelectList(Model.Zips, "ZipId", "PostalCode"), "", new { @class = "form-control" })
        @Html.ValidationMessageFor(z => z.ZipId)
    </div>

    <div class="form-group">
        <button type="submit" class="btn btn-primary">Submit</button>
    </div>
}

@section scripts {
    <script src="~/lib/jquery-validation/dist/jquery.validate.js"></script>
    <script src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js"></script>
    <script src="~/lib/js/example.js"></script>,
}

解决方案

I had a similar situation but in my example I have a Root folder and depending on which root folder I am using the next drop down list would display the corresponding sub-folders.

Not sure if there is a purly asp.net solution but, I used Jquery/Ajax for this.

Your code should look something like this:

html list:

<label asp-for="StateId "></label>
<select asp-for="StateId " asp-items="Model.States" class="form-control" id="state-target"></select>
<span asp-validation-for="StateId " class="text-danger"></span>

<label asp-for="CityId"></label>
<select asp-for="CityId" asp-items="Model.Citys" class="form-control" id="city-target"></select>
<span asp-validation-for="CityId" class="text-danger"></span>

Jquery code, you write this in .js file and then add it to a specific view with this statement<script src="~/js/example.js"></script>, Don't forget you need to add a jquery library to your project before any other javascript, and your example.js will contain:

$(document).ready(function () {
  $("#state-target").on("change", function () {
    $list = $("#city-target");
    $.ajax({
        url: "/getCities",
        type: "GET",
        data: { id: $("#state-target").val() }, //id of the state which is used to extract cities
        traditional: true,
        success: function (result) {
            $list.empty();
            $.each(result, function (i, item) {
                $list.append('<option value="' + item["CityId"] + '"> ' + item["Name"] + ' </option>');
            });
        },
        error: function () {
            alert("Something went wrong call the police");
        }
    });
  });
});

The Ajax request will call this action in the Controller which will retrieve a list of cities from the database (using something like return dbContext.CityTable.Where(c => c.StateId == id).ToList() inside a getCititesFromDatabaseByStateId(id) method) and then return the Json object, the success function will create a list of options and apply it:

public IActionResult getCities(int id)
{
    var cities = new List<City>();
    cities = getCititesFromDatabaseByStateId(id); //call repository
    return Json(citites);
}

In your ViewModel consider changing IEnumerable<State/City/Zip> (IEnumerable<T>) to IEnumerable<SelectListItem>. I can say as well your Model's are messy (but if you can get data the from the database focus on getting the list working 1st), consider improving them later.

Fix for 2 errors mentioned in the comments:

public List<City> getCititesFromDatabaseByStateId(int id)
{
    return db.Citys.Where(c => c.StateId == id).ToList();
}

public ActionResult Create()
{
     var states = new SelectList(db.States.ToList(), "StateId", "Abbr");
     var citys = new SelectList(db.Citys.ToList(), "CityId", "Name");
     var zips = new SelectList(db.Zips.ToList(), "ZipId", "Code");

     var viewModel = new CustomerFormVM
     {
         States = states,
         Citys = citys,
         Zips = zips
     };

     return View(viewModel);
}

这篇关于ASP.NET MVC 核心级联 DropDownList的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆