在 Razor 页面的 OnGetAsync 中将值分配给另一个模型
Assign values to a Model from another at OnGetAsync in Razor Page
我正在尝试将值分配给 Razor Page
中 OnGetAsync
的另一个 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
.
我正在尝试将值分配给 Razor Page
中 OnGetAsync
的另一个 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
.