【发布时间】:2021-09-25 19:04:32
【问题描述】:
我正在尝试在我的 .net 核心应用程序中复制以下 Cascading DropDowns tutorial。我正在为我的控制器和服务使用 WebAPI...但是为了简化和更接近本教程,我已将控制器移至客户端。 Controller 中的逻辑与教程中的逻辑非常相似,显然它运行良好,至少可以在页面加载时填充下拉菜单。
我在 Javascript 上有点挣扎(我相信这是 400 错误的原因),并且我使用了一个半定制模型框架,大约 90% 基于教程模型。疯狂的是 Javascript 正在运行(我相信),因为它在 JS 代码中的断点处停止,因为它最初正确填充了页面加载的 3 个下拉菜单。但是,一旦我在 3 个下拉控件中的任何一个中选择了任何项目...而不是调用“on change”事件,它就会触发以下错误:
加载资源失败:服务器响应状态为 400 () [https://localhost:44317/]
如果需要,我可以提供更多代码,但我已经粘贴了我认为问题所在的逻辑症结下方:
==== Index.cshtml 代码如下====
@page
@using Microsoft.Extensions.Configuration
@model MTGCardTracker.Client.Pages.IndexModel
<div id="dropDownListdiv">
@using (Html.BeginForm("Index", "CascadingDropDownList", FormMethod.Post))
{
@Html.DropDownListFor(m => m.CascadingDropDown.FormatId, Model.CascadingDropDown.Formats, "Please select", new { @class = "form-control" })
@Html.DropDownListFor(m => m.CascadingDropDown.EditionId, Model.CascadingDropDown.Editions, "Please select", new { @class = "form-control" })
@Html.DropDownListFor(m => m.CascadingDropDown.CardListId, Model.CascadingDropDown.Cards, "Please select", new { @class = "form-control" })
<input type="submit" value="Submit" />
}
</div>
@section scripts {
<script type="text/javascript">
$(function () {
$("#dropDownListdiv").on("change", "select", function () {
var value = $(this).val();
var id = $(this).attr("id");
$.post("@Url.Action("SetDropDrownList")", { type: id, value: value }, function (data) {
switch (id) {
case "FormatId":
PopulateDropDown("#CascadingDropDown_EditionId", data.CascadingDropDown.Editions);
PopulateDropDown("#CascadingDropDown_CardListId", data.CascadingDropDown.Cards);
break;
case "EditionId":
PopulateDropDown("#CascadingDropDown_CardListId", data.CascadingDropDown.Cards);
break;
}
});
});
});
function PopulateDropDown(dropDownId, list) {
$(dropDownId).empty();
$(dropDownId).append("<option>Please select</option>")
$.each(list, function (index, row) {
if (index == 0) {
$(dropDownId).append("<option value='" + row.Value + "' selected='selected'>" + row.Text + "</option>");
} else {
$(dropDownId).append("<option value='" + row.Value + "'>" + row.Text + "</option>")
}
});
}
</script>
}
下面是我的模型:
using Microsoft.AspNetCore.Mvc.Rendering;
using System.Collections.Generic;
namespace MTGTracker.DTO
{
public class CascadingDropDownDTO
{
public string FormatId { get; set; }
public string EditionId { get; set; }
public string CardListId { get; set; }
public SelectList Formats { get; set; }
public SelectList Editions { get; set; }
public SelectList Cards { get; set; }
public IEnumerable<FormatDTO> FormatObject { get; set; }
public IEnumerable<EditionDTO> EditionObject { get; set; }
public IEnumerable<CardDetailDTO> CardObject { get; set; }
}
}
下面(在 _Layout.cshtm 中)是 我相信我现在在我的代码中引用 JS 和 Boostrap 文件的唯一地方:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>@ViewData["Title"] - MTGCardTracker</title>
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css" />
<link rel="stylesheet" href="~/css/site.css" />
<script type="text/javascript" src="~/lib/jquery/dist/jquery.js"></script>
@*<script src="~/lib/jquery/dist/jquery.min.js"></script>*@
<script src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
<script src="~/js/site.js" asp-append-version="true"></script>
</head>
<body>
<header>
<nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
<div class="container">
<a class="navbar-brand" asp-area="" asp-page="/Index">MTGCardTracker</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target=".navbar-collapse" aria-controls="navbarSupportedContent"
aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="navbar-collapse collapse d-sm-inline-flex justify-content-between">
<ul class="navbar-nav flex-grow-1">
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-page="/Index">Home</a>
</li>
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-page="/Privacy">Privacy</a>
</li>
</ul>
</div>
</div>
</nav>
</header>
<div class="container">
<main role="main" class="pb-3">
@RenderBody()
</main>
</div>
<footer class="border-top footer text-muted">
<div class="container">
© 2021 - MTGCardTracker - <a asp-area="" asp-page="/Privacy">Privacy</a>
</div>
</footer>
@await RenderSectionAsync("Scripts", required: false)
</body>
</html>
========== SetDropDownList ==========
[HttpPost]
public JsonResult SetDropDrownList(string type, int value)
{
CascadingDropDownDTO model = GetCascadingDropDownListObject(CascadingDropDown);
switch (type)
{
case "FormatId":
var EditionsList = CascadingDropDown.EditionObject.Where(m => m.FormatId == value).ToList();
model.Editions = new SelectList(EditionsList, "EditionId", "EditionName");
var defaultEditionId = EditionsList.Select(m => m.EditionId).FirstOrDefault();
model.Cards = new SelectList(CascadingDropDown.CardObject.Where(m => m.EditionId == defaultEditionId).ToList(), "CardListId", "Name");
break;
case "EditionId":
model.Cards = new SelectList(CascadingDropDown.CardObject.Where(m => m.EditionId == value).ToList(), "CardListId", "Name");
break;
}
return Json(model);
}
即使在我删除了提交按钮后,以下代码中仍显示令牌。所以它似乎只是与页面和/或下拉列表相关联。
下面是帖子。不确定我是否可以进一步深入了解更多细节,因为我对尝试在浏览器中调试 JS 还是很陌生:
【问题讨论】:
-
也许您可以通过将 .js 引用放在 head 元素中来测试它,就在 .css 引用下方。我在页面末尾遇到了一些关于 JQuery 引用的问题。
-
感谢您的建议。我将它们移到了顶部(并更新了上面的代码示例以反映它),并且每当我尝试更改下拉列表时仍然会得到相同的 400 错误。我认为这可能更多是因为我没有在我的 javascript 代码中正确引用下拉对象。但我不知道。
-
抱歉,我看不到 SetDropDrownList action 。请问可以发一下吗?
-
更新了代码以添加 SetDropDownList 方法。如果它在控制器中的某个地方出现故障......我至少不应该让代码在调试时在控制器内部中断吗?我在控制器中每个方法的开头都设置了断点......并且在页面初始加载后没有调用任何内容。
-
页面中是否添加了防伪令牌?然后 Ajax POST 命令应该在其 post 语句中包含该标记,否则将返回 400 错误。 mikesdotnetting.com/article/336/…
标签: javascript c# asp.net asp.net-mvc dropdown