.NET Core 3.0 est disponible !

Le 23 septembre Microsoft à livré .NET Core 3.0 en release.

Voici un résumé des nouveautés de cette version très attendue :

Support du développement d’applications Windows Desktop

Une des nouveauté phare de cette version est la prise en charge native des applications desktop.
Il est donc désormais possible de créer des applications Windows Forms et WPF avec .NET Core sous Windows.
Bien sûr pour les applications de bureau de .NET Framework déjà existantes, Microsoft a veillé à faciliter leur migration vers .NET Core.

blog ai3 Winforms-vs-WPF .NET Core 3.0 est disponible !


Prise en charge JSON native haute performance

NET Core 3.0 inclut une nouvelle famille d’API JSON permettant des scénarios de lecture / écriture, un accès aléatoire avec un modèle de document (DOM) et un sérialiseur.
De nombreux utilisateurs sont probablement familiarisés avec l’utilisation de Json.NET.
Les nouvelles API sont conçues pour répondre à de nombreux scénarios identiques, mais avec moins de mémoire et une exécution plus rapide.

Microsoft a voulu créer une nouvelle API JSON qui tire parti de toutes les nouvelles fonctionnalités de performance de .NET Core tout en fournissant des performances de haut niveau.
Cela n’était pas possible avec la base de code existante de Json.NET en maintenant la compatibilité.

Voici la nouvelle API, couche par couche :

Utf8JsonReader
System.Text.Json.Utf8JsonReader est un lecteur hautes performances, à faible allocation, orienté uniquement vers l’avant pour le texte JSON codé en UTF-8, lu à partir d’un ReadOnlySpan.
Utf8JsonReader est un type fondamental, de bas niveau, qui peut être utilisé pour créer des analyseurs syntaxiques et des desérialiseurs personnalisés. La lecture d’une charge JSON à l’aide du nouveau Utf8JsonReader est deux fois plus rapide que celle du lecteur de Json.NET.
Il n’alloue pas tant que vous n’avez pas besoin d’actualiser les jetons JSON en tant que chaînes (UTF16).

Utf8JsonWriter
System.Text.Json.Utf8JsonWriter fournit un moyen hautement performant, non mis en cache, de transmettre uniquement du texte JSON codé en UTF-8 à partir de types .NET courants tels que String, Int32 et DateTime.
Comme le reader, le writer est un type fondamental, de bas niveau, qui peut être utilisé pour créer des sérialiseurs personnalisés.
L’écriture d’un contenu JSON à l’aide du nouvel utilitaire Utf8JsonWriter est 30 à 80% plus rapide que l’utilisation du writer de Json.NET.

JsonDocument
System.Text.Json.JsonDocument permet d’analyser des données JSON et de créer un DOM (Document Object Model) en lecture seule qui peut être interrogé pour prendre en charge l’accès et l’énumération aléatoires.
Il est construit au dessus de Utf8JsonReader.
Les éléments JSON qui composent les données sont accessibles via le type JsonElement exposé par le JsonDocument en tant que propriété appelée RootElement.
JsonElement contient les énumérateurs de tableau et d’objet JSON, ainsi que des API permettant de convertir du texte JSON en types .NET courants.
L’analyse d’un contenu JSON et l’accès à tous ses membres à l’aide de JsonDocument sont deux à trois fois plus rapides que Json.NET, avec très peu d’allocations pour des données de taille raisonnable (<1 Mo).

Sérialiseur JSON
Les couches System.Text.Json.JsonSerializer se trouvent au-dessus des systèmes hautes performances Utf8JsonReader et Utf8JsonWriter.
Il désérialise les objets à partir de JSON et sérialise les objets en JSON.
Les allocations de mémoire sont réduites au minimum et prennent en charge la lecture et l’écriture de JSON avec Stream de manière asynchrone.


Support de C# 8.0

Ajoutez des flux asynchrones, des plages / index, davantage de modèles et des types de référence nullables.
Nullable vous permet de cibler directement les failles de code qui conduisent à des exceptions de type NullReferenceException.
La couche la plus basse des bibliothèques de structure a été annotée afin que vous sachiez quand il faut s’attendre à null.

C # 8.0 introduit des types de référence nullables et des types de référence non nullables qui vous permettent de formuler des instructions importantes sur les propriétés des variables de type de référence :

  • une référence n’est pas censée être nulle :
    lorsque les variables ne sont pas censées être nulles, le compilateur applique des règles garantissant la possibilité de déréférencer ces variables en toute sécurité sans vérifier au préalable qu’elles ne sont pas nulles.
  • une référence peut être nulle :
    lorsque les variables peuvent être nulles, le compilateur applique différentes règles pour vous assurer que vous avez correctement vérifié la présence d’une référence nulle.

Cette nouvelle fonctionnalité offre des avantages importants par rapport au traitement des variables de référence dans les versions antérieures de C#, dans lesquelles l’intention lors du développement n’était pas possible à définir à partir de la déclaration de la variable.
Avec l’ajout de types de référence nullables, vous pouvez déclarer votre intention plus clairement et le compilateur vous aide à le faire correctement et à détecter les bogues dans votre code.

blog ai3 csharp-8-new .NET Core 3.0 est disponible !


Nouveau SqlClient

SqlClient est le fournisseur de données que vous utilisez pour accéder à Microsoft SQL Server et à la base de données Azure SQL, par l’intermédiaire de l’un des plus populaires .NET ORM, tels que EF Core ou Dapper, ou directement à l’aide des API ADO.NET.
Il va maintenant être publié et mis à jour en tant que package Microsoft.Data.SqlClient NuGet, et pris en charge pour les applications .NET Framework et .NET Core.
En utilisant NuGet, il sera plus facile pour l’équipe SQL de fournir des mises à jour aux utilisateurs .NET Framework et .NET Core.


Prise en charge de Linux ARM64

Microsoft a ajouté la prise en charge de Linux ARM64 dans cette version, après l’ajout de la prise en charge d’ARM32 pour Linux et Windows dans les versions 2.1 et 2.2 de .NET Core, respectivement.
Les puces Raspberry Pi et ARM sont désormais prises en charge pour permettre le développement IoT, y compris avec le débogueur Visual Studio distant.
Vous pouvez déployer des applications qui écoutent des capteurs et affichent des messages ou des images sur un écran, le tout à l’aide des nouvelles API GPIO. ASP.NET peut être utilisé pour exposer des données en tant qu’API ou en tant que site pour la configuration d’un périphérique IoT.


Mise à jour de ASP.NET Core et de Blazor

Les principales nouvelles fonctionnalités de cette version d’ASP.NET Core et de Blazor sont les suivantes:

  • création d’applications Web interactives côté client riches en utilisant C # au lieu de JavaScript avec Blazor,
  • création de services backend hautes performances avec gRPC (framework RPC),
  • SignalR prend désormais en charge la reconnexion automatique et la diffusion en continu d’un client à un serveur,
  • génération de code client fortement typé pour les API Web avec des documents OpenAPI,
  • routage des points d’extrémité intégré à travers le framework,
  • HTTP/2 est maintenant activé par défaut dans Kestrel,
  • prise en charge de l’authentification pour les API Web et les applications mono-page (SPA) intégrées à IdentityServer,
  • prise en charge du certificat et de l’authentification Kerberos,
  • intégration avec le nouveau sérialiseur System.Text.Json,
  • nouvelle configuration du host générique incluant des services courants tels que l’injection de dépendance, la configuration et les logs,
  • nouveau modèle de Worker Service pour la création de services de longue durée,
  • nouveau EventCounters créé pour obtenir les requêtes par seconde, le nombre total de requêtes, les requêtes en cours et les requêtes ayant échoué,
  • les erreurs de démarrage sont maintenant consignées dans le journal des événements Windows lorsqu’elles sont hébergées dans IIS,
  • nouveau pipeline de demandes intégré à System.IO.Pipelines,
  • amélioration des performances sur toute la pile.


F# 4.7

F# 4.7 est la nouvelle version de F# qui met l’accent sur les modifications d’infrastructure apportées au compilateur et à la bibliothèque principale, ainsi que quelques assouplissements sur les exigences de syntaxe précédemment onéreuses.

Cette nouvelle version a été entièrement développée sur la base de RFCs (request for comments) avec l’appui de la communauté F#.

blog ai3 Screen-Shot-2019-09-22-at-14.40.08 .NET Core 3.0 est disponible !


.NET Standard 2.1

Cette nouvelle version du standard .NET introduit de nouveaux types que vous pouvez utiliser dans le code pouvant être utilisé avec .NET Core et Xamarin.
.NET Standard 2.1 inclut tous les types depuis .NET Core 2.1.
Au total, il est prévu d’ajouter environ 3k APIs dans .NET Standard 2.1.
Une bonne partie d’entre elles sont des API nouvelles, tandis que d’autres sont des API existantes que Microsoft a ajoutées à la norme afin de faire converger davantage les implémentations .NET.

Voici les principales nouveautés du .NET Standard 2.1 :

  • Span<T> :
    c’est un type de tableau qui permet de représenter la mémoire gérée et non gérée de manière uniforme et qui prend en charge le découpage sans opération de copie,
  • API de base compatibles avec Span :
    de nombreuses API permettant de travailler avec Span ont été ajoutées, telles que Stream.Read(Span<Byte>),
  • Reflection emit :
    pour accroître la productivité, l’écosystème .NET a toujours fait un usage intensif de fonctionnalités dynamiques telles que la réflexion et l’émission de réflexion.
    Emit est souvent utilisé comme un outil d’optimisation des performances ainsi que comme moyen de générer des types à la volée pour des interfaces de proxy,
  • SIMD :
    .NET Framework et .NET Core supportaient SIMD depuis un moment.
    Microsoft les a utilisés pour accélérer les opérations de base dans la BCL, telles que les comparaisons de chaînes,
  • ValueTask and ValueTask<T> :
    dans .NET Core 2.1, la principale caractéristique consistait à améliorer les fondamentaux du framework afin de prendre en charge des scénarios hautes performances, ce qui incluait également une optimisation de l’efficacité async / wait.
    La ValueTask existe déjà et permet de renvoyer les résultats si l’opération est terminée de manière synchrone sans avoir à affecter une nouvelle tâche.
    Microsoft a amélioré cette fonctionnalité.
    Il était utile d’avoir une ValueTask non générique correspondante qui permet de réduire les allocations, même dans les cas où l’opération doit être terminée de manière asynchrone, une fonctionnalité utilisée actuellement par Socket et NetworkStream.
    Exposer ces API dans .NET Standard 2.1 permet aux auteurs de bibliothèques de bénéficier de ces améliorations, à la fois en tant que consommateur et producteur,
  • DbProviderFactories:
    dans .NET Standard 2.0, presque toutes les primitives dans ADO.NET pour permettre aux mappeurs O/R et aux implémenteurs de base de données de communiquer.
    DbProviderFactories permet aux bibliothèques et aux applications d’utiliser un fournisseur ADO.NET spécifique sans connaître ses types spécifiques au moment de la compilation, en effectuant une sélection parmi les instances enregistrées de DbProviderFactory en fonction d’un nom qui peut être lu, par exemple, dans les paramètres de configuration,
  • Divers :
    Microsoft a ajouté de nombreuses petites fonctionnalités dans les bibliothèques de classes de base telles que System.HashCode pour combiner des codes de hachage ou de nouvelles surcharges sur System.String.
    Il y a environ 800 nouveaux membres dans .NET Core et la plupart d’entre eux ont été ajoutés dans .NET Standard 2.1.
blog ai3 net_standard-1024x552 .NET Core 3.0 est disponible !


Compilation hiérarchisée

La compilation hiérarchisée (tiered compilation) a été ajoutée en tant que fonctionnalité opt-in dans .NET Core 2.1, elle était désactivée par défaut.
C’est une fonctionnalité qui permet au moteur d’exécution d’utiliser de manière plus adaptative le compilateur Just-In-Time (JIT) afin d’améliorer les performances, à la fois pour le démarrage et pour l’optimisation du débit.
Désormais elle est activé par défaut dans .NET Core 3.0.
Microsoft a apporté de nombreuses améliorations à cette fonctionnalité au cours cette année en la testant avec diverses charges de travail, notamment des sites Web, des applications de bureau PowerShell Core et Windows.
Les performances sont désormais bien meilleures, ce qui a permis à Microsoft de l’activer par défaut.

blog ai3 asp_net_startup-1024x489 .NET Core 3.0 est disponible !
blog ai3 asp_net_steady_state-1024x491 .NET Core 3.0 est disponible !
blog ai3 console_app_performance-1024x488 .NET Core 3.0 est disponible !


Support de TLS 1.3 et OpenSSL 1.1.1 sur Linux

.NET Core peut maintenant tirer parti de la prise en charge de TLS 1.3 dans OpenSSL 1.1.1.

Les principaux avantages de TLS 1.3 sont les suivants :

  • amélioration des temps de connexion grâce à une réduction du nombre d’allers et retours nécessaires entre le client et le serveur,
  • amélioration de la sécurité grâce à la suppression de divers algorithmes de chiffrement obsolètes et non sécurisés et au cryptage de plusieurs transactions.

.NET Core 3.0 peut utiliser ou OpenSSL 1.0.2, OpenSSL 1.1.0 ou OpenSSL 1.1.1.
Lorsque OpenSSL 1.1.1 est disponible, les types SslStream et HttpClient utilisent TLS 1.3 lorsqu’ils utilisent SslProtocols.None (protocoles par défaut du système), en supposant que TLS 1.3 soit pris en charge par le client et le serveur.

.NET Core prend donc désormais en charge TLS 1.3 sous Windows et macOS


Cryptographie

Microsoft a ajouté la prise en charge des chiffrements AES-GCM et AES-CCM, implémentée via System.Security.Cryptography.AesGcm et System.Security.Cryptography.AesCcm.
Ces algorithmes sont des algorithmes AEAD (Authenticated Encryption with Association Data), et ce sont les premiers algorithmes AE (Authenticated Encryption) ajoutés à .NET Core.

.NET Core 3.0 prend désormais en charge l’importation et l’exportation de clés publiques et privées asymétriques à partir de formats standard, sans avoir à utiliser de certificat X.509.


Nouvelle ère Japonaise (Reiwa)

Le 1er mai 2019, le Japon est entré dans une nouvelle ère appelée Reiwa. Les logiciels prenant en charge les calendriers japonais, tels que .NET Core, doivent être mis à jour pour prendre en charge Reiwa.
.NET Core et .NET Framework ont été mis à jour et gèrent correctement le formatage et l’analyse de dates japonaises avec la nouvelle ère.


Stratégie de mise à jour du runtime .NET Core

Le runtime .NET Core, plus précisément le binder du runtime, permet désormais d’activer en opt-in (facultatif) la montée de version majeure.
Le binder du runtime active aussi par défaut la restauration sur les versions correctives et les versions mineures.

Il existe désormais une propriété appelée RollForward, qui accepte les valeurs suivantes:

  • LatestPatch : passe à la version corrective la plus élevée.
    Cela désactive la stratégie mineure
  • Minor : avance vers la version mineure la plus basse, si la version mineure demandée est manquante.
    Si la version mineure demandée est présente, la stratégie LatestPatchest utilisée.
    C’est la politique par défaut,
  • Major : passe à la version majeure la plus élevée et à la version mineure la plus basse si la version majeure demandée est manquante. Si la version majeure demandée est présente, la stratégie mineure est utilisée,
  • LatestMinor : avance vers la version mineure la plus élevée, même si la version mineure demandée est présente,
  • LatestMajor : passage à la version majeure la plus importante et à la version mineure la plus élevée, même si la version majeure demandée est présente,
  • Disable : n’avance par vers une version plus élevée.
    Se lie uniquement à la version spécifiée.
    Cette stratégie n’est pas recommandée pour une utilisation générale, car elle désactive la possibilité de passer à la dernière version.
    Elle n’est recommandée que pour les tests .


Plateformes supportées

.NET Core 3.0 est supporté sur les systèmes d’exploitation suivants :

  • Alpine: 3.9+
  • Debian: 9+
  • openSUSE: 42.3+
  • Fedora: 26+
  • Ubuntu: 16.04+
  • RHEL: 6+
  • SLES: 12+
  • macOS: 10.13+
  • Windows Client: 7, 8.1, 10 (1607+)
  • Windows Server: 2012 R2 SP1+

Note: Windows Forms et les apps WPF ne sont supportés que sur Windows.

Le support des puces est le suivant :

  • x64 sur Windows, macOS, et Linux,
  • x86 sur Windows,
  • ARM32 sur Windows et Linux,
  • ARM64 sur Linux (kernel 4.14+).

Mise en place d’Azure SignalR avec ASP.NET Core

blog ai3 téléchargement-1 Mise en place d'Azure SignalR avec ASP.NET Core

Qu’est-ce que c’est ?

SignalR

Lors de la communication entre un client et un serveur, c’est la plupart du temps le client qui engage cette communication et le serveur qui y répond.

Cependant, il peut arriver que le serveur ait besoin d’engager la conversation. Ce sera par exemple nécessaire pour gérer les notifications, pour gérer la messagerie instantanée ou encore l’actualisation en direct des données que l’on regarde.

Il existe plusieurs moyens de faire ceci (WebSocket, Long Polling…). SignalR est une technologie de Microsoft permettant d’abstraire ça et d’utiliser la meilleure technologie disponible pour le navigateur du client.

Azure SignalR Service

Plutôt que d’avoir un endpoint local, l’idée est d’avoir un service azure auquel n’importe qui (un service, un webjob…) peut envoyer un message à destination d’un client qui y serait connecté.

La mise en place

Côté Azure

Commençons par ajouter une ressource de type « SignalR Service ».

blog ai3 image-15 Mise en place d'Azure SignalR avec ASP.NET Core

On lui donne ensuite un nom, un ResourceGroup, un emplacement géographique, on choisit si on le veut gratuit (mais avec un nombre de connexions et de messages limité) ou payant, et on crée notre service.

Ensuite, dans l’onglet « Keys », on trouvera les clés, host name et ConnectionStrings nécessaires pour se connecter à notre service.

Côté service externe

J’appelle « service externe » tout service ou application, en dehors du front ASP.NET Core principal, qui souhaite pouvoir envoyer des messages aux clients.

C’est là que la version service Azure de SignalR prend tout son intérêt. En effet, le service expose une API Rest que l’on va utiliser.

L’API se trouve sur cette URL :
https://{nom-du-service}.service.signalr.net:5002/api/v1/
Et sa documentation se trouve ici :
https://github.com/Azure/azure-signalr/blob/dev/docs/rest-api.md

Authentification

Avoir l’URL de l’API ne donne rien si l’on n’a pas l’autorisation de l’utiliser. On va donc s’authentifier avec un token JWT.

Vous aurez probablement besoin du package nuget System.IdentityModel.Tokens.Jwt pour que ça fonctionne. Personnellement, j’utilise la version 5.2.4. Pour utiliser l’API, j’utilise j’appelle cette méthode avec les paramètres suivants :

L’accessKey correspond à la clé indiquée dans l’onglet « Keys » de Azure. L’audienceUrl, en revanche, est variable : elle correspond à l’URL appelée.

Envoi d’un message à un utilisateur

Pour cela, il faut 4 choses :

  • Le nom du hub (qu’on définira dans la troisième partie : ASP.NET Core)
  • L’identifiant de l’utilisateur (qui pourra être un GUID, un email, un login…)
  • Un type d’événement (une simple chaîne de caractères – ex : « notification »)
  • Éventuellement un tableau d’objets qui sera ensuite sérialisé en JSON et transmis (ex : [« Nouveau message »])

L’URL complète sera donc :
https://{nom-du-service}.service.signalr.net:5002/api/v1/hubs/{nom-du-hub}/users/{identifiant-utilisateur}.
Ensuite, on peut générer le token (puisque celui-ci dépend de l’URL).

Étape suivante : générer le corps de la requête. Ce sera un objet JSON avec 2 propriétés : target et arguments. target correspond au type du message et arguments correspond aux informations supplémentaires que vous souhaiteriez transmettre.

Une fois que tout est prêt, on fait donc une requête POST vers l’URL déterminée précédemment, avec le body que l’on vient de définir, et avec ces headers :

On lance la requête et le message est transmis (si le destinataire existe et est connecté).

Côté application ASP.NET Core

Les packages NuGet

Il est nécessaire d’ajouter 2 packages NuGet, l’un pour gérer SignalR, l’autre pour la gestion du service Azure :

  • Microsoft.AspNetCore.SignalR (version 1.0.4)
  • Microsoft.Azure.SignalR (version 1.0.3)

Le Hub

Il s’agit du point central par lequel passent tous les messages. Il va falloir créer une classe héritant de la classe abstraite Microsoft.AspNetCore.SignalR.Hub.

Et que doit-on implémenter / surcharger dans notre classe ? Uniquement des comportements spécifiques. Autrement dit, pour un comportement de base, notre hub est vide. Si l’on veut des comportements particuliers lors de la connexion ou déconnexion d’un utilisateur, on peut surcharger les méthodes OnConnectedAsync() et OnDisconnectedAsync(). Il est également possible d’utiliser un attribut [Authorize] sur la classe pour n’accepter que les utilisateurs connectés à l’application.

Envoyer un message depuis l’application ASP.NET Core

Pour ça, il faut d’abord obtenir (via l’injection de dépendances) l’objet IHubContext<TypeDuHub>. On accède ensuite à la propriété Clients, puis on filtre sur les destinataires du message (ou on ne filtre pas du tout grâce à la propriété All), puis on appelle SendAsync en indiquant le nom de l’événement et éventuellement des données.

Définir l’identifiant de l’utilisateur

J’ai parlé plusieurs fois de l’identifiant de l’utilisateur. On est donc en droit de se demander comment celui-ci est choisi. L’idée est simple : implémenter l’interface IUserIdProvider. Voici donc un exemple simple se basant sur les claims de l’utilisateur connecté.

Initialiser SignalR

Il ne nous reste donc plus qu’à initialiser SignalR. On va donc faire ceci dans le fichier Startup.cs.

Côté JavaScript

Package NPM

Il faut commencer par installer les scripts (par exemple via npm) : @aspnet/signalr (j’utilise la version 1.0.4).

Ce package donne accès aux quelques fonctions JavaScript dont vous aurez besoin.

Connexion au hub

Ensuite, on démarre la connexion.

Envoi d’un message depuis JavaScript

Envoyons, depuis le client JavaScript, un message de type « notification » via SignalR à l’utilisateur de notre choix.

Abonnement aux messages SignalR

Dernière ligne droite. On a vu comment configurer SignalR côté client et côté serveur. On a vu comment envoyer un message depuis la solution ASP.NET Core, depuis un service externe et depuis JavaScript. Il ne reste plus qu’à réagir à la réception d’un tel message.

Conclusion

En très peu de ligne de code, on peut ainsi faire réagir notre client JavaScript à un événement asynchrone, provenant du site ou même d’un service externe.

Microsoft nous propose une solution compatible avec tous les navigateurs (même ceux qui ne sont pas compatibles avec WebSocket), simple à mettre en place et efficace.

.Net 5, vers un environnement .NET unifié

Lors du Build 2019 les équipes Microsoft ont dévoilé beaucoup de nouveautés, parmi lesquelles la prochaine version majeure de dotnet : .NET 5.0.

À compter de la publication de .NET 5 en novembre 2020, ce sera le seul framework .NET à être mis à jour.

Vous vous demandez peut-être pourquoi la version passe de .NET Core 3 à .NET 5, voici l’explication officielle :

Nous omettons la version 4, car elle risque de perturber les utilisateurs familiarisés avec le .NET Framework, qui utilise la série 4.x depuis longtemps. De plus, nous voulions clairement communiquer que .NET 5 était l’avenir de la plate-forme .NET

Microsoft tient par ailleurs à apporter les précisions suivantes :

« Nous en profitons également pour simplifier les noms. Nous pensions que s’il n’y avait qu’un seul .NET à l’avenir, nous n’aurions pas besoin d’un terme de clarification comme «Core». Le nom abrégé est une simplification et indique également que .NET 5 possède des fonctionnalités et des comportements uniformes. N’hésitez pas à continuer à utiliser le nom «.NET Core» si vous le préférez. » 

Concernant le versioning, de nouvelles versions seront publiées tous les mois de novembre les années suivantes.

A noter que les versions à numéro pair, par exemple .NET 6, seront des versions LTS (Long Term Support) bénéficiant d’un support à long terme.

Une version préliminaire de .NET 5 devrait être disponible dans la première moitié de 2020.

blog ai3 dotnet5_platform-1024x546 .Net 5, vers un environnement .NET unifié

Les principaux axes d’amélioration de .NET 5 ont été les suivants :

  • créer un environnement d’exécution et de framework .NET unique, utilisable partout et offrant des comportements d’exécution et des expériences de développement uniformes,
  • développer les fonctionnalités de .NET en exploitant le meilleur de .NET Core, .NET Framework, Xamarin et Mono,
  • construire ce produit à partir d’une base de code unique sur laquelle les développeurs de la communauté Microsoft peuvent travailler et se développer ensemble, ce qui améliore tous les scénarios.

L’ambition est grande puisque cette version permettra :

  • d’avoir un framework unique et un .NET runtime unique,
  • de profiter de .NET Core, Xamarin et Mono pour améliorer et rendre .NET plus moderne,
  • pour la première fois, de cibler les OS Windows, Apple, Linux et Android ainsi que les WebAssembly.

Tout ce que vous appréciez dans .NET Core continuera d’exister:

  • open source et orienté communauté sur GitHub,
  • implémentation multi-plateforme,
  • prise en charge de l’exploitation de fonctionnalités spécifiques à la plateforme, telles que Windows Forms et WPF sous Windows, ainsi que des liaisons natives vers chaque plateforme native de Xamarin,
  • haute performance,
  • installation côte à côte,
  • petits fichiers de projet (style SDK),
  • interface de ligne de commande (CLI),
  • intégration de Visual Studio, Visual Studio pour Mac et Visual Studio Code.

Les principales nouveautés seront les suivantes :

  • vous aurez plus de choix sur les expériences d’exécution,
  • l’interopérabilité Java sera disponible sur toutes les plateformes,
  • l’interopérabilité Objective-C et Swift sera prise en charge sur plusieurs systèmes d’exploitation,
  • CoreFX sera étendu pour prendre en charge la compilation statique de .NET (ahead-of-time – AOT), des empreintes plus petites et un support pour davantage de systèmes d’exploitation.

Microsoft a aussi annoncé que .NET Core continue à exister en parallèle, toujours en open source. Une interopérabilité avec Java est dans les tuyaux, ainsi que pour Objective-C et Swift. Seule l’interopérabilité avec Kotlin manquera à l’appel pour être complet. La couche CoreFX, utilisée par toutes les app .NET 5, sera optimisée et disponible ultérieurement sur plus d’OS.

L’éditeur de Redmond annonce aussi un gros travail sur l’optimisation, la gestion mémoire, l’empreinte mémoire et les compilateurs : il y aura même un compilateur AOT (ahead-of-time) basé sur LLVM (Low Level Virtual Machine). Blazor quant à lui utilise déjà l’outil provenant de Mono.

L’agenda des releases est le suivant :

  • .NET Core 3 : septembre, version non LTS (Long Term Support),
  • .NET Core 3.1 : version LTS vers novembre 2019,
  • .NET 5 : novembre 2020,
  • .NET 6 / 7 / 8 : 2021, 2022 et 2023.
blog ai3 dotnet_schedule-1024x566 .Net 5, vers un environnement .NET unifié

Docker et .NET Core

Si vous avez déjà entendu parler de docker sans savoir ce que c’était exactement : cet article va vous permettre de faire en sorte que vos doutes se dissipent… Je pendrais l’exemple d’une application .NET Core pour illustrer cela.

Docker, qu’est ce que c’est?

Docker est une plateforme logicielle permettant de regrouper des logiciels dans des conteneurs.

Pour comprendre plus simplement, il suffit de comparer Docker à un porte-conteneurs.

blog ai3 280px-Container_ships_President_Truman_%28IMO_8616283%29_and_President_Kennedy_%28IMO_8616295%29_at_San_Francisco Docker et .NET Core

Dans l’image ci-dessus, vous pouvez vous apercevoir que ce porte conteneurs contient un nombre important de conteneurs avec à l’intérieur de la marchandise. D’un point de vue logiciel, cela fonctionne de la même façon: Docker va héberger des conteneurs logiciels avec à l’intérieur ce que vous souhaitez.

Si une VM est en mesure d’émuler une infrastructure matériel, un conteneur lui sera en mesure d’émuler un système d’exploitation.

Les conteneur et les images

  • Une Image va être composé d’un système de fichier contenant l’OS, l’application, la base de données etc.. bref tout ce que vous souhaitez intégrer dans votre conteneur.
  • On l’a vu au dessus : un conteneur est un réceptacle. Celui-ci va être alimenté par l’image crée préalablement par vos soins.

Tout image Docker que l’on voudra crée où utilisé (en récupérant par exemple l’image d’un repository) sera obligatoirement mis dans un conteneur.

Docker, .NET Core et VS Code

Pour vous montrer l’utilisation de Docker, je vais prendre le cas d’une application .NET Core MVC en utilisation Visual Studio Code.

  • Création du projet .NET Core

Depuis une invite de commande, lancer les commandes suivantes

mkdir dockerapp
cd dockerapp
dotnet new mvc -o DockerApp

blog ai3 image-3-1024x487 Docker et .NET Core
  • Publication de notre application

Dans la même invite de commande, lancer la commande suivante

dotnet publish -o ./publish

blog ai3 image-10-1024x229 Docker et .NET Core

Cette commande permet de compiler l’application sous forme d’exécutable optimisé. Tout cela se trouve dans le répertoire publish.

cd publish

  • Exécution de l’application

Dans la même invite de commande, lancer la commande suivante

dotnet DockerApp.dll

blog ai3 image-11-1024x264 Docker et .NET Core
blog ai3 image-6-1024x406 Docker et .NET Core
  • Maintenant, on va dockeriser cette application 🙂

On va ouvrir le code source de cette application avec Visual Studio Code

blog ai3 image-12-1024x213 Docker et .NET Core

Nous allons ensuite créer un dockerfile : c’est un fichier sans extension avec le nom dockerfile où sont décrit les opérations étapes par étapes de création de conteneur.

blog ai3 image-7 Docker et .NET Core
  • On va remplir ce fichier dockerfile en ajoutant les lignes ci-dessous dans ce fichier.

FROM microsoft/dotnet:2.1-aspnetcore-runtime AS base

WORKDIR /app

COPY /publish .

ENTRYPOINT [« dotnet », « DockerApp.dll »]

  1. Première ligne : va récupérer l’image d’ASP.NET Core 2.1 depuis un repository pour l’inclure dans notre conteneur.
  2. Deuxième ligne : va récupérer le répertoire de travail de notre appli pour l’inclure dans notre conteneur.
  3. Troisième ligne : va copier tout le contenu du répertoire publish
  4. Quatrième ligne : cette dernière ligne est le point d’entrée. Cela indique à Docker que l’on doit exécuter la dotnet command avec DockerApp.dll en paramètre.
  • On va construire l’image myimage qui se trouvera à l’intérieur du conteneur.

Depuis le terminal VS Code, lancer la commande suivante

blog ai3 image-13-1024x478 Docker et .NET Core
blog ai3 image-14-1024x668 Docker et .NET Core
  • On va indiquer à Docker d’exécuter l’image myimage dans un conteneur.

Dans la console vsCode, lancer la commande suivante

blog ai3 image-15-1024x28 Docker et .NET Core
  • Vous pouvez vous apercevoir que l’application s’est lancée normalement. Seule grosse différence : elle est maintenant encapsulée dans un conteneur.
blog ai3 image-16-1024x419 Docker et .NET Core

Les nouveautés de Visual Studio 2019

L’objectif de cet article est de faire le tour d’horizon des principales nouveautés et améliorations de la prochaine version majeure de Visual Studio, l’outil phare de développement de Microsoft.

IntelliCode

Vous connaissiez certainement IntelliSense, une fonctionnalité très appréciée de Visual Studio, voici la version dopée à l’IA : IntelliCode.
IntelliCode se forme sur votre référentiel de code en créant une hiérarchie entre les modèles de code les plus courants ainsi que le code de vos projets et va partager les résultats avec votre équipe.
Pour générer ses recommandations, IntelliCode s’entraîne sur 2 000 projets open source disponibles dans GitHub.
Au final, cela permet de réduire le nombre de frappes dont vous avez besoin et donc de gagner en productivité.

blog ai3 microsoft-vs-code-intellicode Les nouveautés de Visual Studio 2019

La fonctionnalité de recherche a été optimisée : elle est est désormais plus rapide et plus efficace. De plus, les résultats sont affichés au fur et à mesure de la frappe. Enfin, les raccourcis clavier des commandes courantes sont affichés.

blog ai3 search-feature Les nouveautés de Visual Studio 2019

Optimisations du débogueur

Jamais le débogage n’a été aussi simple et intuitif que dans cette version de Visual Studio.
Vous pouvez examiner plusieurs variables dans l’espion sans avoir besoin de scroller.
De plus, la navigation entre plusieurs mot clés de recherche a été facilitée.
Enfin, une option « Profondeur de la recherche » a été ajoutée (valeur de 1 à 10), cette dernière vous sera utile pour spécifier jusqu’à quelle niveau de profondeur la recherche doit être effectuée dans vos projets.

blog ai3 BasicSearch-1024x380 Les nouveautés de Visual Studio 2019
blog ai3 Navigation-1024x379 Les nouveautés de Visual Studio 2019

Nouvelle interface

L’interface a été mise à jour afin d’avoir la meilleur expérience utilisateur possible.
L’icône principal de l’application a été redesigné en utilisant l’approche Fluent Design System.

blog ai3 new-old-vs-win-icons-1 Les nouveautés de Visual Studio 2019

Le menu de démarrage a été optimisé pour plus de simplicité et une meilleure ergonomie.

blog ai3 command-bar-all-1024x838 Les nouveautés de Visual Studio 2019

Un thème bleu a été ajouté.

blog ai3 Visual-Studo-theme-comparison-1024x638 Les nouveautés de Visual Studio 2019

La barre de commande a été optimisée pour une meilleure productivité.

blog ai3 Visual-Studio-command-shelf-comparison-1024x114 Les nouveautés de Visual Studio 2019

La lisibilité des notifications a été améliorée.

blog ai3 Notifications-2-1024x472 Les nouveautés de Visual Studio 2019

Visual Studio Live Share

Visual Studio Live Share est un service de révision de code en temps réel qui vous permet de partager une base de code avec d’autres développeurs.
N’importe quel développeur autorisé peut travailler à distance en simultané sur vos projets de manière transparente, fluide et sécurisée.

blog ai3 indroducing-visual-studio-live-share Les nouveautés de Visual Studio 2019

Pull Request

La fonctionnalité Pull Request a été améliorée : vous pouvez désormais consulter, exécuter et déboguer les Pull Request de votre équipe sans quitter l’EDI.
Ceci nécessite de télécharger l’extension Pull Requests for Visual Studio à partir de Visual Studio Marketplace.

C#

Visual Studio 2019 ajoute quelques fonctionnalités supplémentaires à C# 8.0 :

  • flux asynchrones,
  • types Range et Index,
  • expressions Switch,
  • modèles récursifs,
  • déclarations using,
  • fonctions locales static.

F#

Améliorations des performances pour les solutions comportant de nombreux projets et corrections de bugs.

Universal Windows Platform (UWP)

Le déploiement sur des périphériques Windows Mobile n’est plus pris en charge dans Visual Studio 2019. Toute tentative de déploiement sur un périphérique Windows 10 Mobile provoquera une erreur indiquant que « Le déploiement sur des périphériques Windows Mobile n’est pas pris en charge dans Visual Studio 2019 ». Si vous devez continuer à travailler sur une application pour les appareils Windows 10 Mobile, continuez à utiliser Visual Studio 2017.

JavaScript/TypeScript

Le débogage JavaScript dans les tests unitaires des projets Node.js a été ajouté.

Prise en charge de .NET Core 3 Preview

Visual Studio 2019 permet la génération d’applications .NET Core 3 pour n’importe quelle plateforme.

blog ai3 dot-net-core-three-dev Les nouveautés de Visual Studio 2019

Pour information le lancement officiel de Visual Studio 2019 aura lieu le 2 avril.

blog ai3 visual Les nouveautés de Visual Studio 2019

Les nouveautés de C# 7

L’objectif de cet article est de présenter aux développeurs les dernières nouveautés de la version 7 de C# en les présentant de manière simple et concise.

Bien entendu, si vous souhaitez avoir plus de détails sur ces nouveautés, je vous invite à vous documenter personnellement pour récupérer les informations qui pourrait vous manquer.

  • La version 7.0

  • Amélioration de la lisibilité du code avec les variables OUT
C# 6 C# 7
string nombreAConvertir = « 7878 »;

int nombre;

if (Int32.TryParse(nombreAConvertir, out nombre))

{

}

string nombreAConvertir = « 7878 »;

if(Int32.TryParse(nombreAConvertir, out int nombre))

{

}

Avec la version 7,  la variable OUT est déclaré au moment où on souhaite l’utiliser, nous ne sommes plus obligés de déclarer préalablement la variable.

  • Amélioration de l’utilisation des tuples
Avant C# 7
Un tuple peut être défini de la façon ci-dessous

Tuple<int, string> tuple = new Tuple<int, string, bool>(1, « pomme »);

Pour accéder aux propriétés du tuples, on le fait simplement avec les propriétés item1, item2… suivant le nombre de propriétés défini dans le tuple.

if (tuple.Item1 == 1) {

Console.WriteLine(tuple.Item1);

}

if (tuple.Item2 == « pomme »){

Console.WriteLine(tuple.Item2);

}

Depuis C# 7
Il est bien entendu toujours possible de déclarer les tuples comme indiqué ci-dessus.

Cependant, d’autres façons de le faire sont maintenant disponible depuis la version 7 de C#.

  • var monTuple = (« test », « test1 »);

monTuple est bien un objet de type Tuple et pour accéder aux valeurs de ce tuple (test et test1), on appellera les propriétés item1 et item2.

  •   (string a, string b) monTuple = (« test », « test1 »);

monTuple est bien un objet de type Tuple et pour accéder aux valeurs de ce tuple(test et test1), on appellera les propriétés a et b.

  •   var monTuple = (a: « test », b: « test1 »);

monTuple est bien une instance d’ objet de type Tuple et pour accéder aux valeurs de ce tuple(test et test1), on appellera les propriétés a et b.

  • Apparition des éléments ignorés avec C# 7
Les éléments ignorés sont des variables temporaires factices utilisées dans le code,

  • n’ayant aucune valeur.
  • défini juste par un underscore (_).

 

Utilisé dans le cadre de la déconstruction d’un tuple
var (_, _, _, a, _, b) = ReturnTuple();

ReturnTuple est une méthode qui retourne un tuple de six éléments.

De tous ces élements retournés, certaines valeurs peuvent être inutilisés car , pas nécessaire. Les éléments ignorés indiqués ci-dessus permettent ainsi de réduire les allocations de mémoire : la methode retourne bien les valeurs du tuple mais du fait que certaines valeurs ne nous intéresse pas, on définit alors des élements ignorés.

  • Apparition du pattern matching avec C# 7
Avant C# 7
  • Le mot-clé is vérifie si un objet est compatible avec un type donné

Exemple : expr is Type

  • Le mot-clé switch est une instruction de sélection qui teste la valeur d’une constante.

Exemple : switch (expr)

case constant:

Après C# 7
  • Le mot-clé is prend en charge en plus
  • Le modèle de type : expr is Type nomVariable
    • is vérifie si expr peut être convertie avec le type Type, et si cela est possible effectue le cast directement.

Exemple : if (o is Employee e)

{return (e.Name);

  • Le modèle de variable : expr is var varName
    • Is vérifie si expr peut être assigné dans la variable varName, et si cela est possible effectue l’assignation directement.

Exemple : if (item is var obj){}

  • Le mot-clé switch prend en charge en plus
    • Tout expression de correspondance non null (IEnumerable, ICollection, Array, Int…).
    • L’apparition de la clause when sur la même ligne d’un case.

Exemple : case Shape shape when shape == null:

  • Apparition des fonctions locales avec C# 7

Une fonction locale est une méthode définie à l’intérieur d’une autre méthode. Cette fonctionnalité a été créé dans le but d’avoir plus de facilité de compréhension dans la lecture du code.

Exemple de fonction locale
private static string GetText(string path, string filename)

{

var sr = File.OpenText(AppendPathSeparator(path) + filename);

var text = sr.ReadToEnd();

return text;

// Ci-dessous, vous trouverez la fonction locale

string AppendPathSeparator(string filepath)

{

if (! filepath.EndsWith(@ »\ »))

filepath += @ »\ »;

return filepath;

}

}

  • Généralisation des expressions-bodied dans C# 7

Les expressions-bodied sont apparus dans la version 6 de C#. En C# 7, elles ont été généralisées au niveau des constructeurs et ses accesseurs.

Exemple d’expression-bodied en C# 7
// Accesseurs

public string Label

{

get => label;

set => this.label = value ?? « Default label »;

}

// Constructeur

public ExpressionMembersExample(string label) => this.Label = label;

  • Valeurs de retour de référence et variables locales de référence en C# 7
Variables de retour de référence
Une valeur de retour de référence permet à une méthode de retourner à un appelant une référence à une variable, plutôt qu’à une valeur.

Exemple :

public ref Person GetContactInformation(string fname, string lname)

{

return ref p;

}

On peut s’apercevoir que la méthode retourne une référence à un objet Person nommé p.

Variables locales de référence
Une variable locale de référence est une variable qui va recevoir une affectation de données ( généralement une méthode) non par par valeur mais par référence.

Exemple :

Person p = contacts.GetContactInformation(« Scott », « Hanselman »);

Ci-dessus, nous avons faire face à une variable locale : la valeur de p est copié à partir de la méthode GetContactInformation, si on modifie p par la suite, la valeur renvoyé par GetContactInformation ne sera pas impactée.

Ref Person p = contacts.GetContactInformation(« Scott », « Hanselman »);

Ci-dessus, nous avons faire face à une variable locale de référence : la valeur de p est désormais un alias de la valeur retournée par GetContactInformation, si on modifie p par la suite, la valeur renvoyée par GetContactInformation sera impactée.

  • Types de retours async généralisés
Nouveautés de C# 7
Au niveau asynchronisme, je ne m’étendrais pas dans cet article sur les mot-clés async et await. Je précise juste que les types de retour retournés dans le cadre d’utilisation de ces mots clés peuvent être Task,Task<TResult> ou void. Pour simplifier tout cela, C#7 permet d’utiliser maintenant un type globale, utilisable dés qu’une méthode est awaitable.

System.Threading.Tasks.ValueTask<TResult>

using System;

using System.Threading.Tasks;

class Program

{

static Random rnd;

static void Main()

{

Console.WriteLine($ »You rolled {GetDiceRoll().Result} »);

}

private static async ValueTask<int> GetDiceRoll()

{

int roll1 = await Roll();

int roll2 = await Roll();

return roll1 + roll2;

}

private static async ValueTask<int> Roll()

{

if (rnd == null)

rnd = new Random();

await Task.Delay(500);

int diceRoll = rnd.Next(1, 7);

return diceRoll;

}

}

  • Amélioration de la syntaxe litérale numérique
Nouveautés de C# 7
Avec C# 7, il est possible désormais d’utiliser  des séparateurs de chiffres pour une meilleure compréhension du code dans la lecture de constantes numériques.

public const int SixtyFour = 0b0100_0000;

public const long BillionsAndBillions = 100_000_000_000;

public const double AvogadroConstant = 6.022_140_857_747_474e23;

public const decimal GoldenRatio = 1.618_033_988_749_894_848_204_586_834_365_638_117_720 ;


  • La version 7.1

  • Expressions littérales par défaut
Nouveautés de C# 7
Dans l’optique de toujours plus simplifier le code, le mot-clé default pourra être utilisé de manière littérale pour initialiser des variables, des paramètres de méthodes où bien des instructions de retour.

Cela initialise la chaine à la valeur par défaut d’une string, à savoir null.

string maChaine=default ;

L’utilisation du mot clé dans un paramètre de méthode.

public LabeledPoint(double x, double y, string label = default)

{

X = x;

Y = y;

Label = label;

}

L’utilisation du mot clé en retour d’une méthode.

public static LabeledPoint MovePoint(LabeledPoint source,

double xDistance, double yDistance)

{

// return a default value:

if (source == null)

return default;

return new LabeledPoint(source.X + xDistance, source.Y + yDistance,

source.Label);

}

  • Async dans main
Le mot-clé async pourra être utilisé dans une méthode main.
  • Simplification de fonctionnalité de tuple
  • var monTuple = (a: « test », b: « test1 »);

monTuple est bien un objet de type Tuple et pour accéder aux valeurs de ce tuple(test et test1), on appellera les propriétés a et b.

Cependant en version C# 7.1, la définition du tuple  peut être redéfini de la façon suivante, toujours pour des raisons de simplification de code.

string a= « test »,

string b= »test1″,

  • var monTuple = (a, b);

  • La version 7.2

  • Apparition de private protected
  • Private protected :  cela veut dire qu’un membre pourra être accessible depuis les classes dérivés du même assembly de la classe principale
  • Arguments nommés non placés à la position de fin
Depuis C#4 sont apparus les arguments nommés (exemple ci-dessous)

PrintOrderDetails(orderNum: 31, productName: « Red Mug », sellerName: « Gift Shop »);

Les arguments nommés améliorent la lisibilité du code en identifiant ce que chaque argument représente.

Il ne faut pas les confondre avec des arguments de position (exemple ci-dessous)

PrintOrderDetails(orderNum, productName, sellerName);

 

Depuis la version C# 7.2, nous avons la possibilité de mixer les deux types d’arguments dans l’appel de la méthode.

PrintOrderDetails(orderNum :31, « Red Mug » , sellerName: « Gift Shop » );


  • La version 7.3

  • Prise en charge des opérateurs d’égalité et d’inégalité avec les tuples
Depuis la version 7.3, nous avons la possibilité dorénavant d’utiliser les opérateurs d’égalité == et d’inégalité. Le mode de fonctionnement est basique, il compare chaque membre de l’argument de gauche à chaque membre de l’argument de droite.
Exemple :
var test= (a: 5, b: 10);
var test1= (a: 5, b: 10);
Console.WriteLine(test== test1); // Le résultat sera True
  • Réaffectation des variables locales Ref
Il est désormais maintenant possible de pouvoir réaffecter une variable local Ref , qui était déjà un pointeur vers une autre variable.
Exemple :
ref VeryLargeStruct refLocal = ref veryLargeStruct;
refLocal = ref anotherVeryLargeStruct;On voit bien ci-dessus que la variable qui était un pointeur vers l’objet veryLargeStruct sur la première ligne, est désormais un nouveau pointeur vers l’objet anotherVeryLargeStruct sur la deuxième ligne.
  • Amélioration des tableaux stackalloc
Le mot-clé stackalloc est utilisé dans un contexte de code unsafe pour allouer un bloc de mémoire sur la pile. Avec la version 7.3, ce mot-clé peut dorénavant être utilisé avec des tableaux

Avant 7.3
var arr = new int[3] {1, 2, 3};
var arr2 = new int[] {1, 2, 3};
Depuis 7.3
int* pArr = stackalloc int[3] {1, 2, 3};
int* pArr2 = stackalloc int[] {1, 2, 3};
Span<int>arr = stackalloc [] {1, 2, 3};

  • D’autres types pour l’instruction fixed
L’instruction fixed définit un pointeur un pointeur vers une variable managée et épingle cette variable pendant l’exécution de l’instruction.

À compter de C# 7.3, l’instruction fixed s’applique à d’autres types au-delà des tableaux, chaînes, mémoires tampons de taille fixe ou variables non managées.

 

Blazor : Framework Web .NET

Introduction

Depuis les premiers navigateurs, Javascript a beaucoup évolué pour permettre de développer des applications web plus complexes. L’émergence récente des Web Assembly ouvre la possibilité de compiler du code que les navigateurs pourront exécuter directement sans avoir à parser le code source. Ceci offre une alternative à Javascript pour les développeurs qui souhaitent dynamiser leurs applications avec des langages comme C, C++ ou C#.

Web Assembly est un standard W3C qui consiste en un bytecode s’exécutant dans une sandbox compatible avec Javascript. L’objectif est d’exécuter du code à une vitesse proche du natif avec des fonctionnalités avancées tout en conservant la sécurité et la rétrocompatibilité. L’écosystème Web Assembly est toujours en développement et il est supporté par la plupart des navigateurs web.

Présentation

Microsoft a publié plusieurs versions beta de Blazor, un Framework Web .NET qui s’exécute au sein du navigateur. Blazor se base sur le moteur de rendu Razor pour simplifier la création d’application web monopage aussi appelée Single Page Application.

Frontend

Blazor s’appuie sur les technologies HTML et CSS, mais le C# vient remplacer le Javascript. En effet, la runtime C# .NET est embarquée dans le WASM (Web Assembly) et le navigateur exécute le bytecode du WASM. Il comporte toutes les fonctionnalités d’un Framework moderne tel que le modèle de composant, le routage, la mise en page, l’injection de dépendances, le rendu côté serveur, le débogage .NET et le rechargement à chaud pendant le développement.

blog ai3 Blazor_frontend-300x275 Blazor : Framework Web .NET

Backend

Si le navigateur ne supporte pas Web Assembly, Blazor permet de faire fonctionner l’application dans un environnement asm.js. L’exécution de Blazor côté serveur vous permettra d’écrire votre application web entièrement en C# avec ASP.NET Core, mais il présente quelques inconvénients. Chaque interaction avec l’UI gérée par SignalR nécessite un saut réseau, ceci implique que l’application ne fonctionnera pas hors-ligne et qu’il pourrait y avoir quelques latences en fonction du nombre de connexion.

blog ai3 blazor_backend Blazor : Framework Web .NET

Get started

Prérequis

Votre première application

Ouvrir Visual Studio puis Fichier -> Nouveau -> Projet…
Sélectionner Web et ASP.NET Core Web Application

blog ai3 blazor_tuto1 Blazor : Framework Web .NET

Sélectionnez le template Blazor et compiler la solution.

blog ai3 blazor_tuto2 Blazor : Framework Web .NET

Lancer l’application, vous devez avoir l’écran ci-dessous dans votre navigateur.

blog ai3 blazor_tuto3 Blazor : Framework Web .NET

Ouvrir la page Counter où l’incrémentation dynamique est effectuée en C#.

blog ai3 blazor_tuto4 Blazor : Framework Web .NET

Vous pouvez regarder l’implémentation dans le fichier Counter.cshtml

blog ai3 blazor_tuto5 Blazor : Framework Web .NET

Créer un nouveau fichier Todo.cshtml dans le dossier Pages avec l’implémentation suivante :

Ouvrir le fichier NavMenu.cshtml et ajouter les lignes suivantes :

Créer une classe TodoItem.cs à la racine du projet avec le code suivant :

blog ai3 blazor_tuto9 Blazor : Framework Web .NET

Vous pouvez compiler et relancer votre application, vous venez de coder une todolist avec Blazor !

blog ai3 blazor_tuto10 Blazor : Framework Web .NET

Conclusion

Le projet Blazor est open source et disponible sur Github. Bien que le Framework soit encore au stade expérimental, son approche est vraiment intéressante. Il ne s’agit pas de concurrencer ASP.NET MVC ou Javascript, mais de proposer une nouvelle solution full-stack .NET pour développer des « Single Page Application ».

Sources :
https://blazor.net/index.html
https://blogs.msdn.microsoft.com/webdev/2018/07/25/blazor-0-5-0-experimental-release-now-available/

 

LINQ Expressions

What is it ?

Compiled Expressions, Lambda Expressions, Expression Trees… LINQ Expressions can be named in many ways. This object describes a tree of members, operators, calls, conditions… that can be, during runtime, either read/parsed or compiled into a delegate.

EntityFramework

If you’re using EntityFramework, you’ll find that this C# instruction :

will execute this SQL query :

Well, the SQL query clearly does what we wanted it to do. But how did it know what to do ?

looks like a simple lambda, which would be a C# call to a C# method. Yet the call is not made in C#. It is included in the SQL query. The thing is you’re not using the extension method

but the extension method

The syntax when using both methods is exactly the same. However, the first method’s parameter is a lambda whereas the second method’s parameter is a lambda expression which means the code is not compiled with the app. Instead, it contains the expression tree :

  • We have a parameter named u of type User.
  • We access the property LastName of the parameter.
  • We call the method string.StartsWith on this property, with the parameter « F ».

This expression tree can be accessed and read at runtime. That way, the Where implementation will be able to convert some C# code we wrote into SQL.

Creating a LINQ expression at runtime

Let’s say you want to get, for a given object, the value of a property, which name you got as a string. You can do it with reflection. That’s quite easy. However, it is very slow. Yet, LINQ expressions can be compiled into lambdas, which is about as fast a if you wrote the code directly.

The easiest way to start is to write the lambda you would want :

And then decompose it :

  • You have a parameter of type User.
  • You access a property of this parameter.
  • The lambda type is Func<User, string>.

So here is the detailed code to create the expression :

All you need is calling the right static method of the Expression class.

Once you have the expression, you can compile it with the Compile() method.

A concrete example : an object mapper

In a multi-layer application, you often have more than one class for the same business concept. For example, you might have a UserEntity that matches what you have in your database and a UserDto that only contains the information you want to display.

Both those entities will have some identical properties (same type, same name). Some libraries enable you to automatically map those identical properties from one object to the other (AutoMapper being a famous one). Let’s do our own simple yet fast one.

Let’s imagine those objects :

The goal is to fill a UserDto from a UserEntity.

We will create OurOwnMapper class :

Then we will create a method to prepare the mapping from one class to another. Its prototype will be quite simple :

This method will have to find the matching properties :

Each property will be set from one object to another via a lambda that we will create with LINQ expressions. So, for each (TFrom, TTo) couple, we will have lamba array. However, the lambda array type will be different for each (Type, Type) couple. If you want to save all lambda arrays into the same Dictionary, I see 2 choices :

  • Use a Dictionary<(Type, Type), object[]> and cast the delegate into their real types when needed.
  • Use a Dictionary<(Type, Type), Action<object, object>[]> and do the cast inside the delegate.

I will use the second solution. That means my lambdas should look like that :

Now we add the code to create such lambdas :

Then we add the lambdas collection into a dictionary :

The only thing left to do is the Map method. For that, we just have to get the lambdas for the from and to types, then call all of them on the two objects :

Now, you can use your class like this :

Here is the full code for the OurOwnMapper class :

Not so complicated, is it ?

 

Envoyer un rapport SSRS au format MHTML, en tant que corps de mail

On peut avoir besoin d’envoyer un rapport Sql Server Reporting Services (SSRS) dans un mail. En général pour cela, on génère un fichier au format choisi (PDF, Excel, Word…), qui est ajouté en pièce jointe au mail. Ceci dit on peut aussi avoir besoin d’envoyer ce rapport en tant que corps du mail, en utilisant un export au format html. A première vue ça a l’air assez basique, mais la solution technique ne l’est pas tant que ça, et on peut trouver des bouts de solutions, mais jamais la solution complète. Elle existe pourtant, et je vais la détailler.

Mais d’abord un petit rappel sur la manière dont on génère un rapport dans du code, cette génération se fait en utilisant le web service « ReportExecution2005.asmx » présent sur le serveur de rapports. Voici un exemple de code C# :

Le paramètre « format » correspond au format d’export (ici PDF), à choisir parmi les formats disponibles. Il ne reste plus qu’à écrire le contenu de la valeur de retour « results » dans un fichier avec la bonne extension, et c’est bon.

Maintenant pour générer un email avec un rapport en tant que corps de mail, le but va être de faire un rendu du rapport au format html, pour intégrer ce rendu en tant que corps d’un mail.

Reporting services supporte 2 types de format html, qui sont « HTML4.0 » et « MHTML ». Le premier format nous donne un code html compréhensible et utilisable, mais si le rapport contient des images, elles sont fournies comme des liens vers le serveur de rapport, ce qui n’est pas acceptable, les images doivent être intégrées dans l’email. On va donc se diriger vers le format « MHTML », qui contient toutes les données et est normalement adapté à ce genre d’usage.

Ceci dit en essayant de générer un rapport en MHTML, on se rend compte que le contenu est encodé en base64, et s’il peut être ouvert dans un navigateur, ce contenu n’est pas reconnu par les clients email et il ne peut donc pas être envoyé tel quel.

On peut essayer de décoder ce contenu (c’est assez complexe), mais il existe une solution beaucoup plus simple si on s’intéresse au paramètre « deviceInfo » de la fonction de rendu du web service SSRS. Ce paramètre, souvent passé à null pour avoir des valeurs par défaut, est en fait un descriptif au format XML, permettant de positionner certaines valeurs pour le rendu. Parmi ces valeurs, il y a l’attribut « MHTMLFragment » qui permet de déterminer si on doit générer le html avec les tags html et body, ou s’il est intégré dans un tag table, et surtout l’attribut « OutlookCompat » qui a l’air intéressant dans le cadre d’une utilisation pour un email.

On peut donc essayer de générer le rapport au format MHTML, en utilisant la valeur de deviceInfo :

<DeviceInfo><OutlookCompat>True</OutlookCompat><MHTMLFragment>True</MHTMLFragment></DeviceInfo>

En regardant le résultat, on voit enfin du html utilisable, mais les images ne sont pas présentes. Ceci dit les références à ces images dans le html sont sous la forme « cid:a64b27da3c7a464d9102053b5fa7e8d1 », qui ressemble bien à ce qu’on trouve dans un email html, on approche. Reste à trouver à quoi correspond cette valeur, et où trouver l’image en question. La piste se trouve en regardant le contenu de la variable de sortie streamIDs, récupérée dans la fonction de rendu du rapport. Cette variable contient en fait la liste des codes correspondant aux liens vers les images du rapport, bingo ! il reste ensuite à récupérer le contenu de ces images à partir de ces streamIDs, pour pouvoir les intégrer au mail. Ceci se fait grâce à une autre fonction du web service de SSRS : « RenderStream ».

On a donc le html, les images et la liaison entre les deux grâce à ces ID, il ne reste plus qu’à construire un mail avec toutes ces données ! Si on utilise la classe « MailMessage » du Framework .NET, il va nous falloir passer par un objet de type « AlternateView », qui permet de définir des ressources liées au mail telles les images insérées. Voici donc un exemple de code final en C# qui permet de générer un tel mail :

Il faut juste rajouter certaines données à l’email (expéditeur, destinataire, sujet…), et il est prêt à être envoyé !

La procédure n’est pas très compliquée, mais reste mal documentée, j’espère que ce petit article sera utile.

Introduction a Microsoft Azure Profiler

Au menu du jour, une présentation de Azure Profiler qui est un nouveau service proposé par Microsoft, en mode preview, permettant de mettre en place une solution de profilage de vos applications Web. Ce service permet de faire des analyses poussées d’une application, et d’explorer les métriques remontés afin de trouver les causes de problèmes que peuvent rencontrés vos applications. Pour faire un parallèle avec un produit du marché, Azure Profiler propose des fonctionnalités proche de ANTS performance Profiler.

Pour fonctionner, cette solution s’articule autour de trois éléments principaux :

  • Un agent permettant de collecter les données de votre application.
  • Un compte de stockage Azure utilisé pour stocker les informations récoltées par l’agent Profiler.
  • Une application Web qui vous permettra d’accéder aux informations récoltées par l’agent.

Pour pouvoir créer une nouvelle instance de ce service, il vous faudra vous rendre à l’adresse suivante: https://www.azureserviceprofiler.com/ . Vous devrez ensuite vous connectez avec un compte possédant un abonnement Azure et pouvant manipuler des comptes de stockage.

Une fois connecté vous arriverez sur l’écran d’accueil du service.

blog ai3 Azure-Profiler-Portal Introduction a Microsoft Azure Profiler

A partir de cet écran vous pourrez soit créer un nouveau Data Cube, soit utilisez un wizard de création d’une nouvelle instance de profiler, en cliquant sur le lien « Get started » se trouvant sur la page d’accueil du portail. C’est cette seconde option que nous allons voir dans la suite de cet article pour mettre en place notre première instance de service Azure Profiler.

Le premier niveau de configuration concerne le choix de l’abonnement sur lequel vous désirez travailler. Au cours de mes tests je n’ai pas pu changer l’abonnement sur lequel je voulais déployer un agent. L’application me remonte tout le temps le premier de mes abonnements.

blog ai3 Azure-Profiler-Create-Data-Cube-Step1 Introduction a Microsoft Azure Profiler

Vous devez ensuite choisir l’application sur laquelle vous désirez mettre en place votre agent. Si votre application est en mode PAAS, il  faudra au minimum que votre application se trouve dans un App Service de type B1, et quel’option Always On soit activée. Vous pouvez apporter ces modifications, si nécessaire, directement depuis le portail de configuration de votre Cube, ou alors effectuer celles-ci à partir le portail Azure, et revenir ensuite finir la mise en place de votre agent. Tant que ces prérequis ne sont pas remplis vous ne pouvez pas aller plus loin au niveau de la configuration.

blog ai3 Azure-Profiler-Create-Data-Cube-Step2 Introduction a Microsoft Azure Profiler

Dès que tous les prérequis sont respectés, vous pouvez alors sélectionner votre application Web.

blog ai3 Azure-Profiler-Create-Data-Cube-Step3 Introduction a Microsoft Azure Profiler

L’étape de sélection de l’application étant effectuée, l’étape suivante consiste à choisir soit de vous appuyez sur un cube existant, soit de créer un nouveau cube. Si vous décidez de créer un nouveau cube, il vous faudra alors sélectionné un compte de stockage de votre abonnement Azure pour héberger les données en provenance de l’agence. Il est important de noté qu’un compte de stockage ne peut être lié qu’à une seule instance de cube. Si vous décidez de créer un nouveau cube, et d’utiliser un compte de stockage déjà lié à un cube, toutes les données seront écrasées par votre nouvelle instance de cube.

blog ai3 Azure-Profiler-Create-Data-Cube-Step4 Introduction a Microsoft Azure Profiler

Votre cube est maintenant créé. Il ne reste plus qu’à déployer le nécessaire au niveau de l’application Web afin de pouvoir la monitorer et c’est ce que nous allons voir lors de l’étape suivante.

blog ai3 Azure-Profiler-Create-Data-Cube-Step5 Introduction a Microsoft Azure Profiler

Comme vous pouvez le voir au niveau de la copie d’écran ci-dessous, un certain nombre d’opérations vont être effectuées afin de pouvoir déployer le nécessaire à la mise en place de l’agent de monitoring au niveau de votre application. durant cette opération les opérations suivantes vont être réalisées :

  • Une extension permettant à Azure Profiler de fonctionner va être publier au niveau de votre application web.
  • Une chaine de connexion va être rajouter aux settings de votre application web, afin que l’agent puisse sauvegarder les informations concernant votre application.
  • Une instance de Web Job va être ajoutée. Ce Web Job hébergera l’agent.

Afin de lancer le déploiement de votre service profiler, veuillez cliquer sur le bouton « Deploy ».

blog ai3 Azure-Profiler-Create-Data-Cube-Step6 Introduction a Microsoft Azure Profiler

Vous allez alors arriver sur une page vous informant sur l’avancée de l’installation et de la configuration des différents éléments. la dernière opération consistant à l’instanciation d’un service de type Web Job prenant un certain temps, vous pouvez aller boire un petit café et revenir. Il arrive dès fois que l’information concernant l’avancée de l’installation du Web Job soit erronée (statut reste toujours à en cours), dans ce cas là rafraichissez l’écran.

blog ai3 Azure-Profiler-Create-Data-Cube-Step7 Introduction a Microsoft Azure Profiler

 

Une fois toutes les opérations terminées vous pourrez revenir à la page de gestion des Data Cubes afin d’accéder au cube que vous venez de créer. Vous pourrez voir que votre cube a été correctement créé, que l’agent est en cours d’exécution et que la collecte des données relatives à votre application est effective.

blog ai3 Azure-Profiler-Create-Data-Cube-Step8 Introduction a Microsoft Azure Profiler

Afin de vérifier la bonne installation du Web Job, vous pouvez vous connecter au portail Azure, et ouvrir le groupe de ressources concernant votre application Web. En allant dans le détails de celle-ci vous pourrez voir qu’une instance de Web Job a été ajoutée.

blog ai3 Azure-Profiler-Create-Data-Cube-Step9 Introduction a Microsoft Azure Profiler

Votre profiler est maintenant opérationnel, vous allez maintenant pouvoir analyser votre application, et pouvoir trouver les potentiels problèmes pouvant exister au niveau de celle-ci. Pour se faire connectez vous au portail Azure Profiler à l’adresse suivante : https://www.azureserviceprofiler.com/. Au niveau de la page d’accueil cliquez sur le cube afin d’aller sur l’écran de détails. Vous pouvez maintenant explorer votre application, et accéder aux informations récoltés par votre agent.

blog ai3 Azure-Profiler-App Introduction a Microsoft Azure Profiler

Vous pouvez ensuite aller sur le détails de chacune de vos requête, et voir les portions de code qui consomme le plus de ressources en cliquant sur le lien « show hotpath ».

blog ai3 Azure-Profiler-App1 Introduction a Microsoft Azure Profiler

 

Voilà cette introduction à Azure Profiler touche à sa fin. N’hésitez surtout pas à faire des tests par vous même et à approfondir les possibilités de ce service. Celui-ci étant encore en preview il est sur que des ajouts de fonctionnalités seront effectuées pour enrichir encore plus le produit.

David Moïsa.