Fermer

juin 10, 2023

Faits saillants de Blazor des premières versions d’aperçu de .NET 8

Faits saillants de Blazor des premières versions d’aperçu de .NET 8


De grands changements arrivent pour Blazor dans .NET 8, et nous commençons déjà à voir certains de ces changements émerger dans les premières versions de prévisualisation. Voici comment Blazor se présente avant sa sortie en novembre.

Rendu côté serveur avec Blazor

L’un des principaux objectifs de .NET 8 est de permettre de créer une application Web à l’aide du modèle de composants productifs et testé au combat de Blazor, mais de rendre ces composants sur le serveur.

Cela ouvre la porte à l’utilisation de Blazor là où vous utiliseriez autrement MVC ou Razor Pages, pour s’exécuter sur votre serveur et renvoyer HTML au navigateur. Avec ce flux, il n’y a pas de connexions de socket ouvertes et il n’est pas nécessaire d’envoyer des DLL au navigateur.

Pour de nombreuses applications, il s’agit d’une option intéressante et, à partir de .NET 8 Preview 3, une première version de ce rendu côté serveur est en place.

Voici comment cela fonctionne actuellement (notez que les détails de mise en œuvre présentés ici changeront probablement dans les mois à venir).

J’ai commencé avec un projet d’application Web ASP.NET standard et un composant de mise en page (MainLayout.razor).

@inherits LayoutComponentBase
@implements IRazorComponentApplication<MainLayout>

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8"/>
    <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
    <base href="/"/>
    <link href="css/bootstrap/bootstrap.min.css" rel="stylesheet"/>
    <link href="css/app.css" rel="stylesheet"/>
    <link href="Net8Demos.styles.css" rel="stylesheet"/>
    <HeadOutlet></HeadOutlet>
</head>
<body>
<PageTitle>.NET 8 Demos</PageTitle>

<div class="page">
    <main>
        <article class="content px-4">
            @Body
        </article>
    </main>
</div>

</body>
</html>

Notez l’appel à mettre en œuvre IRazorComponentApplication<MainLayout>. Cette ligne est actuellement nécessaire pour qu’ASP.NET puisse acheminer les demandes vers vos composants, mais cette exigence est susceptible de disparaître dans une future version.

J’ai ensuite créé un composant de test simple :

Index.razor

@layout MainLayout
@page "https://www.telerik.com/"

<h2>
    Hello Blazor (Server Side Rendering)
</h2>

Ce que nous visons, ce sont toutes les requêtes vers la page d’accueil / à acheminer vers ce composant.

Pour que cela fonctionne, nous devons nous assurer que nous ajoutons quelques lignes à Programme.cs.

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorComponents();

var app = builder.Build();

...

app.MapRazorComponents<MainLayout>();

app.Run();

Les principaux appels ici sont de AddRazorComponents et MapRazorComponents.

Avec cela, exécutons l’application et visualisons-la dans le navigateur.

dotnet run

Une page simple dans le navigateur, affichant un message Hello World

Eh bien, nous n’allons pas gagner de prix de design pour celui-ci, mais ça marche !

Remarquez qu’il y a une seule requête (à localhost) et que la réponse est du HTML standard. Blazor a rendu le Index.razor composant (qui utilise le Mise en page principale page de mise en page) sur le serveur et renvoyait le code HTML standard au navigateur.

Voici un autre composant, cette fois pour rendre un fil d’actualités « style Github ».

NewsFeed.razor

@page "/News"

<section class="container">
    <p>For you (beta)</p>

    <h4>Trending Repositories</h4>

    <section>
        <Card User="jonhilton"
              Repository="practicalBlazorComponents"
              Description="A new online, interactive workshop!"
              Languages="@(new List<string> { "C#", "JavaScript" })"/>

        <Card User="AdrienTorris"
              Repository="awesome-blazor"
              Description="Resources for Blazor, a .NET web framework using
                           C#/Razor and HTML that runs in the browser with WebAssembly."
              Languages="@(new List<string> { "C#" })"/>
    </section>
</section>

Cela rend les instances d’un autre composant, Card (qui affiche les détails de chaque « référentiel »).

Exécutez ceci dans le navigateur et nous voyons les mêmes résultats, HTML pur renvoyé dans la réponse.

Une liste des référentiels de tendances, avec des titres et des détails pour chacun

Messages de formulaire

Si le rendu côté serveur s’attaque à l’affichage des données dans le navigateur, qu’en est-il de la capture des entrées de l’utilisateur ?

Bien avant les applications monopage (SPA) et l’émergence de JavaScript en tant que technologie de référence pour la création d’applications Web, les interactions sur les sites Web étaient généralement gérées par des formulaires. Dans Preview 4, nous trouvons une prise en charge précoce de l’utilisation de formulaires avec le rendu côté serveur Blazor.

Pour que cela fonctionne, vous devez utiliser quelque chose appelé CascadingModelBinder pour vos composants. Dans notre exemple ci-dessus, nous pouvons ajouter ceci à MainLayout.razor.

...

<div class="page">
    <main>
        <article class="content px-4">
            <CascadingModelBinder>
                @Body
            </CascadingModelBinder>
        </article>
    </main>
</div>

...

Ensuite, nous pouvons utiliser la norme de Blazor EditForm composant pour définir un formulaire.

Voici un formulaire pour recueillir les suggestions des utilisateurs pour notre fil d’actualité Github.

SuggestRepository.razor

@page "/SuggestRepository"

<EditForm OnValidSubmit="HandleSubmit" Model="model" method="POST">
    <section class="form-group">
        <label for="name">Your name:</label>
        <InputText @bind-Value="model.YourName" class="form-control" id="name"/>
    </section>

    <section class="form-group">
        <label for="repoUrl">Repository URL:</label>
        <InputText @bind-Value="model.RepositoryUrl" class="form-control" id="repoUrl"/>
    </section>

    <section class="form-group">
        <label for="notes">Your notes:</label>
        <InputTextArea @bind-Value="model.YourNotes" class="form-control" id="notes"/>
    </section>

    <section class="py-2">
        <button type="submit" class="btn btn-primary">Submit your suggestion</button>
    </section>
</EditForm>
@code {

    SuggestionModel model = new();

    private void HandleSubmit()
    {
        Console.WriteLine("OK, we're handling the submit!");
    }

    record SuggestionModel
    {
        public string YourName { get; set; }
        public string RepositoryUrl { get; set; }
        public string YourNotes { get; set; }
    }

}

Ceci est une norme EditForm avec un peu de Bootstrap CSS ajouté, pour le rendre raisonnable dans le navigateur.

Remarquez le formulaire method est réglé sur POST (GET les requêtes ne sont pas prises en charge avec Blazor SSR).

Affichez ceci dans le navigateur et nous verrons un formulaire HTML standard. Soumettez le formulaire, et nous voyons une demande POST à /SuggestRepositoryy compris les valeurs de formulaire saisies.

Un formulaire avec des entrées pour le nom, l'URL du référentiel et les notes, avec un bouton d'envoi en bas

Dans le SuggestRepository Composant Blazor, nous pouvons gérer ces données entrantes dans le HandleSubmit méthode et faire ce que nous voulons avec (poster dans une base de données, API, etc.)

La preuve que cela fonctionne réside dans les journaux du serveur pour l’application ASP.NET en cours d’exécution :

Un instantané d'une fenêtre de terminal affichant le message

(J’ai peut-être appuyé plusieurs fois sur ce bouton d’envoi !)

Au moment de la rédaction, la liaison et la validation du modèle ne sont pas encore en place (ça vient). La solution de contournement pour l’instant est de descendre à la FormDataProvider service et gérer manuellement les données de formulaire entrantes.

@page "/SuggestRepository"
@inject FormDataProvider FormData

<EditForm ...>
	...
</EditForm>
@code {
    
    SuggestionModel model = new();

    protected override void OnInitialized()
    {
        
        if (FormData.Entries.TryGetValue("YourName", out var yourNameValues))
        {
            model.YourName = yourNameValues.First();
        }
    }
    
    private void HandleSubmit()
    {
        Console.WriteLine("OK, we're handling the submit from " + model.YourName);
    }  
    
    ...
    
}

Maintenant, lorsque nous soumettons le formulaire, notre instance de SuggestionModel est mis à jour avec les valeurs affichées, et nous pouvons y accéder dans notre HandleSubmit gestionnaire.

Un formulaire avec l'entrée Nom pré-remplie avec le nom Jon

Rendu en continu avec des composants Blazor

L’autre grande mise à jour pour les versions de prévisualisation est le rendu en continu.

Cela gère le scénario dans lequel vous avez un composant Blazor qui récupère des données et vous souhaitez afficher un message pendant que la récupération des données a lieu.

Avec le rendu côté serveur, vous n’auriez généralement qu’une seule chance d’envoyer une réponse au navigateur (lorsque tout a été chargé, les données ont été récupérées et le HTML rendu).

Le rendu en streaming permet d’effectuer un premier retour avec le HTML pour la structure essentielle de la page, puis de renseigner le reste des détails au fur et à mesure de leur disponibilité (lorsque la récupération des données est terminée).

Pour que cela fonctionne, nous devons ajouter un script supplémentaire à notre application.

Ajoutons-le au MainLayout.razor mise en page que nous utilisons.

<body> 
	...
    
	<script src="_framework/blazor.web.js" suppress-error="BL9992"></script>
</body>

Nous pouvons maintenant ajouter un attribut à notre composant pour activer le rendu en continu.

NewsFeed.razor

@attribute [StreamRendering(true)]
@page "/News"

...

Maintenant, pour les besoins de notre démo, simulons un appel réseau et ajoutons une interface utilisateur pour gérer la situation où nous attendons que cet appel se termine.

@attribute [StreamRendering(true)]
@page "/News"

@if (loading)
{
    <p>Fetching news feed!</p>
}
else
{
	...
}
@code {

    bool loading;

    protected override async Task OnInitializedAsync()
    {
        loading = true;
        await Task.Delay(1000);
        loading = false;
    }

}

Ainsi, lorsque quelqu’un visitera cette page, le composant s’affichera sans attendre la fin des tâches asynchrones et affichera l’interface utilisateur de chargement que nous avons définie.

Ensuite, une fois l’appel asynchrone terminé, il diffusera le code HTML mis à jour dans la réponse, et Blazor le corrigera dans le DOM.

animation montrant un écran de chargement initial, suivi d'un simple fil d'actualité

Router vers des éléments nommés

Passons aux petits changements !

Vous pouvez désormais acheminer directement vers un élément HTML spécifique sur une page à l’aide de fragments d’URL standard.

Supposons que vous ayez une page de produit et un élément avec le id mis à BuyNow.

@page "/product"

...

<div id="BuyNow">
    <h3>Buy Now</h3>
    <p>It's really good!</p>
</div>

Si quelqu’un accède à <your-site-url/product#BuyNowils seront acheminés vers cette page et Blazor défilera correctement jusqu’à BuyNow div.

Prise en charge des rubriques

Comme nous l’avons vu, vous pouvez utiliser des mises en page pour vos composants Blazor, mais jusqu’à présent, vous ne pouviez injecter du contenu que dans une partie de votre mise en page.

<main>
    <article>
    	@Body
    </article>
</main>

Lorsqu’un composant utilise cette disposition, @body sera remplacé par le contenu de ce composant.

Mais que se passe-t-il si vous souhaitez afficher du contenu dans différentes parties de la mise en page ?

Par exemple, vous souhaiterez peut-être afficher le contenu dans une barre latérale pour votre page, ainsi que dans la section principale.

<main>
	<aside>
        
    </aside>
    <article>
    	@body
    </article>
</main>

Avec .NET 8, vous pouvez définir un SectionOutlet où vous souhaitez afficher du contenu supplémentaire :

@using Microsoft.AspNetCore.Components.Sections

<main>
	<aside>
        <SectionOutlet SectionName="Sidebar" />
    </aside>
    <article>
    	@body
    </article>
</main>

Avec cela, tout composant utilisant cette mise en page peut fournir du contenu pour cela sidebar section.

Par exemple, voici un composant pour afficher un article, qui récupère également une liste d’articles connexes. Il peut rendre ces liens d’articles connexes dans la barre latérale à l’aide du nouveau .NET 8 SectionContent composant.

Article.razor

<SectionContent SectionName="Sidebar">
    @foreach(var article in related){
        <a href="@article.Link">@article.Title</a>
    }
</SectionContent>

@articleContent
...
@code {
    
    List<ContentLink> related;
    string articleContent;
    
    ...
    
}

Emballage Webcil pour les applications Blazor WASM

Enfin, Blazor WASM échouera parfois à se charger dans certains environnements en raison de politiques de réseau/de sécurité qui bloquent le téléchargement ou l’utilisation de fichiers .dll.

La nouveauté des versions préliminaires de .NET 8 est une option permettant d’activer l’utilisation de Webcil à la place. Webcil est un package convivial pour le Web d’assemblys .NET qui, en supprimant le contenu spécifique à l’exécution native de Windows, devrait éviter ces problèmes.

Vous pouvez activer Webcil via le fichier de projet de votre application Blazor WASM :

<PropertyGroup>
    <WasmEnableWebcil>true</WasmEnableWebcil>
</PropertyGroup>

En résumé

Les premières versions préliminaires de .NET 8 montrent des indices prometteurs de ce qui va arriver pour Blazor plus tard cette année.

Alors que le rendu côté serveur et le rendu en continu attirent l’attention et prouveront probablement l’intérêt de .NET 8, il vaut la peine de garder un œil sur les autres changements plus petits, qui semblent prêts à combler certaines des lacunes restantes dans le modèle de composants riches de Blazor en novembre. .


Ensuite :
De grands changements à venir pour Blazor dans .NET 8.




Source link