模型绑定 - 级联关系

时间:2021-03-05 08:00:43

标签: asp.net-mvc asp.net-core model-binding

hi 考虑以下三个具有级联关系的类

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

像这样的东西会在最后发送:

enter image description here

我的问题是我应该如何在服务器端获得这个模型? 另外,括号内的ID是用来存储信息的。

1 个答案:

答案 0 :(得分:2)

请参考以下示例并使用 Asp.net Core Tag helper 显示模型属性。

添加以下视图模型以在视图中显示数据:

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并做一些事情。结果如下:

enter image description here