如何使用 asp.net mvc 在数据库中保存级联下拉列表项

how to save items of cascading drop down list in database with asp.net mvc

我的下拉菜单运行良好,问题是当我想保存我的表单时。

这是我的控制器

[HttpPost]
[ValidateAntiForgeryToken]
    public ActionResult Create([Bind(Include = "Id,TourId,StartDate,EndDate")] TourDate tourDate)
    {
        if (ModelState.IsValid)
        {
            db.TourDates.Add(tourDate);
            db.SaveChanges();

            return RedirectToAction("Index", "Home");
        }

        ViewBag.TourId = new SelectList(db.Tours, "Id", "TourName", tourDate.TourId);
        return RedirectToAction("Index", "test");
    }


     [HttpPost]
    public JsonResult GetT(int? id)
    {
        var tours = db.Tours.Where(e => e.CountryId == id).ToList()
           .Select(e => new
           {
               Id = e.Id,
               TourName= e.TourName
           }).ToList();


        return Json(tours);
    }

这是我的表格。在此 From 中,带有 id=TourIdselect 标签正在从外部下拉列表 dropdownId 中填充 ajax 中的数据并且工作正常

@Html.DropDownList("dropdownId",
Model.Countries.Select(m => new SelectListItem
{
    Value = m.Id.ToString(),
    Text = m.CountryName
}),
new { @class = "form-control" })


@using (Html.BeginForm("Create", "test"))
{
 @Html.AntiForgeryToken()

 <div class="form-horizontal">
    <h4>TourDate</h4>
    <hr />
    @Html.ValidationSummary(true, "", new { @class = "text-danger" })

    <div class="form-group">
        @Html.LabelFor(model => model.TourDate.TourId, "TourId", htmlAttributes: new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            <select class="form-control" id="TourId"></select>

            @Html.ValidationMessageFor(model => model.TourDate.TourId, "", new { @class = "text-danger" })
        </div>
    </div>

    <br />
    <div class="form-group">
        @Html.LabelFor(model => model.TourDate.StartDate, htmlAttributes: new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.EditorFor(model => model.TourDate.StartDate, new { htmlAttributes = new { @class = "form-control" } })
            @Html.ValidationMessageFor(model => model.TourDate.StartDate, "", new { @class = "text-danger" })
        </div>
    </div>
    <br />
    <div class="form-group">
        @Html.LabelFor(model => model.TourDate.EndDate, htmlAttributes: new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.EditorFor(model => model.TourDate.EndDate, new { htmlAttributes = new { @class = "form-control" } })
            @Html.ValidationMessageFor(model => model.TourDate.EndDate, "", new { @class = "text-danger" })
        </div>
    </div>

    <div class="form-group">
        <div class="col-md-offset-2 col-md-10">
            <input type="submit" value="Create" class="btn btn-default" />
        </div>
    </div>
</div>

}

问题是当我提交表单时,无论选择哪个 Tour,总是有 TourId=0。

感谢任何帮助,如果需要,也可以在此处 ajax

$("#dropdownId").change(function () {
    $('#TourId').empty();
    var countrySelected = $(this).val();

    $.ajax
        ({
            url: '/test/GetT/' + countrySelected,
            type: 'POST',
            data: {
                'countryId': countrySelected
            },
            success: function (data)
            {
                var $select = $('#TourId');
                for (var i = 0; i < data.length; i++)
                {

                    $('<option/>').attr('value', data[i].Id).html(data[i].TourName).appendTo('#TourId');

                }



            }
        });

});

您的第二个 <select> 元素没有提交值的原因是它没有 name 属性。需要

<select class="form-control" name="TourDate.TourId" id="TourId"></select>

但是,您的代码还有多个其他错误和问题。仅需注意其中几个:

  1. 您认为的模型不是 typeof TourDate(它是一个模型 包含一个 属性 即 TourDate) 所以你的控件 none 可以绑定到 POST 中的 TourDate tourDate 参数 method(参数中的model需要和model一样 在视图中,或者您需要使用 [Bind(Prefix = "TourDate")] 属性,您还需要删除 [Bind(Include = "..")] 属性).
  2. 您没有获得与您相关的客户端验证 下拉列表和 POST 方法中,如果 ModelState 无效, 你只是重定向(用户会假设对象有 被保存并且不明白发生了什么事)。你需要 return 可以更正错误的视图,但在您的情况下,值 用户输入的内容将被重置为默认值(烦人的用户 经验)。

您的编辑数据,因此您应该始终使用 view model 并且在控制器方法中您需要填充 SelectList 以考虑初始值和编辑值(当您需要 return风景)。你的代码应该是

public class TourDateVM
{
    [Required(ErrorMessage = "Please select a country")]
    [Display(Name = "Country")]
    public int? SelectedCountry { get; set; }
    [Required(ErrorMessage = "Please select a tour")]
    [Display(Name = "Country")]
    public int? SelectedTour { get; set; }
    [Required(ErrorMessage = "Please enter a start date")]
    [Display(Name = "Start date")]
    public DateTime? StartDate { get; set; }
    .... // ditto above for EndDate
    public IEnumerable<SelectListItem> CountryList { get; set; }
    public IEnumerable<SelectListItem> TourList { get; set; }
}

并在控制器中

public ActionResult Create()
{
    TourDateVM model = new TourDateVM();
    ConfigureViewModel(model);
    return View(model);
}
[HttpPost]
public ActionResult Create(TourDateVM model)
{
    if (!ModelState.IsValid)
    {
        ConfigureViewModel(model);
        return View(model);
    }
    TourDate tour = new TourDate()
    {
        TourId = model.SelectedTour,
        StartDate = model.StartDate,
        EndDate= model.EndDate
    };
    db.TourDates.Add(tour);
    db.SaveChanges();
    return RedirectToAction("Index", "Home");
}
private ConfigureViewModel(TourDateVM model)
{
    var counties = db.Countries;
    model.CountryList = new SelectList(counties, "ID", "Name"); // adjust to suit your property names
    if (model.SelectedCountry.HasValue)
    {
        var tours = db.Tours.Where(e => e.CountryId == model.SelectedCountry);
        model.TourList = new SelectList(tours, "Id", "TourName");
    }
    else
    {
        model.TourList = new SelectList(Enumerable.Empty<SelectListItem>());
    }
}

最后在视图中(注意两个下拉列表都需要在 <form> 元素内)

@model TourDateVM
....
@using Html.BeginForm())
{
    ....
    <div class="form-group">
        @Html.LabelFor(m => m.SelectedCountry, new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.DropDownListFor(m => m.SelectedCountry, Model.CountryList, "- Please select -", new { @class = "form-control" })
            @Html.ValidationMessageFor(m => m.SelectedCountry, "", new { @class = "text-danger" })
        </div>
    </div>
    <div class="form-group">
        @Html.LabelFor(m => m.SelectedTour, new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.DropDownListFor(m => m.SelectedTour, Model.TourList, "- Please select -", new { @class = "form-control" })
            @Html.ValidationMessageFor(m => m.SelectedTour, "", new { @class = "text-danger" })
        </div>
    </div>
    ....
}

脚本应该是

var url = '@Url.Action("GetT")'; // assumes its in the same controller
var tours = $('#SelectedTour');

$('#SelectedCountry').change(function() {
    tours.empty();
    $.post(url , { id: $(this).val() }, function(data) {
        if (!data) {
            return;
        }
        tours.append($('<option></option>').val('').text('- Please select -'));
        $.each(data, function(index, item) {
            tours.append($('<option></option>').val(item.Id).text(item.TourName));
        });
    });
})