如何使用 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=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>
}
问题是当我提交表单时,无论选择哪个 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>
但是,您的代码还有多个其他错误和问题。仅需注意其中几个:
- 您认为的模型不是 typeof
TourDate
(它是一个模型
包含一个 属性 即 TourDate
) 所以你的控件 none
可以绑定到 POST 中的 TourDate tourDate
参数
method(参数中的model需要和model一样
在视图中,或者您需要使用 [Bind(Prefix = "TourDate")]
属性,您还需要删除 [Bind(Include = "..")]
属性).
- 您没有获得与您相关的客户端验证
下拉列表和 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));
});
});
})
我的下拉菜单运行良好,问题是当我想保存我的表单时。
这是我的控制器
[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=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>
}
问题是当我提交表单时,无论选择哪个 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>
但是,您的代码还有多个其他错误和问题。仅需注意其中几个:
- 您认为的模型不是 typeof
TourDate
(它是一个模型 包含一个 属性 即TourDate
) 所以你的控件 none 可以绑定到 POST 中的TourDate tourDate
参数 method(参数中的model需要和model一样 在视图中,或者您需要使用[Bind(Prefix = "TourDate")]
属性,您还需要删除[Bind(Include = "..")]
属性). - 您没有获得与您相关的客户端验证
下拉列表和 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));
});
});
})