Put `@model` at the top of a CSHTML view to declare the type of data the view expects. An action method passes the object to the view; expressions use `Model`—capital M—to access it. `@model` declares the type, while `Model` is the object you render. section 21.3.1 section 21.4.1
Without a declared type, the generated view class uses `RazorPage<dynamic>`. A misspelled member can then fail when a response is generated. With `@model WebApp.Models.Product`, the generated class uses `RazorPage<WebApp.Models.Product>`: editors can suggest members, and an invalid member is reported during editing or building. section 21.3.1
Listing 21.15 Declaring the type in the Watersports.cshtml file in the Views/Home folder
@model WebApp.Models.Product
<!DOCTYPE html>
<html>
<head>
<link href="/lib/bootstrap/css/bootstrap.min.css" rel="stylesheet" />
</head>
<body>
<h6 class="bg-secondary text-white text-center m-2 p-2">
Watersports
</h6>
<div class="m-2">
<table class="table table-sm table-striped table-bordered">
<tbody>
<tr><th>Name</th><td>@Model.Name</td></tr>
<tr>
<th>Price</th>
<td>@Model.Price.ToString("c")</td>
</tr>
<tr><th>Category ID</th><td>@Model.CategoryId</td></tr>
<tr><th>Tax Rate</th><td>@Model.TaxRate</td></tr>
</tbody>
</table>
</div>
</body>
</html>
A typed product view declares `@model WebApp.Models.Product` before rendering properties through `Model`. section 21.3.1
The declared type can be a collection. For a view receiving products, `@model IQueryable<Product>` lets `@foreach` render each product’s name, description, and price. Razor view model data is always nullable, even when its declared type is not, so the loop can use `Model ?? Enumerable.Empty<Product>()`. The view needs to know how to display a product, not how the products were obtained. section 7.3.2
Use a fully qualified type name, or import its namespace in `Views/_ViewImports.cshtml` with `@using WebApp.Models` and write `@model Product`. A partial view is also a CSHTML view and can declare its own model type; a row partial, for example, uses a `Product` to render name and price cells. section 21.3.1 section 22.5.2
Listing 22.26 The contents of the _RowPartial.cshtml file in the Views/Home folder
@model Product <tr> <td>@Model.Name</td> <td>@Model.Price</td> </tr>
The row partial shows `@model Product` alongside the `Model` property expressions that fill its table cells. section 22.5.2
Watch the change of meaning in a Razor Page. There, `@model IndexModel` selects a page model class, not an object supplied by a controller action. A page model can receive a service through its constructor and populate a property in a request handler; the page then renders that property through `Model`. 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 `/index` Razor Page selects `IndexModel`, loads a product in `OnGetAsync`, and displays `@Model.Product?.Name`. section 23.2.2

