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

De Banane Atomic
Aller à la navigationAller à la recherche
 
(2 versions intermédiaires par le même utilisateur non affichées)
Ligne 3 : Ligne 3 :
* [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-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://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.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]
* [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 =
= dotnet CLI =
Ligne 24 : Ligne 26 :
dotnet add reference ../otherproject/otherproject.csproj
dotnet add reference ../otherproject/otherproject.csproj


# restore and build
# restore and build with the release configuration
dotnet build
dotnet build --configuration Release
# restore, build and run
# restore, build and run
dotnet run
dotnet run

Dernière version du 26 octobre 2024 à 13:10

Links

dotnet CLI

Bash.svg
# 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

Nuget packages

Bash.svg
# 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:

  1. appsettings.json
  2. appsettings.<EnvironmentName>.json
  3. UserSecrets in Development environment
  4. Environment variables
  5. 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.

Bash.svg
# 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();

Non-prefixed environment variables

/etc/systemd/system/kestrel-myapp.service
Environment=ConnectionStrings__MyApp=server\x3dlocalhost\x3bdatabase\x3dMyDb\x3buser\x3dMyUser\x3bpassword\x3dMyPwd
Environment=SqlServerVersion=10.10.5-MariaDB

Command-line

Bash.svg
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)
Bash.svg
# 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 the application binaries and its dependencies.

  • lighter deployment: only the application binaries and its dependencies are deployed
  • the .NET runtime security updates are managed by the system
  • the required .NET runtime of the application has to match the installed .NET runtime
Bash.svg
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 the application binaries, its dependencies and the required .NET runtime.

  • runs on hosts which doesn't have the .NET runtime installed
  • bigger deployment
  • doesn't follow the .NET security updates
Bash.svg
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 )

Bug MissingMethodException occured when deploying Blazor Server app with 'Trim Unused code'

System.MissingMethodException: Cannot dynamically create an instance of type 'Microsoft.AspNetCore.Components.Web.HeadOutlet'.
Reason: No parameterless constructor defined.
App.razor
@using System.Diagnostics.CodeAnalysis;

@code {
    [DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(HeadOutlet))] // Prevent HeadOutlet from being trimmed
    protected override void OnInitialized() { }
}

Linux

Service file

/etc/systemd/system/kestrel-myproject.service
[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
Bash.svg
# 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>
Cs.svg
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

Bash.svg
# 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>

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" />

Git

.gitignore
# Build folders
bin/
obj/

# Visual Studio local state folder
.vs/

Log

By default, an app is logging into Console, Debug, EventSource, EventLog (only when running on Windows).
This include the linux journal for production and the VS code DEBUG CONSOLE for development.
Cs.svg
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");
    }
}
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
    }
  }
Program.cs
builder.Logging.ClearProviders();  // remove all the providers: no more logs
The Log methods are synchronous.
There is no file log provider.

Built-in logging providers

Console
  • VS code "DEBUG CONSOLE" tab
  • In the console window when the app is run with dotnet run
Debug Debug window when debugging in Visual Studio
On Linux journal or /var/log/message or /var/log/syslog
EventSource Event Tracing for Windows (ETW)
EventLog Windows Event Log
TraceSource System.Diagnostics.TraceSource libraries and providers ()
Azure App Service text files in an Azure App Service app's file system and to blob storage in an Azure Storage account

Console

appsettings.json
{
  "Logging": {
    "LogLevel": {
      "Default": "Error"  // default log level
    }
  },
  "Console": {
    "LogLevel": {
      "Default": "Information"  // overwrite log level
    },
    "FormatterName": "json"  // log in JSON format
  }
}

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

Bash.svg
# 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

Code analysis

Code quality analysis

Those rules are enabled by default.
Here is how to enabled additional rules:

MyProject.csproj
<PropertyGroup>
  <!-- ... -->
  <AnalysisLevel>latest-recommended</AnalysisLevel>
</PropertyGroup>
Prefer the use of editorconfig to globalconfig
.globalconfig
# 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

Code style analysis

Bash.svg
# verify that all code is correctly formatted
dotnet format --verify-no-changes

# format all code
dotnet format
.editorconfig
###############################
# 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  =

Visual Studio Code integration

settings.json
"omnisharp.enableRoslynAnalyzers": true,
"omnisharp.enableEditorConfigSupport": true,

Visual Studio

Set the scope of live code analysis

  1. Tools → Options
  2. Text Editor → C# → Advanced
    1. Run background code analysis for: Current document
    2. Show compiler errors and warnings for: Open documents

Roslynator

  1. Install the Roslynator extension in Visual Studio or Visual Studio Code
  2. Configure Roslynator on a user-wide basis
    1. vscode → Ctrl + Shift + P → enter roslynator → select Roslynator: Open Default Configuration File (.roslynatorconfig)
~/.local/share/JosefPihrt/Roslynator/.roslynatorconfig
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

Roslynator CLI

Bash.svg
# 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'.
The system cannot find the file specified.

Bash.svg
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 .

Code coverage

Bash.svg
# 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

Bash.svg
# 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

ASP.NET Core.jpg

Migrate from ASP.NET Core 7.0 to 8.0

MyProject.csproj
<!-- <TargetFramework>net7.0</TargetFramework> -->
<TargetFramework>net8.0</TargetFramework>

Update the following nuget packages to 8.0 Microsoft.AspNetCore.* Microsoft.EntityFrameworkCore.* Microsoft.Extensions.* System.Net.Http.Json.

Check your data provider (ex: Pomelo) has released a version which handles .NET 8

Installation

Archlinux

Bash.svg
pacman -S aspnet-runtime dotnet-sdk
# install 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
Powershell.svg
# version de .net core installée
dotnet --version

Ubuntu ARM 20.04

Errors

Failed to bind to address http://127.0.0.1:xxxx: address already in use

Bash.svg
lsof -i :xxxx
kill -9 [PID]