在 Razor 页面的 OnGetAsync 中将值分配给另一个模型

Assign values to a Model from another at OnGetAsync in Razor Page

我正在尝试将值分配给 Razor PageOnGetAsync 的另一个 Model 以进行一些数据验证,然后将它们分配回 [=16] 上的实际 Model =] 用于数据保存。

我在这一行收到 NullReferenceException 错误 Input.TestName = TestData.TestName;

public class TestData
{
    [Key]
    public int TestID { get; set; }
    public string TestName { get; set; }
}

页面模型

    private readonly Test.Models.TestContext _context;
    public EditModel(Test.Models.TestContext context)
    {
        _context = context;
    }
    [BindProperty]
    public TestData TestData { get; set; }

    [BindProperty]
    public InputModel Input { get; set; }

    public class InputModel
    {
        [Required, MaxLength(50), MinLength(3)]
        public string TestName { get; set; }
    }

    public async Task<IActionResult> OnGetAsync(int? id)
    {
        TestData = await _context.TestData.FirstOrDefaultAsync(m => m.TestID == id);
        Input.TestName = TestData.TestName; //Error Occurs here. TestData.TestName has value while debug.
        return Page();
    }

    public async Task<IActionResult> OnPostAsync()
    {
        TestData.TestName = Input.TestName;
        _context.Attach(TestData).State = EntityState.Modified;
        await _context.SaveChangesAsync();
        return RedirectToPage("./Index");
    }

我在 InputModel class 之外尝试了 TestName,效果很好,但我有很多属性可以像这样使用。所以我想把它们放在一个 class

请提出我在这里遗漏的内容。

正如您在问题中确认 TestData.TestName 在调试器中查看时有一个值,您应该将注意力转向 Input.TestName。更具体地说,这可能意味着 Input 属性 本身是 null,这将导致您的 NullReferenceException.

这也是有道理的。当 OnPostAsync 被调用时,ASP.NET Core 尝试使用来自请求的数据绑定到您的 Input 属性,这导致它创建一个 InputModel 的实例你。这是通过使用您在 Input 属性 本身上设置的 [BindProperty] 属性启用的。

然而,当调用OnGetAsync时,不会发生同样的过程。默认情况下,[BindProperty] 只会触发非 GET 请求来执行此绑定,这意味着 Input 内部的 OnGetAsync 调用将是 null(这是默认值以供参考-类型属性)。

要解决此问题,请更新您的 OnGetAsync 实现以在尝试设置其 TestName 值之前创建自己的 Input 实例。这是实现该目标的一种方法:

public async Task<IActionResult> OnGetAsync(int? id)
{
    TestData = await _context.TestData.FirstOrDefaultAsync(m => m.TestID == id);
    Input = new InputModel { TestName = TestData.TestName };
    return Page();
}

同样值得记住的是,如果 ID 不匹配,您对 FirstOrDefaultAsync 的调用会将 TestData 设置为 null,这会给您一个不同的 NullReferenceException.