使用 MVC Razor Entity Framework 和存储过程的级联下拉列表

Cascading dropdowns using MVC Razor Entity Framework and stored procedures

我是 MVC 和 Razor 的新手,看过很多这方面的示例和教程,但无法使其正常工作。看起来很简单,但我认为我正在尝试使用存储过程这一事实使一切变得复杂。

我正在尝试使用存储过程和 entity framework.

在 MVC 中创建一些简单的级联下拉菜单

我的实体由以下存储过程组成:

exec prcGetMakes
exec prcGetModels 'BMW'
exec prcGetVariants '1 SERIES 5-DOOR'

我创建了一个名为 VehicleViewModel 的视图模型 class:

public class VehicleViewModel
{
    [Display(Name = "Manufacturer")]
    public string BrandName { get; set; }
    public string BrandID { get; set; }

    [Display(Name = "Model")]
    public string ModelName { get; set; }
    public string ModelID { get; set; }

    [Display(Name = "Variant")]
    public string VariantName { get; set; }

    public IEnumerable<SelectListItem> Manufacturer { get; set; }
    public IEnumerable<SelectListItem> Model { get; set; }
    public IEnumerable<SelectListItem> Variant { get; set; }
}

我正在使用名为 HomeController.cs:

的默认控制器 class
public class HomeController : Controller
{
    VehicleInfoEntities db = new VehicleInfoEntities();

    public ActionResult Index()
    {
        var app = new VehicleViewModel
        {
            Manufacturer = GetMakes()
        };

        return View(app);
    }


    private IEnumerable<SelectListItem> GetMakes()
    {
        var list = new VehicleViewModel();
        IEnumerable<SelectListItem> manufacturer = from s in db.prcGetMakes(null)
                                            select new SelectListItem
                                            {
                                                Selected = s.ToString() == "Active",
                                                Text = s.BrandName,
                                                Value = s.BrandID
                                            };
        return manufacturer;

    }

    private IEnumerable<SelectListItem> GetModels(string brandName)
    {
        var list = new VehicleViewModel();
        IEnumerable<SelectListItem> models = from s in db.prcGetModels(brandName)
                                            select new SelectListItem
                                            {
                                                Selected = s.ToString() == "Active",
                                                Text = s.ModelName,
                                                Value = s.ModelID
                                            };
        return models;

    }

    private IEnumerable<SelectListItem> GetVariants(string modelName)
    {
        var list = new VehicleViewModel();
        IEnumerable<SelectListItem> variants = from s in db.prcGetVariants(modelName)
                                             select new SelectListItem
                                             {
                                                 Selected = s.ToString() == "Active",
                                                 Text = s.VariantName,
                                                 Value = s.VariantName
                                             };
        return variants;

    }
}

这是我的看法

@model WebApplication12.Models.VehicleViewModel

@{
    ViewBag.Title = "Home Page";
}
@using (Html.BeginForm("Index", "Sample", FormMethod.Post))
{
@Html.AntiForgeryToken()

@Html.ValidationSummary()
<div class="form-group" style="text-align:left;">
    @Html.Label("Manufacturer:", new { @class = "col-md-2 control-label" })
    <div class="col-md-10">
        @Html.DropDownList("Manufacturer", ViewData["Manufacturer"] as SelectList, new { @class = "form-control" })
    </div>
</div><br />

}

期望的结果是

我现在只想知道如何使用 JQuery 使级联 DropDown 工作并筛选每个 DropDown 的选择。

与胖客户端应用程序相比,网络级联下拉列表错综复杂,但这就是网络编程!请记住,javascript 根本不关心您的 MVC 内容。您只需要一个 web 方法(响应 web URL 的东西),它接受一个参数和 returns 正确格式的正确列表。无论它在内部使用什么方法(EF 存储过程、硬编码列表、PHP 读取文本文件)都没有任何区别

要执行您想要的操作,您需要在下拉列表中添加一个 "event handler",它会调用一些 javascript,它会调用您的方法来查找正确的列表,然后填充目标下拉列表使用该列表。

我会在这里放一些示例代码,但是

  • 需要'wiring up'的程度(使用正确的事物名称)

  • 我要做一些假设

  • 我从网上学来的,有些语法可能不正确

因此,首先将一个 onchange 事件处理程序添加到您的下拉列表中,以便当某些内容发生更改时它会触发一些 javascript 代码

@Html.DropDownList("Manufacturer", 
                   ViewData["Manufacturer"] as SelectList, 
                   htmlAttributes: 
                         new { @class = "form-control" , 
                               @onchange = "refreshModelFromManufacturer()"
                             }
                   )

当下拉值改变时它会调用javascript函数refreshModelFromManufacturer()

这里是javascript函数。希望你知道如何添加它。它要求您还需要一个名称为 "Model" 的下拉菜单(您的视图中还没有,所以请添加它):

function refreshModelFromManufacturer()() {
    // get references to the source and target drop downs html controls
    // These are jquery searches to find the drop down controls

    // find a control with id=Manufacturer
    src = $("#Manufacturer");

    // find a control with id=Model (you need to add this to your view)
    tgt = $("#Model");

    // clear drop down
    tgt.empty();

    // Get new model dataset via ajax 
    // based on manufacturer
    // The url parameter points at your web method
    $.ajax({
        type: 'GET',
        url: 'Home/GetModels',
        dataType: 'json',
        data: { brandName: src.val() },
        // success is called when dataset returns
        success: function (p) {
                // Populate with each returned member
                $.each(p, function (i, pr) {
                    tgt.append(
                        '<option value="' + pr.Value + '">' +
                        pr.Text + '</option>'
                        );
                })
            }
        });
    }

这是最有可能出错的地方。 Javascript 是无情的,区分大小写,并且有太多容易搞砸的括号。确保你使用的是源代码控制,这样你就可以回滚,因为有时可能无法计算出放错地方的括号,因为代码在 jquery 库深处的某处失败,给你任何线索

最后一件事是您的 Web 方法必须是 Json 类型,以便 ajax 调用有效

public JsonResult GetModels(string brandName)
{
    var list = db.prcGetModels(brandName)

    return Json(new SelectList(list, "your id column","your label column"));
}

我的代码中唯一的其他区别是实际上像这样定义了一个下拉列表:

@Html.DropDownList("Customer_ID", null, htmlAttributes: new { @class = "form-
control", @onchange = "refreshProjectFromClient()" })

我觉得如果你的ViewBag名字和你的下拉一样,那么你就不需要显式定义viewbag(我的第二个参数是null)

对于调试(因为这不会第一次起作用),请确保您知道如何使用 F12 调试器调试 javascript 以及观察内部网络调用(网络选项卡)。例如,当你 运行 这个时,你应该在网络选项卡

中看到对 Home/GetModels 方法的调用