Site icon Blog ARC Optimizer

Mises à jour Build 2022 pour les développeurs ASP.NET Core


Dans cet article, récapitulons trois discussions de Build 2022 qui présentent certaines fonctionnalités intéressantes fournies avec ASP.NET Core 7.

La construction 2022 a eu lieu la semaine dernière, donnant aux développeurs Microsoft de quoi s’enthousiasmer, qu’il s’agisse des nouvelles cloches et sifflets d’Azure, du développement Windows, des mises à jour de productivité des développeurs ou de tonnes d’autres contenus que vous pouvez afficher à partir du liste des sessions.

Dans cet article, j’aimerais récapituler trois présentations qui ont mis en lumière les nouveautés du monde .NET, en particulier pour les applications Web ASP.NET Core.

  • Mises à jour C# 11
  • Mise en cache de sortie dans ASP.NET Core 7
  • Mises à jour minimales de l’API

Noter: Ce message comprend des exemples de code. Les exemples sont sujets à des modifications de syntaxe mineures avant les versions de .NET 7 en novembre 2022.

Mises à jour C# 11

Avec le pivotement de .NET vers les versions annuelles de novembre ces dernières années, les langages emboîtent également le pas. Avec le développement de C# 11 en plein essor, Build est toujours un bon moment pour avoir un aperçu de ce qui s’en vient. Dans cet esprit, Mads Torgersen a dirigé la session, Quelle est la prochaine étape en C# 11pour nous donner un aperçu de quelques nouveautés.

En voici quelques-uns :

  • Membres abstraits statiques
  • Les mises à jour de correspondance de modèle prennent en charge les modèles de liste
  • Propriétés requises
  • Littéraux de chaîne bruts

Membres abstraits statiques

C# 11 inclura la possibilité d’ajouter des membres abstraits statiques dans les interfaces, où vous pouvez inclure des propriétés statiques, des opérateurs surchargeables ou d’autres membres statiques. Un grand cas d’utilisation est l’utilisation d’opérateurs mathématiques, et Mads a montré un exemple.

Imaginez que vous avez un programme rapide qui additionne tous les éléments d’un tableau donné et renvoie le total (par souci de brièveté, cela utilise déclarations de niveau supérieurce qui élimine le besoin d’un Main méthode):

var result = AddAll(new[] { 1, 2, 3, 4, 5 });
Console.WriteLine(result);

int AddAll(int[] values)
{
    int result = 0;

    foreach (var value in values)
    {
        result += value;
    }
    return result;
}

Et si nous pouvions faire en sorte que les types numériques implémentent des interfaces ? C’est ce que nous pouvons faire avec les membres abstraits statiques avec cette modification AddAll méthode:

T AddAll<T>(T[] values) where T : INumber<T>
{
    T result = T.AdditiveIdentity;

    foreach (var value in values)
    {
        result += value;
    }
    return result;
}

Maintenant, nous prenons Tqui est tout type qui implémente le INumber<TSelf> interfaces (int, short, long, float, decimal ou tout type qui représente un nombre). L’interface donne accès à des API comme Abs, Min, Max, TryParse et les opérateurs mathématiques typiques, qui à leur tour permettent aux développeurs d’écrire du code qui s’appuie sur les interfaces avec ces membres abstraits comme une contrainte.

Si vous vouliez changer le result tableau à un mélange de int et decimal types, il calculerait correctement sans avoir à déclarer explicitement le type spécifique, grâce à la beauté des interfaces. Pour plus de détails sur les interfaces abstraites statiques, consultez la documentation Microsoft.

Modèles de liste de prise en charge des mises à jour de correspondance de modèles

En utilisant le même exemple fourni par Mads, C# 11 fournit des mises à jour de la correspondance de modèles qui facilitent le traitement des éléments de liste entrants. Cela peut grandement simplifier les choses, comme dans l’exemple suivant :

T AddAll<T>(T[] values) where T : INumber<T> => values switch
{
    [] => T.AdditiveIdentity,
    [var t1, .. var middle] => t1 + AddAll(middle),
};

Propriétés requises

Mads a également démontré quelque chose que nous attendions tous avec impatience : les propriétés requises. Pour illustrer les avantages, construisons un fidèle Person classer:

public class Person 
{
    public string FirstName { get; set; }
    public string MiddleName { get; set; }
    public string LastName { get; set; }
}

Pour appliquer l’instanciation de certains champs, vous devez vous appuyer sur une approche basée sur les constructeurs. Si vous souhaitez obliger un appelant à instancier un FirstName et LastName, il n’y a pas moyen de le faire avec l’initialisation de l’objet. Par exemple, que se passe-t-il si un développeur écrit du code avant son café du matin et fait accidentellement le LastName la MiddleName?

var person = new Person()
{
    FirstName = "Saul",
    MiddleName = "Goodman"
};

Avec les propriétés requises, nous pouvons appliquer cela en utilisant l’initialisation de l’objet, comme ceci :

public class Person 
{
    public required string FirstName { get; set; }
    public string MiddleName { get; set; }
    public required string LastName { get; set; }
}

Dans ce cas, le compilateur renverra une erreur lorsque LastName n’est pas initialisé.

Je suis extrêmement excité par cette fonctionnalité – elle était initialement prévue pour C # 10 et est enfin là. Il aurait vraiment dû être livré avec les fonctionnalités de nullabilité dans les dernières versions, car les développeurs ont utilisé des solutions de contournement hacky comme
= null! pour accommoder ces situations. Avec cette mise à jour, qui a besoin de constructeurs ? Pas moi.

Littéraux de chaîne bruts

Mads a également montré littéraux de chaîne bruts. Nous avons tous fait face à la douleur d’échapper à des caractères embêtants à l’intérieur de nos chaînes, comme les guillemets, les guillemets doubles, les espaces blancs et les barres obliques inverses. Avec C # 11, il est beaucoup plus facile de créer des chaînes multilignes ou des caractères qui vous obligeaient auparavant à les échapper.

Selon la documentation, les littéraux de chaîne bruts :

  • Commencez et terminez par une séquence d’au moins trois guillemets doubles («  » »). Vous pouvez également inclure plus de trois caractères consécutifs pour prendre en charge les chaînes contenant au moins trois guillemets répétés.
  • Les littéraux de chaîne brute sur une seule ligne nécessitent les guillemets ouvrants et fermants sur la même ligne et les littéraux de chaîne brute multilignes nécessitent à la fois des guillemets ouvrants et fermants sur leur propre ligne.
  • Dans les littéraux de chaîne bruts multilignes, tout espace blanc à gauche des guillemets fermants est supprimé.

Voici un exemple simple. Notez que l’interpolation de chaîne est également prise en charge :

var author = "Andy Dwyer";  
string longMessage = $"""  
"Leslie, I typed your symptoms  
into this thing here and  
it says you have 'internet  
'connectivity problems.'"  
  
— {author}  
""";  
  
Console.WriteLine(longMessage);  

La valeur est immédiate lorsque vous travaillez avec des structures de type JSON ou XML, comme ceci :

string html = """
           <body style="normal">
              <div class="book-content">
               This is information about the "C# 11" book.
           </body>
           <footer>
               This is information about the author of the "C# 11" book.
           </footer>
       </element>
       """;

Intergiciel de mise en cache de sortie dans ASP.NET Core 7

Dans sa séance, Mise en cache de sortie dans ASP.NET Core 7Sebastian Ros a parlé d’un nouveau middleware pour la mise en cache des points de terminaison.

Si vous n’êtes pas familier, ASP.NET Core a déjà intergiciel de mise en cache des réponses qui permet aux développeurs d’activer la mise en cache des réponses de serveur en fonction des en-têtes de cache HTTP. Cela a une valeur limitée pour les applications d’interface utilisateur telles que Blazor et Razor Pages, car les navigateurs définissent souvent des en-têtes de requête pour empêcher la mise en cache. De plus, le middleware de mise en cache des réponses a des options de personnalisation limitées.

Le nouveau middleware de mise en cache de sortie permettra aux développeurs ASP.NET Core de :

  • Stockez les résultats dans une application Web au lieu de l’exécuter à plusieurs reprises, offrant des avantages en termes de performances
  • Configurez la mise en cache sans avoir à vous soucier des en-têtes HTTP
  • Options de stockage (comme l’enregistrement sur disque ou Azure Storage)
  • Utiliser des balises pour invalider les entrées du cache
  • Avoir le verrouillage des ressources activé par défaut

Vous pourrez l’utiliser via une variété d’applications Web ASP.NET Core, mais voyons comment cela fonctionne à l’aide d’une API minimale. Pour commencer, mettons en cache le point de terminaison racine. Pour modifier légèrement l’exemple de Sebastian, disons que nous avons un magasin d’entretien des pelouses appelé Mandy’s Mowers, où nous récupérons les détails des tondeuses à gazon à vendre.

using Microsoft.AspNetCore.OutputCaching;
using Microsoft.AspNetCore.OutputCaching.Policies;

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddOutputCaching();

var app = builder.Build();

app.UseOutputCaching();
app.MapGet("https://www.telerik.com/", MowerInventory.GetMowers).OutputCache();
await app.RunAsync();

Si je veux désactiver la mise en cache pour un point de terminaison, je ferais ceci :

app.MapGet("/nocache", MowerInventory.GetMowers).OutputCache(cache => cache.NoStore());

Si je souhaite activer la mise en cache pour tous les points de terminaison, je peux ajouter une stratégie à la configuration.

builder.Services.AddOutputCaching(options =>
{
  options.Policies.Add(new OutputCachingPolicy());
});

Vous pouvez également attribuer des stratégies à des terminaux spécifiques. Supposons que je souhaite mettre en cache les pages de résultats détaillés des produits pendant seulement 15 secondes :

builder.Services.AddOutputCaching(options =>
{
  options.Policies.Add(new OutputCachingPolicy());
  options.Profiles["QuickCache"] = new OutputCachePolicyBuilder().Expires(TimeSpan.FromSeconds(15)).Build();
});



app.MapGet("/results", MowerInventory.GetMowers).OutputCache(cache => cache.Profile("QuickCache"));

Si vous souhaitez mettre en cache par valeur de chaîne de requête, vous pouvez également le faire. Considérez ce point de terminaison où un utilisateur filtre par type et couleur.

https://mandysmowers.com/results?type=push&color=red

Si je voulais uniquement spécifier une politique de mise en cache par couleur, je peux utiliser le VaryByQuery API :

app.MapGet("/results", MowerInventory.GetMowers).OutputCache(p => p.VaryByQuery("color"));

Bien sûr, vous pouvez également travailler avec des points de terminaison imbriqués. Un scénario courant serait des pages pour obtenir toutes les tondeuses et en afficher une spécifique.

Nous allons d’abord mettre en place une politique :

builder.Services.AddOutputCaching(options =>
{
    options.Policies.Add(new OutputCachingPolicy());
    options.Policies.Add(new OutputCachePolicyBuilder().Path("/mowers").Tag("mowers").Build());
});

Ensuite, appliquez une balise aux points de terminaison :

app.MapGet("/mowers", MowerInventory.GetMowers).OutputCache(cache => cache.Tag("mowers"));
app.MapGet("/mowers/{id}", MowerInventory.GetMowers).OutputCache(cache => cache.Tag("mowers"));

Ensuite, vous pouvez effectuer des actions sur une balise en une seule action, comme effectuer une éviction du cache. Comme indiqué dans l’exposé, vous pourriez construire un /purge point final pour faire ceci:

app.MapPost("/purge/{tag}", async (IOutputCacheStore cache, string tag))
{
    await cache.EvictByTagAsync(tag);
};

Il y a beaucoup plus à venir avec cette fonctionnalité passionnante, et vous pouvez suivez-le sur GitHub.

Mises à jour minimales de l’API

Dans le discours de Stephen Halter et Safia Abdalla, API minimales : passé, présent et futurils ont discuté de l’évolution des API minimales et de ce qui attend .NET 7.

Si vous n’êtes pas familiarisé avec les API minimales, vous les utilisez pour créer des API HTTP avec un minimum de dépendances et de frais généraux sans l’encombrement qui accompagne souvent ASP.NET Core MVC. (Bien sûr, MVC ne va nulle part et c’est à vous de déterminer ce qui correspond le mieux à votre cas d’utilisation.)

J’ai d’abord écrit sur API minimales à leurs débuts et aussi écrit sur leurs capacités avec .NET 6. Comme indiqué dans la conférence, .NET 6 a été le moment où les API minimales sont vraiment arrivées, tirant parti des instructions de niveau supérieur, des lambdas et des groupes de méthodes, des attributs sur les lambdas, de nouveaux Map méthodes, et plus encore. Dans l’attente de .NET 7, voici quelques-uns de mes favoris.

Filtres de point de terminaison

Avec .NET 7, les API minimales prennent en charge les filtres de point de terminaison, qui vous permettent d’inspecter et de modifier les paramètres d’entrée avant d’exécuter un gestionnaire d’itinéraire. Cela permettra aux développeurs d’intercepter une requête, un peu comme dans un contrôleur MVC, et d’exécuter une logique basée sur les paramètres.

Cela implique une nouvelle IRouteHandlerFilter interface ça prend un RouteHandlerFilterContext que les développeurs peuvent implémenter pour les filtres personnalisés. La RouteHandlerFilterContext contient HttpContext et Parameters propriétés—les Parameters est un IList afin que les développeurs puissent effectuer des mises à jour à la volée.

Groupes de routage

.NET 7 est également livré groupes de routage qui vous permettent de définir un seul préfixe de route pour un groupe de points de terminaison, ce qui permet une variété de IEndpointConventionBuilder méthodes d’extension (comme RequireCors et RequireAuthorization). Vous pouvez dire adieu à l’ajout manuel d’autorisations à des points de terminaison uniques. Il permet également la nidification.

Résultats typés

Avec .NET 7 Aperçu 4, résultats typés devrait rendre le travail et le test des gestionnaires de route plus simples et plus faciles. Pour emprunter à la conversation, voici un exemple rapide.

Dans .NET 6, voici comment renvoyer une réponse spécifique selon qu’un enregistrement d’un type spécifique est trouvé :

app.MapGet("/todo/{id}", async (int id, ToDoDb db) =>
    await db.Todos.FindAsync(id) is Todo todo
        ? Results.Ok(todo)
        : Results.NotFound());

Et voici à quoi cela ressemble avec des résultats typés dans .NET 7 :

app.MapGet("/todo/{id}", async Task<Results<Ok<Todo>, NotFound>> (int id, ToDoDb db) =>
    await db.Todos.FindAsync(id) is Todo todo;

Cela rend les tests beaucoup plus faciles, comme le montre cet exemple :

[Fact]
public async Task GetAllTodos_ReturnsOk()
{
    var db = CreateDbContext();
    var result = await TodosApi.GetAllTodos(db);
    Assert.IsType<Ok<object>>(result);
}

Emballer

Je n’ai fait qu’effleurer la surface de tout le contenu Web .NET de Build 2022. L’équipe .NET a créé une liste de lecture YouTube de Contenu de génération .NETet vous pouvez également découvrez les 389 sessions à la demande. Voici quelques autres discussions que j’ai aimées mais que je n’avais pas la place d’aborder :

Restez à l’écoute, car nous couvrirons bon nombre de ces sujets à l’approche de la sortie de .NET 7 en novembre. Bon codage !




Source link
Quitter la version mobile