[英]Saving an item in a collection in ASP.NET Core Razor Pages
I'm not understanding how to properly bind a single item from a collection.我不明白如何正确绑定集合中的单个项目。 In my project, a student can have multiple plans with these models:在我的项目中,学生可以使用以下模型制定多个计划:
public class Student
{
public Student()
{
Plans = new HashSet<Plan>();
}
public int StudentId { get; set; }
public string Designee { get; set; }
public string DesigneePhone { get; set; }
public virtual ICollection<Plan> Plans { get; set; }
}
public partial class Plan
{
public int PlanId { get; set; }
public int StudentId { get; set; }
public DateTime? StartDate { get; set; }
public DateTime? EndDate { get; set; }
public virtual Student Student { get; set; }
}
I'm listing each plan with its own Save button on the page.我在页面上列出了每个计划都有自己的保存按钮。 I thought I was using the asp-for helper correctly according to this Learn Razor Pages post .我以为我根据这篇 Learn Razor Pages post正确使用了 asp-for 助手。
@page "{studentId:int}"
@model CollectionTest.PlansModel
<form asp-page-handler="SaveMain" method="post">
<div class="row mt-3">
<input type="hidden" asp-for="Student.StudentId" />
<div class="col">
<label asp-for="Student.Designee"></label>
<input asp-for="Student.Designee" class="form-control" />
</div>
<div class="col">
<label asp-for="Student.DesigneePhone"></label>
<input asp-for="Student.DesigneePhone" class="form-control" />
</div>
<div class="col-auto align-self-end">
<input type="submit" value="Save" class="btn btn-primary" />
</div>
</div>
</form>
<hr />
@for (int i = 0; i < Model.Student.Plans.Count(); i++)
{
var planId = Model.Student.Plans.ToList()[i].PlanId.ToString();
<div id="@("card_Plan" + planId)" class="card">
<div class="card-header">
<h5>Plan #@planId</h5>
</div>
<div class="card-body">
<form id="@("form_Plan" + planId)" asp-page-handler="SavePlan" method="post">
<input type="hidden" asp-for="Student.Plans.ToList()[i].PlanId" />
<div class="row">
<div class="col">
<label asp-for="Student.Plans.ToList()[i].StartDate"></label>
<input asp-for="Student.Plans.ToList()[i].StartDate" class="form-control" />
<span asp-validation-for="Student.Plans.ToList()[i].StartDate"></span>
</div>
<div class="col">
<label asp-for="Student.Plans.ToList()[i].EndDate"></label>
<input asp-for="Student.Plans.ToList()[i].EndDate" class="form-control" />
<span asp-validation-for="Student.Plans.ToList()[i].EndDate"></span>
</div>
</div>
</form>
</div>
<div class="card-footer">
<div class="float-right">
<button type="submit" class="btn btn-primary" form="@("form_Plan" + planId)">Save</button>
</div>
</div>
</div>
}
But it seems like nothing is being bound in the SavePlan page handler:但似乎 SavePlan 页面处理程序中没有绑定任何内容:
[BindProperty]
public Student Student { get; set; }
.
.
.
public async Task<IActionResult> OnPostSavePlan(int planId)
{
if (!ModelState.IsValid)
{
return Page();
}
/******************************
*
* Student.Plans is empty and planId is zero
*
*******************************/
Plan plan = await _planContext.Plan.FirstAsync(p => p.PlanId == planId);
_planContext.Attach(plan).State = EntityState.Modified;
try
{
await _planContext.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!PlanExists(plan.PlanId))
{
return NotFound();
}
else
{
throw;
}
}
return RedirectToPage("./Plans");
}
What am I doing wrong?我究竟做错了什么?
According to your code, because what you pass in the razor page is [0].PlanId
, but what you receive in the OnPostSavePlan method is planId
.根据您的代码,因为您在 razor 页面中传递的是[0].PlanId
,但您在 OnPostSavePlan 方法中收到的是planId
。 If you only need to receive planId
, you need to change the form.如果您只需要接收planId
,则需要更改表单。
<div class="card-body">
<form id="@("form_Plan" + planId)" asp-page-handler="SavePlan" method="post">
<input type="hidden" asp-for="@planId" />
From your requirement,it seems you want to pass a list of plans.根据您的要求,您似乎想通过一个计划列表。 So you need to modify your code in the following steps:因此,您需要按以下步骤修改您的代码:
Plans.cshtml:计划.cshtml:
<form id="form_Plan" asp-page-handler="SavePlan" method="post">
@for (int i = 0; i < Model.Student.Plans.Count(); i++)
{
var planId = Model.Student.Plans.ToList()[i].PlanId.ToString();
<div id="@("card_Plan" + planId)" class="card">
<div class="card-header">
<h5>Plan #@planId</h5>
</div>
<div class="card-body">
<input type="hidden" asp-for="Student.Plans.ToList()[i].PlanId" />
<div class="row">
<div class="col">
<label asp-for="Student.Plans.ToList()[i].StartDate"></label>
<input asp-for="Student.Plans.ToList()[i].StartDate" class="form-control" />
<span asp-validation-for="Student.Plans.ToList()[i].StartDate"></span>
</div>
<div class="col">
<label asp-for="Student.Plans.ToList()[i].EndDate"></label>
<input asp-for="Student.Plans.ToList()[i].EndDate" class="form-control" />
<span asp-validation-for="Student.Plans.ToList()[i].EndDate"></span>
</div>
</div>
</div>
</div>
}
<div class="card-footer">
<div class="float-right">
<button type="submit" class="btn btn-primary" form="form_Plan">Save</button>
</div>
</div>
</form>
Plans.cshtml.cs:计划.cshtml.cs:
public class PlansModel : PageModel
{
public IActionResult OnGet()
{
//for easy testing,I add the data manually
Student = new Student()
{
Plans = new List<Plan>()
{
new Plan(){ PlanId=1, StartDate=DateTime.Parse("2019-8-7")},
new Plan(){ PlanId=2, StartDate=DateTime.Parse("2019-4-7")},
new Plan(){ PlanId=3, StartDate=DateTime.Parse("2019-6-7")}
}
};
return Page();
}
[BindProperty]
public Student Student { get; set; }
public async Task<IActionResult> OnPostSavePlan(List<Plan> plans)
{
//...
}
}
Update:更新:
Plans.cshtml:计划.cshtml:
@foreach (var plan in Model.Student.Plans)
{
var planId = plan.PlanId.ToString();
<div id="@("card_Plan" + planId)" class="card">
<div class="card-header">
<h5>Plan #@planId</h5>
</div>
<div class="card-body">
<form id="@("form_Plan" + planId)" asp-page-handler="SavePlan" method="post">
<input type="hidden" asp-for="@plan.PlanId" />
<div class="row">
<div class="col">
<label asp-for="@plan.StartDate"></label>
<input asp-for="@plan.StartDate" class="form-control" />
<span asp-validation-for="@plan.StartDate"></span>
</div>
<div class="col">
<label asp-for="@plan.EndDate"></label>
<input asp-for="@plan.EndDate" class="form-control" />
<span asp-validation-for="@plan.EndDate"></span>
</div>
</div>
</form>
</div>
<div class="card-footer">
<div class="float-right">
<button type="submit" class="btn btn-primary" form="@("form_Plan" + planId)">Save</button>
</div>
</div>
</div>
}
Plans.cshtml.cs:计划.cshtml.cs:
public async Task<IActionResult> OnPostSavePlan(Plan plan)
{
//...
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.