【问题标题】:Cascading dropdowns using MVC Razor Entity Framework and stored procedures使用 MVC Razor 实体框架和存储过程的级联下拉列表
【发布时间】:2017-12-28 17:02:05
【问题描述】:

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

我正在尝试使用存储过程和实体框架在 MVC 中创建一些简单的级联下拉列表。

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

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

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

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 的默认控制器类:

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 的选择。

【问题讨论】:

  • 你当然可以使用存储过程,尽管像查找表这样的事情在普通实体框架中非常简单。您可能希望开发一个 Vehicle 实体模型,该模型很可能具有 VehicleId、ManufacturerId、ModelId、VariantId 等字段。然后您可能会创建一个 VehicleViewModel,其中您将拥有 View 所需的东西,例如下拉列表集合,等等然后你的控制器填充视图模型并显示视图。那里有很多很好的教程。
  • 谢谢,链接中的解决方案不起作用,存在拼写错误,并且 public ActionResult Create() 给出错误“并非所有代码路径都返回一个值”,我将如何使用实体框架?
  • @SteveGreene 感谢您的回答和建议。我很清楚你在说什么,并且我看过很多教程,但我希望基于我的实际实体和模型的特定代码作为示例。正如我所说,我是 MVC 的新手。你是对的,有很多教程,但没有一个使用我的模型和实体,作为初学者,很难适应现有的教程。
  • 您可能一次咬得太多。也许从一个只有 VehicleId 和 VehicleDescription 的简单车辆模型开始。让模型、视图和控制器 CRUD 正常工作。然后添加一个下拉列表。然后做级联部分。等等。

标签: jquery asp.net-mvc entity-framework stored-procedures cascadingdropdown


【解决方案1】:

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

要做你想做的事,你需要在你的下拉列表中添加一个“事件处理程序”,它会调用一些 javascript,调用你的方法来查找正确的列表,然后用该列表填充目标下拉列表。

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

  • 需要一定程度的“接线”(使用正确的事物名称)

  • 我要做一些假设

  • 我是从网上了解到的,有些语法可能不正确

所以首先在你的下拉列表中添加一个 onchange 事件处理程序,这样当某些东西发生变化时它会触发一些 javascript 代码

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

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

这里是javascript函数。希望你知道如何添加它。它还要求您有一个名为“模型”的下拉列表(您的视图中还没有,所以添加它):

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 方法的调用

【讨论】:

  • 非常感谢非常详细的示例和解释。我能够使用它来使我的解决方案正常工作:)
  • 很高兴听到这个消息!
猜你喜欢
  • 2023-03-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-12-27
  • 1970-01-01
  • 1970-01-01
  • 2020-08-05
相关资源
最近更新 更多