简体   繁体   English

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

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

My Drop-Downs works well the problem is when I want to save my form. 我的下拉菜单效果很好,问题是当我要保存表单时。

here is my controller 这是我的控制器

[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);
    }

and here is My form. 这是我的表格。 in this From, select tag with id=TourId is filling with data in ajax from the outer drop down dropdownId and it works fine 在此From中, id=TourId select标签从外部下拉列表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>

} }

the problem is when I submit the form no diffrent which Tour is chosen always there is TourId=0. 问题是当我提交没有区别的表格时,总是选择了TourId = 0。

在此处输入图片说明

Appreciate any help and also here is the ajax if needed 感谢任何帮助,如果需要,这里也是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');

                }



            }
        });

});

The reason your second <select> element does not submit a value is because it does not have a name attribute. 第二个<select>元素不提交值的原因是因为它没有name属性。 It would need to be 它需要是

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

However there are multiple other errors and problems with your code. 但是,您的代码还有许多其他错误和问题。 To note just a couple of them: 仅需注意其中几个:

  1. The model in your view is is not typeof TourDate (its a model containing a property which is TourDate ) so none of your controls can be bound to your TourDate tourDate parameter in the POST method (the model in the parameter needs to be the same as the model in the view, or you need to use the [Bind(Prefix = "TourDate")] attribute and you also need to remove the [Bind(Include = "..")] attribute). 您视图中的模型不是TourDate (它的模型包含一个属性TourDate ),因此您的控件都不能绑定到POST方法中的TourDate tourDate参数(该参数中的模型必须与视图中的模型,或者您需要使用[Bind(Prefix = "TourDate")]属性,还需要删除[Bind(Include = "..")]属性)。
  2. Your not getting client side validation associated with your dropdownlists and in the POST method, if ModelState is invalid, your just redirecting (the user would just assume the object has been saved and not understand what is going on). 您没有与下拉列表和POST方法相关联的客户端验证,如果ModelState无效,则仅进行重定向(用户将仅假定对象已保存并且不了解发生了什么)。 You need to return the view so errors can be corrected, but in your case, the values the user has entered will be reset to the defaults (an annoying user experience). 您需要返回视图,以便可以纠正错误,但是在您的情况下,用户输入的值将重置为默认值(令人讨厌的用户体验)。

Your editing data, so you should always use a view model and in the controller method you need to populate the SelectList's to account for initial values and edited values (for when you need to return the view). 您的编辑数据,因此您应该始终使用视图模型,并且在控制器方法中,需要填充SelectList来考虑初始值和已编辑的值(用于何时需要返回视图)。 You code should be 您的代码应该是

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; }
}

And in the controller 并在控制器中

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>());
    }
}

and finally in the view (note that both dropdownlists need to be inside the <form> element) 最后是视图(请注意,两个下拉列表都必须在<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>
    ....
}

and the script should be 并且脚本应该是

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));
        });
    });
})

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM