【问题标题】:Razor Pages: Values not staying from OnGet() to OnPost()Razor 页面:值不会从 OnGet() 停留在 OnPost()
【发布时间】:2020-10-08 19:16:37
【问题描述】:

我正在使用 Razor Pages 开发 ASP.NET Core 网页。在一个页面上,添加或选择了一个客户,并且在 OnGet 函数中正确传递了 customer_id(通过调试看到)。当我让用户填写表单时,我尝试使用实体框架调用 SQL 服务器数据库。一切都应该正常工作,但是,在 OnPostAsync() 中,当我尝试导入我在 OnGet() 中设置的 customer_id 值时,我收到一个错误,因为该值以某种方式设置为 0 而不是我之前设置的值.我不知道为什么会发生这种情况,因为我通常是 Razor 页面和实体框架的新手,但我已经发布了下面的代码。任何建议都会很棒!

AddAssessment.cshtml.cs:

namespace CustomerPageTest.Pages.Assessment
{
public class AddAssessmentModel : PageModel
{
    private readonly CustomerPageTest.Data.CustomerPageTestContext _context;

    public AddAssessmentModel(CustomerPageTest.Data.CustomerPageTestContext context)
    {
        _context = context;
    }

    public static List<SelectListItem> InDatabaseUserData()
    {
        List<SelectListItem> Users = new List<SelectListItem>();

            string connString = "Data Source = DESKTOP-5A23I9M; Initial Catalog = DataWarehouse; User ID = sa; pwd = 2128Swan";
            string commandString = "SELECT user_id, name FROM KelderUser";

            SqlConnection conn = new SqlConnection(connString);
            SqlDataAdapter adapter = new SqlDataAdapter(commandString, conn);
            DataTable dtCustomers = new DataTable();
            adapter.Fill(dtCustomers);

            foreach (DataRow dataRow in dtCustomers.Rows)
            {
                SelectListItem temp = new SelectListItem()
                {
                    Value = dataRow[0].ToString(),
                    Text = dataRow[1].ToString()
                };
                Users.Add(temp);
            }
        return Users;
    }

    [BindProperty]
    public CustomerPageTest.Assessment Assessment { get; set; } = new CustomerPageTest.Assessment();
    public List<SelectListItem> SelectUser { get; set; } = new List<SelectListItem>();

    public void OnGet(int customerId)
    {
        SelectUser = InDatabaseUserData();
        Assessment.customer_id = customerId;
        if(Assessment == null)
        {
            return RedirectToPage("/Customer/List");
        }
        return Page();
    }

    // To protect from overposting attacks, enable the specific properties you want to bind to, for
    // more details, see https://aka.ms/RazorPagesCRUD.
    public async Task<IActionResult> OnPostAsync()
    {
        if (!ModelState.IsValid)
        {
            return Page();
        }

        foreach(var item in SelectUser)
        {
            if (item.Selected)
            {
                try { Assessment.user_id = Convert.ToInt32(item.Value); } catch (Exception) { }
            }
        }

        try { Assessment.imported_data_datetime = Convert.ToDateTime(Assessment.imported_data_datetime); } catch(Exception) { }
        _context.Assessment.Add(Assessment);
        await _context.SaveChangesAsync();

        return RedirectToPage("/Customer/List");
    }
}

}

然后AddCustomer.cshtml:

@page
@model CustomerPageTest.Pages.Assessment.AddAssessmentModel

@{
    ViewData["Title"] = "AddAssessment";
}

<h1>AddAssessment</h1>

<h4>Assessment</h4>
<hr />
<div class="row">
    <div class="col-md-4">
        <form method="post">
            <div asp-validation-summary="ModelOnly" class="text-danger"></div>
            <div class="form-group">
                <label asp-for="Assessment.vcenter" class="control-label"></label>
                <input asp-for="Assessment.vcenter" class="form-control" />
                <span asp-validation-for="Assessment.vcenter" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="Assessment.imported_data_datetime" class="control-label"></label>
                <input asp-for="Assessment.imported_data_datetime" class="form-control" />
                <span asp-validation-for="Assessment.imported_data_datetime" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="Assessment.notes" class="control-label"></label>
                <input asp-for="Assessment.notes" class="form-control" />
                <span asp-validation-for="Assessment.notes" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="Assessment.user_id"></label>
                <select class="form-control" asp-for="Assessment.user_id" asp-items="Model.SelectUser">
                    <option value="">Select a User</option>
                </select>
            </div>
            <div class="form-group">
                <input type="submit" value="Create" class="btn btn-primary" />
            </div>
        </form>
    </div>
</div>

<div>
    <a asp-page="/Customer/List">Back to List</a>
</div>

@section Scripts {
    @{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}

另外,如果您对我的代码中发生的事情有任何疑问,请告诉我,因为在此之前还有其他类和页面。主要思想是我有一个带有整数的评估类:customer_id,需要设置但没有设置。

【问题讨论】:

    标签: c# html asp.net-core entity-framework-core razor-pages


    【解决方案1】:

    发生这种情况的原因是因为 HTTP 是无状态的。一旦处理了该请求,您在一个请求中创建的任何状态(数据)都会被销毁,除非您采取措施将其持久化。

    在 Razor 页面 (https://www.learnrazorpages.com/razor-pages/state-management) 中有多种管理状态的方法,但在您的情况下,您应该使用隐藏的表单字段,将选定的客户 ID 发布到 OnPost 处理程序

    【讨论】:

    • 谢谢!我会检查一下,看看情况如何。
    【解决方案2】:

    我写了一个demo,发现你没有在cshtml中绑定customer_id,所以你在cshtml.cs中发布日期时,并没有贴上customer_id。可以在cshtml中添加&lt;input hidden asp-for="Assessment.customer_id" class="form-control" /&gt;绑定 customer_id。

    这是一个演示:

    cshtml:

    <div class="row">
        <div class="col-md-4">
            <form method="post">
                <div asp-validation-summary="ModelOnly" class="text-danger"></div>
                <div class="form-group">
                    <label asp-for="Assessment.vcenter" class="control-label"></label>
                    <input asp-for="Assessment.vcenter" class="form-control" />
                    <span asp-validation-for="Assessment.vcenter" class="text-danger"></span>
                </div>
                <div class="form-group">
                    <label asp-for="Assessment.imported_data_datetime" class="control-label"></label>
                    <input asp-for="Assessment.imported_data_datetime" class="form-control" />
                    <span asp-validation-for="Assessment.imported_data_datetime" class="text-danger"></span>
                </div>
                <div class="form-group">
                    <label asp-for="Assessment.notes" class="control-label"></label>
                    <input asp-for="Assessment.notes" class="form-control" />
                    <span asp-validation-for="Assessment.notes" class="text-danger"></span>
                </div>
                <div class="form-group">
                    <label asp-for="Assessment.user_id"></label>
                    <select class="form-control" asp-for="Assessment.user_id" asp-items="Model.SelectUser">
                        <option value="">Select a User</option>
                    </select>
                </div>
                <input hidden asp-for="Assessment.customer_id" class="form-control" />
                <div class="form-group">
                    <input type="submit" value="Create" class="btn btn-primary" />
                </div>
            </form>
        </div>
    </div>
    

    cshtml.cs:

    public class AddCustomerModel : PageModel
        {
            [BindProperty]
            public Assessment Assessment { get; set; } = new Assessment();
            public List<SelectListItem> SelectUser { get; set; } = new List<SelectListItem>();
            public IActionResult OnGet()
            {
                for (int i = 1; i < 6; i++) {
                    SelectListItem temp = new SelectListItem()
                    {
                        Value = i+"",
                        Text = "user"+i
                    };
                    SelectUser.Add(temp);
                }
                Assessment.customer_id = 2;
                Assessment.vcenter = "vcenter";
                return Page();
    
    
            }
            public IActionResult OnPost() {
                if (!ModelState.IsValid)
                {
                    return Page();
                }
                return Page();
            }
        }
    

    结果:

    【讨论】:

    • 感谢您的示例!但是,我在通过 OnGet() 导入的评估中已经有了 customer_id。我不想在 cshtml 中绑定 customerId,因为它不应该在那里看到。我想,由于我的 cshtml.cs 中有 [BindProperty(SupportsGet = true)],它允许在 OnGet() 中设置这些属性,以便我可以在 OnPost() 中访问它们。
    猜你喜欢
    • 1970-01-01
    • 2020-07-09
    • 2021-06-18
    • 2020-08-21
    • 2022-01-12
    • 2020-10-01
    • 2020-03-27
    • 1970-01-01
    • 2020-05-26
    相关资源
    最近更新 更多