使用 C# 在 ASP.NET MVC 的同一视图中创建父项和多个子项
Create Parent and Multiple Children in same view in ASP.NET MVC with C#
我一直在网上搜索,试图找到一个简单的解决方案(或至少定期浏览)我认为是常见的 activity,但我一直找不到任何解决方案。我有以下 类:
public class Attribute
{
...
public int Id { get; set; }
[Required]
public string AttributeName { get; set; }
public string Description { get; set; }
public bool UserCanChangeValue { get; set; }
public ICollection<AttributeValue> Values { get; set; }
}
class AttributeValue
{
public int Id { get; set; }
[ForeignKey("AssociatedAttribute")]
public int AssociatedAttributeId { get; set; }
public virtual Attribute AssociatedAttribute { get; set; }
[Required]
public string Value { get; set; }
public bool PromptChange { get; set; } = true;
public bool ShowonInvoice { get; set; } = false;
}
然后在标准控制器中:
...
// GET: AttributesController/Create
public ActionResult Create()
{
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create([Bind("Id,Name,Description,Values")] Attribute newAttribute)
....
我感到困惑的是如何在属性必须具有需要同时创建的 1 个或多个值的情况下创建它,并且动态属性可以具有可变编号。理想情况下,我会为要创建的每个属性值在表单中添加行。
一些脚手架细节:
...
<form asp-action="Create">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="AttributeName" class="control-label"></label>
<input asp-for="AttributeName" class="form-control" />
<span asp-validation-for="AttributeName" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Description" class="control-label"></label>
<input asp-for="Description" class="form-control" />
<span asp-validation-for="AttributeName" class="text-danger"></span>
</div>
<div class="form-group form-check">
<label class="form-check-label">
<input class="form-check-input" asp-for="UserCanChangeValue" /> @Html.DisplayNameFor(model => model.UserCanChangeValue)
</label>
</div>
<div>
<table>
<thead>
<tr>
<th>Value</th>
<th>Prompt Change</th>
<th>Show on Invoice</th>
</tr>
</thead>
<tbody>
INSERT DYNAMIC NEW VALUE FORM?
</tbody>
</table>
</div>
首先,您设置PromptChange
和ShowonInvoice
默认值,如果您不选中checkbox/radio
输入,它们将通过默认值(PromptChange= true
和ShowonInvoice=false
) 到后端。但实际上,我更喜欢不设置默认值,可以通过选中或不选中来控制true/false。不知道自己想要哪种方式,自己修改。
那么你的 class AttributeValue
需要 public 访问修饰符。
这是一个您可以遵循的简单工作演示:
型号:
namespace MvcProj5_0.Models
{
public class Attribute
{
public int Id { get; set; }
[Required]
public string AttributeName { get; set; }
public string Description { get; set; }
public bool UserCanChangeValue { get; set; }
public ICollection<AttributeValue> Values { get; set; }
}
public class AttributeValue
{
public int Id { get; set; } //add a primary key
[ForeignKey("AssociatedAttribute")]
public int AssociatedAttributeId { get; set; }
public virtual Attribute AssociatedAttribute { get; set; }
[Required]
public string Value { get; set; }
public bool PromptChange { get; set; }
public bool ShowonInvoice { get; set; }
}
}
视图(Create.cshtml):
@model MvcProj5_0.Models.Attribute
<form asp-action="Create">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="AttributeName" class="control-label"></label>
<input asp-for="AttributeName" class="form-control" />
<span asp-validation-for="AttributeName" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Description" class="control-label"></label>
<input asp-for="Description" class="form-control" />
<span asp-validation-for="AttributeName" class="text-danger"></span>
</div>
<div class="form-group form-check">
<label class="form-check-label">
<input class="form-check-input" asp-for="UserCanChangeValue" /> @Html.DisplayNameFor(model => model.UserCanChangeValue)
</label>
</div>
<button type="button" onclick="AddRow()">Add row</button> //add button
<div>
<table>
<thead>
<tr>
<th>Value</th>
<th>Prompt Change</th>
<th>Show on Invoice</th>
</tr>
</thead>
<tbody id="AttributeValueList" data-count="0"> //add id and data-count
INSERT DYNAMIC NEW VALUE FORM?
</tbody>
</table>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</form>
Create.cshtml 中的 JS:
@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
<script>
function AddRow()
{
var countVal = parseInt($('#AttributeValueList').attr('data-count'));
var html = '';
html += '<tr>';
html += '<td><input type="text" name="Values[' + countVal + '].Value" class="form-control"/></td>';
html += '<td><input type="checkbox" name="Values[' + countVal + '].PromptChange" value="true"/></td>';
html += '<td><input type="checkbox" name="Values[' + countVal + '].ShowonInvoice" value="true"/></td>';
html += '</tr>';
$('#AttributeValueList').append(html);
countVal += 1;
$('#AttributeValueList').attr('data-count', countVal);
}
</script>
}
控制器:
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create(
[Bind("Id,AttributeName,Description,UserCanChangeValue,Values")] MvcProj5_0.Models.Attribute attribute)
{
if (ModelState.IsValid)
{
_context.Add(attribute);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
return View(attribute);
}
我一直在网上搜索,试图找到一个简单的解决方案(或至少定期浏览)我认为是常见的 activity,但我一直找不到任何解决方案。我有以下 类:
public class Attribute
{
...
public int Id { get; set; }
[Required]
public string AttributeName { get; set; }
public string Description { get; set; }
public bool UserCanChangeValue { get; set; }
public ICollection<AttributeValue> Values { get; set; }
}
class AttributeValue
{
public int Id { get; set; }
[ForeignKey("AssociatedAttribute")]
public int AssociatedAttributeId { get; set; }
public virtual Attribute AssociatedAttribute { get; set; }
[Required]
public string Value { get; set; }
public bool PromptChange { get; set; } = true;
public bool ShowonInvoice { get; set; } = false;
}
然后在标准控制器中:
...
// GET: AttributesController/Create
public ActionResult Create()
{
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create([Bind("Id,Name,Description,Values")] Attribute newAttribute)
....
我感到困惑的是如何在属性必须具有需要同时创建的 1 个或多个值的情况下创建它,并且动态属性可以具有可变编号。理想情况下,我会为要创建的每个属性值在表单中添加行。
一些脚手架细节:
...
<form asp-action="Create">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="AttributeName" class="control-label"></label>
<input asp-for="AttributeName" class="form-control" />
<span asp-validation-for="AttributeName" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Description" class="control-label"></label>
<input asp-for="Description" class="form-control" />
<span asp-validation-for="AttributeName" class="text-danger"></span>
</div>
<div class="form-group form-check">
<label class="form-check-label">
<input class="form-check-input" asp-for="UserCanChangeValue" /> @Html.DisplayNameFor(model => model.UserCanChangeValue)
</label>
</div>
<div>
<table>
<thead>
<tr>
<th>Value</th>
<th>Prompt Change</th>
<th>Show on Invoice</th>
</tr>
</thead>
<tbody>
INSERT DYNAMIC NEW VALUE FORM?
</tbody>
</table>
</div>
首先,您设置PromptChange
和ShowonInvoice
默认值,如果您不选中checkbox/radio
输入,它们将通过默认值(PromptChange= true
和ShowonInvoice=false
) 到后端。但实际上,我更喜欢不设置默认值,可以通过选中或不选中来控制true/false。不知道自己想要哪种方式,自己修改。
那么你的 class AttributeValue
需要 public 访问修饰符。
这是一个您可以遵循的简单工作演示:
型号:
namespace MvcProj5_0.Models
{
public class Attribute
{
public int Id { get; set; }
[Required]
public string AttributeName { get; set; }
public string Description { get; set; }
public bool UserCanChangeValue { get; set; }
public ICollection<AttributeValue> Values { get; set; }
}
public class AttributeValue
{
public int Id { get; set; } //add a primary key
[ForeignKey("AssociatedAttribute")]
public int AssociatedAttributeId { get; set; }
public virtual Attribute AssociatedAttribute { get; set; }
[Required]
public string Value { get; set; }
public bool PromptChange { get; set; }
public bool ShowonInvoice { get; set; }
}
}
视图(Create.cshtml):
@model MvcProj5_0.Models.Attribute
<form asp-action="Create">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="AttributeName" class="control-label"></label>
<input asp-for="AttributeName" class="form-control" />
<span asp-validation-for="AttributeName" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Description" class="control-label"></label>
<input asp-for="Description" class="form-control" />
<span asp-validation-for="AttributeName" class="text-danger"></span>
</div>
<div class="form-group form-check">
<label class="form-check-label">
<input class="form-check-input" asp-for="UserCanChangeValue" /> @Html.DisplayNameFor(model => model.UserCanChangeValue)
</label>
</div>
<button type="button" onclick="AddRow()">Add row</button> //add button
<div>
<table>
<thead>
<tr>
<th>Value</th>
<th>Prompt Change</th>
<th>Show on Invoice</th>
</tr>
</thead>
<tbody id="AttributeValueList" data-count="0"> //add id and data-count
INSERT DYNAMIC NEW VALUE FORM?
</tbody>
</table>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</form>
Create.cshtml 中的 JS:
@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
<script>
function AddRow()
{
var countVal = parseInt($('#AttributeValueList').attr('data-count'));
var html = '';
html += '<tr>';
html += '<td><input type="text" name="Values[' + countVal + '].Value" class="form-control"/></td>';
html += '<td><input type="checkbox" name="Values[' + countVal + '].PromptChange" value="true"/></td>';
html += '<td><input type="checkbox" name="Values[' + countVal + '].ShowonInvoice" value="true"/></td>';
html += '</tr>';
$('#AttributeValueList').append(html);
countVal += 1;
$('#AttributeValueList').attr('data-count', countVal);
}
</script>
}
控制器:
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create(
[Bind("Id,AttributeName,Description,UserCanChangeValue,Values")] MvcProj5_0.Models.Attribute attribute)
{
if (ModelState.IsValid)
{
_context.Add(attribute);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
return View(attribute);
}