如何在一对多关系列表中添加多个选定的选项值 class

how to add multiple selected option value in list of one-to-many relationship class

这是“项目”class

using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;

namespace RandApp.Models
{
    public class Item : BaseEntity
    {
        [Required]
        [Display(Name = "Item Photo")]
        public string ItemPhoto { get; set; }
        [Required]
        [Display(Name = "Item Type")]
        public string ItemType { get; set; }
        [Required]
        [Display(Name = "Item Category")]
        public string ItemCategory { get; set; }
        [Required]
        [Display(Name = "Item Name")]
        public string Name { get; set; }
        [Required]
        [Display(Name = "Item Colors")]
        public List<ItemColors> Color { get; set; } = new List<ItemColors>();
        [Required]
        [Display(Name = "Item Size")]
        public List<ItemSizes> Size { get; set; } = new List<ItemSizes>();
        [Required]
        [Display(Name = "Item Material Type")]
        public string MaterialType { get; set; }
        [Required]
        [Display(Name = "Designed For")]
        public string DesignedFor { get; set; }
        [Required]
        [Display(Name = "Item Price")]
        public double Price { get; set; }
        [Required]
        [Display(Name = "Item Description")]
        public string Description { get; set; }
    }
}

这是“ItemColors”和“ItemSizes”classes

using System.ComponentModel.DataAnnotations.Schema;

namespace RandApp.Models
{
    public class ItemColors : BaseEntity
    {
        public string ItemColor { get; set; }
        public int? ItemId { get; set; }
        [ForeignKey("ItemId")]
        public Item Item { get; set; }
    }
}

using System.ComponentModel.DataAnnotations.Schema;

namespace RandApp.Models
{
    public class ItemSizes : BaseEntity
    {
        public string ItemSize { get; set; }
        public int? ItemId { get; set; }
        [ForeignKey("ItemId")]
        public Item Item { get; set; }
    }
}

这是风景

@model RandApp.Models.Item

<h4>Add Item</h4>
<hr />
<div class="row">
    <div class="col-md-4">
        <form asp-action="CreateItem" enctype="multipart/form-data">
            <div class="form-group">
                <label asp-for="@Model.ItemPhoto" class="control-label"></label>
                <input type="file" name="ItemPhoto" class="form-control-file" onchange="SetValue(this)" />
                <input asp-for="@Model.ItemPhoto" hidden />
                <span asp-validation-for="@Model.ItemPhoto" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="@Model.Name" class="control-label"></label>
                <input asp-for="@Model.Name" class="form-control" />
                <span asp-validation-for="@Model.Name" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="@Model.DesignedFor" class="control-label"></label>
                <select asp-for="@Model.DesignedFor" class="form-control">
                    <option value="" selected>Select Designed For</option>
                    @foreach (var desigendFor in Enum.GetValues(typeof(RandApp.Enums.DesignedFor)))
                    {
                        <option val="@desigendFor" value="@desigendFor.ToString()">@desigendFor</option>
                    }
                </select>
                <span asp-validation-for="@Model.DesignedFor" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="@Model.ItemCategory" class="control-label"></label>
                <select asp-for="@Model.ItemCategory" class="form-control">
                </select>
                <span asp-validation-for="@Model.ItemCategory" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="@Model.ItemType" class="control-label"></label>
                <select asp-for="@Model.ItemType" class="form-control">
                </select>
                <span asp-validation-for="@Model.ItemType" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="@Model.MaterialType" class="control-label"></label>
                <select asp-for="@Model.MaterialType" class="form-control">
                    <option value="" selected>Select Material Type</option>
                    @foreach (var materialType in Enum.GetValues(typeof(RandApp.Enums.MaterialType)))
                    {
                        <option value="@materialType.ToString()">@materialType</option>
                    }
                    <option value="Other">Other</option>
                </select>
                <input id="otherMaterialInp" asp-for="@Model.MaterialType" class="form-control" style="display:none; margin-top:8px" placeholder="Enter Material Type" />
                <span asp-validation-for="@Model.MaterialType" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="@Model.Color" class="control-label"></label>
                <select asp-for="@Model.Color" multiple class="form-control">
                    @foreach (var color in Enum.GetValues(typeof(RandApp.Enums.ItemColor)))
                    {
                        <option value="@color.ToString()">@color.ToString()</option>
                    }
                    <option value="Other">Other</option>
                </select>
                <input id="otherColorInp" asp-for="@Model.Color" class="form-control" style="display:none; margin-top:8px" placeholder="Enter Item Color" />
                <span asp-validation-for="@Model.Color" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="@Model.Size" class="control-label"></label>
                <select asp-for="@Model.Size" multiple class="form-control">
                </select>
                <span asp-validation-for="@Model.Size" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="@Model.Price" class="control-label"></label>
                <input asp-for="@Model.Price" class="form-control" />
                <span asp-validation-for="@Model.Price" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="@Model.Description" class="control-label"></label>
                <textarea asp-for="@Model.Description" class="form-control"></textarea>
                <span asp-validation-for="@Model.Description" class="text-danger"></span>
            </div>
            <div class="form-group">
                <input type="submit" value="Create" asp-for- class="btn btn-primary" />
            </div>
        </form>
    </div>
</div>

所以这就是我想要做的:我想 select 多种颜色和尺寸并将它们的值添加到 Item.Color 和 Item.Size 列表中,但是当我尝试时,我在控制器中得到空列表。有控制器

// POST Create
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> CreateItem(Item item, IFormFile ItemPhoto)
{
     if (!ModelState.IsValid)
     {
         return View();
     }

     var path = Path.Combine(_webHostEnvironment.WebRootPath, "assets", ItemPhoto.FileName);
     var stream = new FileStream(path, FileMode.Create);
     await ItemPhoto.CopyToAsync(stream);
     item.ItemPhoto = ItemPhoto.FileName;

     await _itemRepo.CreateAsync(item);
     stream.Close();
     return RedirectToAction("Index");
}

如何从下拉列表中获取多个值并将它们添加到列表中?当我尝试使用 JavaScript 代码控制 selected 值时,它会打印正确的值,但问题是,我可以将它们发送到控制器并将它们保存在 db

模型绑定按名称绑定 属性。对于您的多项选择,它们与 List<ItemColors> Color/List<ItemSizes> Size 中的模型 属性 匹配。所以当你传递选择的值时,名称应该是这样的:Color[index].ItemColor/Size[index].ItemSize.

不确定您的 js 代码如何,不需要为我的演示中的 select 添加额外的输入元素

<input id="otherMaterialInp" asp-for="@Model.MaterialType" class="form-control" style="display:none; margin-top:8px" placeholder="Enter Material Type" />
<input id="otherColorInp" asp-for="@Model.Color" class="form-control" style="display:none; margin-top:8px" placeholder="Enter Item Color" />

我的整个工作演示:

型号class:

public class BaseEntity
{
    public int Id { get; set; }
}
public class Item : BaseEntity
{
    [Display(Name = "Item Photo")]
    public string ItemPhoto { get; set; }
    [Display(Name = "Item Type")]
    public string ItemType { get; set; }      
    [Display(Name = "Item Category")]
    public string ItemCategory { get; set; }
    [Display(Name = "Item Name")]
    public string Name { get; set; }
    [Display(Name = "Item Colors")]
    public List<ItemColors> Color { get; set; } = new List<ItemColors>();
    [Display(Name = "Item Size")]
    public List<ItemSizes> Size { get; set; } = new List<ItemSizes>();
    [Display(Name = "Item Material Type")]
    public string MaterialType { get; set; }
    [Display(Name = "Designed For")]
    public string DesignedFor { get; set; }
    [Display(Name = "Item Price")]
    public double Price { get; set; }
    [Display(Name = "Item Description")]
    public string Description { get; set; }
}
public class ItemColors : BaseEntity
{
    public string ItemColor { get; set; }
    public int? ItemId { get; set; }
    [ForeignKey("ItemId")]
    public Item Item { get; set; }
}
public class ItemSizes : BaseEntity
{
    public string ItemSize { get; set; }
    public int? ItemId { get; set; }
    [ForeignKey("ItemId")]
    public Item Item { get; set; }
}

枚举:

public enum MaterialType
{
    Meterial1,
    Meterial2,
    Meterial3
}
public enum ItemColor
{
    Red,
    Blue,
    Green
}
public enum DesignedFor
{
    Student,
    Teacher,
    Normal
}

查看:

@model Item

<div class="row">
    <div class="col-md-4">
        <form asp-action="CreateItem" enctype="multipart/form-data">
            <div class="form-group">
                <label asp-for="@Model.ItemPhoto" class="control-label"></label>
                <input type="file" name="ItemPhoto" class="form-control-file" onchange="SetValue(this)" />
                <input asp-for="@Model.ItemPhoto" hidden />
                <span asp-validation-for="@Model.ItemPhoto" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="@Model.Name" class="control-label"></label>
                <input asp-for="@Model.Name" class="form-control" />
                <span asp-validation-for="@Model.Name" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="@Model.DesignedFor" class="control-label"></label>
                <select asp-for="@Model.DesignedFor" class="form-control">
                    <option value="" selected>Select Designed For</option>
                    @foreach (var desigendFor in Enum.GetValues(typeof(DesignedFor)))
                    {
                        <option val="@desigendFor" value="@desigendFor.ToString()">@desigendFor</option>
                    }
                </select>
                <span asp-validation-for="@Model.DesignedFor" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="@Model.ItemCategory" class="control-label"></label>
                <select asp-for="@Model.ItemCategory" class="form-control">
                    <option value="Cat1">Cat1</option>
                    <option value="Cat2">Cat2</option>
                    <option value="Cat3">Cat3</option>
                </select>
                <span asp-validation-for="@Model.ItemCategory" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="@Model.ItemType" class="control-label"></label>
                <select asp-for="@Model.ItemType" class="form-control">
                    <option value="Item1">Item1</option>
                    <option value="Item2">Item2</option>
                    <option value="Item3">Item3</option>
                </select>
                <span asp-validation-for="@Model.ItemType" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="@Model.MaterialType" class="control-label"></label>
                <select asp-for="@Model.MaterialType" class="form-control">
                    <option value="" selected>Select Material Type</option>
                    @foreach (var materialType in Enum.GetValues(typeof(MaterialType)))
                    {
                        <option value="@materialType.ToString()">@materialType</option>
                    }
                    <option value="Other">Other</option>
                </select>
 <!-- useless input   -->
                @*<input id="otherMaterialInp" asp-for="@Model.MaterialType" class="form-control" style="display:none; margin-top:8px" placeholder="Enter Material Type" />*@
                <span asp-validation-for="@Model.MaterialType" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="@Model.Color" class="control-label"></label>
                <select asp-for="@Model.Color" multiple class="form-control">
                    @foreach (var color in Enum.GetValues(typeof(ItemColor)))
                    {
                        <option value="@color.ToString()">@color.ToString()</option>
                    }
                    <option value="Other">Other</option>
                </select>
     <!-- useless input   -->
                @*<input id="otherColorInp" asp-for="@Model.Color" class="form-control" style="display:none; margin-top:8px" placeholder="Enter Item Color" />*@
                <span asp-validation-for="@Model.Color" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="@Model.Size" class="control-label"></label>
                <select asp-for="@Model.Size" multiple class="form-control">
                    <option value="1">1</option>
                    <option value="2">2</option>
                    <option value="3">3</option>
                </select>
                <span asp-validation-for="@Model.Size" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="@Model.Price" class="control-label"></label>
                <input asp-for="@Model.Price" class="form-control" />
                <span asp-validation-for="@Model.Price" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="@Model.Description" class="control-label"></label>
                <textarea asp-for="@Model.Description" class="form-control"></textarea>
                <span asp-validation-for="@Model.Description" class="text-danger"></span>
            </div>
            <div class="form-group">    
                              <!-- change here   -->
                <input type="button" onclick="Create()" value="Create" asp-for- class="btn btn-primary" />
            </div>
        </form>
    </div>
</div>

我认为的JS:

@section Scripts {
    <script>
        function SetValue(el) {
            $("input:text#ItemPhoto").val($(el).val());
        }
        function Create () {           
            var fdata = new FormData();
            var fileInput = $("input:file")[0];
            var file = fileInput.files[0];
            fdata.append("ItemPhoto", file);

            fdata.append($("textarea").attr("name"), $("textarea").val());

            $("form input[type='text']").each(function (x, y) {
                fdata.append($(y).attr("name"), $(y).val());
            });
            $('select:not([multiple]) >option:selected').each(function () {
                var name = $(this).parent("select").attr("name");
                console.log(name);
                fdata.append(name, $(this).val());                   
            });
            $('select#Color >option:selected').each(function (index, obj) {
                fdata.append("Color[" + index +"].ItemColor", $(this).val());
                console.log($(obj).val());
            });
            $('select#Size >option:selected').each(function (index, obj) {
                fdata.append("Size[" + index +"].ItemSize", $(this).val());
                console.log($(obj).val());
            }); 
            var options = {};
            options.type = "POST";
            options.url = "/Items/CreateItem";
            options.dataType = "JSON";
            options.contentType = false;   
            options.processData = false;    
            options.data = fdata;
            options.beforeSend = function (xhr) {
                xhr.setRequestHeader("RequestVerificationToken", $('input:hidden[name="__RequestVerificationToken"]').val());
            };

            options.success = function (data) {
            };
            options.error = function (res) {
            };
            $.ajax(options);
        
        }
</script>
}

控制器:

[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> CreateItem(Item item,IFormFile ItemPhoto)
{
    if (ModelState.IsValid)
    {  
       //be sure your wwwroot folder contains a folder named `assets`
       var path = Path.Combine(_webHostEnvironment.WebRootPath, "assets", ItemPhoto.FileName);
       var stream = new FileStream(path, FileMode.Create);
       await ItemPhoto.CopyToAsync(stream);
        item.ItemPhoto = ItemPhoto.FileName;
        _context.Add(item);
        await _context.SaveChangesAsync();
        return RedirectToAction(nameof(Index));
    }
    return View(item);
}

结果:


另一种方式就是直接使用表单提交,多选需要设置参数。以<select asp-for="@Model.Color" multiple>为例,需要在后端添加一个名为Color的类型List<string>参数。

注意:多选不需要添加额外输入

整个工作演示:

查看:

@model Item

<div class="row">
    <div class="col-md-4">
        <form asp-action="CreateItem" enctype="multipart/form-data">
            <div class="form-group">
                <label asp-for="@Model.ItemPhoto" class="control-label"></label>
                <input type="file" name="ItemPhoto" class="form-control-file" onchange="SetValue(this)" />
                <input asp-for="@Model.ItemPhoto" hidden />
                <span asp-validation-for="@Model.ItemPhoto" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="@Model.Name" class="control-label"></label>
                <input asp-for="@Model.Name" class="form-control" />
                <span asp-validation-for="@Model.Name" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="@Model.DesignedFor" class="control-label"></label>
                <select asp-for="@Model.DesignedFor" class="form-control">
                    <option value="" selected>Select Designed For</option>
                    @foreach (var desigendFor in Enum.GetValues(typeof(DesignedFor)))
                    {
                        <option val="@desigendFor" value="@desigendFor.ToString()">@desigendFor</option>
                    }
                </select>
                <span asp-validation-for="@Model.DesignedFor" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="@Model.ItemCategory" class="control-label"></label>
                <select asp-for="@Model.ItemCategory" class="form-control">
                    <option value="Cat1">Cat1</option>
                    <option value="Cat2">Cat2</option>
                    <option value="Cat3">Cat3</option>
                </select>
                <span asp-validation-for="@Model.ItemCategory" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="@Model.ItemType" class="control-label"></label>
                <select asp-for="@Model.ItemType" class="form-control">
                    <option value="Item1">Item1</option>
                    <option value="Item2">Item2</option>
                    <option value="Item3">Item3</option>
                </select>
                <span asp-validation-for="@Model.ItemType" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="@Model.MaterialType" class="control-label"></label>
                <select asp-for="@Model.MaterialType" class="form-control">
                    <option value="" selected>Select Material Type</option>
                    @foreach (var materialType in Enum.GetValues(typeof(MaterialType)))
                    {
                        <option value="@materialType.ToString()">@materialType</option>
                    }
                    <option value="Other">Other</option>
                </select>
    <!-- useless input   -->
                @*<input id="otherMaterialInp" asp-for="@Model.MaterialType" class="form-control" style="display:none; margin-top:8px" placeholder="Enter Material Type" />*@
                <span asp-validation-for="@Model.MaterialType" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="@Model.Color" class="control-label"></label>
                <select asp-for="@Model.Color" multiple class="form-control">
                    @foreach (var color in Enum.GetValues(typeof(ItemColor)))
                    {
                        <option value="@color.ToString()">@color.ToString()</option>
                    }
                    <option value="Other">Other</option>
                </select>
     <!-- useless input   -->
                @*<input id="otherColorInp" asp-for="@Model.Color" class="form-control" style="display:none; margin-top:8px" placeholder="Enter Item Color" />*@
                <span asp-validation-for="@Model.Color" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="@Model.Size" class="control-label"></label>
                <select asp-for="@Model.Size" multiple class="form-control">
                    <option value="1">1</option>
                    <option value="2">2</option>
                    <option value="3">3</option>
                </select>
                <span asp-validation-for="@Model.Size" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="@Model.Price" class="control-label"></label>
                <input asp-for="@Model.Price" class="form-control" />
                <span asp-validation-for="@Model.Price" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="@Model.Description" class="control-label"></label>
                <textarea asp-for="@Model.Description" class="form-control"></textarea>
                <span asp-validation-for="@Model.Description" class="text-danger"></span>
            </div>
            <div class="form-group">
                <input type="submit" value="Create" asp-for- class="btn btn-primary" />
            </div>
        </form>
    </div>
</div>

视图中的 JS:

@section Scripts {
    <script>
        function SetValue(el) {
            console.log($(el).val());
            $("input:text#ItemPhoto").val($(el).val());
        }       
</script>
}

控制器:

[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> CreateItem(Item item,IFormFile ItemPhoto,List<string> Color,List<string> Size)
{
    foreach(var c in Color)
    {
        item.Color.Add(new ItemColors() { ItemColor = c });
    }
    foreach (var s in Size)
    {
        item.Size.Add(new ItemSizes() { ItemSize = s });
    }
    //......
    return View(item);
}

结果: