Pagine, routing e layout
Suggerimento
Questo contenuto è un estratto dell'eBook, Blazor per gli sviluppatori di Web Forms ASP.NET per Azure, disponibile in .NET Docs o come PDF scaricabile gratuitamente che può essere letto offline.
Web Forms ASP.NET sono costituite da pagine definite nei file .aspx. L'indirizzo di ogni pagina si basa sul percorso fisico del file nel progetto. Quando un browser effettua una richiesta alla pagina, il rendering del contenuto della pagina viene eseguito in modo dinamico nel server. Gli account di rendering sia per il markup HTML della pagina che per i relativi controlli server.
In Blazor, ogni pagina dell'app è un componente, in genere definito in un file con estensione razor, con una o più route specificate. Il routing avviene principalmente sul lato client senza coinvolgere una richiesta server specifica. Il browser effettua prima una richiesta all'indirizzo radice dell'app. Un componente radice Router
nell'app Blazor gestisce quindi l'intercettazione delle richieste di spostamento e le inoltra al componente corretto.
Blazor supporta anche il deep linking. Il deep linking si verifica quando il browser effettua una richiesta a una route specifica diversa dalla radice dell'app. Le richieste di collegamenti diretti inviati al server vengono instradate all'app Blazor, che instrada quindi il lato client della richiesta al componente corretto.
Una pagina semplice in ASP.NET Web Form può contenere il markup seguente:
Name.aspx
<%@ Page Title="Name" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true" CodeBehind="Name.aspx.cs" Inherits="WebApplication1.Name" %>
<asp:Content ID="BodyContent" ContentPlaceHolderID="MainContent" runat="server">
<div>
What is your name?<br />
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
<asp:Button ID="Button1" runat="server" Text="Submit" OnClick="Button1_Click" />
</div>
<div>
<asp:Literal ID="Literal1" runat="server" />
</div>
</asp:Content>
Name.aspx.cs
public partial class Name : System.Web.UI.Page
{
protected void Button1_Click1(object sender, EventArgs e)
{
Literal1.Text = "Hello " + TextBox1.Text;
}
}
La pagina equivalente in un'app Blazor sarà simile alla seguente:
Name.razor
@page "/Name"
@layout MainLayout
<div>
What is your name?<br />
<input @bind="text" />
<button @onclick="OnClick">Submit</button>
</div>
<div>
@if (name != null)
{
@:Hello @name
}
</div>
@code {
string text;
string name;
void OnClick() {
name = text;
}
}
Creare pagine
Per creare una pagina in Blazor, creare un componente e aggiungere la direttiva Razor @page
per specificare la route per il componente. La direttiva @page
accetta un singolo parametro, ovvero il modello di route da aggiungere a tale componente.
@page "/counter"
Il parametro del modello di route è obbligatorio. A differenza di ASP.NET Web Form, la route a un componente Blazornon viene dedotta dal percorso del file (anche se potrebbe essere una funzionalità aggiunta in futuro).
La sintassi del modello di route è la stessa sintassi di base usata per il routing in ASP.NET Web Form. I parametri di route vengono specificati nel modello usando parentesi graffe. Blazor associa i valori di route ai parametri del componente con lo stesso nome (senza distinzione tra maiuscole e minuscole).
@page "/product/{id}"
<h1>Product @Id</h1>
@code {
[Parameter]
public string Id { get; set; }
}
È anche possibile specificare vincoli sul valore del parametro di route. Ad esempio, per vincolare l'ID prodotto come int
:
@page "/product/{id:int}"
<h1>Product @Id</h1>
@code {
[Parameter]
public int Id { get; set; }
}
Per un elenco completo dei vincoli di route supportati da Blazor, vedere Vincoli di route.
Componente router
Il routing in Blazor viene gestito dal componente Router
. Il componente Router
viene in genere usato nel componente radice dell'app (App.razor).
<Router AppAssembly="@typeof(Program).Assembly">
<Found Context="routeData">
<RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />
</Found>
<NotFound>
<LayoutView Layout="@typeof(MainLayout)">
<p>Sorry, there's nothing at this address.</p>
</LayoutView>
</NotFound>
</Router>
Il componente Router
individua i componenti instradabili nell'oggetto AppAssembly
specificato e facoltativamente nell'oggetto AdditionalAssemblies
specificato. Quando il browser si sposta, Router
intercetta la struttura di spostamento ed esegue il rendering del contenuto del parametro Found
con l’oggetto RouteData
estratto se una route corrisponde all'indirizzo, altrimenti Router
esegue il rendering del suo parametro NotFound
.
Il componente RouteView
gestisce il rendering del componente corrispondente specificato da RouteData
con il relativo layout, se presente. Se il componente corrispondente non ha un layout, viene usato facoltativamente DefaultLayout
.
Il componente LayoutView
esegue il rendering del contenuto figlio all'interno del layout specificato. Più avanti in questo capitolo verranno esaminati in dettaglio i layout.
Navigazione
In Web Forms ASP.NET si attiva la navigazione in una pagina diversa restituendo una risposta di reindirizzamento al browser. Ad esempio:
protected void NavigateButton_Click(object sender, EventArgs e)
{
Response.Redirect("Counter");
}
La restituzione di una risposta di reindirizzamento non è in genere possibile in Blazor. Blazor non usa un modello request-reply. È tuttavia possibile attivare direttamente gli spostamenti del browser, come è possibile usare JavaScript.
Blazor fornisce un servizio NavigationManager
che può essere usato per:
- Ottenere l'indirizzo del browser corrente
- Ottenere l'indirizzo di base
- Attivare spostamenti
- Ricevere una notifica quando cambia l'indirizzo
Per passare a un indirizzo diverso, usare il metodo NavigateTo
:
@page "/"
@inject NavigationManager NavigationManager
<button @onclick="Navigate">Navigate</button>
@code {
void Navigate() {
NavigationManager.NavigateTo("counter");
}
}
Per una descrizione di tutti i membri NavigationManager
, vedere URI e helper dello stato di spostamento.
URL di base
Se l'app Blazor viene distribuita in un percorso di base, è necessario specificare l'URL di base nei metadati della pagina usando il tag <base>
per il routing della proprietà work. Se la pagina host per l'app viene sottoposta a rendering server usando Razor, è possibile usare la sintassi ~/
per specificare l'indirizzo di base dell'app. Se la pagina host è html statico, è necessario specificare l'URL di base in modo esplicito.
<base href="~/" />
Layout della pagina
Il layout di pagina in Web Forms ASP.NET viene gestito dalle pagine master. Le pagine master definiscono un modello con uno o più segnaposto di contenuto che possono quindi essere forniti da singole pagine. Le pagine master sono definite nei file .master e iniziano con la direttiva <%@ Master %>
. Il contenuto dei file .master viene codificato come si farebbe con una pagina .aspx, ma con l'aggiunta di controlli <asp:ContentPlaceHolder>
per contrassegnare dove le pagine possono fornire contenuto.
Site.master
<%@ Master Language="C#" AutoEventWireup="true" CodeBehind="Site.master.cs" Inherits="WebApplication1.SiteMaster" %>
<!DOCTYPE html>
<html lang="en">
<head runat="server">
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title><%: Page.Title %> - My ASP.NET Application</title>
<link href="~/favicon.ico" rel="shortcut icon" type="image/x-icon" />
</head>
<body>
<form runat="server">
<div class="container body-content">
<asp:ContentPlaceHolder ID="MainContent" runat="server">
</asp:ContentPlaceHolder>
<hr />
<footer>
<p>© <%: DateTime.Now.Year %> - My ASP.NET Application</p>
</footer>
</div>
</form>
</body>
</html>
In Blazor, gestire il layout di pagina usando i componenti di layout. I componenti di layout ereditano da LayoutComponentBase
, che definisce una singola proprietà Body
di tipo RenderFragment
, che può essere usata per eseguire il rendering del contenuto della pagina.
MainLayout.razor
@inherits LayoutComponentBase
<h1>Main layout</h1>
<div>
@Body
</div>
Quando viene eseguito il rendering della pagina con un layout, il rendering della pagina viene eseguito all'interno del contenuto del layout specificato nella posizione in cui il layout esegue il rendering della relativa proprietà Body
.
Per applicare un layout a una pagina, usare la direttiva @layout
:
@layout MainLayout
È possibile specificare il layout per tutti i componenti in una cartella e sottocartelle usando un file _Imports.razor. È anche possibile specificare un layout predefinito per tutte le pagine usando il componente Router.
Le pagine master possono definire più segnaposto del contenuto, ma i layout in Blazor hanno solo una singola proprietà Body
. Questa limitazione dei componenti di layout Blazor verrà risolta in una versione futura.
Le pagine master in ASP.NET Web Form possono essere annidate. Ovvero, una pagina master può anche usare una pagina master. Anche i componenti di layout in Blazor possono essere annidati. È possibile applicare un componente di layout a un componente di layout. Il rendering del contenuto del layout interno verrà eseguito all'interno del layout esterno.
ChildLayout.razor
@layout MainLayout
<h2>Child layout</h2>
<div>
@Body
</div>
Index.razor
@page "/"
@layout ChildLayout
<p>I'm in a nested layout!</p>
L'output di cui è stato eseguito il rendering per la pagina sarà quindi:
<h1>Main layout</h1>
<div>
<h2>Child layout</h2>
<div>
<p>I'm in a nested layout!</p>
</div>
</div>
I layout in Blazor non definiscono in genere gli elementi HTML radice per una pagina (<html>
, <body>
, <head>
e così via). Gli elementi HTML radice vengono invece definiti nella pagina host di un'app Blazor, che viene usata per eseguire il rendering del contenuto HTML iniziale per l'app (vedere Bootstrap Blazor). La pagina host può eseguire il rendering di più componenti radice per l'app con markup circostante.
I componenti in Blazor, incluse le pagine, non possono eseguire il rendering dei tag <script>
. Questa restrizione per il rendering esiste perché i tag <script>
vengono caricati una sola volta e non possono essere modificati. Un comportamento imprevisto può verificarsi se si tenta di eseguire il rendering dei tag in modo dinamico usando la sintassi Razor. Tutti i tag <script>
devono invece essere aggiunti alla pagina host dell'app.