ASP.NET Core Razor Pages - 复杂模型 属性 在返回 Page() 后为空
ASP.NET Core Razor Pages - Complex model property is null after returning Page()
我显然不了解有关 Razor Pages 中模型绑定复杂属性的一些基本知识。当我的模型无效时,我 return Page();
但在引用模型的复杂 属性 时出现异常。这是我的精简版:
型号:
public class Movie
{
public int Id { get; set; }
public string Title { get; set; }
public Director Director { get; set; }
public string Description { get; set; }
}
public class Director
{
public int Id { get; set; }
public string Name { get; set; }
}
Index.cshtml.cs:
[BindProperty]
public Movie Movie { get; set; }
[BindProperty, Required]
public string Description { get; set; }
public IActionResult OnGet()
{
// Pretend we're loading from the DB...
Movie = new Movie
{
Id = 1,
Title = "Citizen Kane",
Director = new Director
{
Id = 101,
Name = "Orson Wells"
}
};
return Page();
}
public IActionResult OnPost()
{
if (!ModelState.IsValid)
return Page();
Movie.Description = Description;
//Save to DB
// ...
return RedirectToPage("/Index");
}
Index.cshtml:
@page
@model IndexModel
<h5>@Model.Movie.Title</h5>
<h6>Directed by @Model.Movie.Director.Name</h6>
<form method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<input type="hidden" asp-for="Movie.Id" />
<textarea asp-for="Description" placeholder="Enter Description"></textarea>
<button type="submit">Submit</button>
</form>
当我将描述留空时,模型在 OnPost
和 returns Page()
中如预期的那样无效。但是后来我在这里得到了 System.NullReferenceException; Object reference not set to an instance of an object
:
<h6>Directed by @Model.Movie.Director.Name</h6>
这里为什么Movie.Director
为空?返回Page()
时是否必须重新获取数据?我以为它会再次触发 OnGet()
但它没有。我做错了什么?
Why is Movie.Director
null here? Do I have to get the data again when returning Page()
? I was thinking it would fire OnGet()
again but it doesn't.
不,OnGet
方法不会在您的 OnPost
方法实际执行时自动调用。这两个处理程序彼此独立,它们唯一共享的是底层 Razor 视图和页面模型。如果您的视图需要将数据加载到模型中,那么您也需要为 OnPost
执行此操作。
您 可以 从 POST 方法中调用 GET 方法,但是根据您在 OnGet
中实际执行的操作,这可能会覆盖数据已由 OnPost
明确设置。我建议的是添加一个额外的方法,该方法将由 OnGet
和 OnPost
调用,以设置您的视图需要呈现的 shared 模型属性.
public IActionResult OnGet()
{
Movie = LoadMovie();
return Page();
}
public IActionResult OnPost()
{
if (!ModelState.IsValid)
{
Movie = LoadMovie();
return Page();
}
// …
return RedirectToPage("/Index");
}
private Movie LoadMovie()
{
// …
}
请注意,如果您确实需要呈现页面视图,您也只需要执行此方法。
混淆可能源于 OnGet
和 OnPost
方法的用途:对于 Razor 页面,这些方法是 入口点 。当请求与 Razor 页面匹配的路由时,ASP.NET 核心框架会调用它们。如果是 GET 请求,则调用 OnGet
方法;如果是 POST 请求,则为 OnPost
方法。除了共享相同的视图(cshtml)和模型之外,这些方法之间没有直接关系。
因为这些方法是入口点,所以 POST 请求不会执行 OnGet
方法,GET 请求不会执行 OnPost
方法——当然,除非你让那些在这些方法中调用自己的人。
现在,当您 return Page()
时,唯一发生的事情就是告诉 ASP.NET 核心框架然后使用您准备的数据呈现 Razor 视图页面模型。所以它只是渲染 cshtml
传递页面模型作为视图的模型。但是,此时这不会导致对 OnGet
或 OnPost
的任何调用,因为那些已经 运行 进入 进入 Razor 页面执行。
这意味着如果您想始终在呈现视图之前执行某些逻辑,那么您将需要在 returning Page()
之前从页面处理程序中显式执行该逻辑。 =33=]
我显然不了解有关 Razor Pages 中模型绑定复杂属性的一些基本知识。当我的模型无效时,我 return Page();
但在引用模型的复杂 属性 时出现异常。这是我的精简版:
型号:
public class Movie
{
public int Id { get; set; }
public string Title { get; set; }
public Director Director { get; set; }
public string Description { get; set; }
}
public class Director
{
public int Id { get; set; }
public string Name { get; set; }
}
Index.cshtml.cs:
[BindProperty]
public Movie Movie { get; set; }
[BindProperty, Required]
public string Description { get; set; }
public IActionResult OnGet()
{
// Pretend we're loading from the DB...
Movie = new Movie
{
Id = 1,
Title = "Citizen Kane",
Director = new Director
{
Id = 101,
Name = "Orson Wells"
}
};
return Page();
}
public IActionResult OnPost()
{
if (!ModelState.IsValid)
return Page();
Movie.Description = Description;
//Save to DB
// ...
return RedirectToPage("/Index");
}
Index.cshtml:
@page
@model IndexModel
<h5>@Model.Movie.Title</h5>
<h6>Directed by @Model.Movie.Director.Name</h6>
<form method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<input type="hidden" asp-for="Movie.Id" />
<textarea asp-for="Description" placeholder="Enter Description"></textarea>
<button type="submit">Submit</button>
</form>
当我将描述留空时,模型在 OnPost
和 returns Page()
中如预期的那样无效。但是后来我在这里得到了 System.NullReferenceException; Object reference not set to an instance of an object
:
<h6>Directed by @Model.Movie.Director.Name</h6>
这里为什么Movie.Director
为空?返回Page()
时是否必须重新获取数据?我以为它会再次触发 OnGet()
但它没有。我做错了什么?
Why is
Movie.Director
null here? Do I have to get the data again when returningPage()
? I was thinking it would fireOnGet()
again but it doesn't.
不,OnGet
方法不会在您的 OnPost
方法实际执行时自动调用。这两个处理程序彼此独立,它们唯一共享的是底层 Razor 视图和页面模型。如果您的视图需要将数据加载到模型中,那么您也需要为 OnPost
执行此操作。
您 可以 从 POST 方法中调用 GET 方法,但是根据您在 OnGet
中实际执行的操作,这可能会覆盖数据已由 OnPost
明确设置。我建议的是添加一个额外的方法,该方法将由 OnGet
和 OnPost
调用,以设置您的视图需要呈现的 shared 模型属性.
public IActionResult OnGet()
{
Movie = LoadMovie();
return Page();
}
public IActionResult OnPost()
{
if (!ModelState.IsValid)
{
Movie = LoadMovie();
return Page();
}
// …
return RedirectToPage("/Index");
}
private Movie LoadMovie()
{
// …
}
请注意,如果您确实需要呈现页面视图,您也只需要执行此方法。
混淆可能源于 OnGet
和 OnPost
方法的用途:对于 Razor 页面,这些方法是 入口点 。当请求与 Razor 页面匹配的路由时,ASP.NET 核心框架会调用它们。如果是 GET 请求,则调用 OnGet
方法;如果是 POST 请求,则为 OnPost
方法。除了共享相同的视图(cshtml)和模型之外,这些方法之间没有直接关系。
因为这些方法是入口点,所以 POST 请求不会执行 OnGet
方法,GET 请求不会执行 OnPost
方法——当然,除非你让那些在这些方法中调用自己的人。
现在,当您 return Page()
时,唯一发生的事情就是告诉 ASP.NET 核心框架然后使用您准备的数据呈现 Razor 视图页面模型。所以它只是渲染 cshtml
传递页面模型作为视图的模型。但是,此时这不会导致对 OnGet
或 OnPost
的任何调用,因为那些已经 运行 进入 进入 Razor 页面执行。
这意味着如果您想始终在呈现视图之前执行某些逻辑,那么您将需要在 returning Page()
之前从页面处理程序中显式执行该逻辑。 =33=]