« Asp.net core 7 » : différence entre les versions
Ligne 263 : | Ligne 263 : | ||
= [https://learn.microsoft.com/en-us/dotnet/core/deploying/deploy-with-cli Publish] = | = [https://learn.microsoft.com/en-us/dotnet/core/deploying/deploy-with-cli Publish] = | ||
== [https://learn.microsoft.com/en-us/dotnet/core/deploying/deploy-with-cli#framework-dependent-executable Framework-dependent executable] == | |||
Creates a platform-specific executable with only your application binaries and its dependencies.<br> | |||
Host machine of the application have to have installed the corresponding .NET runtime. | |||
<kode lang='bash'> | <kode lang='bash'> | ||
dotnet publish -c Release -r linux-arm64 --self-contained false | dotnet publish -c Release -r linux-arm64 --self-contained false | ||
# -c : configuration : Debug (default), Release | # -c : configuration : Debug (default), Release | ||
# -r <RUNTIME_IDENTIFIER> : publishes the application for a given runtime | # -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) | # --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: | # -o /path/folder : output directory (default: bin/[configuration]/[framework]/[runtime]/publish ) | ||
</kode> | </kode> | ||
* [https://docs.microsoft.com/en-us/dotnet/core/tools/dotnet-publish dotnet publish] | * [https://docs.microsoft.com/en-us/dotnet/core/tools/dotnet-publish dotnet publish] | ||
[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|linux-arm64}}, {{boxx|linux-x64}}, {{boxx|win10-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|linux-arm64}}, {{boxx|linux-x64}}, {{boxx|win10-x64}} | ||
== [https://learn.microsoft.com/en-us/dotnet/core/deploying/deploy-with-cli#self-contained-deployment Self-contained deployment] == | |||
Creates a platform-specific executable with all the required .NET files to run your app but it doesn't include the native dependencies of .NET. These dependencies must be present on the system before the app runs.<br> | |||
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. | |||
<kode lang='bash'> | |||
dotnet publish -c Release -r linux-arm64 --self-contained true -p:PublishTrimmed=true | |||
# -c : configuration : Debug (default), Release | |||
# -r <RUNTIME_IDENTIFIER> : publishes the application for a given runtime | |||
# -o /path/folder : output directory (default: bin/[configuration]/[framework]/[runtime]/publish ) | |||
</kode> | |||
* [https://learn.microsoft.com/en-us/dotnet/core/deploying/trimming/trim-self-contained Trim self-contained deployments and executables] | |||
== Define the port on deployed application == | == Define the port on deployed application == |
Version du 26 juillet 2023 à 11:54
Links
- What's new in ASP.NET Core 7.0
- .NET Core Release Notes
- Safe storage of app secrets
- Doc Microsoft
- Catégorie .NET Core
- Blazor
- Web API
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 --name 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
|
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
Framework-dependent executable
Creates a platform-specific executable with only your application binaries and its dependencies.
Host machine of the application have to have installed the corresponding .NET runtime.
dotnet publish -c Release -r linux-arm64 --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]/[runtime]/publish )
|
RID Catalog (list): linux-arm64, linux-x64, win10-x64
Self-contained deployment
Creates a platform-specific executable with all the required .NET files to run your app but it doesn't include the native dependencies of .NET. These dependencies must be present on the system before the app runs.
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.
dotnet publish -c Release -r linux-arm64 --self-contained true -p:PublishTrimmed=true
# -c : configuration : Debug (default), Release
# -r <RUNTIME_IDENTIFIER> : publishes the application for a given runtime
# -o /path/folder : output directory (default: bin/[configuration]/[framework]/[runtime]/publish )
|
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
|
Nuget
# Display locals for all folders
dotnet nuget locals all --list
# http-cache: /home/[user]/.local/share/NuGet/http-cache
# global-packages: /home/[user]/.nuget/packages/
# temp: /tmp/NuGetScratch
# plugins-cache: /home/[user]/.local/share/NuGet/plugin-cache
# Clear all caches
dotnet nuget locals all --clear
# Clear the global packages folder
dotnet nuget locals global-packages --clear
|
Git
.gitignore |
# Build results
bin/
obj/
# .NET Core
Properties/launchSettings.json
# Log files
*.log
|
Log
![]() |
The Log methods are synchronous. There is no file log provider. |
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
Unit tests
# create the unit tests project for MyService
dotnet new xunit -o MyService.Tests
# add a reference to the project to test
cd MyService.Tests
dotnet add reference ../MyService/MyService.csproj
cd ..
# create a solution if you don't have one yet
dotnet new sln --name MySolution
# add the unit tests project to the solution
dotnet sln add ./MyService.Tests/MyService.Tests.csproj
# run the unit tests
dotnet test
|
Code analysis
Code quality analysis
Those rules are enabled by default.
Here is how to enabled additional rules:
MyProject.csproj |
<PropertyGroup>
<AnalysisLevel>latest-All</AnalysisLevel>
</PropertyGroup>
|
Code style analysis
# verify that all code is correctly formatted
dotnet format --verify-no-changes
# format all code
dotnet format
|
- Configuration files for code analysis rules
- An example of .editorconfig file with the default options
- Code-style rules IDExxxx
- Change encoding
.editorconfig |
Visual Studio Code integration
settings.json |
"omnisharp.enableRoslynAnalyzers": true,
"omnisharp.enableEditorConfigSupport": true,
|
Roslynator
- Install the Roslynator extension in Visual Studio Code
- Configure Roslynator on a user-wide basis
- vscode → Ctrl + Shift + P → enter roslynator → select Roslynator: Open Default Configuration File (.roslynatorconfig)
~/.local/share/JosefPihrt/Roslynator/.roslynatorconfig |
Roslynator CLI
# install
dotnet tool install -g roslynator.dotnet.cli
roslynator analyze \
--analyzer-assemblies \
~/.vscode/extensions/josefpihrt-vscode.roslynator-4.3.0/roslyn/common \
~/.vscode/extensions/josefpihrt-vscode.roslynator-4.3.0/roslyn/analyzers
|
![]() |
To fix the error: Could not load file or assembly 'System.Composition.AttributedModel, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'.
|
Code coverage
# add the XunitXML.TestLogger nuget package to the unit test project
dotnet add package XunitXML.TestLogger
# run unit tests with Coverlet data collector and log the results
dotnet test MySolution.sln --collect="XPlat Code Coverage" --logger:"xunit;LogFilePath=TestResults.xml"
# creates a TestResults.xml report and a TestResults/[guid]/coverage.cobertura.xml report
# extract the line coverage:
xmllint --xpath "string(/coverage/@line-rate)" TestResults/[guid]/coverage.cobertura.xml
sed -n -r 's/<coverage line-rate="([0-9.]+)".*/\1/p' TestResults/[guid]/coverage.cobertura.xml
# install the ReportGenerator tool
dotnet tool install -g dotnet-reportgenerator-globaltool
# get a text summary report from all the cobertura reports
reportgenerator -reports:"*/TestResults/*/coverage.cobertura.xml" -targetdir:CoverageReport -reporttypes:TextSummary
# creates CoverageReport/TextSummary.txt
# extract the line coverage:
sed -n -r 's/Line coverage: ([0-9.]+)%/\1/p' CoverageReport/Summary.txt
|
Ignore generated code
Create an .editorconfig file in a folder to not run code analysis on the files of this folder.
MyWebapi/DataAccess/.editorconfig |
[*]
generated_code = true
dotnet_analyzer_diagnostic.severity = silent
|
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
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
|