I was learning the Microsoft Learn Module - Create a web UI with ASP.NET Core.
Razor Pages is a server-side, page-centric programming model for building rich web UI with ASP.NET Core. Razor Pages makes it easy to get started building dynamic web applications when all you need is to define UI logic using a combination of HTML, CSS, and C#.
Razor pages have the extension .cshtml
. Razor syntax is a combination of HTML and C# where the C# code defines the dynamic rendering logic for the page.
In a webpage that uses the Razor syntax, there can be two kinds of content: client content and server code:
- Client content: Contains what you’re used to in webpages: HTML markup (elements), style information such as CSS, maybe some client script such as JavaScript, and plain text.
- Server code: Razor syntax lets you add server code to your client content. If there is server code in the page, the server runs that code first, before it sends the page to the browser. From the browser’s perspective, client content that’s generated by your server code is no different than any other client content.
Razor Pages
Each Razor page is a pair of files:
- A .cshtml file that contains markup with C# code using Razor syntax.
- A .cshtml.cs PageModel class file that defines:
- Page handlers for requests sent to the page.
- Data used to render the page.
PageModel (.cshtml.cs)
A model object defines data properties and encapsulates logic or operations related to those data properties. A PageModel is essentially the same thing, but is a model that more specifically encapsulates the data properties and logic operations scoped just to its Razor page.
DataAnnotations
Models in ASP.NET Core often make use of data annotations to constrain or customize model properties.
Data annotations are attributes used to specify behavior that you want to enforce on the model properties to which they’re applied.
For example, a range of minimum and maximum acceptable values.
The Pages directory structure and routing requests
Razor Pages uses the directory structure within the Pages directory as the convention for routing requests by default. An index page located in the root of the Pages directory, for example, is the default page for the app’s site.
Razor Syntax
Razor syntax uses the @
symbol to transition from HTML to C#.
- If the @ symbol is followed by a Razor reserved keyword, it transitions into Razor-specific markup;
- otherwise, it transitions to C#. Razor evaluates the C# expressions and renders them in the HTML output.
Reserved Razor keywords:
@page
The @page directive is what makes this a Razor page. It indicates this page can handle HTTP requests. The @page directive must be the first directive on a Razor page.
@model
The @model directive is Razor syntax specifying the type of the model made available to the Razor page.
C# code
The @
character starts single-statement C# blocks. Multi-statement C# blocks can be created when using @{}. For example:
1 | @{ |
Razor Tag Helpers
Here’s the example Pages/Products/Create.cshtml
file:
1 | @page |
Tag Helpers are components for automating HTML generation in ASP.NET Core web applications. By design, they’re reusable, customizable building blocks that save you time. Most built-in Tag Helpers extend standard HTML elements you’re familiar with and provide additional server-side attributes for the element, making them more robust.
The Label Tag Helper
<label asp-for="Product.Name" class="control-label"></label>
The Label Tag Helper extends the standard HTML element. As is common for many Razor Tag Helpers, it uses an asp-for attribute which takes a specified PageModel property. The PageModel property is defined in C#. In this case, the value of the PageModel Name property will be rendered as the content for an HTML
The Input Tag Helper
In Create.cshtml
:<input asp-for="Product.Name" class="form-control" />
Generated output:<input name="Product.Name" class="form-control" id="Product_Name" type="text" value="" data-val-required="The Name field is required." data-val="true">
- It evaluates the Product.Name property defined in the PageModel in C#, adds an id and name based on that property and sets the input type appropriately.
- It provides client-side validation using JQuery based on the model’s data annotation attributes provided through the PageModel.
The Validation Message Tag Helper
The following markup uses the Validation Message Tag Helper. It displays a validation message for a single property on your model.
1 | <span asp-validation-for="Product.Price" class="text-danger"></span> |
Generated output:
1 | <input |
The type, data-val-range-min, data-val-range-max and error response are dynamically set by the model’s data annotations for the model’s Product.Price property.
PageModel
A Razor Page’s PageModel class file defines any page handlers for requests sent to the page, and data used to render the page.
1 | using ContosoPets.Ui.Models; |
Typed HTTPClient service architecture
Typed HTTPClient service architecture is responsible for managing HTTP requests to the web API.
Provided as a typed service you have the advantage of injecting it as a constructor parameter directly into the PageModel classes in this project.
Using this architecture provides the advantage of letting the framework take on the responsibility of creating an instance of the HttpClient class and disposing of it when it’s no longer needed. This is a great feature for a project such as this one which will make use of HttpClient instances for each CRUD operation.