Aller au contenu

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

De Banane Atomic
Contenu remplacé par « Category:.NET Core = 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://github.com/dotnet/core/blob/main/release-notes/8.0/README.md .NET 8 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.mic... »
Balise : Contenu remplacé
Ligne 10 : Ligne 10 :
= Changes =
= Changes =
* [[Swashbuckle]] is no longer actively maintained and has been remove from .NET 9 templates. [https://github.com/dotnet/aspnetcore/issues/54599 ]
* [[Swashbuckle]] is no longer actively maintained and has been remove from .NET 9 templates. [https://github.com/dotnet/aspnetcore/issues/54599 ]
= dotnet CLI =
<kode lang='bash'>
# 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
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>
This include the linux journal for production and the VS code DEBUG CONSOLE for development.}}
<kode lang='cs'>
public class MyClass(ILogger<MyClass> logger)
{
    public void MyMethod()
    {
        // to optimize the performances, test if the log level is enabled
        if (logger.IsEnabled(LogLevel.Debug)) logger.LogDebug("Debug");
        logger.LogTrace("Trace");
        logger.LogInformation("Info");
        logger.LogWarning("Warn");
        logger.LogError("Error");
        logger.LogCritical("Fatal");
    }
}
</kode>
<filebox fn='appsettings.json'>
{
  "Logging": {
    "LogLevel": {
      "Default": "Information",      // log level par défaut
      "Microsoft": "Warning",        // pour les loggers commençant par Microsoft
      "MyNamespace.MyClass": "Debug"  // pour les loggers de MyClass
    }
  }
</filebox>
<filebox fn='Program.cs'>
builder.Logging.ClearProviders();  // remove all the providers: no more logs
</filebox>
{{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.}}
== [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
|}
=== [https://learn.microsoft.com/en-us/dotnet/core/extensions/console-log-formatter Console] ===
<filebox fn='appsettings.json'>
{
  "Logging": {
    "LogLevel": {
      "Default": "Error"  // default log level
    }
  },
  "Console": {
    "LogLevel": {
      "Default": "Information"  // overwrite log level
    },
    "FormatterName": "json"  // log in JSON format
  }
}
</filebox>
=== 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
= [[Tests_unitaires#NUnit|Unit tests]] =
<kode lang='bash'>
# 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 all the unit tests
dotnet test
# run the unit tests of a specific namespace / class
dotnet test --filter Namespace.Class
</kode>
= [https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/overview?tabs=net-8 Code analysis] =
* [https://editorconfig.org/ editorconfig]
== Code quality analysis ==
Those [https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/overview?tabs=net-7#enabled-rules rules] are enabled by default.<br>
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'>
<PropertyGroup>
  <!-- ... -->
  <AnalysisLevel>latest-recommended</AnalysisLevel>
</PropertyGroup>
</filebox>
* [https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ Code quality rules CAxxxx]
{{info | Prefer the use of {{boxx|editorconfig}} to {{boxx|globalconfig}}}}
<filebox fn='.globalconfig' lang='ini' collapsed>
# Top level entry required to mark this as a global AnalyzerConfig file
is_global = true
# 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>
== Code style analysis ==
<kode lang='bash'>
# verify that all code is correctly formatted
dotnet format --verify-no-changes
# format all code
dotnet format
</kode>
* [https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/configuration-files#global-analyzerconfig Configuration files for code analysis rules]
* [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]
* [https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules Code-style rules IDExxxx]
* [[Encodage_de_caractères#Convertion|Change encoding]]
<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>
== Visual Studio Code integration ==
<filebox fn='settings.json'>
"omnisharp.enableRoslynAnalyzers": true,
"omnisharp.enableEditorConfigSupport": true,
</filebox>
== Visual Studio ==
=== [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] ===
# Tools → Options
# 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] ==
# Install the Roslynator extension in Visual Studio or Visual Studio Code
# 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>
is_global = true
# enable all analyzers by default and set the severity to warning
roslynator_analyzers.enabled_by_default = true
dotnet_analyzer_diagnostic.category-roslynator.severity = warning
# enable all refactorings
roslynator_refactorings.enabled = true
# enable all compiler diagnostic fixes
roslynator_compiler_diagnostic_fixes.enabled = true
# Options
roslynator_accessibility_modifiers = explicit
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
# Add blank line between single-line declarations
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>
{{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 ==
* [https://reportgenerator.io/ ReportGenerator]
<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:
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
</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>
= 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://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>
== [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_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'>
lsof -i :xxxx
kill -9 [PID]
</kode>

Version du 18 janvier 2025 à 11:00

Links

Changes

  • Swashbuckle is no longer actively maintained and has been remove from .NET 9 templates. [1]