[英]ASP.Net Core MVC how to post unknown number of fields against strongly-typed model
完全被这个难住了。 我有一个页面,用户可以在其中单击“添加步骤”按钮,并且一些 javascript 将带有来自<template>
标记的其他输入的行附加到表单中。 从控制器调试时,值为空。
我查看了以下帖子,但两个答案似乎都没有帮助(不确定是不是因为我使用的是 .Net 核心 - 可能不是):
模型 (Procedure.cs)
public class Procedure
{
public int Id { get; set; }
public string Name { get; set; }
public string Type { get; set; }
public int MinNumber { get; set; }
public int MaxNumber { get; set; }
}
控制器(ProceduresController.cs)
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create([FromForm]List<Procedure> model)
{
if (ModelState.IsValid)
{
foreach(var field in model)
{
// Database things will happpen eventually, but at this point the Count = 0
}
}
return View(model);
}
目前Create
动作签名包括[FromForm]
属性,但我不知道这里是否需要。 我也试过List<Procedure> model
。
和视图(Create.cshtml)
我去掉了很多 UI 和 javascript 以使事情更容易阅读
@model List<Procedure>
/* also tried @model Procedure */
@{
ViewData["Title"] = "Create Procedure";
ViewData["Sidebar"] = "App";
}
<form asp-action="Create" enctype="multipart/form-data">
<div asp-validation-summary="All" class="field-validation-summary"></div>
<div class="builder">
<div class="field-row">
<div class="field-group">
<label class="field-label">Instruction Name</label>
<input type="text" name="Name" class="field type:text" placeholder="Enter an instruction name" />
</div>
<div class="field-group">
<label for="Type" class="field-label">Instruction Type</label>
<select id="Type" name="Type" class="field type:select stretch">
/* removing for brevity */
</select>
</div>
</div>
<div class="field-row">
<div class="field-group">
<label class="field-label">Minimum Number</label>
<input type="number" name="MinNumber" class="field type:number" />
</div>
<div class="field-group">
<label class="field-label">Maximum Number</label>
<input type="number" name="MaxNumber" class="field type:number" />
</div>
</div>
</div>
<div class="field-row">
<div class="field-group">
<div class="add-step">Add Step</div>
</div>
</div>
<div class="field-row">
<div class="field-group">
<input type="submit" value="Submit Procedures" class="button button-submit" />
</div>
</div>
</form>
<template id="template">
<details class="accordion" open>
<summary>Procedure Step</summary>
<div class="details-content">
<div class="field-row">
<div class="field-group">
<label class="field-label">Instruction Name</label>
<input type="text" name="Name" class="field type:text" placeholder="Enter an instruction name" />
</div>
<div class="field-group">
<label for="Type" class="field-label">Instruction Type</label>
<select id="Type" name="Type" class="field type:select stretch">
/* removing for brevity */
</select>
</div>
</div>
<div class="field-row">
<div class="field-group">
<label class="field-label">Minimum Number</label>
<input type="number" name="MinNumber" class="field type:number" />
</div>
<div class="field-group">
<label class="field-label">Maximum Number</label>
<input type="number" name="MaxNumber" class="field type:number" />
</div>
</div>
</div>
</details>
</template>
@section Scripts {
@{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); }
<script>
const modal = new Modal();
function getParent(element, selector) {
for (; element && element !== document; element = element.parentNode) {
if (element.classList.contains(selector)) {
return element;
}
}
return null;
}
this.Builder = function () {
this.template = document.querySelector('#template');
this.builder = document.querySelector('.builder');
this.addStep = document.querySelector('.add-step');
this.clone = null;
this.counter = 0;
this.addStep.addEventListener('click', this.add.bind(this));
};
Builder.prototype = {
add: function () {
this.counter++;
this.clone = document.importNode(this.template.content, true);
this.builder.appendChild(this.clone);
// i'm doing things here to set the new field attribute values - removed for brevity
}
};
let builder = new Builder();
builder.add();
</script>
}
在 javascript 中,我是否需要以特定方式设置新字段name
值? 它们应该看起来像<input type="text" name="Name[index]">
还是<input type="text" name="@Model.Procedure[index].Name">
?
我都试过,但回发时计数仍然为 0。 我几乎碰壁了,所以我很感激任何和所有的帮助。
.NET 需要为复杂类型的模型绑定做更多的努力。 元素的命名很重要。
<input name="model[index].Name" />
<input name="model[index].Type" />
<input name="model[index].MinNumber" />
<input name="model[index].MaxNumber" />
要绑定的命名约定是:控制器(模型)中的参数名称、索引、属性名称。 这将正确地将所有对象传递到您的列表。
如果您将对象传递给模型内的列表,情况也是如此。 例如
public class Example {
public int Id { get; set; }
public List<Procedure> Procedures { get; set; }
}
在这种情况下,我们只需要告诉 .NET 您正在映射的属性。
<input name="model.Procedures[index].Name" />
在某些情况下,您可能还需要为索引添加一个隐藏字段: https : //www.red-gate.com/simple-talk/dotnet/asp-net/model-binding-asp-net-core/
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.