如何将动态数量的 HTML 表单作为对象列表发送到控制器?

How to send dynamic amount of HTML forms to controller as list of objects?

我正在做一个 .NET Core MVC 项目。在部分视图中,我希望用户的一些信息填写为 HTML 表单。该信息是模型的变量,因此每个填充列表都是一个对象。用户填充对象后,我想将该对象作为该对象的列表发送到我的控制器。用户可以发送 3 个表格或 5 个表格或 1 个表格。我的问题是,当它只发送 1 个表单时,一切正常,我将模型的变量名称作为名称属性提供给表单标签中的 HTML 输入,并且我的对象正在填充。但是在那种情况下,我不知道会有多少对象出现,我无法弄清楚如何获得对象列表。我希望它是清楚的。

这是我的观点:

@model List<EpubAdmin.Models.KyProducts>
@{
    ViewData["Title"] = "AddBook";
    Layout = null;
}

@foreach(var product in Model)
{
    <div class="col col-xl-12">
    <div class="row justify-content-center">
        

        <div class="col-xl-5 col-lg-5 ">
            <form method="post" action="/File/AddProductFile" enctype="multipart/form-data" id="myForm">
                
                <br />
                <b>Kitap Adı: </b>
                <input class="form-control" value="@(Html.Raw(product.Name))" name="Name"/>
                <br />
                <b>Sayfa Sayısı: </b>
                <input class="form-control" value="@product.PageNumber" name="PageNumber" />
                <br />
                <b>Product Id: </b>
                <input class="form-control" value="@product.KyProductId" name="KyProductId" readonly />
                <br />
                <b>Barkod:  </b>
                <input class="form-control" value="@product.Barcode" name="Barcode" readonly />
                <input class="form-control" value="@product.Author" name="Author" hidden />
                <input class="form-control" value="@product.ImageId" name="ImageId" hidden />
                <input class="form-control" value="@product.PublisherName" name="PublisherName" hidden />
                <input class="form-control" value="@product.PublisherId" name="PublisherId" hidden />
                
                <br />
                @*<select class="selectpicker" data-live-search="true" data-show-subtext="true">
                        <option value="0">Tarih</option>
                        <option value="1">Çocuk</option>
                        <option value="2">Psikoloji</option>
                        <option value="3">Kültür</option>
                    </select>*@
                @if (product.IsDuplicate)
                {
                    <div class="alert alert-danger">
                        <p>* Bu kitap zaten ekli.</p>
                    </div>}

                else
                {
                    <h5>Kategori Seç</h5>
                    <select class="form-select ml-0" data-live-search="true">
                        <option selected>Tarih</option>
                        <option value="1">Çocuk</option>
                        <option value="2">Psikoloji</option>
                        <option value="3">Kültür</option>
                    </select>
                    <select class="form-select ml-5">
                        <option selected>Tarih</option>
                        <option value="1">Çocuk</option>
                        <option value="2">Psikoloji</option>
                        <option value="3">Kültür</option>
                    </select>
                    <select class="form-select ml-5">
                        <option selected>Tarih</option>
                        <option value="1">Çocuk</option>
                        <option value="2">Psikoloji</option>
                        <option value="3">Kültür</option>
                    </select>
                    <br />
                    <br />
                    <label for="file">Yüklenecek kitabı seçin.</label>
                    <input type="file" class="form-control-file" id="File" accept=".epub" name="File">   
                }
            </form>
            <br />         
            <br />
        </div>
    </div>
    <br />
    <hr />
    <br />
</div>
}

<div class="float-right">
    <button class="btn btn-info w-100" onclick="onclk()">Ekle</button>
</div>
<br />
<br />


<script>  
    function onclk() {
        $("#myForm").submit();       
        alert("a");
    }
</script>

控制器:

        [HttpPost]
        public IActionResult AddProductFile(List<KyProducts> model)                                              
        {
            foreach(var product in model)
            {
                if (product.file == null || product.KyProductId == 0 || product.PublisherId == 0)
                {
                    return RedirectToAction("List", "Books");
                }
}
}

我考虑过在我看来使用 for 而不是 foreach,这样我可以获得索引并将我的 HTML 属性命名为 name="id+@i",但这对我来说似乎不是最佳实践,也不是确定它是否有效。我还考虑过为每个表单放置隐藏的提交按钮,并在单击主提交按钮时触发所有隐藏的提交按钮,但这似乎又不是最佳实践......你有什么想法?

如果您想将列表传递给您的操作,请尝试将表单放在 foreach 之外,并更改输入的名称:

@model List<EpubAdmin.Models.KyProducts>
@{
    ViewData["Title"] = "AddBook";
    Layout = null;
}
<form method="post" action="/File/AddProductFile" enctype="multipart/form-data" id="myForm">
    @{ var i = 0;}
    @foreach (var product in Model)
    {
        <div class="col col-xl-12">
            <div class="row justify-content-center">


                <div class="col-xl-5 col-lg-5 ">


                    <br />
                    <b>Kitap Adı: </b>
                    <input class="form-control" value="@(Html.Raw(product.Name))" name="model[@i].Name" />
                    <br />
                    <b>Sayfa Sayısı: </b>
                    <input class="form-control" value="@product.PageNumber" name="model[@i].PageNumber" />
                    <br />
                    <b>Product Id: </b>
                    <input class="form-control" value="@product.KyProductId" name="model[@i].KyProductId" readonly />
                    <br />
                    <b>Barkod:  </b>
                    <input class="form-control" value="@product.Barcode" name="model[@i].Barcode" readonly />
                    <input class="form-control" value="@product.Author" name="model[@i].Author" hidden />
                    <input class="form-control" value="@product.ImageId" name="model[@i].ImageId" hidden />
                    <input class="form-control" value="@product.PublisherName" name="model[@i].PublisherName" hidden />
                    <input class="form-control" value="@product.PublisherId" name="model[@i].PublisherId" hidden />

                    <br />

                    @if (product.IsDuplicate)
                    {
                        <div class="alert alert-danger">
                            <p>* Bu kitap zaten ekli.</p>
                        </div>}

                    else
                    {
                        <h5>Kategori Seç</h5>
                        <select class="form-select ml-0" data-live-search="true">
                            <option selected>Tarih</option>
                            <option value="1">Çocuk</option>
                            <option value="2">Psikoloji</option>
                            <option value="3">Kültür</option>
                        </select>
                        <select class="form-select ml-5">
                            <option selected>Tarih</option>
                            <option value="1">Çocuk</option>
                            <option value="2">Psikoloji</option>
                            <option value="3">Kültür</option>
                        </select>
                        <select class="form-select ml-5">
                            <option selected>Tarih</option>
                            <option value="1">Çocuk</option>
                            <option value="2">Psikoloji</option>
                            <option value="3">Kültür</option>
                        </select>
                        <br />
                        <br />
                        <label for="file">Yüklenecek kitabı seçin.</label>
                        <input type="file" class="form-control-file" id="File" accept=".epub" name="File">
                    }

                    <br />
                    <br />
                </div>
            </div>
            <br />
            <hr />
            <br />
        </div>
        i++;
    }
    <input type="submit" value="submit"/>
</form>

这样当您点击按钮时,它会将整个列表传递给操作。