Asp.net core 3

De Banane Atomic
Révision datée du 9 juin 2019 à 22:18 par Nicolas (discussion | contributions) (→‎dotnet CLI)
(diff) ← Version précédente | Voir la version actuelle (diff) | Version suivante → (diff)
Aller à la navigationAller à la recherche

Liens

dotnet CLI

Bash.svg
# help
dotnet -h

# version installée
dotnet --info

# liste des templates de création (mvc, angular, webapi)
dotnet new
# créer un projet ASP.NET Core Web App (Model-View-Controller)
dotnet new mvc

# lister les templates
dotnet new -l
# installer un template
dotnet new -i Microsoft.AspNetCore.Blazor.Templates
# désinstaller un template
dotnet new -u Microsoft.AspNetCore.Blazor.Templates

# compiler
dotnet build
# compiler et executer
dotnet run
# forcer l'url et le port (défaut: http://127.0.0.1:5000)
ASPNETCORE_URLS="http://127.0.0.1:5123" dotnet run         # linux
dotnet run --ASPNETCORE_ENVIRONMENT Development            # powershell
$env:ASPNETCORE_URLS="http://127.0.0.1:5123" ; dotnet run  # powershell

# ajouter un package NuGet
dotnet add package <package_name>

Log

Cs.svg
public class MyClass
{
    private readonly ILogger<MyClass> _logger;

    public MyClass(ILogger<MyClass> logger)
    {
        _logger = logger;
    }

    public void MyMethod()
    {
        _logger.LogDebug("Debug");
        _logger.LogTrace("Trace");
        _logger.LogInformation("Info");
        _logger.LogWarning("Warn");
        _logger.LogError("Error");
        _logger.LogCritical("Fatal");
    }
}
config.json
"Logging": {
  "LogLevel": {
    "Default": "Information",  // log level par défaut
    "Microsoft": "Warning",    // pour les loggers commençant par Microsoft
    "MyClass": "Debug"         // pour les loggers commençant par MyClass
  }
}

Built-in logging providers

Console Console après avoir lancé dotnet run
Debug Debug window when debugging in Visual Studio
Sur Linux /var/log/message
EventSource Event Tracing for Windows (ETW)
EventLog Windows Event Log
TraceSource System.Diagnostics.TraceSource libraries and providers ()
Azure App Service text files in an Azure App Service app's file system and to blob storage in an Azure Storage account

Log dans un fichier - Serilog.Extensions.Logging.File

NuGet → Serilog.Extensions.Logging.File

Startup.cs
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
    loggerFactory.AddFile(Configuration.GetSection("Logging:PathFormat").Value, 
        fileSizeLimitBytes: 1024 * 1024 * 5, retainedFileCountLimit: 2, 
        isJson: true);
    // JSON, par défaut False
    // MaxSize, par défaut 1GB (1024 * 1024 * 1024)
    // MaxNbFiles, par défaut 31
config.json
"Logging": {
  "PathFormat": "MyApp-{Date}.log"
}
MyApp-20180501.log
2018-05-01T14:45:26.9980829+02:00 0HLDFC5FFGHTQ:00000004 [INF] Info (859a4ace)
MyApp-20180501.log
{
    "@t": "2018-05-01T12:51:41.3576555Z",
    "@m": "Info",
    "@i": "859a4ace",
    "SourceContext": "MyApp.Data.MyAppRepository",
    "ActionId": "7e10a1a8-7ad5-4c85-9e24-eca298b66616",
    "ActionName": "MyApp.Controllers.ListController.Add (MyApp)",
    "RequestId": "0HLDFC8VQARGR:00000008",
    "RequestPath": "/List/Add"
}

Javascript - téléchargement et utilisation des bibliothèques

Le téléchargement des bibliothèques javascript peut se faire avec npm ou yarn dans le dossier node_modules.
Ce dossier n'est pas accessible par le site web.

Rendre le dossier node_modules accessible comme fichiers statiques

Startup.cs
// For wwwroot directory
app.UseStaticFiles();
 
// Add support for node_modules but only during development
if (env.IsDevelopment())
{
    app.UseStaticFiles(new StaticFileOptions()
    {
        FileProvider = new PhysicalFileProvider(Path.Combine(Directory.GetCurrentDirectory(), @"node_modules")),
        // allow you access the node_modules directory as /vendor
        RequestPath = new PathString("/vendor")
Html.svg
<link rel="stylesheet" href="~/vendor/bootstrap/dist/css/bootstrap.css" />
<script src="~/vendor/bootstrap/dist/js/bootstrap.js"></script>

Copier les fichiers dans wwwroot avec gulp

Powershell.svg
# installer gulp
yarn global add gulp-cli

# ajouter gulp comme dépendance du projet
yarn add --dev gulp

# run the gulp tasks
gulp

# lister les tasks
gulp --tasks
gulpfile.js
var gulp = require('gulp');
var merge = require('merge');

// Dependency Dirs
var deps = {
    "jquery": {
        "dist/*": ""
    },
    "bootstrap": {
        "dist/**/*": ""
    },
    "font-awesome": {
        "css/*": ""
    }
};

gulp.task('default', function () {
    // place code for your default task here
});

gulp.task("scripts", function () {
    var streams = [];

    for (var prop in deps) {
        console.log("Prepping Scripts for: " + prop);
        for (var itemProp in deps[prop]) {
            streams.push(gulp.src("node_modules/" + prop + "/" + itemProp)
                .pipe(gulp.dest("wwwroot/vendor/" + prop + "/" + deps[prop][itemProp])));
        }
    }

    return merge(streams);
});

Environment Tag Helpers

Cshtml.svg
<!-- pour le développement, garder chaque fichier séparé -->
<environment include="Development">
    <script src="~/vendor/jquery/dist/jquery.js"></script>
    <script src="~/vendor/bootstrap/dist/js/bootstrap.js"></script>
    <script src="~/js/index.js"></script>
</environment>

<!-- pour la production, src: lien CDN ou fichier local minifié -->
<environment exclude="Development">
    <script src="//cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.slim.min.js"
            asp-fallback-src="~/vendor/jquery/dist/jquery.min.js"
            asp-fallback-test="window.jQuery"></script>
    <script src="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.1/js/bootstrap.min.js"
            asp-fallback-src="~/vendor/bootstrap/dist/js/bootstrap.min.js"
            asp-fallback-test="window.jQuery && window.jQuery.fn && window.jQuery.fn.modal"></script>
    <script src="~/dist/all.min.js" asp-append-version="true"></script>
</environment>

src (lien CDN) est chargé puis asp-fallback-test est testé. Si le test est négatif, la page charge asp-fallback-src (fichier local)
Les liens CDN ne sont pas téléchargé s'ils l'ont déjà été pour un autre site, ce qui permet de gagner du temps.
asp-append-version ajoute un hash à la fin de l'url du fichier pour forcer le téléchargement du nouveau fichier et non l'utilisation du cache.

Configuration

Sources des settings par défaut dans l'ordre de lecture:

  1. appsettings.json
  2. appsettings.<EnvironmentName>.json
  3. Azure Vault Key
  4. UserSecrets dans le mode Development
  5. Variables d'environment
  6. Ligne de commandes
Cs.svg
// recherche Key, si Key n'a pas été trouvé affecte default value à la variable value
var value = Configuration.GetValue<string>("Key", "default value");
var value = Configuration["Key"];
// pour les connection strings
Configuration.GetConnectionString("SqlServerConnectionString")
appsettings.json
{
  "Key": "Value",
  "ConnectionStrings": {
    "SqlServerConnectionString": "Server=(localdb)\\mssqllocaldb;Database=MyDb;Trusted_Connection=True;"
  }
}

File Configuration Provider

Program.cs
public static IWebHostBuilder CreateWebHostBuilder(string[] args)
{
    var config = new ConfigurationBuilder()
        .SetBasePath(Directory.GetCurrentDirectory())
        .AddJsonFile("passwords.json", false, false)  // optional, reloadOnChange
        .Build();

    return WebHost.CreateDefaultBuilder(args)
        .UseConfiguration(config)
        .UseStartup<Startup>();
}

Safe storage of app secrets in development in ASP.NET Core

À partir d'ASP.NET Core 2.0, CreateDefaultBuilder (fichier Program.cs - méthode CreateWebHostBuilder) appelle AddUserSecrets dans le mode Development
Bash.svg
# aller dans le dossier contenant le *.csproj
cd MyProject
# ajoute <PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="2.1.1" /> au *.csproj
dotnet add package Microsoft.Extensions.Configuration.UserSecrets
MyProject.csproj
  <PropertyGroup>
    <TargetFramework>netcoreapp2.1</TargetFramework>
    <UserSecretsId>UserSecretId - GUID</UserSecretsId>
  </PropertyGroup>

  <ItemGroup>
    <DotNetCliToolReference Include="Microsoft.Extensions.SecretManager.Tools" Version="2.0.2" />
  </ItemGroup>

Version

Bash.svg
dotnet restore

# avec un espace devant pour ne pas enregistrer la commande dans l'historique
 dotnet user-secrets set "ConnectionStringPasswords:SqlServer:MyUserName" "MyPassword"
# les secrets sont sauvegardés dans 
# Windows: %APPDATA%\microsoft\UserSecrets\<userSecretsId>\secrets.json
# Linux:   ~/.microsoft/usersecrets/<userSecretsId>/secrets.json

# to remove it
dotnet user-secrets remove "ConnectionStringPasswords:SqlServer:MyUserName"
# to list all secrets
dotnet user-secrets list
# to clear all
dotnet user-secrets clear
Startup.cs
public void ConfigureServices(IServiceCollection services)
{
    var builder = new SqlConnectionStringBuilder(Configuration.GetConnectionString("MyConnectionString"));
    builder.Password = Configuration["ConnectionStringPasswords:SqlServer:MyUser"];

    // Add database services.
    services.AddDbContext<MyAppContext>(options =>
        options.UseSqlServer(builder.ConnectionString)
    );

Environnement

L’environnement utilisé est contenu dans la variable environnement ASPNETCORE_ENVIRONMENT 3 valeurs sont supportées par le framework:

  • Development
  • Staging
  • Production (valeur par défaut)
Bash.svg
# lancer le service avec l'environnement Development
ASPNETCORE_ENVIRONMENT=Development dotnet run
dotnet run --ASPNETCORE_ENVIRONMENT Development

Configuration pour la ligne de commande:

Properties/launchSettings.json
{
  "profiles": {
    "my_project": {
      "commandName": "Project",
      "launchBrowser": true,
      "launchUrl": "api/values",
      "applicationUrl": "https://localhost:5001;http://localhost:5000",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    }
  }
}

Configuration pour vs code:

.vscode/launch.json
"configurations": [
    {
        "name": ".NET Core Launch (web)",
        "env": {
            "ASPNETCORE_ENVIRONMENT": "Development"
        }
    }
]

Configuration pour vs:
VS → Projet Properties → Debug → Environment variables → ASPNETCORE_ENVIRONMENT = Development

Deployment Scripts

MyProject.csproj
<Target Name="MyPublishScripts" AfterTargets="BeforePublish">
  <Exec Command="npm install" />
  <Exec Command="gulp minify" />
  <Exec Command="ng build" />
</Target>

Publish

Bash.svg
# publier dans le dossier bin\Debug\netcoreapp2.0\publish
dotnet publish -c Release -r ubuntu.16.04-x64
# -o /chemin/dossier : choisit un autre dossier pour publier
# --self-contained : publie pour le runtime spécifié dans la configuration
# -r : choix du runtime parmi ceux spécifiés dans la configuration (bin\Release\netcoreapp2.1\ubuntu.16.04-x64\publish)
# -c : configuration (Debug, Release)

# rendre l'executacle éxécutable pour tous
chmod +x bin/Release/netcoreapp2.1/ubuntu.16.04-x64/publish/myproject
MyProject.csproj
<Project Sdk="Microsoft.NET.Sdk.Web">
  <PropertyGroup>
    <RuntimeIdentifier>win10-x64</RuntimeIdentifier>
    <RuntimeIdentifier>win10-x64,ubuntu-x64,linux-x64</RuntimeIdentifier>
  </PropertyGroup>
Par défaut la publication se fait en mode portable: le dossier contient seulement les dll du projet.
En spécifiant le runtime la publication se fait en mode self-contained: le dossier contient toutes les dll nécessaire ainsi qu'un exécutable adapté au runtime.

Linux

/etc/systemd/system/kestrel-myproject.service
[Unit]
Description=My Project description

[Service]
WorkingDirectory=/srv/myproject
ExecStart=/srv/myproject/myproject
Restart=always
RestartSec=10  # Restart service after 10 seconds if dotnet service crashes
SyslogIdentifier=myproject
User=http
Environment=ASPNETCORE_ENVIRONMENT=Production
Environment=DOTNET_PRINT_TELEMETRY_MESSAGE=false
Environment=ASPNETCORE_URLS=http://localhost:5001

[Install]
WantedBy=multi-user.target

Angular

Dans le cas d'un projet WebApi avec Angular, les fichiers Angular ne sont pas générés et donc pas copiés.

Bash.svg
cd ClientApp
# generate angular files in folder ClientApp/dist
ng build --prod
cd ..

# copy ClientApp/dist to bin/Release/netcoreapp2.1/ubuntu.16.04-x64/publish/ClientApp
rm -rf bin/Release/netcoreapp2.1/ubuntu.16.04-x64/publish/ClientApp/dist
cp -r ClientApp/dist bin/Release/netcoreapp2.1/ubuntu.16.04-x64/publish/ClientApp
ClientApp/angular.json
{
  "projects": {
    "ClientApp": {
      "architect": {
        "build": {
          "options": {
            "outputPath": "dist",
Startup.cs
public void ConfigureServices(IServiceCollection services)
{
    services.AddSpaStaticFiles(configuration =>
    {
        configuration.RootPath = "ClientApp/dist";

How to configure Kestrel URLs in ASP.NET Core RC2

Program.cs
public static IWebHost BuildWebHost(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
        .UseUrls("http://*:5000")  // plus seulement disponible sur localhost
        .UseStartup<Startup>()
        .Build();

Bower

Utiliser plutôt yarn. ASP.NET Core 2.0 and the End of Bower

Gestionnaire de bibliothèques javascript.

  • Ajouter le fichier de configuration: clique-droit sur le projet → Add → New Item → Bower Configuration File
Powershell.svg
npm -g install bower
# créer le fichier bower.json
bower init
# installer jquery
bower install jquery --save
  • Clique-doit sur le fichier bower.json → Manage Bower Packages
bower.json
{
    "name":"MyWebAppDotNetCore",
    "ignore": [
        "**/.*",
        "node_modules",
        "bower_components",
        "test",
        "tests"
    ],
    "dependencies": {
        "jQuery": "3.3.1"
    }
}

Les packages sont installés dans le dossier bower_components.
Il est possible de configurer bower dans le fichier .bowerrc.

.bowerrc
{
    "directory": "wwwroot/lib"
}
npm installe chaque paquet avec ses propres dépendances. Utile pour les outils de développement.
bower utilise un arbre de dépendance plat. Utile pour le code front-end.
bower ne gère pas les bibliothèques angular-2+

Git

.gitignore
# Build results
[Bb]in/
[Oo]bj/

# User-specific files
*.user

# .NET Core
**/Properties/launchSettings.json

# Log files
*.log

# Visual Studio 2015/2017 cache/options directory
.vs/
/wwwroot/dist/
/ClientApp/dist/

# bower, npm
bower_components/
node_modules/

Erreurs

It was not possible to find any compatible framework version

It was not possible to find any compatible framework version.
The specified framework 'Microsoft.AspNetCore.App', version '2.1.0' was not found.

Problème avec les versions sdk 2.1.300, runtime 2.1.0, host 2.1.0.
Retourner aux versions sdk 2.1.200, runtime 2.0.7, host 2.0.7.

The project was restored using version x, but with current settings, version y would be used instead

The project was restored using Microsoft.NETCore.App version 2.1.2, but with current settings, version 2.1.0 would be used instead.
To resolve this issue, make sure the same settings are used for restore and for subsequent operations such as build or publish.
Typically this issue can occur if the RuntimeIdentifier property is set during build or publish but not during restore.
Bash.svg
dotnet restore

ARM

Bash.svg
# créé un dossier /bin/Debug/netcoreapp2.0/linux-arm/publish/ contenant l’exécutable et ses dépendances pour ARM
dotnet publish -r linux-arm

# copier le dossier linux-arm sur le serveur ARM
cd linux-arm/publish
./MyApp
# [1]    8952 segmentation fault (core dumped)  ./MyApp
# systemd-coredump[8962]: Failed to parse PID "0": Numerical result out of range

# Unhandled Exception: [1]    9060 segmentation fault (core dumped)  ./MyApp
# systemd-coredump[9083]: Failed to parse PID "0": Numerical result out of range

Description

Réécriture de ASP.NET:

  • moderne, plus besoin de conserver la compatibilité
  • léger, l'application ne charge que ce dont elle a besoin (packages MVC, Logging, Identity)
  • performant
  • cross platform et open source
  • MVC et Web API, plus de WebForm

ASP.NET Core.jpg

Installation

Linux

dotnet-host is not available for the 'armv7h' architecture.
Bash.svg
# installation du runtime seul
pacman -S dotnet-runtime
# installation du sdk et du runtime
pacman -S dotnet-sdk
Les assembly sont installées dans /opt/dotnet/shared/Microsoft.NETCore.App/2.0.7

Windows

  • Visual Studio Installer → Workloads → ASP.NET and web development
Powershell.svg
# version de .net core installée
dotnet --version