In a Razor Page, `@functions` puts C# supporting code in the same `.cshtml` file as the markup. It can contain the page model class selected by `@model`. Keep `@page` first so the file is handled as a Razor Page rather than mistaken for a controller view. section 23.2.2
Listing 23.4 The contents of the Index.cshtml file in the Pages folder
@page
@model IndexModel
@using Microsoft.AspNetCore.Mvc.RazorPages
@using WebApp.Models;
<!DOCTYPE html>
<html>
<head>
<link href="/lib/bootstrap/css/bootstrap.min.css" rel="stylesheet" />
</head>
<body>
<div class="bg-primary text-white text-center m-2 p-2">
@Model.Product?.Name
</div>
</body>
</html>
@functions {
public class IndexModel : PageModel {
private DataContext context;
public Product? Product { get; set; }
public IndexModel(DataContext ctx) {
context = ctx;
}
public async Task OnGetAsync(long id = 1) {
Product = await context.Products.FindAsync(id);
}
}
}
The complete `Pages/Index.cshtml` example declares `IndexModel : PageModel` inside `@functions`. Its constructor receives a `DataContext`; `OnGetAsync` loads a product, and the markup renders its name through `@Model`. section 23.2.2
An inline page model is convenient while the page is small. If code and markup become difficult to manage together, move the class to a separate `Index.cshtml.cs` file and remove the `@functions` block. The page can then name the class with `@model WebApp.Pages.IndexModel`; a `_ViewImports.cshtml` namespace declaration can shorten that to `@model IndexModel`. section 23.4.1
Check the page
With `Index.cshtml` in the `Pages` folder, restart ASP.NET Core and request `http://localhost:5000/index`. The same URL checks the page again after moving its model into `Index.cshtml.cs`. section 23.2.2 section 23.4.1
