简体   繁体   English

将项目保存在 ASP.NET 核心 Razor 页面中的集合中

[英]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)
    {
        //...
    }
}

Result:结果: 在此处输入图像描述

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)
{
    //...
}

Result:结果: 在此处输入图像描述

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM