#asp.net-mvc #asp.net-core #model-binding
#asp.net-mvc #asp.net-ядро #привязка модели
Вопрос:
привет Рассмотрим следующие три класса, которые имеют каскадную связь
public class Specification
{
public int SpecificationId { get; set; }
public string Caption { get; set; }
public ICollection<Feature> Features { get; set; }
}
public class Feature
{
public int? SpecificationId { get; set; }
public Specification Specification { get; set; }
public int FeatureId { get; set; }
public string Caption { get; set; }
public ICollection<FeatureValue> FeatureValues { get; set; }
}
public class FeatureValue
{
public int? FeatureId { get; set; }
public Feature Feature { get; set; }
public int FeatureValueId { get; set; }
public string Caption { get; set; }
}
На следующем шаге и в форме я считываю и отображаю информацию, относящуюся к вышеупомянутым классам (из базы данных)
Например, следующий фрагмент кода:
@foreach (var specification in Model.FirstOrDefault().Specifications)
{
<fieldset>
<legend> @specification.Caption</legend>
@foreach (var feature in specification.Features)
{
<div class="form-group">
<label for="Specification_@(specification.SpecificationId)__Feature_@(feature.FeatureId)__FeatureValues">@feature.Caption :</label>
<select name="Specifications[@specification.SpecificationId].Feature[@feature.FeatureId].FeatureValues"
id="Specification_@(specification.SpecificationId)__Feature_@(feature.FeatureId)__FeatureValues"
@(feature.IsMultipleChoices ? "multiple" : null)
data-multiple="@(feature.IsMultipleChoices?"true":"false")"
class="sffv-select form-control"
>
<option></option>
@foreach (var featureValue in feature.FeatureValues)
{
<option value="@featureValue.FeatureValueId">
@featureValue.Caption
</option>
}
</select>
</div>
}
</fieldset>
}
Наконец, я отправляю информацию о форме на сервер, что-то вроде следующего фрагмента кода:
$.ajax({
async: true,
data: $('#MyForm').serialize(),
type: "Post",
url: "@FormUrl",
contentType: 'application/x-www-form-urlencoded; charset=UTF-8',
success: function () {
alert("Submitted!");
}
});
Что-то вроде этого будет отправлено в конце:
Мой вопрос в том, как мне получить эту модель на стороне сервера? Кроме того, идентификаторы внутри скобки необходимы для хранения информации.
Ответ №1:
Пожалуйста, обратитесь к следующему образцу и используйте Asp.net Помощник по основным тегам для отображения свойств модели.
Добавьте следующие модели представления для отображения данных в представлении:
public class SpecificationViewModel
{
public List<SpecificationVM> Specifications { get; set; }
}
public class SpecificationVM
{
public int SpecificationId { get; set; }
public string Caption { get; set; }
public List<FeatureVM> Features { get; set; }
}
public class FeatureVM
{
public int? SpecificationId { get; set; }
public Specification Specification { get; set; }
public int FeatureId { get; set; }
public string Caption { get; set; }
public Boolean IsMultipleChoices { get; set; } // Whether the <select> element is multiple select or single select.
public List<int> selectedFeatureValue { get; set; } // used to store the selected FeatureValueId.
public List<FeatureValueVM> FeatureValues { get; set; }
}
public class FeatureValueVM
{
public int? FeatureId { get; set; }
public Feature Feature { get; set; }
public int FeatureValueId { get; set; }
public string Caption { get; set; }
}
Код контроллера:
private readonly ApplicationDbContext _context;
public SpecificationController(ApplicationDbContext context)
{
_context = context;
}
public IActionResult Index()
{
//query database and set value for the ViewModel.
List<SpecificationViewModel> items = new List<SpecificationViewModel>()
{
new SpecificationViewModel(){ Specifications= _context.Specifications.Include(c=>c.Features).ThenInclude(c=>c.FeatureValues)
.Select(c=>new SpecificationVM()
{
SpecificationId = c.SpecificationId,
Caption = c.Caption,
Features = c.Features.Select(d=> new FeatureVM()
{
Caption = d.Caption,
IsMultipleChoices = d.IsMultipleChoices,
FeatureId = d.FeatureId,
Specification =d.Specification,
SpecificationId = d.SpecificationId,
FeatureValues = d.FeatureValues.Select(v=> new FeatureValueVM()
{
Caption = v.Caption,
FeatureValueId = v.FeatureValueId,
FeatureId = v.FeatureId,
Feature =v.Feature
}).ToList()
}).ToList()
}).ToList() }
};
return View(items);
}
[HttpPost]
public IActionResult SaveSpecification(SpecificationViewModel model)
{
return Ok("success");
}
Просмотр страницы:
@model IEnumerable<WebApplication.Models.SpecificationViewModel>
@{
ViewData["Title"] = "Index";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<form id="MyForm">
@for (var i = 0; i < Model.FirstOrDefault().Specifications.Count; i )
{
<fieldset>
<legend>@Model.FirstOrDefault().Specifications[i].Caption</legend>
<input type="hidden" asp-for="@Model.FirstOrDefault().Specifications[i].Caption" />
<input type="hidden" asp-for="@Model.FirstOrDefault().Specifications[i].SpecificationId" />
@for (var f = 0; f < Model.FirstOrDefault().Specifications[i].Features.Count; f )
{
<div class="form-group">
<label>@Model.FirstOrDefault().Specifications[i].Features[f].Caption :</label>
<input type="hidden" asp-for="@Model.FirstOrDefault().Specifications[i].Features[f].Caption" />
<input type="hidden" asp-for="@Model.FirstOrDefault().Specifications[i].Features[f].FeatureId" />
<input type="hidden" asp-for="@Model.FirstOrDefault().Specifications[i].Features[f].SpecificationId" />
<input type="hidden" asp-for="@Model.FirstOrDefault().Specifications[i].Features[f].IsMultipleChoices" />
<select asp-for="@Model.FirstOrDefault().Specifications[i].Features[f].selectedFeatureValue"
asp-items='new SelectList(Model.FirstOrDefault().Specifications[i].Features[f].FeatureValues, "FeatureValueId", "Caption")'
data-multiple="@Model.FirstOrDefault().Specifications[i].Features[f].IsMultipleChoices"
class="sffv-select form-control">
<option></option>
</select>
</div>
}
</fieldset>
}
<input type="button" value="Submit" id="btnSubmit" />
</form>
@section Scripts{
<script>
$(function () {
//loop through the <select> element, add or remove multiple attribute from the <select> element
$(".sffv-select").each(function (index, item) {
if ($(item).attr("data-multiple") == "True") {
$(item).attr("multiple", "multiple");
}
else {
$(item).removeAttr("multiple");
}
});
$("#btnSubmit").click(function () {
$.ajax({
async: true,
data: $('#MyForm').serialize(),
type: "Post",
url: "/Specification/SaveSpecification", //change the url to yours
contentType: 'application/x-www-form-urlencoded; charset=UTF-8',
success: function () {
alert("Submitted!");
}
});
});
});
</script>
}
После отправки формы в методе Post вы можете перебрать ViewModel и получить все выбранные значения (selectedFeatureValue ), затем, в соответствии с ними, найти соответствующее FeatureValue и что-то сделать. Результат выглядит так: