Привязка модели — каскадная связь

#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 и что-то сделать. Результат выглядит так:

введите описание изображения здесь