Links
dotnet CLI
|
dotnet -h
dotnet --info
dotnet new
dotnet new webapi -o [project-name] --no-https
dotnet new sln -o MySolution
dotnet sln add ./MyProject/MyProject.csproj
dotnet add reference ../otherproject/otherproject.csproj
dotnet build
dotnet run
ASPNETCORE_URLS="http://127.0.0.1:5123" dotnet run
dotnet run --ASPNETCORE_ENVIRONMENT Development
$env:ASPNETCORE_URLS="http://127.0.0.1:5123" ; dotnet run
dotnet test
|
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();
})
.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",
"Microsoft": "Warning",
"MyClass": "Debug"
}
}
|
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
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);
|
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"
}
|
 |
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
|
dotnet add package <package_name>
dotnet add package <package_name> --version 2.0.0
dotnet list package
dotnet list package --outdated
dotnet remove package <package_name>
|
Allows you to manage the versions of Nuget packages in a single centralized file.
Directory.Build.targets
|
<Project>
<ItemGroup>
<PackageReference Update="AutoMapper" Version="10.1.1" />
|
MyProject/MyProject.csproj
|
<Project Sdk="Microsoft.NET.Sdk.Web">
<ItemGroup>
<PackageReference Include="AutoMapper" />
|
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;
public IConfiguration Configuration { get; }
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
var value = Configuration.GetValue<string>("Key", "default value");
var value = Configuration["Key"];
Configuration.GetConnectionString("SqlServer1")
// dotnet add package System.Data.SqlClient
var builder = new SqlConnectionStringBuilder(Configuration.GetConnectionString("SqlServer4"));
builder.Password = Configuration["DbPassword"];
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": "****"
}
|
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>();
}
|
Useful in dev environment to not store password in source code.
|
cd MyProject
dotnet user-secrets init
dotnet user-secrets set "key" "secret"
dotnet user-secrets set "ConnectionStrings:SqlServer" "server=localhost;database=test;user=test;password=****"
dotnet user-secrets set "DbPassword" "****"
dotnet user-secrets list
dotnet user-secrets remove "key"
dotnet user-secrets clear
|
WebApi/Program.cs
|
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();
builder.AddUserSecrets<Program>();
Configuration = builder.Build();
|
|
dotnet MyApp MyKey="value"
|
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)
|
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>
|
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.
|
dotnet publish -c Release -r linux-arm --self-contained false
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
/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
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
|
|
systemd-escape "<value-to-escape>"
|
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;
Assembly.GetEntryAssembly().GetName().Version;
Assembly.GetEntryAssembly().GetCustomAttribute<AssemblyFileVersionAttribute>().Version;
Assembly.GetEntryAssembly().GetCustomAttribute<AssemblyInformationalVersionAttribute>().InformationalVersion;
|
Git
.gitignore
|
bin/
obj/
Properties/launchSettings.json
*.log
|
ARM
|
dotnet publish -r linux-arm
cd linux-arm/publish
./MyApp
|
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
Erreur lors de la création de la vignette : /bin/bash: /usr/bin/convert: No such file or directory Error code: 127
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);
var app = builder.Build();
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": [
{
"program": "${workspaceFolder}/MyProject/bin/Debug/net6.0/MyProject.dll",
|
Update the settings
appsettings.json
|
"Logging": {
"LogLevel": {
"Microsoft.AspNetCore": "Warning"
|
Installation
|
pacman -S 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
|
DOTNET_CLI_TELEMETRY_OPTOUT=1
|
- Visual Studio Installer → Workloads → ASP.NET and web development
|
dotnet --version
|