|
|
(23 versions intermédiaires par le même utilisateur non affichées) |
Ligne 1 : |
Ligne 1 : |
| [[Category:.NET Core]] | | [[Category:ASP.NET]] |
| = Links = | | = Links = |
| * [https://learn.microsoft.com/en-us/aspnet/core/release-notes/aspnetcore-8.0?view=aspnetcore-8.0 What's new in ASP.NET Core 8.0] | | * [https://learn.microsoft.com/en-us/aspnet/core/release-notes/aspnetcore-9.0?view=aspnetcore-9.0 What's new in ASP.NET Core 9.0] |
| * [https://github.com/dotnet/core/blob/main/release-notes/8.0/README.md .NET 8 Releases] | | * [https://github.com/dotnet/core/blob/main/release-notes/9.0/README.md .NET 9 Releases] |
| * [https://learn.microsoft.com/en-us/aspnet/core/?view=aspnetcore-8.0 ASP.NET documentation]
| |
| * [https://learn.microsoft.com/en-us/aspnet/core/mvc/controllers/filters?view=aspnetcore-8.0 Filters]
| |
| * [https://learn.microsoft.com/en-us/aspnet/core/fundamentals/owin?view=aspnetcore-8.0 OWIN and Katana]
| |
| * [[:Catégorie:.NET_Core|Catégorie .NET Core]]
| |
|
| |
|
| = dotnet CLI = | | = Changes = |
| <kode lang='bash'>
| | * [[Swashbuckle]] is no longer actively maintained and has been remove from .NET 9 templates. [[Asp.net_core_9_web_api#OpenAPI_/_Swagger|OpenAPI in ASP.NET Core 9 Web API]] |
| # 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 with the release configuration
| |
| dotnet build --configuration Release
| |
| # 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>
| |
| | |
| == 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://learn.microsoft.com/en-us/aspnet/core/fundamentals/configuration/?view=aspnetcore-8.0 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>
| |
| | |
| == [https://learn.microsoft.com/en-us/aspnet/core/fundamentals/configuration/?view=aspnetcore-8.0#appsettingsjson 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://learn.microsoft.com/en-us/aspnet/core/fundamentals/configuration/?view=aspnetcore-8.0#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://learn.microsoft.com/en-us/aspnet/core/security/app-secrets?view=aspnetcore-8.0&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
| | = [https://learn.microsoft.com/en-us/aspnet/core/fundamentals/logging/?view=aspnetcore-9.0 Log] = |
| 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://learn.microsoft.com/en-us/aspnet/core/fundamentals/configuration/?view=aspnetcore-8.0#non-prefixed-environment-variables Non-prefixed environment variables] ==
| |
| <filebox fn='/etc/systemd/system/kestrel-myapp.service' lang='ini'>
| |
| Environment=ConnectionStrings__MyApp=server\x3dlocalhost\x3bdatabase\x3dMyDb\x3buser\x3dMyUser\x3bpassword\x3dMyPwd
| |
| Environment=SqlServerVersion=10.10.5-MariaDB
| |
| </filebox>
| |
| | |
| == [https://learn.microsoft.com/en-us/aspnet/core/fundamentals/configuration/?view=aspnetcore-8.0#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://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 the application binaries and its dependencies.
| |
| {{ListPlusMinus|type=plus|list=
| |
| * lighter deployment: only the application binaries and its dependencies are deployed
| |
| * the .NET runtime security updates are managed by the system
| |
| }}
| |
| {{ListPlusMinus|type=minus|list=
| |
| * the required .NET runtime of the application has to match the installed .NET runtime
| |
| }}
| |
| <kode lang='bash'>
| |
| 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 )
| |
| </kode>
| |
| * [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://learn.microsoft.com/en-us/dotnet/core/deploying/deploy-with-cli#self-contained-deployment Self-contained deployment] ==
| |
| Creates a platform-specific executable with the application binaries, its dependencies and the required .NET runtime.
| |
| {{ListPlusMinus|type=plus|list=
| |
| * runs on hosts which doesn't have the .NET runtime installed
| |
| }}
| |
| {{ListPlusMinus|type=minus|list=
| |
| * bigger deployment
| |
| * doesn't follow the .NET security updates
| |
| }}
| |
| <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]
| |
| | |
| === [https://github.com/dotnet/aspnetcore/issues/40033 Bug MissingMethodException occured when deploying Blazor Server app with 'Trim Unused code'] ===
| |
| <pre>
| |
| System.MissingMethodException: Cannot dynamically create an instance of type 'Microsoft.AspNetCore.Components.Web.HeadOutlet'.
| |
| Reason: No parameterless constructor defined.
| |
| </pre>
| |
| <filebox fn='App.razor'>
| |
| @using System.Diagnostics.CodeAnalysis;
| |
| | |
| @code {
| |
| [DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(HeadOutlet))] // Prevent HeadOutlet from being trimmed
| |
| protected override void OnInitialized() { }
| |
| }
| |
| </filebox>
| |
| | |
| == Linux ==
| |
| * [[Nginx#.Net_Core|Configurer Nginx pour .Net Core]]
| |
| * [[Apache_et_ubuntu#Dotnet_core|Configurer Apache pour .Net Core]]
| |
| | |
| === [https://learn.microsoft.com/en-us/aspnet/core/host-and-deploy/linux-apache?view=aspnetcore-8.0#create-the-service-file Service file] ===
| |
| <filebox fn='/etc/systemd/system/kestrel-myproject.service' lang=ini>
| |
| [Unit]
| |
| Description=My Project description
| |
| | |
| [Service]
| |
| WorkingDirectory=/var/www/myproject
| |
| ExecStart=/var/www/myproject/MyProject
| |
| Restart=always
| |
| RestartSec=10 # Restart service after 10 seconds if dotnet service crashes
| |
| KillSignal=SIGINT
| |
| SyslogIdentifier=myproject
| |
| User=http
| |
| Environment=DOTNET_ROOT=/usr/share/dotnet8.0.4 ; to force a specific version of dotnet
| |
| 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
| |
| Environment=SqlServerVersion=10.10.5-MariaDB
| |
| Environment=MyWebapiUrl=http://localhost:5002
| |
| | |
| [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>
| |
| | |
| = Nuget =
| |
| <kode lang='bash'>
| |
| # 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
| |
| | |
| # add a NuGet package
| |
| dotnet add package <package_name>
| |
| dotnet add package <package_name> --version 2.0.0
| |
| | |
| # list the NuGet packages
| |
| dotnet list package
| |
| | |
| # remove a NuGet 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>
| |
| | |
| = Git =
| |
| <filebox fn='.gitignore' lang='bash'>
| |
| # Build folders
| |
| bin/
| |
| obj/
| |
| | |
| # Visual Studio local state folder
| |
| .vs/
| |
| </filebox>
| |
| | |
| = [https://learn.microsoft.com/en-us/aspnet/core/fundamentals/logging/?view=aspnetcore-8.0 Log] =
| |
| {{info | By default, an app is logging into {{boxx|Console}}, {{boxx|Debug}}, {{boxx|EventSource}}, {{boxx|EventLog}} (only when running on Windows).<br> | | {{info | By default, an app is logging into {{boxx|Console}}, {{boxx|Debug}}, {{boxx|EventSource}}, {{boxx|EventLog}} (only when running on Windows).<br> |
| This include the linux journal for production and the VS code DEBUG CONSOLE for development.}} | | This include the linux journal for production and the VS code DEBUG CONSOLE for development.}} |
Ligne 458 : |
Ligne 44 : |
| {{warn | 1=The Log methods are [https://learn.microsoft.com/en-us/aspnet/core/fundamentals/logging/?view=aspnetcore-7.0#no-asynchronous-logger-methods synchronous].<br> | | {{warn | 1=The Log methods are [https://learn.microsoft.com/en-us/aspnet/core/fundamentals/logging/?view=aspnetcore-7.0#no-asynchronous-logger-methods synchronous].<br> |
| There is no file log provider.}} | | There is no file log provider.}} |
| | |
| | == [https://learn.microsoft.com/en-us/aspnet/core/fundamentals/logging/?view=aspnetcore-9.0#log-in-programcs Log in Program.cs] == |
| | <filebox fn='Program.cs'> |
| | app.Logger.LogInformation("message"); |
| | </filebox> |
|
| |
|
| == [https://docs.microsoft.com/en-us/aspnet/core/fundamentals/logging#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] == |
Ligne 509 : |
Ligne 100 : |
| * {{boxx|error.log}} is never filled | | * {{boxx|error.log}} is never filled |
|
| |
|
| = [[Tests_unitaires#NUnit|Unit tests]] = | | == [https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca1848 LoggerMessage] == |
| <kode lang='bash'> | | Use LoggerMessage over Logger extension methods to improve performances. |
| # create the unit tests project for MyService
| | <kode lang='cs'> |
| dotnet new xunit -o MyService.Tests
| | logger.LogInformation("Message: {Message}", message); |
| # 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
| | static partial class Log |
| dotnet new sln --name MySolution
| | { |
| | | [LoggerMessage(Level = LogLevel.Information, Message = "Message: {Message}")] |
| # add the unit tests project to the solution
| | public static partial void LogRequest(ILogger logger, string Message); |
| dotnet sln add ./MyService.Tests/MyService.Tests.csproj
| | } |
|
| |
|
| # run all the unit tests
| | Log.LogRequest(logger, message); |
| dotnet test
| |
| # run the unit tests of a specific namespace / class
| |
| dotnet test --filter Namespace.Class
| |
| </kode> | | </kode> |
|
| |
|
| = [https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/overview?tabs=net-8 Code analysis] = | | = [https://learn.microsoft.com/en-us/aspnet/core/fundamentals/configuration/?view=aspnetcore-9.0 Configuration] = |
| * [https://editorconfig.org/ editorconfig]
| | Sources des settings par défaut dans l'ordre de lecture: |
| | # {{boxx|appsettings.json}} |
| | # {{boxx|appsettings.<EnvironmentName>.json}} (Development, Staging, Production) |
| | # {{boxx|UserSecrets}} in {{boxx|Development}} environment |
| | # Environment variables |
| | # Command-line arguments |
| | {{info | Les settings de la source suivante écrasent ceux déjà chargés.}} |
|
| |
|
| == Code quality analysis ==
| | <filebox fn='ItemsController.cs'> |
| Those [https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/overview?tabs=net-7#enabled-rules rules] are enabled by default.<br>
| | public class ItemsController(IConfiguration configuration) : ControllerBase |
| Here is how to enabled [https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/overview?tabs=net-7#enable-additional-rules additional rules]:
| | { |
| <filebox fn='MyProject.csproj' lang='xml'> | | [HttpGet] |
| <PropertyGroup>
| | public IActionResult Get() |
| <!-- ... -->
| | { |
| <AnalysisLevel>latest-recommended</AnalysisLevel>
| | // recherche Key, si Key n'a pas été trouvé affecte default value à la variable value |
| </PropertyGroup> | | var value = Configuration.GetValue<string>("Key", "default value"); |
| </filebox>
| | var value = Configuration["Key"]; |
|
| |
|
| * [https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ Code quality rules CAxxxx]
| | // pour les connection strings |
| | configuration.GetConnectionString("SqlServer1") |
|
| |
|
| {{info | Prefer the use of {{boxx|editorconfig}} to {{boxx|globalconfig}}}}
| | // dotnet add package System.Data.SqlClient |
| <filebox fn='.globalconfig' lang='ini' collapsed>
| | var builder = new SqlConnectionStringBuilder(Configuration.GetConnectionString("SqlServer4")); // from appsettings.json |
| # Top level entry required to mark this as a global AnalyzerConfig file
| | builder.Password = configuration["DbPassword"]; // from secrets storage in Dev and appsettings.json in Prod |
| is_global = true
| | var connectionString = builder.ConnectionString; |
| | |
| # NOTE: No section headers for configuration entries
| |
| | |
| #### .NET Coding Conventions ####
| |
| | |
| # this. and Me. preferences
| |
| dotnet_style_qualification_for_method = true:warning
| |
| | |
| #### Diagnostic configuration ####
| |
| | |
| # CA2007: Do not directly await a Task
| |
| dotnet_diagnostic.CA2007.severity = none
| |
| </filebox> | | </filebox> |
|
| |
|
| == Code style analysis == | | == [https://learn.microsoft.com/en-us/aspnet/core/fundamentals/configuration/?view=aspnetcore-9.0#appsettingsjson appsettings.json] == |
| <kode lang='bash'>
| | <filebox fn='appsettings.json'> |
| # verify that all code is correctly formatted
| | { |
| dotnet format --verify-no-changes
| | "Key": "Value", |
| | | "ConnectionStrings": { |
| # format all code
| | "SqlServer1": "Server=(localdb)\\MSSQLLocalDB;Database=MyDb;Integrated Security=True;MultipleActiveResultSets=True", |
| dotnet format
| | "SqlServer2": "Server=(localdb)\\mssqllocaldb;Database=MyDb;Trusted_Connection=True;", |
| </kode>
| | "SqlServer3": "Server=localhost;Database=MyDb;User=sa;Password=pwd;", |
| | | "SqlServer4": "server=localhost;database=MyDb;user=sa;", |
| * [https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/configuration-files#global-analyzerconfig Configuration files for code analysis rules]
| | "MySql": "Server=localhost;Database=MyDb;User=root;Password=pwd;", |
| * [https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/code-style-rule-options#example-editorconfig-file An example of .editorconfig file with the default options]
| | "Sqlite": "Data Source=MyDb.db" |
| * [https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules Code-style rules IDExxxx]
| | }, |
| * [[Encodage_de_caractères#Convertion|Change encoding]]
| | "DbPassword": "****" |
| | | } |
| <filebox fn='.editorconfig' lang='ini' collapsed> | |
| ###############################
| |
| # Core EditorConfig Options #
| |
| ###############################
| |
| root = true
| |
| | |
| # All files
| |
| [*]
| |
| indent_style = space
| |
| insert_final_newline = true
| |
| charset = utf-8
| |
| | |
| # XML project files
| |
| [*.csproj]
| |
| indent_size = 2
| |
| | |
| # JSON config files
| |
| [*.json]
| |
| indent_size = 2
| |
| | |
| # C# code files
| |
| [*.cs]
| |
| indent_size = 4
| |
| trim_trailing_whitespace = true
| |
| | |
| ###############################
| |
| # Analyzer configuration #
| |
| ###############################
| |
| | |
| # set the rules severity to warning
| |
| dotnet_analyzer_diagnostic.severity = warning
| |
| # speller
| |
| dotnet_diagnostic.VSSpell001.severity = suggestion
| |
| dotnet_diagnostic.VSSpell002.severity = suggestion
| |
| | |
| ###############################
| |
| # .NET Coding Conventions #
| |
| ###############################
| |
| [*.cs]
| |
| # Organize usings
| |
| dotnet_sort_system_directives_first = true
| |
| | |
| ###############################
| |
| # Code Quality configuration #
| |
| ###############################
| |
| # CA1826: Use property instead of Linq Enumerable method
| |
| # Exclude FirstOrDefault and LastOrDefault methods
| |
| dotnet_code_quality.CA1826.exclude_ordefault_methods = true
| |
| | |
| ###############################
| |
| # Style configuration #
| |
| ###############################
| |
| # IDE0003 / IDE0009: this and Me preferences
| |
| dotnet_style_qualification_for_field = true
| |
| | |
| # IDE0007 / IDE0008: 'var' preferences
| |
| csharp_style_var_for_built_in_types = true
| |
| csharp_style_var_when_type_is_apparent = true
| |
| csharp_style_var_elsewhere = true : silent
| |
| | |
| # IDE0011: Add braces
| |
| csharp_prefer_braces = when_multiline
| |
| | |
| # IDE0022: Use expression body for methods
| |
| csharp_style_expression_bodied_methods = when_on_single_line
| |
| | |
| # IDE0160 / IDE0161: Namespace declaration preferences
| |
| csharp_style_namespace_declarations = file_scoped : error
| |
| | |
| ###############################
| |
| # Disabled rules #
| |
| ###############################
| |
| # IDE0046: Use conditional expression for return
| |
| dotnet_diagnostic.IDE0046.severity = suggestion
| |
| | |
| # IDE0058: Remove unnecessary expression value
| |
| dotnet_diagnostic.IDE0058.severity = none
| |
| | |
| # CA1305: Specify IFormatProvider
| |
| dotnet_diagnostic.CA1305.severity = none
| |
| | |
| # CA1310: Specify StringComparison for correctness
| |
| dotnet_diagnostic.CA1310.severity = none
| |
| | |
| # Specify CultureInfo
| |
| dotnet_diagnostic.CA1304.severity = suggestion
| |
| # Specify a culture
| |
| dotnet_diagnostic.CA1311.severity = suggestion
| |
| | |
| ###############################
| |
| # Naming Conventions #
| |
| ###############################
| |
| # Style Definitions
| |
| dotnet_naming_style.upper_case_style.capitalization = all_upper
| |
| dotnet_naming_style.camel_case_style.capitalization = camel_case
| |
| | |
| # Use UpperCase for constant fields
| |
| dotnet_naming_symbols.constant_fields.applicable_kinds = field
| |
| dotnet_naming_symbols.constant_fields.required_modifiers = const
| |
| dotnet_naming_rule.constant_fields_should_be_upper_case.symbols = constant_fields
| |
| dotnet_naming_rule.constant_fields_should_be_upper_case.style = upper_case_style
| |
| dotnet_naming_rule.constant_fields_should_be_upper_case.severity = warning
| |
| | |
| # Use camelCase for variables
| |
| dotnet_naming_symbols.local_symbol.applicable_kinds = local
| |
| dotnet_naming_rule.variables_should_be_camel_case.symbols = local_symbol
| |
| dotnet_naming_rule.variables_should_be_camel_case.style = camel_case_style
| |
| dotnet_naming_rule.variables_should_be_camel_case.severity = warning
| |
| | |
| # Use camelCase for parameters
| |
| dotnet_naming_symbols.parameter_symbol.applicable_kinds = parameter
| |
| dotnet_naming_rule.parameters_should_be_camel_case.symbols = parameter_symbol
| |
| dotnet_naming_rule.parameters_should_be_camel_case.style = camel_case_style
| |
| dotnet_naming_rule.parameters_should_be_camel_case.severity = warning
| |
| | |
| # Async methods should have "Async" suffix
| |
| dotnet_naming_rule.async_methods_end_in_async.symbols = any_async_methods
| |
| dotnet_naming_rule.async_methods_end_in_async.style = end_in_async
| |
| dotnet_naming_rule.async_methods_end_in_async.severity = suggestion
| |
| dotnet_naming_symbols.any_async_methods.applicable_kinds = method
| |
| dotnet_naming_symbols.any_async_methods.applicable_accessibilities = *
| |
| dotnet_naming_symbols.any_async_methods.required_modifiers = async
| |
| dotnet_naming_style.end_in_async.required_prefix =
| |
| dotnet_naming_style.end_in_async.required_suffix = Async
| |
| dotnet_naming_style.end_in_async.capitalization = pascal_case
| |
| dotnet_naming_style.end_in_async.word_separator =
| |
| </filebox> | | </filebox> |
|
| |
|
| == Visual Studio Code integration == | | == [https://learn.microsoft.com/en-us/aspnet/core/security/app-secrets?view=aspnetcore-9.0 Safe storage of app secrets in development in ASP.NET Core] == |
| <filebox fn='settings.json'>
| | * [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?] |
| "omnisharp.enableRoslynAnalyzers": true,
| | Useful in dev environment to not store password in source code. |
| "omnisharp.enableEditorConfigSupport": true,
| |
| </filebox>
| |
|
| |
|
| == Visual Studio == | | <kode lang='bash'> |
| === [https://learn.microsoft.com/en-us/visualstudio/code-quality/configure-live-code-analysis-scope-managed-code?view=vs-2022#custom-analysis-scope Set the scope of live code analysis] ===
| | # aller dans le dossier contenant le *.csproj |
| # Tools → Options
| | cd MyProject |
| # Text Editor → C# → Advanced
| |
| ## Run background code analysis for: Current document
| |
| ## Show compiler errors and warnings for: Open documents
| |
|
| |
|
| == [https://github.com/josefpihrt/roslynator Roslynator] ==
| | # adds a UserSecretsId element within a PropertyGroup of the .csproj file |
| # Install the Roslynator extension in Visual Studio or Visual Studio Code | | dotnet user-secrets init |
| # Configure Roslynator on a user-wide basis
| |
| ## vscode → Ctrl + Shift + P → enter roslynator → select Roslynator: Open Default Configuration File (.roslynatorconfig)
| |
| * [https://github.com/JosefPihrt/Roslynator/tree/main/docs/analyzers Analyzers RCSxxxx]
| |
|
| |
|
| <filebox fn='~/.local/share/JosefPihrt/Roslynator/.roslynatorconfig' lang='ini' collapsed>
| | # set a secret |
| is_global = true
| | # 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" "****" |
|
| |
|
| # enable all analyzers by default and set the severity to warning | | # the secrets are stored in a JSON configuration file in a system-protected user profile folder on the local machine |
| roslynator_analyzers.enabled_by_default = true
| | # Windows: %APPDATA%\microsoft\UserSecrets\<userSecretsId>\secrets.json |
| dotnet_analyzer_diagnostic.category-roslynator.severity = warning
| | # Linux: ~/.microsoft/usersecrets/<userSecretsId>/secrets.json |
|
| |
|
| # enable all refactorings
| |
| roslynator_refactorings.enabled = true
| |
|
| |
|
| # enable all compiler diagnostic fixes | | # list all secrets of the current project |
| roslynator_compiler_diagnostic_fixes.enabled = true
| | dotnet user-secrets list |
|
| |
|
| # Options | | # remove a secret in the current project |
| roslynator_accessibility_modifiers = explicit
| | dotnet user-secrets remove "key" |
| roslynator_accessor_braces_style = single_line_when_expression_is_on_single_line
| |
| roslynator_array_creation_type_style = implicit_when_type_is_obvious
| |
| roslynator_arrow_token_new_line = before
| |
| roslynator_binary_operator_new_line = before
| |
| roslynator_blank_line_after_file_scoped_namespace_declaration = true
| |
| roslynator_blank_line_between_closing_brace_and_switch_section = false
| |
| roslynator_blank_line_between_single_line_accessors = false
| |
| roslynator_blank_line_between_using_directives = never
| |
| roslynator_block_braces_style = single_line_when_empty
| |
| #roslynator_body_style = block|expression
| |
| roslynator_conditional_operator_condition_parentheses_style = omit
| |
| roslynator_conditional_operator_new_line = beforeroslynator_configure_await = false
| |
| roslynator_doc_comment_summary_style = multi_line
| |
| roslynator_empty_string_style = field
| |
| roslynator_enum_flag_value_style = decimal_number
| |
| roslynator_enum_has_flag_style = method
| |
| roslynator_equals_token_new_line = before
| |
| roslynator_infinite_loop_style = while
| |
| roslynator_max_line_length = 140
| |
| roslynator_new_line_at_end_of_file = false
| |
| roslynator_new_line_before_while_in_do_statement = false
| |
| roslynator_null_conditional_operator_new_line = before
| |
| roslynator_null_check_style = pattern_matching
| |
| roslynator_object_creation_parentheses_style = omit
| |
| roslynator_object_creation_type_style = implicit_when_type_is_obvious
| |
| roslynator_prefix_field_identifier_with_underscore = false
| |
| roslynator_suppress_unity_script_methods = true
| |
| roslynator_use_anonymous_function_or_method_group = method_group
| |
| roslynator_use_block_body_when_declaration_spans_over_multiple_lines = true
| |
| roslynator_use_block_body_when_expression_spans_over_multiple_lines = true
| |
| roslynator_use_var_instead_of_implicit_object_creation = true
| |
|
| |
|
| # Analyzers | | # remove all secrets of the current project |
| # Add blank line between single-line declarations
| | dotnet user-secrets clear |
| dotnet_diagnostic.rcs0012.severity = none
| |
| # Remove braces from if-else
| |
| dotnet_diagnostic.rcs1004.severity = none
| |
| # Use explicit type instead of 'var' (when the type is not obvious)
| |
| dotnet_diagnostic.rcs1008.severity = none
| |
| # Use explicit type instead of 'var' (foreach variable)
| |
| dotnet_diagnostic.rcs1009.severity = none
| |
| # Use explicit type instead of 'var' (when the type is obvious)
| |
| dotnet_diagnostic.rcs1012.severity = none
| |
| # Avoid unnecessary boxing of value type
| |
| dotnet_diagnostic.rcs1198.severity = none
| |
| # Mark publicly visible type with DebuggerDisplay attribute
| |
| dotnet_diagnostic.rcs1223.severity = none
| |
| </filebox>
| |
| | |
| === [https://github.com/JosefPihrt/Roslynator/blob/main/docs/cli/README.md Roslynator CLI] ===
| |
| <kode lang='bash'>
| |
| # 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
| |
| </kode> | | </kode> |
| {{info | 1=To fix the error:<br>
| |
| Could not load file or assembly 'System.Composition.AttributedModel, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'.<br>
| |
| The system cannot find the file specified.<br>
| |
| <kode lang='bash'>
| |
| cd ~/.dotnet/tools/.store/roslynator.dotnet.cli/0.6.0/roslynator.dotnet.cli/0.6.0/tools/net7.0/any/
| |
| # backup the provided System.Composition.AttributedModel.dll which is in version 6.0
| |
| mv System.Composition.AttributedModel.dll System.Composition.AttributedModel-6.0.dll
| |
| # replace it by its version 7.0
| |
| cp /usr/share/dotnet/sdk/7.0.105/DotnetTools/dotnet-format/System.Composition.AttributedModel.dll .
| |
| </kode>
| |
| }}
| |
|
| |
|
| == Code coverage ==
| | {{info | The user secrets configuration source is automatically added in development mode for Web API project when {{boxx|WebApplication.CreateBuilder(args)}} is called.<br> |
| * [https://reportgenerator.io/ ReportGenerator]
| | {{boxx|CreateBuilder}} calls {{boxx|AddUserSecrets}} when the {{boxx|EnvironmentName}} is {{boxx|Development}}}} |
| <kode lang='bash'> | |
| # 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:
| | <filebox fn='Console/Program.cs'> |
| xmllint --xpath "string(/coverage/@line-rate)" TestResults/[guid]/coverage.cobertura.xml
| | public static IConfigurationRoot Configuration { get; set; } |
| sed -n -r 's/<coverage line-rate="([0-9.]+)".*/\1/p' TestResults/[guid]/coverage.cobertura.xml
| |
|
| |
|
| # install the ReportGenerator tool
| | private static void Main() |
| dotnet tool install -g dotnet-reportgenerator-globaltool
| | { |
| # get a text summary report from all the cobertura reports
| | var builder = new ConfigurationBuilder(); |
| reportgenerator -reports:"*/TestResults/*/coverage.cobertura.xml" -targetdir:CoverageReport -reporttypes:TextSummary
| | // dotnet add package Microsoft.Extensions.Configuration.UserSecrets |
| # creates CoverageReport/TextSummary.txt
| | builder.AddUserSecrets<Program>(); |
| # extract the line coverage:
| | Configuration = builder.Build(); |
| sed -n -r 's/Line coverage: ([0-9.]+)%/\1/p' CoverageReport/Summary.txt
| |
| </kode> | |
| | |
| == Ignore generated code ==
| |
| Create an {{boxx|.editorconfig}} file in a folder to not run code analysis on the files of this folder.
| |
| <filebox fn='MyWebapi/DataAccess/.editorconfig' lang='ini'>
| |
| [*]
| |
| generated_code = true
| |
| dotnet_analyzer_diagnostic.severity = silent
| |
| </filebox> | | </filebox> |
|
| |
|
| = ARM = | | == [https://learn.microsoft.com/en-us/aspnet/core/fundamentals/configuration/?view=aspnetcore-9.0#non-prefixed-environment-variables Non-prefixed environment variables] == |
| * [https://github.com/dotnet/core/blob/master/samples/RaspberryPiInstructions.md .NET Core on Raspberry Pi]
| | <filebox fn='/etc/systemd/system/kestrel-myapp.service' lang='ini'> |
| * [https://archlinuxarm.org/forum/viewtopic.php?f=60&t=11990 Archlinux ARMv7]
| | Environment=ConnectionStrings__MyApp=server\x3dlocalhost\x3bdatabase\x3dMyDb\x3buser\x3dMyUser\x3bpassword\x3dMyPwd |
| <kode lang='bash'>
| | Environment=SqlServerVersion=10.10.5-MariaDB |
| # 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://learn.microsoft.com/en-us/aspnet/core/migration/70-80?view=aspnetcore-8.0&tabs=visual-studio Migrate from ASP.NET Core 7.0 to 8.0] = | |
| <filebox fn='MyProject.csproj' lang='xml'> | |
| <!-- <TargetFramework>net7.0</TargetFramework> -->
| |
| <TargetFramework>net8.0</TargetFramework>
| |
| </filebox>
| |
| | |
| Update the following nuget packages to 8.0 {{boxx|Microsoft.AspNetCore.*}} {{boxx|Microsoft.EntityFrameworkCore.*}} {{boxx|Microsoft.Extensions.*}} {{boxx|System.Net.Http.Json}}.
| |
| | |
| {{warn | 1=Check your data provider (ex: [https://github.com/PomeloFoundation/Pomelo.EntityFrameworkCore.MySql?tab=readme-ov-file#dependencies Pomelo]) has released a version which handles .NET 8}}
| |
| | |
| = Installation =
| |
| == [https://wiki.archlinux.org/index.php/.NET_Core Archlinux] == | |
| <kode lang='bash'>
| |
| pacman -S aspnet-runtime dotnet-sdk
| |
| # install 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> | | </filebox> |
|
| |
|
| == [https://www.microsoft.com/net/core#windowscmd Windows] == | | == [https://learn.microsoft.com/en-us/aspnet/core/fundamentals/configuration/?view=aspnetcore-9.0#command-line Command-line] == |
| * Visual Studio Installer → Workloads → ASP.NET and web development
| |
| <kode lang='powershell'>
| |
| # version de .net core installée | |
| dotnet --version
| |
| </kode>
| |
| | |
| == [[Ubuntu_arm_20.04#.NET|Ubuntu ARM 20.04]] ==
| |
| | |
| = Errors =
| |
| == Failed to bind to address http://127.0.0.1:xxxx: address already in use ==
| |
| <kode lang='bash'> | | <kode lang='bash'> |
| lsof -i :xxxx
| | dotnet MyApp MyKey="value" |
| kill -9 [PID]
| |
| </kode> | | </kode> |