« Asp.net core 3 » : différence entre les versions

De Banane Atomic
Aller à la navigationAller à la recherche
 
m (Nicolas a déplacé la page Asp.net core vers Asp.net core 3)
 
(120 versions intermédiaires par le même utilisateur non affichées)
Ligne 3 : Ligne 3 :
* [https://docs.microsoft.com/en-us/aspnet/core/security/app-secrets?view=aspnetcore-2.0&tabs=linux Safe storage of app secrets]
* [https://docs.microsoft.com/en-us/aspnet/core/security/app-secrets?view=aspnetcore-2.0&tabs=linux Safe storage of app secrets]
* [https://docs.microsoft.com/en-us/aspnet/core Doc Microsoft]
* [https://docs.microsoft.com/en-us/aspnet/core Doc Microsoft]
* [[:Catégorie:.NET_Core|Catégorie .NET Core]]
* [https://github.com/dotnet/core/blob/master/release-notes/README.md .NET Core Release Notes]


= dotnet CLI =
= dotnet CLI =
Ligne 15 : Ligne 17 :
dotnet new
dotnet new
# créer un projet ASP.NET Core Web App (Model-View-Controller)
# créer un projet ASP.NET Core Web App (Model-View-Controller)
dotnet new mvc
dotnet new mvc --no-https -o [project-name]


# lister les templates
# lister les templates
Ligne 33 : Ligne 35 :
$env:ASPNETCORE_URLS="http://127.0.0.1:5123" ; dotnet run  # powershell
$env:ASPNETCORE_URLS="http://127.0.0.1:5123" ; dotnet run  # powershell


# ajouter un package NuGet
# run all the unit tests
dotnet add package <package_name>
dotnet test
</kode>
</kode>


= Log =
= [https://docs.microsoft.com/en-us/aspnet/core/fundamentals/logging Log] =
By default, an app is logging into {{boxx|Console}}, {{boxx|Debug}}, {{boxx|EventSource}}, {{boxx|EventLog}} (only when running on Windows).
<filebox fn='Program.cs'>
public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .ConfigureLogging(logging =>
        {
            logging.ClearProviders();  // remove all the providers: no more logs
        })
        .ConfigureWebHostDefaults(webBuilder =>
        {
            webBuilder.UseStartup<Startup>();
        });
</filebox>
 
<kode lang='cs'>
<kode lang='cs'>
public class MyClass
public class MyClass
{
{
     private readonly ILogger<MyClass> _logger;
     private readonly ILogger logger;


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


     public void MyMethod()
     public void MyMethod()
     {
     {
         _logger.LogDebug("Debug");
         logger.LogDebug("Debug");
         _logger.LogTrace("Trace");
         logger.LogTrace("Trace");
         _logger.LogInformation("Info");
         logger.LogInformation("Info");
         _logger.LogWarning("Warn");
         logger.LogWarning("Warn");
         _logger.LogError("Error");
         logger.LogError("Error");
         _logger.LogCritical("Fatal");
         logger.LogCritical("Fatal");
     }
     }
}
}
Ligne 61 : Ligne 77 :


<filebox fn='config.json'>
<filebox fn='config.json'>
"Logging": {
{
  "LogLevel": {
  "Logging": {
    "Default": "Information",  // log level par défaut
    "LogLevel": {
    "Microsoft": "Warning",    // pour les loggers commençant par Microsoft
      "Default": "Information",  // log level par défaut
    "MyClass": "Debug"        // pour les loggers commençant par MyClass
      "Microsoft": "Warning",    // pour les loggers commençant par Microsoft
      "MyClass": "Debug"        // pour les loggers commençant par MyClass
    }
   }
   }
}
</filebox>
</filebox>


== [https://docs.microsoft.com/fr-fr/aspnet/core/fundamentals/logging/?tabs=aspnetcore2x&view=aspnetcore-2.1#built-in-logging-providers Built-in logging providers] ==
== [https://docs.microsoft.com/en-us/aspnet/core/fundamentals/logging#built-in-logging-providers Built-in logging providers] ==
{| class="wikitable wtp wtmono1"  
{| class="wikitable wtp wtmono1"  
|-
|-
| Console || Console après avoir lancé {{boxx|dotnet run}}
| Console ||
* VS code "DEBUG CONSOLE" tab
* In the console window when the app is run with {{boxx|dotnet run}}
|-
|-
| Debug || Debug window when debugging in Visual Studio<br />Sur Linux {{boxx|/var/log/message}}
| Debug || Debug window when debugging in Visual Studio<br />On Linux {{boxx|journal}} or {{boxx|/var/log/message}} or {{boxx|/var/log/syslog}}
|-
|-
| EventSource || Event Tracing for Windows (ETW)
| EventSource || Event Tracing for Windows (ETW)
Ligne 85 : Ligne 104 :
| Azure App Service || text files in an Azure App Service app's file system and to blob storage in an Azure Storage account
| Azure App Service || text files in an Azure App Service app's file system and to blob storage in an Azure Storage account
|}
|}
=== journal ===
<pre>
mar 19 17:53:10 hostname logtest[29321]: fail: LogTest.Controllers.ItemController[0]
mar 19 17:53:10 hostname logtest[29321]:      Log message
mar 19 17:58:27 hostname logtest[29321]: fail: Microsoft.AspNetCore.Server.Kestrel[13]
mar 19 17:58:27 hostname logtest[29321]:      Connection id "...", Request id "...": An unhandled exception was thrown by the application.
mar 19 17:58:27 hostname logtest[29321]: System.Exception: exception message
mar 19 17:58:27 hostname logtest[29321]:    at LogTest.Controllers.ItemController.ThrowException() in /dev-path/LogTest/Controllers/ItemController.cs:line 41
</pre>
=== apache log ===
* {{boxx|access.log}} is well filled by each query
* {{boxx|error.log}} is never filled


== [https://github.com/serilog/serilog-extensions-logging-file Log dans un fichier - Serilog.Extensions.Logging.File] ==
== [https://github.com/serilog/serilog-extensions-logging-file Log dans un fichier - Serilog.Extensions.Logging.File] ==
* [https://nblumhardt.com/2016/10/aspnet-core-file-logger/ ASP.NET Core File Logging in one line of code]
* [https://nblumhardt.com/2016/10/aspnet-core-file-logger/ ASP.NET Core File Logging in one line of code]
Ajoute {{boxx|Serilog.RollingFile}} comme provider, tous les log seront loggués dans un fichier.<br>
NuGet → {{boxx|Serilog.Extensions.Logging.File}}
NuGet → {{boxx|Serilog.Extensions.Logging.File}}
<filebox fn='Startup.cs'>
<filebox fn='Startup.cs'>
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
{
     loggerFactory.AddFile(Configuration.GetSection("Logging:PathFormat").Value,  
     loggerFactory.AddFile(Configuration.GetSection("Logging"));
         fileSizeLimitBytes: 1024 * 1024 * 5, retainedFileCountLimit: 2,
 
        isJson: true);
    loggerFactory.AddFile(
    // JSON, par défaut False
        "MyApplication-{Date}.log",
    // MaxSize, par défaut 1GB (1024 * 1024 * 1024)
        LogLevel.Error,                       // default: LogLevel.Information
    // MaxNbFiles, par défaut 31
         fileSizeLimitBytes: 1024 * 1024 * 5, // MaxSize, default 1GB (1024 * 1024 * 1024)
        retainedFileCountLimit: 2,            // MaxNbFiles, default: 32
        isJson: true);                        // default: false
</filebox>
</filebox>


<filebox fn='config.json'>
<filebox fn='config.json'>
"Logging": {
{
  "PathFormat": "MyApp-{Date}.log"
  "Logging": {
    "PathFormat": "MyApplication-{Date}.log",
    "LogLevel": {
      "Default": "Error",
      "Microsoft": "Information"
    },
    "FileSizeLimitBytes": 5242880,
    "RetainedFileCountLimit": 2,
    "Json": true
  }
}
}
</filebox>
</filebox>


<filebox fn='MyApp-20180501.log'>
<filebox fn='MyApplication-20180501.log'>
2018-05-01T14:45:26.9980829+02:00 0HLDFC5FFGHTQ:00000004 [INF] Info (859a4ace)
2018-05-01T14:45:26.9980829+02:00 0HLDFC5FFGHTQ:00000004 [INF] Info (859a4ace)
</filebox>
</filebox>


<filebox fn='MyApp-20180501.log' lang=json>
<filebox fn='MyApplication-20180501.log' lang=json>
{
{
     "@t": "2018-05-01T12:51:41.3576555Z",
     "@t": "2018-05-01T12:51:41.3576555Z",
Ligne 121 : Ligne 167 :
     "RequestPath": "/List/Add"
     "RequestPath": "/List/Add"
}
}
</filebox>
== [https://mcguirev10.com/2018/02/07/serilog-dependency-injection-easy-ip-logging.html Serilog and Dependency Injection] ==
{{warn | Utiliser plutôt {{boxx|Serilog.Extensions.Logging.File}} avec la DI par défaut fournit par {{boxx|Microsoft.Extensions.Logging}}}}
<filebox fn='Program.cs'>
static void Main(string[] args)
{
    Log.Logger = new LoggerConfiguration()
        .WriteTo.Console(outputTemplate: customTemplate)
        .CreateLogger();
    var services = new ServiceCollection();
    services.AddTransient<IMyClass, MyClass>()
            .AddSingleton(Log.Logger);
    var provider = services.BuildServiceProvider();
    var myObject = provider.GetService<IMyClass>();
    myObject.MyMethod();
</filebox>
<filebox fn='MyClass.cs'>
public class MyClass : IMyClass
{
    private readonly ILogger logger;
    public MyClass(ILogger logger)
    {
        this.logger = logger.ForContext<MyClass>();
    }
    public void MyMethod()
    {
        logger.Debug("message");
</filebox>
= Nuget packages =
<kode lang='bash'>
# ajouter un package NuGet
dotnet add package <package_name>
dotnet add package <package_name> --version 2.0.0
# lister les packages NuGet
dotnet list package
# supprimer un package
dotnet remove package <package_name>
</kode>
== [https://www.mytechramblings.com/posts/centrally-manage-nuget-versions/ Directory.Build.targets] ==
Allows you to manage the versions of Nuget packages in a single centralized file.
<filebox fn='Directory.Build.targets' lang=xml>
<!-- Directory.Build.targets file has to be at the solution root -->
<Project>
  <ItemGroup>
    <PackageReference Update="AutoMapper" Version="10.1.1" />
</filebox>
<filebox fn='MyProject/MyProject.csproj' lang=xml>
<Project Sdk="Microsoft.NET.Sdk.Web">
  <ItemGroup>
    <!-- remove the version -->
    <PackageReference Include="AutoMapper" />
</filebox>
</filebox>


Ligne 227 : Ligne 336 :
# {{boxx|appsettings.json}}
# {{boxx|appsettings.json}}
# {{boxx|appsettings.<EnvironmentName>.json}}
# {{boxx|appsettings.<EnvironmentName>.json}}
# Azure Vault Key
# {{boxx|UserSecrets}} in {{boxx|Development}} environment
# {{boxx|UserSecrets}} dans le mode {{boxx|Development}}
# Environment variables
# Variables d'environment
# Command-line arguments
# Ligne de commandes
{{info | Les settings de la source suivante écrasent ceux déjà chargés.}}
 
<filebox fn='Startup.cs'>
using Microsoft.Extensions.Configuration;  // Microsoft.Extensions.Configuration.Abstractions.dll
 
public IConfiguration Configuration { get; }
 
public Startup(IConfiguration configuration)
{
    Configuration = configuration;
}


<kode lang='cs'>
// recherche Key, si Key n'a pas été trouvé affecte default value à la variable value
// 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.GetValue<string>("Key", "default value");
var value = Configuration["Key"];
var value = Configuration["Key"];
// pour les connection strings
// pour les connection strings
Configuration.GetConnectionString("SqlServerConnectionString")
Configuration.GetConnectionString("SqlServer1")
</kode>
 
// dotnet add package System.Data.SqlClient
var builder = new SqlConnectionStringBuilder(Configuration.GetConnectionString("SqlServer4")); // from appsettings.json
builder.Password = Configuration["DbPassword"]; // from secrets storage in Dev and appsettings.json in Prod
var connectionString = builder.ConnectionString;
</filebox>


== appsettings.json ==
<filebox fn='appsettings.json'>
<filebox fn='appsettings.json'>
{
{
   "Key": "Value",
   "Key": "Value",
   "ConnectionStrings": {
   "ConnectionStrings": {
     "SqlServerConnectionString": "Server=(localdb)\\mssqllocaldb;Database=MyDb;Trusted_Connection=True;"
     "SqlServer1": "Server=(localdb)\\MSSQLLocalDB;Database=MyDb;Integrated Security=True;MultipleActiveResultSets=True",
   }
    "SqlServer2": "Server=(localdb)\\mssqllocaldb;Database=MyDb;Trusted_Connection=True;",
    "SqlServer3": "Server=localhost;Database=MyDb;User=sa;Password=pwd;",
    "SqlServer4": "server=localhost;database=MyDb;user=sa;",
    "MySql": "Server=localhost;Database=MyDb;User=root;Password=pwd;",
    "Sqlite": "Data Source=MyDb.db"
   },
  "DbPassword": "****"
}
}
</filebox>
</filebox>


== [https://docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration/?view=aspnetcore-2.1#file-configuration-provider File Configuration Provider] ==
=== [https://docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration/?view=aspnetcore-2.1#file-configuration-provider File Configuration Provider] ===
Useful for using a file other than {{boxx|appsettings.config}} or for Console projects.
<filebox fn='Program.cs'>
<filebox fn='Program.cs'>
public static IWebHostBuilder CreateWebHostBuilder(string[] args)
public static IHostBuilder CreateHostBuilder(string[] args) =>
{
     Host.CreateDefaultBuilder(args)
     var config = new ConfigurationBuilder()
         .ConfigureHostConfiguration(configHost =>
         .SetBasePath(Directory.GetCurrentDirectory())
        {
        .AddJsonFile("passwords.json", false, false) // optional, reloadOnChange
            configHost.SetBasePath(Directory.GetCurrentDirectory());
         .Build();
            configHost.AddJsonFile("passwords.json", optional: true);
        })
         .UseStartup<Startup>();
}


     return WebHost.CreateDefaultBuilder(args)
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
        .UseConfiguration(config)
     WebHost.CreateDefaultBuilder(args)
        .UseStartup<Startup>();
          .ConfigureAppConfiguration((hostingContext, config) =>
          {
              config.AddJsonFile("passwords.json", optional: false, reloadOnChange: false);
              config.AddXmlFile("appsettings.xml", optional: true, reloadOnChange: true);
          })
          .UseStartup<Startup>();
}
}
</filebox>
</filebox>


== [https://docs.microsoft.com/en-us/aspnet/core/security/app-secrets Safe storage of app secrets in development in ASP.NET Core] ==
== [https://docs.microsoft.com/en-us/aspnet/core/security/app-secrets?view=aspnetcore-3.1&tabs=linux Safe storage of app secrets in development in ASP.NET Core] ==
* [https://dotnetcore.gaprogman.com/2017/09/07/user-secrets-what-are-they-and-why-do-i-need-them/ User Secrets – What Are They And Why Do I Need Them?]
* [https://dotnetcore.gaprogman.com/2017/09/07/user-secrets-what-are-they-and-why-do-i-need-them/ User Secrets – What Are They And Why Do I Need Them?]
Useful in dev environment to not store password in source code.
<kode lang='bash'>
# aller dans le dossier contenant le *.csproj
cd MyProject
# adds a UserSecretsId element within a PropertyGroup of the .csproj file
dotnet user-secrets init
# set a secret
# put a space as first character so the command line is not saved in the history
dotnet user-secrets set "key" "secret"
# the whole connection string
dotnet user-secrets set "ConnectionStrings:SqlServer" "server=localhost;database=test;user=test;password=****"
# only the connection string password
dotnet user-secrets set "DbPassword" "****"
# the secrets are stored in a JSON configuration file in a system-protected user profile folder on the local machine
# Windows: %APPDATA%\microsoft\UserSecrets\<userSecretsId>\secrets.json
# Linux:  ~/.microsoft/usersecrets/<userSecretsId>/secrets.json
# list all secrets of the current project
dotnet user-secrets list
# remove a secret in the current project
dotnet user-secrets remove "key"
# remove all secrets of the current project
dotnet user-secrets clear
</kode>
<filebox fn='WebApi/Program.cs'>
// The user secrets configuration source is automatically added in development mode
// when the project calls CreateDefaultBuilder to initialize a new instance of the host with preconfigured defaults.
// CreateDefaultBuilder calls AddUserSecrets when the EnvironmentName is Development
public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .ConfigureWebHostDefaults(webBuilder =>
        {
            webBuilder.UseStartup<Startup>();
        });
</filebox>
<filebox fn='Console/Program.cs'>
public static IConfigurationRoot Configuration { get; set; }
private static void Main()
{
    var builder = new ConfigurationBuilder();
    // dotnet add package Microsoft.Extensions.Configuration.UserSecrets
    builder.AddUserSecrets<Program>();
    Configuration = builder.Build();
</filebox>
=== Old ===
{{info | À partir d'ASP.NET Core 2.0, {{boxx|CreateDefaultBuilder}} (fichier Program.cs - méthode CreateWebHostBuilder) appelle {{boxx|AddUserSecrets}} dans le mode {{boxx|Development}}}}
{{info | À partir d'ASP.NET Core 2.0, {{boxx|CreateDefaultBuilder}} (fichier Program.cs - méthode CreateWebHostBuilder) appelle {{boxx|AddUserSecrets}} dans le mode {{boxx|Development}}}}


Ligne 315 : Ligne 511 :
     );
     );
</filebox>
</filebox>
== [https://docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration/?view=aspnetcore-3.1#evcp Environment variables] ==
== [https://docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration/?view=aspnetcore-3.1#command-line Command-line] ==
<kode lang='bash'>
dotnet MyApp MyKey="value"
</kode>


= [https://docs.microsoft.com/en-us/aspnet/core/fundamentals/environments Environnement] =
= [https://docs.microsoft.com/en-us/aspnet/core/fundamentals/environments Environnement] =
Ligne 370 : Ligne 574 :
</filebox>
</filebox>


= Publish =
= [https://docs.microsoft.com/en-us/dotnet/core/deploying Publish] =
Applications can be published in two different modes: {{boxx|self-contained}} or {{boxx|runtime-dependent}}.
* {{boxx|self-contained}} includes the .NET Core runtime and libraries, and your application and its dependencies. Users of the application can run it on a machine that doesn't have the .NET Core runtime installed.
* {{boxx|runtime-dependent}} includes only your application itself and its dependencies. Users of the application have to separately install the .NET Core runtime.
 
<kode lang='bash'>
<kode lang='bash'>
# publier dans le dossier bin\Debug\netcoreapp2.0\publish
# publier dans le dossier bin\Debug\netcoreapp2.0\publish
dotnet publish -c Release -r ubuntu.16.04-x64
dotnet publish -c Release -r linux-arm --self-contained false
# -o /chemin/dossier : choisit un autre dossier pour publier
# -c : configuration : Debug (default), Release
# --self-contained : publie pour le runtime spécifié dans la configuration
# -r <RUNTIME_IDENTIFIER> : publishes the application for a given runtime
# -r : choix du runtime parmi ceux spécifiés dans la configuration (bin\Release\netcoreapp2.1\ubuntu.16.04-x64\publish)
# --self-contained [true|false] : publishes the .NET Core runtime with the application (default true if a runtime identifier is specified and the project is an executable project)
# -c : configuration (Debug, Release)
# -o /path/folder : output directory (default: bin/[configuration]/[framework]/publish or bin/[configuration]/[framework]/[runtime]/publish )


# rendre l'executacle éxécutable pour tous
# rendre l'exécutable exécutable pour tous
chmod +x bin/Release/netcoreapp2.1/ubuntu.16.04-x64/publish/myproject
chmod +x bin/Release/netcoreapp2.1/ubuntu.16.04-x64/publish/myproject
</kode>
</kode>
* [https://docs.microsoft.com/en-us/dotnet/core/tools/dotnet-publish dotnet publish]


<filebox fn='MyProject.csproj' lang=xml>
<filebox fn='MyProject.csproj' lang=xml>
Ligne 390 : Ligne 599 :
   </PropertyGroup>
   </PropertyGroup>
</filebox>
</filebox>
{{info | Par défaut la publication se fait en mode {{boxx|portable}}: le dossier contient seulement les dll du projet.<br />
{{info | Par défaut la publication se fait en mode {{boxx|runtime-dependent}}: le dossier contient seulement les dll du projet.<br />
En spécifiant le runtime la publication se fait en mode {{boxx|self-contained}}: le dossier contient toutes les dll nécessaire ainsi qu'un exécutable adapté au runtime.}}
En spécifiant le runtime la publication se fait en mode {{boxx|self-contained}}: le dossier contient toutes les dll nécessaire ainsi qu'un exécutable adapté au runtime.}}
* [https://docs.microsoft.com/en-us/dotnet/core/rid-catalog RID Catalog]
 
** ubuntu.16.04-x64
[https://docs.microsoft.com/en-us/dotnet/core/rid-catalog RID Catalog] ([https://github.com/dotnet/runtime/blob/master/src/libraries/pkg/Microsoft.NETCore.Platforms/runtime.json list]): {{boxx|ubuntu-18.04-arm64}}, {{boxx|arch-x64}}, {{boxx|win10-x64}}
** linux-x64
 
** win10-x64
== Define the port on deployed application ==
By defaut the following urls are used: {{boxx|<nowiki>http://localhost:5000</nowiki>}} {{boxx|<nowiki>https://localhost:5001</nowiki>}}
<filebox fn='appsettings.json'>
{
  "Kestrel": {
    "EndPoints": {
      "Http": {
        "Url": "http://localhost:6000"
</filebox>
 
It can also be configured in the [[Asp.net_core#Service_file|service file]].


== Linux ==
== Linux ==
* [[Nginx#.Net_Core|Configurer Nginx pour .Net Core]]
* [[Nginx#.Net_Core|Configurer Nginx pour .Net Core]]
* [[Apache_et_ubuntu#Dotnet_core|Configurer Apache pour .Net Core]]


=== [https://docs.microsoft.com/en-us/aspnet/core/host-and-deploy/linux-apache?view=aspnetcore-3.1#create-the-service-file Service file] ===
<filebox fn='/etc/systemd/system/kestrel-myproject.service' lang=ini>
<filebox fn='/etc/systemd/system/kestrel-myproject.service' lang=ini>
[Unit]
[Unit]
Ligne 407 : Ligne 628 :
WorkingDirectory=/srv/myproject
WorkingDirectory=/srv/myproject
ExecStart=/srv/myproject/myproject
ExecStart=/srv/myproject/myproject
ExecStart=/usr/bin/dotnet /srv/myproject/myproject.dll
Restart=always
Restart=always
RestartSec=10  # Restart service after 10 seconds if dotnet service crashes
RestartSec=10  # Restart service after 10 seconds if dotnet service crashes
KillSignal=SIGINT
SyslogIdentifier=myproject
SyslogIdentifier=myproject
User=http
User=http
Ligne 414 : Ligne 637 :
Environment=DOTNET_PRINT_TELEMETRY_MESSAGE=false
Environment=DOTNET_PRINT_TELEMETRY_MESSAGE=false
Environment=ASPNETCORE_URLS=http://localhost:5001
Environment=ASPNETCORE_URLS=http://localhost:5001
Environment=ConnectionStrings__MyConnectionString=server\x3dlocalhost\x3bdatabase\x3dMyDb\x3buser\x3dMyUser\x3bpassword\x3dMyPwd


[Install]
[Install]
WantedBy=multi-user.target
WantedBy=multi-user.target
</filebox>
</filebox>
<kode lang='bash'>
# escape value as connection string
systemd-escape "<value-to-escape>"
</kode>


== Angular ==
== Angular ==
Ligne 450 : Ligne 679 :
</filebox>
</filebox>


= [http://benfoster.io/blog/how-to-configure-kestrel-urls-in-aspnet-core-rc2 How to configure Kestrel URLs in ASP.NET Core RC2] =
= [https://edi.wang/post/2018/9/27/get-app-version-net-core Version] =
<filebox fn='Program.cs' lang='csharp'>
<filebox fn='MyProject.csproj' lang='xml'>
public static IWebHost BuildWebHost(string[] args) =>
<Project Sdk="Microsoft.NET.Sdk">
     WebHost.CreateDefaultBuilder(args)
  <PropertyGroup>
        .UseUrls("http://*:5000")  // plus seulement disponible sur localhost
     <TargetFramework>netcoreapp3.1</TargetFramework>
        .UseStartup<Startup>()
    <AssemblyVersion>1.1.1.1</AssemblyVersion>
        .Build();
    <FileVersion>2.2.2.2</FileVersion>
    <Version>3.3.3.3-xyz</Version>
  </PropertyGroup>
</Project>
</filebox>
</filebox>
<kode lang='cs'>
typeof(Startup).Assembly.GetName().Version;  // 1.1.1.1
Assembly.GetEntryAssembly().GetName().Version;  // 1.1.1.1
Assembly.GetEntryAssembly().GetCustomAttribute<AssemblyFileVersionAttribute>().Version;  // 2.2.2.2
Assembly.GetEntryAssembly().GetCustomAttribute<AssemblyInformationalVersionAttribute>().InformationalVersion;  // 3.3.3.3-xyz
</kode>


= [https://docs.microsoft.com/en-us/aspnet/core/client-side/bower?view=aspnetcore-2.1 Bower] =
= [https://docs.microsoft.com/en-us/aspnet/core/client-side/bower?view=aspnetcore-2.1 Bower] =
Ligne 525 : Ligne 764 :


= Erreurs =
= Erreurs =
== Found conflicts between different versions of ... ==
<kode lang='bash'>
# Rebuild with more details to know with assemblies are in conflict
dotnet build --verbosity diagnostic
# look for same error message: Found conflicts between different versions of ...
</kode>
Solution: force the version of assemblies
<filebox fn='MyProject.csproj' lang=xml>
<Project Sdk="Microsoft.NET.Sdk.Web">
  <ItemGroup>
    <PackageReference Include="Microsoft.EntityFrameworkCore" Version="3.1.3" />
</filebox>
== It was not possible to find any compatible framework version ==
== It was not possible to find any compatible framework version ==
<pre>
<pre>
Ligne 570 : Ligne 822 :


= Installation =
= Installation =
== [https://wiki.archlinux.org/index.php/.NET_Core Linux] ==
== [https://wiki.archlinux.org/index.php/.NET_Core Archlinux] ==
{{warn | {{boxx|dotnet-host}} is not available for the 'armv7h' architecture.}}
<kode lang='bash'>
<kode lang='bash'>
# installation du runtime seul
pacman -S aspnet-runtime dotnet-sdk
pacman -S dotnet-runtime
# installe dotnet-host dotnet-runtime aspnet-runtime dotnet-sdk
# installation du sdk et du runtime
pacman -S dotnet-sdk
</kode>
</kode>
{{info | Les assembly sont installées dans {{boxx|/opt/dotnet/shared/Microsoft.NETCore.App/2.0.7}}}}
{{info | Ajouter {{boxx|~/.dotnet/tools}} à {{boxx|PATH}} pour que les dotnet tools fonctionnent depuis le shell.}}
{{info | Les assembly sont installées dans {{boxx|/usr/share/dotnet/shared/Microsoft.NETCore.App/x.y.z}}}}
 
<filebox fn='/etc/environment' lang='bash'>
# disable .net core telemetry
DOTNET_CLI_TELEMETRY_OPTOUT=1
</filebox>


== [https://www.microsoft.com/net/core#windowscmd Windows] ==
== [https://www.microsoft.com/net/core#windowscmd Windows] ==

Dernière version du 17 mai 2021 à 17:39

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 --no-https -o [project-name]

# 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

# run all the unit tests
dotnet test

Log

By default, an app is logging into Console, Debug, EventSource, EventLog (only when running on Windows).

Program.cs
public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .ConfigureLogging(logging =>
        {
            logging.ClearProviders();  // remove all the providers: no more logs
        })
        .ConfigureWebHostDefaults(webBuilder =>
        {
            webBuilder.UseStartup<Startup>();
        });
Cs.svg
public class MyClass
{
    private readonly ILogger logger;

    public MyClass(ILogger<MyClass> logger)
    {
        this.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
  • VS code "DEBUG CONSOLE" tab
  • In the console window when the app is run with dotnet run
Debug Debug window when debugging in Visual Studio
On Linux journal or /var/log/message or /var/log/syslog
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

journal

mar 19 17:53:10 hostname logtest[29321]: fail: LogTest.Controllers.ItemController[0]
mar 19 17:53:10 hostname logtest[29321]:       Log message

mar 19 17:58:27 hostname logtest[29321]: fail: Microsoft.AspNetCore.Server.Kestrel[13]
mar 19 17:58:27 hostname logtest[29321]:       Connection id "...", Request id "...": An unhandled exception was thrown by the application.
mar 19 17:58:27 hostname logtest[29321]: System.Exception: exception message
mar 19 17:58:27 hostname logtest[29321]:    at LogTest.Controllers.ItemController.ThrowException() in /dev-path/LogTest/Controllers/ItemController.cs:line 41

apache log

  • access.log is well filled by each query
  • error.log is never filled

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

Ajoute Serilog.RollingFile comme provider, tous les log seront loggués dans un fichier.
NuGet → Serilog.Extensions.Logging.File

Startup.cs
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
    loggerFactory.AddFile(Configuration.GetSection("Logging"));

    loggerFactory.AddFile(
        "MyApplication-{Date}.log",
        LogLevel.Error,                       // default: LogLevel.Information
        fileSizeLimitBytes: 1024 * 1024 * 5,  // MaxSize, default 1GB (1024 * 1024 * 1024)
        retainedFileCountLimit: 2,            // MaxNbFiles, default: 32
        isJson: true);                        // default: false
config.json
{
  "Logging": {
    "PathFormat": "MyApplication-{Date}.log",
    "LogLevel": {
      "Default": "Error",
      "Microsoft": "Information"
    },
    "FileSizeLimitBytes": 5242880,
    "RetainedFileCountLimit": 2,
    "Json": true
  }
}
MyApplication-20180501.log
2018-05-01T14:45:26.9980829+02:00 0HLDFC5FFGHTQ:00000004 [INF] Info (859a4ace)
MyApplication-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"
}

Serilog and Dependency Injection

Utiliser plutôt Serilog.Extensions.Logging.File avec la DI par défaut fournit par Microsoft.Extensions.Logging
Program.cs
static void Main(string[] args)
{
    Log.Logger = new LoggerConfiguration()
        .WriteTo.Console(outputTemplate: customTemplate)
        .CreateLogger();

    var services = new ServiceCollection();
    services.AddTransient<IMyClass, MyClass>()
            .AddSingleton(Log.Logger);

    var provider = services.BuildServiceProvider();

    var myObject = provider.GetService<IMyClass>();
    myObject.MyMethod();
MyClass.cs
public class MyClass : IMyClass
{
    private readonly ILogger logger;

    public MyClass(ILogger logger)
    {
        this.logger = logger.ForContext<MyClass>();
    }

    public void MyMethod()
    {
        logger.Debug("message");

Nuget packages

Bash.svg
# ajouter un package NuGet
dotnet add package <package_name>
dotnet add package <package_name> --version 2.0.0

# lister les packages NuGet
dotnet list package

# supprimer un package
dotnet remove package <package_name>

Directory.Build.targets

Allows you to manage the versions of Nuget packages in a single centralized file.

Directory.Build.targets
<!-- Directory.Build.targets file has to be at the solution root -->
<Project>
  <ItemGroup>
    <PackageReference Update="AutoMapper" Version="10.1.1" />
MyProject/MyProject.csproj
<Project Sdk="Microsoft.NET.Sdk.Web">
  <ItemGroup>
    <!-- remove the version -->
    <PackageReference Include="AutoMapper" />

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. UserSecrets in Development environment
  4. Environment variables
  5. Command-line arguments
Les settings de la source suivante écrasent ceux déjà chargés.
Startup.cs
using Microsoft.Extensions.Configuration;  // Microsoft.Extensions.Configuration.Abstractions.dll

public IConfiguration Configuration { get; }

public Startup(IConfiguration configuration)
{
    Configuration = configuration;
}

// 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("SqlServer1")

// dotnet add package System.Data.SqlClient
var builder = new SqlConnectionStringBuilder(Configuration.GetConnectionString("SqlServer4")); // from appsettings.json
builder.Password = Configuration["DbPassword"]; // from secrets storage in Dev and appsettings.json in Prod 
var connectionString = builder.ConnectionString;

appsettings.json

appsettings.json
{
  "Key": "Value",
  "ConnectionStrings": {
    "SqlServer1": "Server=(localdb)\\MSSQLLocalDB;Database=MyDb;Integrated Security=True;MultipleActiveResultSets=True",
    "SqlServer2": "Server=(localdb)\\mssqllocaldb;Database=MyDb;Trusted_Connection=True;",
    "SqlServer3": "Server=localhost;Database=MyDb;User=sa;Password=pwd;",
    "SqlServer4": "server=localhost;database=MyDb;user=sa;",
    "MySql": "Server=localhost;Database=MyDb;User=root;Password=pwd;",
    "Sqlite": "Data Source=MyDb.db"
  },
  "DbPassword": "****"
}

File Configuration Provider

Useful for using a file other than appsettings.config or for Console projects.

Program.cs
public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .ConfigureHostConfiguration(configHost =>
        {
            configHost.SetBasePath(Directory.GetCurrentDirectory());
            configHost.AddJsonFile("passwords.json", optional: true);
        })
        .UseStartup<Startup>();
}

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
           .ConfigureAppConfiguration((hostingContext, config) =>
           {
               config.AddJsonFile("passwords.json", optional: false, reloadOnChange: false);
               config.AddXmlFile("appsettings.xml", optional: true, reloadOnChange: true);
           })
           .UseStartup<Startup>();
}

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

Useful in dev environment to not store password in source code.

Bash.svg
# aller dans le dossier contenant le *.csproj
cd MyProject

# adds a UserSecretsId element within a PropertyGroup of the .csproj file
dotnet user-secrets init

# set a secret
# put a space as first character so the command line is not saved in the history
 dotnet user-secrets set "key" "secret"
# the whole connection string
 dotnet user-secrets set "ConnectionStrings:SqlServer" "server=localhost;database=test;user=test;password=****"
# only the connection string password
 dotnet user-secrets set "DbPassword" "****"

# the secrets are stored in a JSON configuration file in a system-protected user profile folder on the local machine
# Windows: %APPDATA%\microsoft\UserSecrets\<userSecretsId>\secrets.json
# Linux:   ~/.microsoft/usersecrets/<userSecretsId>/secrets.json


# list all secrets of the current project
dotnet user-secrets list

# remove a secret in the current project
dotnet user-secrets remove "key"

# remove all secrets of the current project
dotnet user-secrets clear
WebApi/Program.cs
// The user secrets configuration source is automatically added in development mode
// when the project calls CreateDefaultBuilder to initialize a new instance of the host with preconfigured defaults.
// CreateDefaultBuilder calls AddUserSecrets when the EnvironmentName is Development
public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .ConfigureWebHostDefaults(webBuilder =>
        {
            webBuilder.UseStartup<Startup>();
        });
Console/Program.cs
public static IConfigurationRoot Configuration { get; set; }

private static void Main()
{
    var builder = new ConfigurationBuilder();
    // dotnet add package Microsoft.Extensions.Configuration.UserSecrets
    builder.AddUserSecrets<Program>();
    Configuration = builder.Build();

Old

À 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)
    );

Environment variables

Command-line

Bash.svg
dotnet MyApp MyKey="value"

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

Applications can be published in two different modes: self-contained or runtime-dependent.

  • self-contained includes the .NET Core runtime and libraries, and your application and its dependencies. Users of the application can run it on a machine that doesn't have the .NET Core runtime installed.
  • runtime-dependent includes only your application itself and its dependencies. Users of the application have to separately install the .NET Core runtime.
Bash.svg
# publier dans le dossier bin\Debug\netcoreapp2.0\publish
dotnet publish -c Release -r linux-arm --self-contained false
# -c : configuration : Debug (default), Release
# -r <RUNTIME_IDENTIFIER> : publishes the application for a given runtime
# --self-contained [true|false] : publishes the .NET Core runtime with the application (default true if a runtime identifier is specified and the project is an executable project)
# -o /path/folder : output directory (default: bin/[configuration]/[framework]/publish or bin/[configuration]/[framework]/[runtime]/publish )

# rendre l'exécutable exé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 runtime-dependent: 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.

RID Catalog (list): ubuntu-18.04-arm64, arch-x64, win10-x64

Define the port on deployed application

By defaut the following urls are used: http://localhost:5000 https://localhost:5001

appsettings.json
{
  "Kestrel": {
    "EndPoints": {
      "Http": {
        "Url": "http://localhost:6000"

It can also be configured in the service file.

Linux

Service file

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

[Service]
WorkingDirectory=/srv/myproject
ExecStart=/srv/myproject/myproject
ExecStart=/usr/bin/dotnet /srv/myproject/myproject.dll
Restart=always
RestartSec=10  # Restart service after 10 seconds if dotnet service crashes
KillSignal=SIGINT
SyslogIdentifier=myproject
User=http
Environment=ASPNETCORE_ENVIRONMENT=Production
Environment=DOTNET_PRINT_TELEMETRY_MESSAGE=false
Environment=ASPNETCORE_URLS=http://localhost:5001
Environment=ConnectionStrings__MyConnectionString=server\x3dlocalhost\x3bdatabase\x3dMyDb\x3buser\x3dMyUser\x3bpassword\x3dMyPwd

[Install]
WantedBy=multi-user.target
Bash.svg
# escape value as connection string
systemd-escape "<value-to-escape>"

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";

Version

MyProject.csproj
<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>netcoreapp3.1</TargetFramework>
    <AssemblyVersion>1.1.1.1</AssemblyVersion>
    <FileVersion>2.2.2.2</FileVersion>
    <Version>3.3.3.3-xyz</Version>
  </PropertyGroup>
</Project>
Cs.svg
typeof(Startup).Assembly.GetName().Version;  // 1.1.1.1
Assembly.GetEntryAssembly().GetName().Version;  // 1.1.1.1
Assembly.GetEntryAssembly().GetCustomAttribute<AssemblyFileVersionAttribute>().Version;  // 2.2.2.2
Assembly.GetEntryAssembly().GetCustomAttribute<AssemblyInformationalVersionAttribute>().InformationalVersion;  // 3.3.3.3-xyz

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

Found conflicts between different versions of ...

Bash.svg
# Rebuild with more details to know with assemblies are in conflict
dotnet build --verbosity diagnostic
# look for same error message: Found conflicts between different versions of ...

Solution: force the version of assemblies

MyProject.csproj
<Project Sdk="Microsoft.NET.Sdk.Web">
  <ItemGroup>
    <PackageReference Include="Microsoft.EntityFrameworkCore" Version="3.1.3" />

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

Archlinux

Bash.svg
pacman -S aspnet-runtime dotnet-sdk
# installe dotnet-host dotnet-runtime aspnet-runtime dotnet-sdk
Ajouter ~/.dotnet/tools à PATH pour que les dotnet tools fonctionnent depuis le shell.
Les assembly sont installées dans /usr/share/dotnet/shared/Microsoft.NETCore.App/x.y.z
/etc/environment
# disable .net core telemetry
DOTNET_CLI_TELEMETRY_OPTOUT=1

Windows

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