« Asp.net core 6 » : différence entre les versions
(Page créée avec « Category:.NET Core = Links = * [https://docs.microsoft.com/en-us/aspnet/core/release-notes/aspnetcore-6.0?view=aspnetcore-6.0 What's new in ASP.NET Core 6.0] ») |
(→Links) |
||
(13 versions intermédiaires par le même utilisateur non affichées) | |||
Ligne 2 : | Ligne 2 : | ||
= Links = | = Links = | ||
* [https://docs.microsoft.com/en-us/aspnet/core/release-notes/aspnetcore-6.0?view=aspnetcore-6.0 What's new in ASP.NET Core 6.0] | * [https://docs.microsoft.com/en-us/aspnet/core/release-notes/aspnetcore-6.0?view=aspnetcore-6.0 What's new in ASP.NET Core 6.0] | ||
* [https://docs.microsoft.com/en-us/aspnet/core/security/app-secrets?view=aspnetcore-6.0&tabs=linux Safe storage of app secrets] | |||
* [https://docs.microsoft.com/en-us/aspnet/core Doc Microsoft] | |||
* [[:Catégorie:.NET_Core|Catégorie .NET Core]] | |||
* [https://github.com/dotnet/core/blob/main/release-notes/6.0/README.md .NET 6 Release Note] | |||
= dotnet CLI = | |||
<kode lang='bash'> | |||
# help | |||
dotnet -h | |||
# get versions of .NET SDK, Host, .NET runtimes installed | |||
dotnet --info | |||
# list available templates (webapi, blazor) | |||
dotnet new | |||
# create a new Web API project | |||
dotnet new webapi -o [project-name] --no-https | |||
# create a solution file and folder | |||
dotnet new sln -o MySolution | |||
# add a project to the solution | |||
dotnet sln add ./MyProject/MyProject.csproj | |||
# add a reference to another project | |||
dotnet add reference ../otherproject/otherproject.csproj | |||
# restore and build | |||
dotnet build | |||
# restore, build and run | |||
dotnet run | |||
# force url and port (default: 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 | |||
</kode> | |||
= [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'> | |||
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"); | |||
} | |||
} | |||
</kode> | |||
<filebox fn='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 | |||
} | |||
} | |||
</filebox> | |||
== [https://docs.microsoft.com/en-us/aspnet/core/fundamentals/logging#built-in-logging-providers Built-in logging providers] == | |||
{| class="wikitable wtp wtmono1" | |||
|- | |||
| 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 />On Linux {{boxx|journal}} or {{boxx|/var/log/message}} or {{boxx|/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 === | |||
<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://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}} | |||
<filebox fn='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 | |||
</filebox> | |||
<filebox fn='config.json'> | |||
{ | |||
"Logging": { | |||
"PathFormat": "MyApplication-{Date}.log", | |||
"LogLevel": { | |||
"Default": "Error", | |||
"Microsoft": "Information" | |||
}, | |||
"FileSizeLimitBytes": 5242880, | |||
"RetainedFileCountLimit": 2, | |||
"Json": true | |||
} | |||
} | |||
</filebox> | |||
<filebox fn='MyApplication-20180501.log'> | |||
2018-05-01T14:45:26.9980829+02:00 0HLDFC5FFGHTQ:00000004 [INF] Info (859a4ace) | |||
</filebox> | |||
<filebox fn='MyApplication-20180501.log' lang=json> | |||
{ | |||
"@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" | |||
} | |||
</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 | |||
# lists the NuGet packages | |||
dotnet list package | |||
# lists packages that have newer versions available | |||
dotnet list package --outdated | |||
# 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> | |||
= [https://docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration Configuration] = | |||
Sources des settings par défaut dans l'ordre de lecture: | |||
# {{boxx|appsettings.json}} | |||
# {{boxx|appsettings.<EnvironmentName>.json}} | |||
# {{boxx|UserSecrets}} in {{boxx|Development}} environment | |||
# Environment variables | |||
# Command-line arguments | |||
{{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; | |||
} | |||
// 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; | |||
</filebox> | |||
== appsettings.json == | |||
<filebox fn='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": "****" | |||
} | |||
</filebox> | |||
=== [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'> | |||
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>(); | |||
} | |||
</filebox> | |||
== [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?] | |||
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> | |||
== [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] = | |||
L’environnement utilisé est contenu dans la variable environnement {{boxx|ASPNETCORE_ENVIRONMENT}} | |||
3 valeurs sont supportées par le framework: | |||
* Development | |||
* Staging | |||
* Production (valeur par défaut) | |||
<kode lang='bash'> | |||
# lancer le service avec l'environnement Development | |||
ASPNETCORE_ENVIRONMENT=Development dotnet run | |||
dotnet run --ASPNETCORE_ENVIRONMENT Development | |||
</kode> | |||
Configuration pour la ligne de commande: | |||
<filebox fn='Properties/launchSettings.json'> | |||
{ | |||
"profiles": { | |||
"my_project": { | |||
"commandName": "Project", | |||
"launchBrowser": true, | |||
"launchUrl": "api/values", | |||
"applicationUrl": "https://localhost:5001;http://localhost:5000", | |||
"environmentVariables": { | |||
"ASPNETCORE_ENVIRONMENT": "Development" | |||
} | |||
} | |||
} | |||
} | |||
</filebox> | |||
Configuration pour vs code: | |||
<filebox fn='.vscode/launch.json'> | |||
"configurations": [ | |||
{ | |||
"name": ".NET Core Launch (web)", | |||
"env": { | |||
"ASPNETCORE_ENVIRONMENT": "Development" | |||
} | |||
} | |||
] | |||
</filebox> | |||
Configuration pour vs:<br> | |||
VS → Projet Properties → Debug → Environment variables → ASPNETCORE_ENVIRONMENT = Development | |||
= Deployment Scripts = | |||
<filebox fn='MyProject.csproj' lang=xml> | |||
<Target Name="MyPublishScripts" AfterTargets="BeforePublish"> | |||
<Exec Command="npm install" /> | |||
<Exec Command="gulp minify" /> | |||
<Exec Command="ng build" /> | |||
</Target> | |||
</filebox> | |||
= [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'> | |||
# 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 | |||
</kode> | |||
* [https://docs.microsoft.com/en-us/dotnet/core/tools/dotnet-publish dotnet publish] | |||
<filebox fn='MyProject.csproj' lang=xml> | |||
<Project Sdk="Microsoft.NET.Sdk.Web"> | |||
<PropertyGroup> | |||
<RuntimeIdentifier>win10-x64</RuntimeIdentifier> | |||
<RuntimeIdentifier>win10-x64,ubuntu-x64,linux-x64</RuntimeIdentifier> | |||
</PropertyGroup> | |||
</filebox> | |||
{{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.}} | |||
[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}} | |||
== 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 == | |||
* [[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> | |||
[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 | |||
</filebox> | |||
<kode lang='bash'> | |||
# escape value as connection string | |||
systemd-escape "<value-to-escape>" | |||
</kode> | |||
= [https://edi.wang/post/2018/9/27/get-app-version-net-core Version] = | |||
<filebox fn='MyProject.csproj' lang='xml'> | |||
<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> | |||
</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> | |||
= Git = | |||
<filebox fn='.gitignore' lang='bash'> | |||
# Build results | |||
bin/ | |||
obj/ | |||
# .NET Core | |||
Properties/launchSettings.json | |||
# Log files | |||
*.log | |||
</filebox> | |||
= ARM = | |||
* [https://github.com/dotnet/core/blob/master/samples/RaspberryPiInstructions.md .NET Core on Raspberry Pi] | |||
* [https://archlinuxarm.org/forum/viewtopic.php?f=60&t=11990 Archlinux ARMv7] | |||
<kode lang='bash'> | |||
# 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 | |||
</kode> | |||
= 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 | |||
[[File:ASP.NET_Core.jpg|800px]] | |||
= [https://docs.microsoft.com/en-us/aspnet/core/migration/50-to-60?view=aspnetcore-6.0&tabs=visual-studio-code Migrate from ASP.NET Core 5.0 to 6.0] = | |||
== Update the target framework in every project file == | |||
<filebox fn='MyProject.csproj' lang='xml'> | |||
<PropertyGroup> | |||
<TargetFramework>net6.0</TargetFramework> | |||
</filebox> | |||
== Update package references == | |||
<filebox fn='Directory.Build.targets' lang='xml'> | |||
<Project> | |||
<ItemGroup> | |||
<PackageReference Update="Microsoft.AspNetCore.*" Version="6.0.1" /> | |||
<PackageReference Update="Microsoft.Extensions.*" Version="6.0.1" /> | |||
<PackageReference Update="Microsoft.EntityFrameworkCore*" Version="6.0.1" /> | |||
</filebox> | |||
== New hosting model == | |||
{{info | Apps migrating to 6.0 don't need to use the new minimal hosting model.<br> | |||
Using Startup and the Generic Host used by the ASP.NET Core 3.1 and 5.0 templates is fully supported.}} | |||
Remove {{boxx|Startup.cs}}. | |||
<filebox fn='Program.cs'> | |||
public static void Main(string[] args) | |||
{ | |||
var builder = WebApplication.CreateBuilder(args); | |||
// IServiceCollection services → builder.Services | |||
// IConfiguration Configuration → builder.Configuration | |||
var app = builder.Build(); | |||
// IWebHostEnvironment env → app.Environment | |||
// IConfiguration Configuration → app.Configuration | |||
using (var scope = app.Services.CreateScope()) | |||
{ | |||
var context = scope.ServiceProvider.GetRequiredService<MyDbContext>(); | |||
context.Database.Migrate(); | |||
} | |||
app.Run(); | |||
</filebox> | |||
== Update the debug launcher == | |||
<filebox fn='.vscode/launch.json'> | |||
"configurations": [ | |||
{ | |||
// If you have changed target frameworks, make sure to update the program path. | |||
"program": "${workspaceFolder}/MyProject/bin/Debug/net6.0/MyProject.dll", | |||
</filebox> | |||
== Update the settings == | |||
<filebox fn='appsettings.json'> | |||
"Logging": { | |||
"LogLevel": { | |||
// "Microsoft": "Warning", | |||
// "Microsoft.Hosting.Lifetime": "Information" | |||
"Microsoft.AspNetCore": "Warning" | |||
</filebox> | |||
= Installation = | |||
== [https://wiki.archlinux.org/index.php/.NET_Core Archlinux] == | |||
<kode lang='bash'> | |||
pacman -S aspnet-runtime dotnet-sdk | |||
# installe dotnet-host dotnet-runtime aspnet-runtime dotnet-sdk | |||
</kode> | |||
{{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] == | |||
* Visual Studio Installer → Workloads → ASP.NET and web development | |||
<kode lang='powershell'> | |||
# version de .net core installée | |||
dotnet --version | |||
</kode> | |||
== [[Ubuntu_arm_18.04#Installation|Ubuntu ARM]] == |
Dernière version du 6 juin 2023 à 09:40
Links
- What's new in ASP.NET Core 6.0
- Safe storage of app secrets
- Doc Microsoft
- Catégorie .NET Core
- .NET 6 Release Note
dotnet CLI
# help dotnet -h # get versions of .NET SDK, Host, .NET runtimes installed dotnet --info # list available templates (webapi, blazor) dotnet new # create a new Web API project dotnet new webapi -o [project-name] --no-https # create a solution file and folder dotnet new sln -o MySolution # add a project to the solution dotnet sln add ./MyProject/MyProject.csproj # add a reference to another project dotnet add reference ../otherproject/otherproject.csproj # restore and build dotnet build # restore, build and run dotnet run # force url and port (default: 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>(); }); |
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 |
|
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
# ajouter un package NuGet dotnet add package <package_name> dotnet add package <package_name> --version 2.0.0 # lists the NuGet packages dotnet list package # lists packages that have newer versions available dotnet list package --outdated # 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" /> |
Configuration
Sources des settings par défaut dans l'ordre de lecture:
- appsettings.json
- appsettings.<EnvironmentName>.json
- UserSecrets in Development environment
- Environment variables
- 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.
# 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(); |
Environment variables
Command-line
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)
# 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.
# 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 |
# escape value as connection string systemd-escape "<value-to-escape>" |
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> |
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 |
Git
.gitignore |
# Build results bin/ obj/ # .NET Core Properties/launchSettings.json # Log files *.log |
ARM
# 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
Migrate from ASP.NET Core 5.0 to 6.0
Update the target framework in every project file
MyProject.csproj |
<PropertyGroup> <TargetFramework>net6.0</TargetFramework> |
Update package references
Directory.Build.targets |
<Project> <ItemGroup> <PackageReference Update="Microsoft.AspNetCore.*" Version="6.0.1" /> <PackageReference Update="Microsoft.Extensions.*" Version="6.0.1" /> <PackageReference Update="Microsoft.EntityFrameworkCore*" Version="6.0.1" /> |
New hosting model
Apps migrating to 6.0 don't need to use the new minimal hosting model. Using Startup and the Generic Host used by the ASP.NET Core 3.1 and 5.0 templates is fully supported. |
Remove Startup.cs.
Program.cs |
public static void Main(string[] args) { var builder = WebApplication.CreateBuilder(args); // IServiceCollection services → builder.Services // IConfiguration Configuration → builder.Configuration var app = builder.Build(); // IWebHostEnvironment env → app.Environment // IConfiguration Configuration → app.Configuration using (var scope = app.Services.CreateScope()) { var context = scope.ServiceProvider.GetRequiredService<MyDbContext>(); context.Database.Migrate(); } app.Run(); |
Update the debug launcher
.vscode/launch.json |
"configurations": [ { // If you have changed target frameworks, make sure to update the program path. "program": "${workspaceFolder}/MyProject/bin/Debug/net6.0/MyProject.dll", |
Update the settings
appsettings.json |
"Logging": { "LogLevel": { // "Microsoft": "Warning", // "Microsoft.Hosting.Lifetime": "Information" "Microsoft.AspNetCore": "Warning" |
Installation
Archlinux
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
# version de .net core installée dotnet --version |