我有一个带有“MSCustomers”和“MSLocations”的.Net 5.x 项目。 MSLocations 与 MSCustomers 之间存在多对一的关系。
我的“编辑”页面正确显示“MSCustomer”记录和相应的“MSLocations”字段。
PROBLEM:
“编辑”应该允许我修改或“删除”任何 MSLocation。但是当我保存记录时,所有 MSLocations 都没有改变。
MSCustomer.cs:
public class MSCustomer
{
public int ID { get; set; }
public string CustomerName { get; set; }
public string EngagementType { get; set; }
public string MSProjectNumber { get; set; }
// EF Navigation
public virtual ICollection<MSLocation> MSLocations { get; set; }
}
MSLocation.cs
public class MSLocation
{
public int ID { get; set; }
public string Address { get; set; }
public string City { get; set; }
public string State { get; set; }
public string Zip { get; set; }
public int MSCustomerId { get; set; } // FK
// EF Navigation
public MSCustomer MSCustomer { get; set; }
}
编辑.cshtml.cs:
public class EditModel : PageModel
{
[BindProperty]
public MSCustomer MSCustomer { get; set; }
...
public IActionResult OnGet(int? id)
{
if (id == null)
return NotFound();
MSCustomer = ctx.MSCustomer
.Include(location => location.MSLocations)
.FirstOrDefault(f => f.ID == id);
return Page(); // This all works...
}
public async Task<IActionResult> OnPostAsync(string? submitButton)
{
ctx.Attach(MSCustomer).State = EntityState.Modified;
await ctx.SaveChangesAsync();
return RedirectToPage("Index"); // Saves MSCustomer updates, but not MSLocations...
编辑.cshtml.cs
@page
@model HelloNestedFields.Pages.MSFRD.EditModel
@using HelloNestedFields.Models
...
<form method="POST">
<input type="hidden" asp-for="MSCustomer.ID" />
...
<table>
<thead>
<tr>
<th style="min-width:140px">Address</th>
<th style="min-width:140px">City</th>
<th style="min-width:140px">State</th>
<th style="min-width:140px">Zip</th>
</tr>
</thead>
<tbody>
@foreach (MSLocation loc in @Model.MSCustomer.MSLocations)
{
<tr id="[email protected] /cdn-cgi/l/email-protection">
<td><input asp-for="@loc.Address" /></td>
<td><input asp-for="@loc.City" /></td>
<td><input asp-for="@loc.State" /></td>
<td><input asp-for="@loc.Zip" /></td>
<td><button onclick="removeField(@loc.ID);">Remove</button></td>
</tr>
}
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
<td><button id="add_location_btn">Add Location</button></td>
</tr>
</tbody>
</table>
...
@section Scripts {
<script type="text/javascript">
function removeField(element_id) {
try {
let row_id = "row_" + element_id;
console.log("removeField, element_id=" + element_id + ", row_id=" + row_id + "...");
let tr = document.getElementById(row_id);
console.log("tr:", tr);
tr.parentNode.removeChild(tr);
} catch (e) {
console.error(e);
}
debugger;
};
</script>
}
HelloNestedContext.cs
public class HelloNestedContext : DbContext
{
public HelloNestedContext(DbContextOptions<HelloNestedContext> options)
: base(options)
{
}
public DbSet<HelloNestedFields.Models.MSCustomer> MSCustomers { get; set; }
public DbSet<HelloNestedFields.Models.MSLocation> MSLocations { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<MSCustomer>()
.HasMany(d => d.MSLocations)
.WithOne(c => c.MSCustomer)
.HasForeignKey(d => d.MSCustomerId);
}
}
问:我缺少什么?
问:我需要做什么才能MS客户.MS位置更新是否从浏览器传递回 OnPostAsync(),并正确保存?
我确定是POSSIBLE。但我无法在任何地方找到任何文档或示例代码来修改“记录对象”中的“嵌套项目对象”。
任何建议将非常受欢迎!
Update:
Razor 页面似乎不支持绑定到“复杂”对象(在记录中具有嵌套列表)。
因此,我尝试了下面 Okan Karadag 的出色建议 - 我将“MSLocations”拆分为自己的绑定,然后将其添加回“POST”处理程序中的“MSCustomer”。这让我CLOSER- 至少现在我可以更新嵌套字段。但我仍然无法在“编辑”页面中添加或删除 MSLocation。
新建Edit.cshtml.cs
[BindProperty]
public MSCustomer MSCustomer { get; set; }
[BindProperty]
public List<MSLocation> MSLocations { get; set; }
...
public IActionResult OnGet(int? id)
{
MSCustomer = ctx.MSCustomer
.Include(location => location.MSLocations)
.FirstOrDefault(f => f.ID == id);
MSLocations = new List<MSLocation>(MSCustomer.MSLocations);
...
public async Task<IActionResult> OnPostAsync(string? submitButton)
{
MSCustomer.MSLocations = new List<MSLocation>(MSLocations); // Update record with new
ctx.Update(MSCustomer);
await ctx.SaveChangesAsync();
...
新建编辑.cshtml
<div class="row">
...
<table>
...
<tbody id="mslocations_tbody">
@for (int i=0; i < Model.MSLocations.Count(); i++)
{
<tr id="[email protected] /cdn-cgi/l/email-protection[i].ID">
<td><input asp-for="@Model.MSLocations[i].Address" /></td>
<td><input asp-for="@Model.MSLocations[i].City" /></td>
<td><input asp-for="@Model.MSLocations[i].State" /></td>
<td><input asp-for="@Model.MSLocations[i].Zip" /></td>
<td>
<input type="hidden" asp-for="@Model.MSLocations[i].ID" />
<input type="hidden" asp-for="@Model.MSLocations[i].MSCustomerId" />
<button onclick="removeLocation([email protected] /cdn-cgi/l/email-protection[i].ID);">Remove</button>
</td>
</tr>
}
</tbody>
</table>
<button onclick="addLocation();">Add Location</button>
</div>
当前状态:
- 我可以更新顶级“MSCustomer”数据字段。
- 我可以更新现有的“MSlocation”字段。
- I CANNOT添加新的或删除当前的 MSLocation 项目。
- “拦截器”似乎是 Razor 绑定:将“更新的”MSLocations 列表从 Razor“编辑”页面传送回 C#“POST”操作处理程序。
我的下一步将尝试这个:
如何将来自不同实体的项目动态添加到 ASP.NET Core MVC 中的列表 https://stackoverflow.com/questions/63487500/how-to-dynamically-add-items-from-different-entities-to-lists-in-asp-net-core-mv
如果有效的话那就太好了。就会是均匀的BETTER如果有一个不涉及 Ajax 调用的更简单的替代方案..