Net
Net
.NET documentation
Get started
Hello World
Get started tutorials
.NET Live TV
How to install
Overview
Install on Windows
Install on macOS
Install on Linux
Overview
Ubuntu
Alpine
CentOS
CentOS Stream
Debian
Fedora
OpenSUSE
Red Hat Enterprise Linux
SLES
Install with Snap
Install script & binaries
Remove outdated runtimes and SDKs
Manage .NET templates
macOS Notarization issues
Troubleshoot .NET Package mix ups on Linux
How to check .NET versions
Install localized IntelliSense
Overview
Introduction to .NET
.NET implementations
.NET class libraries
.NET Standard overview
Releases, patches, and support
Ecma standards
.NET glossary
Tutorials
.NET 6 template changes
Use Visual Studio
Create a console app
Debug an app
Publish an app
Create a library
Unit test a library
Install and use a package
Create and publish a package
Use Visual Studio Code
Create a console app
Debug an app
Publish an app
Create a library
Unit test a library
Install and use a package
Create and publish a package
Use Visual Studio for Mac
Create a console app
Debug an app
Publish an app
Create a library
Unit test a library
Install and use a package
More tutorials
What's new in .NET
.NET 6
What's new
Breaking changes
.NET 5
What's new
Breaking changes
.NET Core 3.1
What's new
Breaking changes
.NET Core 3.0
What's new
Breaking changes
.NET Core 2.2
.NET Core 2.1
What's new
Breaking changes
.NET Core 2.0
.NET Standard
Tools and diagnostics
Overview
.NET SDK
Overview
Environment variables
dotnet-install scripts
global.json overview
Telemetry
Error messages
List of all SDK errors
NETSDK1004
NETSDK1005 and NETSDK1047
NETSDK1013
NETSDK1022
NETSDK1045
NETSDK1059
NETSDK1064
NETSDK1071
NETSDK1073
NETSDK1079
NETSDK1080
NETSDK1082
NETSDK1100
NETSDK1112
NETSDK1130
NETSDK1135
NETSDK1136
NETSDK1137
NETSDK1138
NETSDK1141
NETSDK1145
NETSDK1147
NETSDK1149
NETSDK1174
NETSDK1182
.NET CLI
Overview
dotnet
dotnet add/list/remove package
dotnet add package
dotnet list package
dotnet remove package
dotnet add/list/remove reference
dotnet add reference
dotnet list reference
dotnet remove reference
dotnet build
dotnet build-server
dotnet clean
dotnet dev-certs
dotnet format
dotnet help
dotnet migrate
dotnet msbuild
dotnet new
dotnet new <TEMPLATE>
dotnet new list
dotnet new search
dotnet new install
dotnet new uninstall
dotnet new update
.NET default templates
Custom templates
dotnet nuget
dotnet nuget delete
dotnet nuget locals
dotnet nuget push
dotnet nuget add source
dotnet nuget disable source
dotnet nuget enable source
dotnet nuget list source
dotnet nuget remove source
dotnet nuget update source
dotnet nuget verify
dotnet nuget trust
dotnet nuget sign
dotnet pack
dotnet publish
dotnet restore
dotnet run
dotnet sdk check
dotnet sln
dotnet store
dotnet test
dotnet tool
dotnet tool install
dotnet tool list
dotnet tool restore
dotnet tool run
dotnet tool search
dotnet tool uninstall
dotnet tool update
dotnet vstest
dotnet watch
dotnet workload
dotnet workload install
dotnet workload list
dotnet workload repair
dotnet workload restore
dotnet workload search
dotnet workload uninstall
dotnet workload update
Elevated access
Enable Tab completion
Develop libraries with the CLI
Create templates for the CLI
1 - Create an item template
2 - Create a project template
3 - Create a template package
SYSLIB diagnostics
Obsoletions
Overview
SYSLIB0001
SYSLIB0002
SYSLIB0003
SYSLIB0004
SYSLIB0005
SYSLIB0006
SYSLIB0007
SYSLIB0008
SYSLIB0009
SYSLIB0010
SYSLIB0011
SYSLIB0012
SYSLIB0013
SYSLIB0014
SYSLIB0015
SYSLIB0016
SYSLIB0017
SYSLIB0018
SYSLIB0019
SYSLIB0020
SYSLIB0021
SYSLIB0022
SYSLIB0023
SYSLIB0024
SYSLIB0025
SYSLIB0026
SYSLIB0027
SYSLIB0028
SYSLIB0029
SYSLIB0030
SYSLIB0031
SYSLIB0032
SYSLIB0033
SYSLIB0034
SYSLIB0035
SYSLIB0036
SYSLIB0037
SYSLIB0038
SYSLIB0039
SYSLIB0040
SYSLIB0041
SYSLIB0042
SYSLIB0043
SYSLIB0047
Source-generated code
Overview
SYSLIB1001
SYSLIB1002
SYSLIB1003
SYSLIB1005
SYSLIB1006
SYSLIB1007
SYSLIB1008
SYSLIB1009
SYSLIB1010
SYSLIB1011
SYSLIB1012
SYSLIB1013
SYSLIB1014
SYSLIB1015
SYSLIB1016
SYSLIB1017
SYSLIB1018
SYSLIB1019
SYSLIB1020
SYSLIB1021
SYSLIB1022
SYSLIB1023
SYSLIB1030
SYSLIB1031
SYSLIB1032
SYSLIB1033
SYSLIB1035
SYSLIB1036
SYSLIB1037
SYSLIB1038
Integrated development environments (IDEs)
Visual Studio
Visual Studio for Mac
Visual Studio Code
MSBuild and project files
Project SDKs
Overview
Reference
Microsoft.NET.Sdk
Microsoft.NET.Sdk.Web
Microsoft.NET.Sdk.Razor
Microsoft.NET.Sdk.Desktop
Target frameworks
Dependency management
Global and local tools
Manage tools
Troubleshoot tools
Create tools for the CLI
1 - Create a tool
2 - Use a global tool
3 - Use a local tool
Additional tools
Overview
.NET uninstall tool
.NET install tool for extension authors
Generate self-signed certificates
WCF web service reference provider
WCF service utility
WCF service XML serializer
XML serializer generator
Diagnostics and instrumentation
Overview
Managed debuggers
Diagnostic port
Dumps
Overview
Linux dumps
SOS debugger extension
Logging and tracing
Overview
Well-known event providers
Event Source
Overview
Getting started
Instrumentation
Collection
Activity IDs
DiagnosticSource and DiagnosticListener
Getting started
EventPipe
Metrics
Overview
Instrumentation
Collection
EventCounters
Overview
Well-known counters
Tutorial: Measure performance with EventCounters
Compare metric APIs
Distributed tracing
Overview
Concepts
Instrumentation
Collection
Symbols
Microsoft.Diagnostics.NETCore.Client library
Overview and examples
API reference
Runtime events
Overview
Contention events
Exception events
Garbage collection events
Interop events
Loader and binder events
Method events
ThreadPool events
Type-system events
Collect diagnostics in containers
.NET CLI global tools
dotnet-counters
dotnet-coverage
dotnet-dump
dotnet-gcdump
dotnet-monitor
dotnet-trace
dotnet-stack
dotnet-symbol
dotnet-sos
dotnet-dsrouter
.NET diagnostics tutorials
Collect performance trace in Linux with PerfCollect
Debug a memory leak
Debug high CPU usage
Debug deadlock
Debug ThreadPool starvation
Debug a StackOverflow
Code analysis
Overview
Configuration
General options
Configuration files
How to suppress warnings
Code quality rules
Rule options
Predefined configurations
Code style rules
Rule options
Rule reference
Categories
Code quality rules
Overview
Design rules
Overview
CA1000
CA1001
CA1002
CA1003
CA1005
CA1008
CA1010
CA1012
CA1014
CA1016
CA1017
CA1018
CA1019
CA1021
CA1024
CA1027
CA1028
CA1030
CA1031
CA1032
CA1033
CA1034
CA1036
CA1040
CA1041
CA1043
CA1044
CA1045
CA1046
CA1047
CA1050
CA1051
CA1052
CA1053
CA1054
CA1055
CA1056
CA1058
CA1060
CA1061
CA1062
CA1063
CA1064
CA1065
CA1066
CA1067
CA1068
CA1069
CA1070
Documentation rules
Overview
CA1200
Globalization rules
Overview
CA1303
CA1304
CA1305
CA1307
CA1308
CA1309
CA1310
CA2101
Portability and interoperability rules
Overview
CA1401
CA1416
CA1417
CA1418
CA1419
Maintainability rules
Overview
CA1501
CA1502
CA1505
CA1506
CA1507
CA1508
CA1509
Naming rules
Overview
CA1700
CA1707
CA1708
CA1710
CA1711
CA1712
CA1713
CA1714
CA1715
CA1716
CA1717
CA1720
CA1721
CA1724
CA1725
CA1727
Performance rules
Overview
CA1802
CA1805
CA1806
CA1810
CA1812
CA1813
CA1814
CA1815
CA1819
CA1820
CA1821
CA1822
CA1823
CA1824
CA1825
CA1826
CA1827
CA1828
CA1829
CA1830
CA1831
CA1832
CA1833
CA1834
CA1835
CA1836
CA1837
CA1838
CA1839
CA1840
CA1841
CA1842
CA1843
CA1844
CA1845
CA1846
CA1847
CA1848
CA1849
CA1850
CA1851
CA1854
SingleFile rules
Overview
IL3000
IL3001
IL3002
IL3003
Reliability rules
Overview
CA2000
CA2002
CA2007
CA2008
CA2009
CA2011
CA2012
CA2013
CA2014
CA2015
CA2016
CA2017
CA2018
Security rules
Overview
CA2100
CA2109
CA2119
CA2153
CA2300
CA2301
CA2302
CA2305
CA2310
CA2311
CA2312
CA2315
CA2321
CA2322
CA2326
CA2327
CA2328
CA2329
CA2330
CA2350
CA2351
CA2352
CA2353
CA2354
CA2355
CA2356
CA2361
CA2362
CA3001
CA3002
CA3003
CA3004
CA3005
CA3006
CA3007
CA3008
CA3009
CA3010
CA3011
CA3012
CA3061
CA3075
CA3076
CA3077
CA3147
CA5350
CA5351
CA5358
CA5359
CA5360
CA5361
CA5362
CA5363
CA5364
CA5365
CA5366
CA5367
CA5368
CA5369
CA5370
CA5371
CA5372
CA5373
CA5374
CA5375
CA5376
CA5377
CA5378
CA5379
CA5380
CA5381
CA5382
CA5383
CA5384
CA5385
CA5386
CA5387
CA5388
CA5389
CA5390
CA5391
CA5392
CA5393
CA5394
CA5395
CA5396
CA5397
CA5398
CA5399
CA5400
CA5401
CA5402
CA5403
CA5404
CA5405
Usage rules
Overview
CA1801
CA1816
CA2200
CA2201
CA2207
CA2208
CA2211
CA2213
CA2214
CA2215
CA2216
CA2217
CA2218
CA2219
CA2224
CA2225
CA2226
CA2227
CA2229
CA2231
CA2234
CA2235
CA2237
CA2241
CA2242
CA2243
CA2244
CA2245
CA2246
CA2247
CA2248
CA2249
CA2250
CA2251
CA2252
CA2253
CA2254
CA2255
CA2256
CA2257
CA2258
Code style rules
Overview
Language rules
Overview
this and Me preferences
Use language keywords for types
Modifier preferences
Parentheses preferences
Expression-level preferences
Namespace declaration preferences
Null-checking preferences
var preferences
Expression-bodied members
Pattern matching preferences
Code block preferences
using directive preferences
File header preferences
Unnecessary code rules
Overview
IDE0001
IDE0002
IDE0004
IDE0005
IDE0035
IDE0051
IDE0052
IDE0058
IDE0059
IDE0060
IDE0079
IDE0080
IDE0081
IDE0100
IDE0110
IDE0140
Miscellaneous rules
Overview
IDE0076
IDE0077
Formatting rules
IDE0055
Naming rules
Platform compatibility analyzer
Portability analyzer
Package validation
Get started
Baseline package validator
Compatible framework in package validator
Compatible framework validator
Diagnostic IDs
Execution model
Common Language Runtime (CLR)
Managed execution process
Assemblies in .NET
Metadata and self-describing components
Dependency loading
Overview
Understand AssemblyLoadContext
Dependency loading details
Default dependency probing
Load managed assemblies
Load satellite assemblies
Load unmanaged libraries
Collect detailed assembly loading information
Tutorials
Create a .NET application with plugins
How to use and debug assembly unloadability in .NET
Versioning
Overview
.NET version selection
Configure .NET Runtime
Settings
Compilation settings
Debugging and profiling settings
Garbage collector settings
Globalization settings
Networking settings
Threading settings
Troubleshoot app launch failures
Deployment models
Overview
Deploy apps with Visual Studio
Publish apps with the CLI
Create a NuGet package with the CLI
Self-contained deployment runtime roll forward
Single file deployment and executable
ReadyToRun
Trim self-contained deployments
Overview and how-to
Intro to trim warnings
Trim incompatibilities
Options
Trimming libraries
Trim warnings
IL2001
IL2002
IL2003
IL2004
IL2005
IL2007
IL2008
IL2009
IL2010
IL2011
IL2012
IL2013
IL2014
IL2015
IL2016
IL2017
IL2018
IL2019
IL2022
IL2023
IL2024
IL2025
IL2026
IL2027
IL2028
IL2029
IL2030
IL2031
IL2032
IL2033
IL2034
IL2035
IL2036
IL2037
IL2038
IL2039
IL2040
IL2041
IL2042
IL2043
IL2044
IL2045
IL2046
IL2048
IL2049
IL2050
IL2051
IL2052
IL2053
IL2054
IL2055
IL2056
IL2057
IL2058
IL2059
IL2060
IL2061
IL2062
IL2063
IL2064
IL2065
IL2066
IL2067
IL2068
IL2069
IL2070
IL2072
IL2073
IL2074
IL2075
IL2077
IL2078
IL2079
IL2080
IL2082
IL2083
IL2084
IL2085
IL2087
IL2088
IL2089
IL2090
IL2091
IL2092
IL2093
IL2094
IL2095
IL2096
IL2097
IL2098
IL2099
IL2100
IL2101
IL2102
IL2103
IL2104
IL2105
IL2106
IL2107
IL2108
IL2109
IL2110
IL2111
IL2112
IL2113
IL2114
IL2115
IL2116
Native AOT deployment model
Overview
AOT warnings
IL3050
IL3051
IL3052
IL3053
IL3054
IL3055
IL3056
Runtime package store
Runtime Identifier (RID) catalog
Resource manifest names
Docker
Introduction to .NET and Docker
Containerize a .NET app
Container tools in Visual Studio
DevOps
GitHub Actions and .NET
.NET CLI and Continuous Integration
Official .NET GitHub Actions
Tutorials
Create a GitHub Action with .NET
Quickstarts
Create a build GitHub workflow
Create a test GitHub workflow
Create a publish GitHub workflow
Create a CodeQL GitHub workflow
Fundamental coding components
Base types overview
Common type system & common language specification
Common type system
Language independence
Type conversion in .NET
Type conversion tables
Choose between anonymous and tuple types
Framework libraries
Class library overview
Generic types
Overview
Intro to generic types
Generic collections in .NET
Generic delegates for manipulating arrays and lists
Generic math
Generic interfaces
Covariance and contravariance
Collections and data structures
Overview
Select a collection class
Commonly used collection types
When to use generic collections
Comparisons and sorts within collections
Sorted collection types
Hashtable and Dictionary types
Thread-safe collections
Delegates and lambdas
Events
Overview
Raise and consume events
Handle multiple events using event properties
Observer design pattern
Overview
Best practices
How to: Implement a provider
How to: Implement an observer
Exceptions
Overview
Exception class and properties
How-tos
Use the try-catch block to catch exceptions
Use specific exceptions in a catch block
Explicitly throw exceptions
Create user-defined exceptions
Create user-defined exceptions with localized exception messages
Use finally blocks
Use user-filtered exception handlers
Handle COM interop exceptions
Best practices
Numeric types
Dates, times, and time zones
Attributes
Overview
Apply attributes
Write custom attributes
Retrieve information stored in attributes
Runtime libraries
Overview
Format numbers, dates, other types
Overview
Standard numeric format strings
Custom numeric format strings
Standard date and time format strings
Custom date and time format strings
Standard TimeSpan format strings
Custom TimeSpan format strings
Enumeration format strings
Composite formatting
How-tos
Pad a number with leading zeros
Extract the day of the week from a date
Use custom numeric format providers
Round-trip date and time values
Display milliseconds in date and time values
Display dates in non-Gregorian calendars
Work with strings
Character encoding in .NET
How to use character encoding classes
Best practices
Comparing strings
Displaying and persisting formatted data
Behavior changes in .NET 5+ (Windows)
Basic string operations
Overview
Create new strings
Trim and remove characters
Pad strings
Comparison methods
Change case
Separate parts of a string
Use the StringBuilder class
How to: Perform basic string manipulations
Parse (convert) strings
Overview
Parse numeric strings
Parse date and time strings
Parse other strings
Regular expressions
Overview
Language reference
Overview
Character escapes
Character classes
Anchors
Grouping constructs
Quantifiers
Backreference constructs
Alternation constructs
Substitutions
Regular expression options
Miscellaneous constructs
Best practices for regular expressions
Regular expression object model
Regular expression behavior
Overview
Backtracking
Compilation and reuse
Thread safety
Examples
Scan for HREFs
Change date formats
Extract a protocol and port number from a URL
Strip invalid characters from a string
Verify that strings are in valid email format
Serialization
Overview
JSON serialization
Overview
Reflection vs. source generation
How to serialize and deserialize JSON
Control serialization behavior
Instantiate JsonSerializerOptions
Enable case-insensitive matching
Customize property names and values
Ignore properties
Allow invalid JSON
Handle overflow JSON, use JsonElement or JsonNode
Preserve references, handle circular references
Deserialize to immutable types, non-public accessors
Polymorphic serialization
Use DOM, Utf8JsonReader, Utf8JsonWriter
Migrate from Newtonsoft.Json
Supported collection types
Advanced
Customize character encoding
Use source generation
Write custom converters
Binary serialization
Overview
BinaryFormatter security guide
BinaryFormatter event source
Serialization concepts
Basic serialization
Selective serialization
Custom serialization
Steps in the serialization process
Version-tolerant serialization
Serialization guidelines
How to: Chunk serialized data
How to: Determine if a .NET Standard object is serializable
XML and SOAP serialization
Overview
XML serialization in depth
Examples
The XML Schema Definition tool
Control XML serialization using attributes
Attributes that control XML serialization
XML serialization with XML Web Services
Attributes that control encoded SOAP serialization
How-tos
Serialize an object
Deserialize an object
Use the XML Schema Definition tool to generate classes and XML schema
documents
Control serialization of derived classes
Specify an alternate element name for an XML stream
Qualify XML element and XML attribute names
Serialize an object as a SOAP-encoded XML stream
Override encoded SOAP XML serialization
XML serialization elements
system.xml.serialization
dateTimeSerialization
schemaImporterExtensions
add element for schemaImporterExtensions
xmlSerializer
Tools
XML Serializer Generator tool (Sgen.exe)
XML Schema Definition tool (Xsd.exe)
System.CommandLine
Overview
Get started tutorial
Command-line syntax
Define commands
Model binding
Tab completion
Dependency injection
Customize help
Handle termination
Use middleware
File and stream I/O
Overview
File path formats on Windows systems
Common I/O tasks
How to: Copy Directories
How to: Enumerate Directories and Files
How to: Read and Write to a Newly Created Data File
How to: Open and Append to a Log File
How to: Write Text to a File
How to: Read Text from a File
How to: Read Characters from a String
How to: Write Characters to a String
How to: Add or Remove Access Control List Entries
How to: Compress and Extract Files
Composing Streams
How to: Convert Between .NET Framework Streams and Windows Runtime
Streams
Asynchronous file I/O
Handle I/O errors
Isolated storage
Types of Isolation
How to: Obtain Stores for Isolated Storage
How to: Enumerate Stores for Isolated Storage
How to: Delete Stores in Isolated Storage
How to: Anticipate Out-of-Space Conditions with Isolated Storage
How to: Create Files and Directories in Isolated Storage
How to: Find Existing Files and Directories in Isolated Storage
How to: Read and Write to Files in Isolated Storage
How to: Delete Files and Directories in Isolated Storage
Pipes
How to: Use Anonymous Pipes for Local Interprocess Communication
How to: Use Named Pipes for Network Interprocess Communication
Pipelines
Work with buffers
Memory-mapped files
The System.Console class
Dependency injection
Overview
Use dependency injection
Dependency injection guidelines
Configuration
Overview
Configuration providers
Implement a custom configuration provider
Options pattern
Options pattern guidance for library authors
Logging
Overview
Logging providers
Compile-time logging source generation
Implement a custom logging provider
High-performance logging
Console log formatting
HostBuilder (generic host)
Networking
Network programming in .NET
Network availability
IPv6 overview
HTTP
HTTP support
HTTP client guidelines
Make HTTP requests
IHttpClientFactory
HTTP/3 with .NET
Sockets
Sockets support
Use Sockets to send and receive data
TCP
TCP support
Use TcpClient and TcpListener
File globbing in .NET
Primitives library in .NET
Globalization and localization
Overview
Globalization
Globalization and ICU
Localizability review
Localization
Culture-insensitive string operations
Overview
String comparisons
Case changes
String operations in collections
String operations in arrays
Best practices for developing world-ready apps
Resources in .NET apps
Overview
Create resource files
Overview
Work with .resx files programmatically
Create satellite assemblies
Package and deploy resources
Retrieve resources
Worker Services
Overview
Create a Queue Service
Use scoped services with a BackgroundService
Create a Windows Service using BackgroundService
Implement the IHostedService interface
Deploy a Worker Service to Azure
Caching
Channels
Data access
LINQ
XML documents and data
Microsoft.Data.Sqlite
Entity Framework Core
Parallel processing, concurrency, and async
Asynchronous programming patterns
Parallel programming
Overview
Task Parallel Library (TPL)
Data parallelism
How to: Write a Simple Parallel.For Loop
How to: Write a Simple Parallel.ForEach Loop
How to: Write a Parallel.For Loop with Thread-Local Variables
How to: Write a Parallel.ForEach Loop with Partition-Local Variables
How to: Cancel a Parallel.For or ForEach Loop
How to: Handle Exceptions in Parallel Loops
How to: Speed Up Small Loop Bodies
How to: Iterate File Directories with the Parallel Class
Task-based asynchronous programming
Chaining Tasks by Using Continuation Tasks
Attached and Detached Child Tasks
Task Cancellation
Exception Handling
How to: Use Parallel.Invoke to Execute Parallel Operations
How to: Return a Value from a Task
How to: Cancel a Task and Its Children
How to: Create Pre-Computed Tasks
How to: Traverse a Binary Tree with Parallel Tasks
How to: Unwrap a Nested Task
How to: Prevent a Child Task from Attaching to its Parent
Dataflow
How to: Write Messages to and Read Messages from a Dataflow Block
How to: Implement a Producer-Consumer Dataflow Pattern
How to: Perform Action When a Dataflow Block Receives Data
Walkthrough: Creating a Dataflow Pipeline
How to: Unlink Dataflow Blocks
Walkthrough: Using Dataflow in a Windows Forms Application
How to: Cancel a Dataflow Block
Walkthrough: Creating a Custom Dataflow Block Type
How to: Use JoinBlock to Read Data From Multiple Sources
How to: Specify the Degree of Parallelism in a Dataflow Block
How to: Specify a Task Scheduler in a Dataflow Block
Walkthrough: Using BatchBlock and BatchedJoinBlock to Improve Efficiency
Use TPL with Other Asynchronous Patterns
TPL and Traditional .NET Asynchronous Programming
How to: Wrap EAP Patterns in a Task
Potential Pitfalls in Data and Task Parallelism
Parallel LINQ (PLINQ)
Introduction to PLINQ
Understanding Speedup in PLINQ
Order Preservation in PLINQ
Merge Options in PLINQ
Potential Pitfalls with PLINQ
How to: Create and Execute a Simple PLINQ Query
How to: Control Ordering in a PLINQ Query
How to: Combine Parallel and Sequential LINQ Queries
How to: Handle Exceptions in a PLINQ Query
How to: Cancel a PLINQ Query
How to: Write a Custom PLINQ Aggregate Function
How to: Specify the Execution Mode in PLINQ
How to: Specify Merge Options in PLINQ
How to: Iterate File Directories with PLINQ
How to: Measure PLINQ Query Performance
PLINQ Data Sample
Data structures for parallel programming
Parallel diagnostic tools
Custom partitioners for PLINQ and TPL
Overview
How to: Implement Dynamic Partitions
How to: Implement a Partitioner for Static Partitioning
Lambda expressions in PLINQ and TPL
Further reading
Threading
Testing
Overview
Unit testing best practices
xUnit
C# unit testing
F# unit testing
VB unit testing
Organize a project and test with xUnit
NUnit
C# unit testing
F# unit testing
VB unit testing
MSTest
C# unit testing
F# unit testing
VB unit testing
Run selective unit tests
Order unit tests
Unit test code coverage
Unit test published output
Live unit test .NET projects with Visual Studio
Security
Advanced topics
Performance
Memory management
What is "managed code"?
Automatic memory management
Clean up unmanaged resources
Overview
Implement a Dispose method
Implement a DisposeAsync method
Use objects that implement IDisposable
Garbage collection
Overview
Fundamentals
Workstation and server GC
Background GC
The large object heap
Garbage collection and performance
Induced collections
Latency modes
Optimization for shared web hosting
Garbage collection notifications
Application domain resource monitoring
Weak references
Memory and span-related types
Overview
Memory<T> and Span<T> usage guidelines
SIMD-enabled types
Native interoperability
Overview
P/Invoke
Overview
Cross-platform P/Invoke
Source generation
Type marshalling
Overview
Charsets and marshalling
Disabled marshalling
Customize structure marshalling
Customize parameter marshalling
Source generation
Interop guidance
Expose .NET components to COM
Host .NET from native code
COM interop
Overview
COM wrappers
Overview
Runtime-callable wrapper
COM-callable wrapper
Tutorial - Use the ComWrappers API
Qualifying .NET types for COM interop
Apply interop attributes
Exceptions
.NET distribution packaging
Open-source library guidance
Framework design guidelines
Overview
Naming guidelines
Capitalization conventions
General naming conventions
Names of assemblies and DLLs
Names of namespaces
Names of classes, structs, and interfaces
Names of type members
Naming parameters
Naming resources
Type design guidelines
Choose between class and struct
Abstract class design
Static class design
Interface design
Struct design
Enum design
Nested types
Member design guidelines
Member overloading
Property design
Constructor design
Event design
Field design
Extension methods
Operator overloads
Parameter design
Design for extensibility
Unsealed classes
Protected members
Events and callbacks
Virtual members
Abstractions (abstract types and interfaces)
Base classes for implementing abstractions
Sealing
Exception design guidelines
Exception throwing
Use standard exception types
Exceptions and performance
Usage guidelines
Arrays
Attributes
Collections
Serialization
System.Xml usage
Equality operators
Common design patterns
Dependency properties
Migration guide
Overview
General Information
About .NET
Versioning info for .NET SDK, MSBuild, and Visual Studio
Choose between .NET 5 and .NET Framework for server apps
.NET Upgrade Assistant tool
Overview
Windows Presentation Foundation
Windows Forms
Universal Windows Platform
ASP.NET Core
Telemetry
Breaking changes
Pre-Migration
Assess the portability of your project
Unsupported Dependencies
Use the Windows Compatibility Pack
Unavailable technologies
Unsupported APIs
Needed changes before porting code
Migration
Create a porting plan
Approaches
Project structure
Application Porting Guides
Windows Forms
Windows Presentation Foundation
Port C++/CLI projects
Get started with .NET
9/10/2022 • 2 minutes to read • Edit Online
This article teaches you how to create and run a "Hello World!" app with .NET.
Create an application
First, download and install the .NET SDK on your computer.
Next, open a terminal such as PowerShell , Command Prompt , or bash .
Type the following commands:
Hello World!
Next steps
Get started on developing .NET applications by following a step-by-step tutorial or by watching .NET 101 videos
on YouTube.
Tutorials for getting started with .NET
9/10/2022 • 2 minutes to read • Edit Online
The following step-by-step tutorials run on Windows, Linux, or macOS, except as noted.
In this article, you'll learn how to install .NET on Windows. .NET is made up of the runtime and the SDK. The
runtime is used to run a .NET app and may or may not be included with the app. The SDK is used to create .NET
apps and libraries. The .NET runtime is always installed with the SDK.
The latest version of .NET is 6.
D O W NLO AD
.NET
.NET Runtime
This is the base runtime, and contains just the components needed to run a console app. Typically, you'd
install the other runtimes.
winget install Microsoft.DotNet.Runtime.6
You can install preview versions of the runtimes by substituting the version number, such as 6 , with the word
Preview . The following example installs the preview release of the .NET Desktop Runtime:
If you want to install .NET silently, such as in a production environment or to support continuous integration, use
the following switches:
/install
Installs .NET.
/quiet
Prevents any UI and prompts from displaying.
/norestart
Suppresses any attempts to restart.
TIP
The installer returns an exit code of 0 for success and an exit code of 3010 to indicate that a restart is required. Any other
value is generally an error code.
Install the SDK by omitting the -Runtime switch. The -Channel switch is set in this example to Current , which
installs the latest supported version.
If you already have Visual Studio installed, you can check your version with the following steps.
1. Open Visual Studio.
2. Select Help > About Microsoft Visual Studio .
3. Read the version number from the About dialog.
Visual Studio can install the latest .NET SDK and runtime.
D O W NLO AD VISU AL .
S TU D IO
Select a workload
When installing or modifying Visual Studio, select one or more of the following workloads, depending on the
kind of application you're building:
The .NET Core cross-platform development workload in the Other Toolsets section.
The ASP.NET and web development workload in the Web & Cloud section.
The Azure development workload in the Web & Cloud section.
The .NET desktop development workload in the Desktop & Mobile section.
Supported releases
The following table is a list of currently supported .NET releases and the versions of Windows they're supported
on. These versions remain supported until either the version of .NET reaches end-of-support or the version of
Windows reaches end-of-life.
Windows 10 versions end-of-service dates are segmented by edition. Only Home , Pro , Pro Education , and
Pro for Workstations editions are considered in the following table. Check the Windows lifecycle fact sheet
for specific details.
TIP
A + symbol represents the minimum version.
O P ERAT IN G SY ST EM . N ET C O RE 3. 1 . N ET 6
Windows 11 ️
✔ ️
✔
Windows 8.1 ️
✔ ️
✔
For more information about .NET 6 supported operating systems, distributions, and lifecycle policy, see .NET 6
Supported OS Versions.
Unsupported releases
The following versions of .NET are ❌ no longer supported:
.NET 5
.NET Core 3.0
.NET Core 2.2
.NET Core 2.1
.NET Core 2.0
Runtime information
The runtime is used to run apps created with .NET. When an app author publishes an app, they can include the
runtime with their app. If they don't include the runtime, it's up to the user to install the runtime.
There are three different runtimes you can install on Windows:
ASP.NET Core runtime
Runs ASP.NET Core apps. Includes the .NET runtime.
Desktop runtime
Runs .NET WPF and Windows Forms desktop apps for Windows. Includes the .NET runtime.
.NET runtime
This runtime is the simplest runtime and doesn't include any other runtime. It's highly recommended that
you install both ASP.NET Core runtime and Desktop runtime for the best compatibility with .NET apps.
D O W NLO AD .NET
R U N TIM E
SDK information
The SDK is used to build and publish .NET apps and libraries. Installing the SDK includes all three runtimes:
ASP.NET Core, Desktop, and .NET.
D O W NLO AD .NET
SDK
The x64 and Arm64 versions of the .NET 6 SDK exist independently from each other. If a new version is released,
each install needs to be upgraded.
Path differences
On an Arm-based Windows PC, all Arm64 versions of .NET are installed to the normal C:\Program Files\dotnet\
folder. However, when you install the x64 version of .NET 6 SDK, it's installed to the C:\Program
Files\dotnet\x64\ folder.
Path conflicts
The x64 .NET 6 SDK installs to its own directory, as described in the previous section. This allows the Arm64 and
x64 versions of the .NET 6 SDK to exist on the same machine. However, any x64 SDK prior to 6.0 isn't supported
and installs to the same location as the Arm64 version, the C:\Program Files\dotnet\ folder. If you want to install
an unsupported x64 SDK, you'll need to first uninstall the Arm64 version. The opposite is also true, you'll need to
uninstall the unsupported x64 SDK to install the Arm64 version.
Path variables
Environment variables that add .NET to system path, such as the PATH variable, may need to be changed if you
have both the x64 and Arm64 versions of the .NET 6 SDK installed. Additionally, some tools rely on the
DOTNET_ROOT environment variable, which would also need to be updated to point to the appropriate .NET 6 SDK
installation folder.
Dependencies
.NET 6
.NET Core 3.1
NOTE
A + symbol represents the minimum version.
OS VERSIO N A RC H IT EC T URES
For more information about .NET 6 supported operating systems, distributions, and lifecycle policy, see .NET 6
Supported OS Versions.
Windows 7 / Vista / 8.1 / Server 2008 R2 / Server 2012 R2
More dependencies are required if you're installing the .NET SDK or runtime on the following Windows versions:
Docker
Containers provide a lightweight way to isolate your application from the rest of the host system. Containers on
the same machine share just the kernel and use resources given to your application.
.NET can run in a Docker container. Official .NET Docker images are published to the Microsoft Container
Registry (MCR) and are discoverable at the Microsoft .NET Docker Hub repository. Each repository contains
images for different combinations of the .NET (SDK or Runtime) and OS that you can use.
Microsoft provides images that are tailored for specific scenarios. For example, the ASP.NET Core repository
provides images that are built for running ASP.NET Core apps in production.
For more information about using .NET in a Docker container, see Introduction to .NET and Docker and Samples.
Troubleshooting
After installing the .NET SDK, you may run into problems trying to run .NET CLI commands. This section collects
those common problems and provides solutions.
It was not possible to find any installed .NET Core SDKs
It was not possible to find any installed .NET Core SDKs
Most likely you've installed both the x86 (32-bit) and x64 (64-bit) versions of the .NET SDK. This is causing a
conflict because when you run the dotnet command it's resolving to the x86 version when it should resolve to
the x64 version. This is usually fixed by adjusting the %PATH% variable to resolve the x64 version first.
1. Verify that you have both versions installed by running the where.exe dotnet command. If you do, you
should see an entry for both the Program Files\ and Program Files (x86)\ folders. If the Program Files
(x86)\ folder is first as indicated by the following example, it's incorrect and you should continue on to the
next step.
If it's correct and the Program Files\ is first, you don't have the problem this section is discussing and you
should create a .NET help request issue on GitHub
2. Press the Windows button and type "Edit the system environment variables" into search. Select Edit the
system environment variables .
3. The System Proper ties window opens up to the Advanced Tab . Select Environment Variables .
4. On the Environment Variables window, under the System variables group, select the Path* row and
then select the Edit button.
5. Use the Move Up and Move Down buttons to move the C:\Program Files\dotnet\ entry above
C:\Program Files (x86)\dotnet\ .
Next steps
How to check if .NET is already installed.
Tutorial: Hello World tutorial.
Tutorial: Create a new app with Visual Studio Code.
Tutorial: Containerize a .NET Core app.
Install .NET on macOS
9/10/2022 • 7 minutes to read • Edit Online
In this article, you'll learn how to install .NET on macOS. .NET is made up of the runtime and the SDK. The
runtime is used to run a .NET app and may or may not be included with the app. The SDK is used to create .NET
apps and libraries. The .NET runtime is always installed with the SDK.
The latest version of .NET is 6.0.
D O W NLO AD .NET
CORE
Supported releases
The following table is a list of currently supported .NET releases and the versions of macOS they're supported
on. These versions remain supported until the version of .NET reaches end-of-support.
A✔️ indicates that the version of .NET is still supported.
A ❌ indicates that the version of .NET isn't supported.
O P ERAT IN G SY ST EM . N ET C O RE 3. 1 . N ET 6
For more information about the life cycle of .NET releases, see .NET and .NET Core Support Policy.
Unsupported releases
The following versions of .NET are ❌ no longer supported:
.NET 5
.NET Core 3.0
.NET Core 2.2
.NET Core 2.1
.NET Core 2.0
Runtime information
The runtime is used to run apps created with .NET. When an app author publishes an app, they can include the
runtime with their app. If they don't include the runtime, it's up to the user to install the runtime.
There are two different runtimes you can install on macOS:
ASP.NET Core runtime
Runs ASP.NET Core apps. Includes the .NET runtime.
.NET runtime
This runtime is the simplest runtime and doesn't include any other runtime. It's highly recommended that
you install ASP.NET Core runtime for the best compatibility with .NET apps.
D O W NLO AD .NET
R U N TIM E
SDK information
The SDK is used to build and publish .NET apps and libraries. Installing the SDK includes both runtimes: ASP.NET
Core and .NET.
Notarization
Beginning with macOS Catalina (version 10.15), all software built after June 1, 2019 that is distributed with
Developer ID, must be notarized. This requirement applies to the .NET runtime, .NET SDK, and software created
with .NET.
The runtime and SDK installers for .NET have been notarized since February 18, 2020. Prior released versions
aren't notarized. If you run a non-notarized app, you'll see an error similar to the following image:
For more information about how enforced-notarization affects .NET (and your .NET apps), see Working with
macOS Catalina Notarization.
libgdiplus
.NET applications that use the System.Drawing.Common assembly require libgdiplus to be installed.
An easy way to obtain libgdiplus is by using the Homebrew ("brew") package manager for macOS. After
installing brew , install libgdiplus by executing the following commands at a Terminal (command) prompt:
brew update
brew install mono-libgdiplus
DOTNET_FILE=dotnet-sdk-6.0.100-osx-x64.tar.gz
export DOTNET_ROOT=$(pwd)/dotnet
export PATH=$PATH:$DOTNET_ROOT
TIP
The preceding export commands only make the .NET CLI commands available for the terminal session in which it was
run.
You can edit your shell profile to permanently add the commands. There are a number of different shells available for
Linux and each has a different profile. For example:
Bash Shell: ~/.bash_profile, ~/.bashrc
Korn Shell: ~/.kshrc or .profile
Z Shell: ~/.zshrc or .zprofile
Edit the appropriate source file for your shell and add :$HOME/dotnet to the end of the existing PATH statement. If no
PATH statement is included, add a new line with export PATH=$PATH:$HOME/dotnet .
This approach lets you install different versions into separate locations and choose explicitly which one to use by
which application.
Arm-based Macs
The following sections describe things you should consider when installing .NET on an Arm-based Mac.
What's supported
The following table describes which versions of .NET are supported on an Arm-based Mac:
. N ET VERSIO N A RC H IT EC T URE SDK RUN T IM E PAT H C O N F L IC T
The x64 and Arm64 versions of the .NET 6 SDK exist independently from each other. If a new version is released,
each install needs to be upgraded.
Path differences
On an Arm-based Mac, all Arm64 versions of .NET are installed to the normal /usr/local/share/dotnet/ folder.
However, when you install the x64 version of .NET 6 SDK, it's installed to the
/usr/local/share/dotnet/x64/dotnet/ folder.
Path conflicts
The x64 .NET 6 SDK installs to its own directory, as described in the previous section. This allows the Arm64 and
x64 versions of the .NET 6 SDK to exist on the same machine. However, any x64 SDK prior to 6.0 isn't supported
and installs to the same location as the Arm64 version, the /usr/local/share/dotnet/ folder. If you want to install
an unsupported x64 SDK, you'll need to first uninstall the Arm64 version. The opposite is also true, you'll need to
uninstall the unsupported x64 SDK to install the Arm64 version.
Path variables
Environment variables that add .NET to system path, such as the PATH variable, may need to be changed if you
have both the x64 and Arm64 versions of the .NET 6 SDK installed. Additionally, some tools rely on the
DOTNET_ROOT environment variable, which would also need to be updated to point to the appropriate .NET 6 SDK
installation folder.
NOTE
The previous command installs the ASP.NET Core runtime for maximum compatability. The ASP.NET Core runtime also
includes the standard .NET runtime.
Docker
Containers provide a lightweight way to isolate your application from the rest of the host system. Containers on
the same machine share just the kernel and use resources given to your application.
.NET can run in a Docker container. Official .NET Docker images are published to the Microsoft Container
Registry (MCR) and are discoverable at the Microsoft .NET Docker Hub repository. Each repository contains
images for different combinations of the .NET (SDK or Runtime) and OS that you can use.
Microsoft provides images that are tailored for specific scenarios. For example, the ASP.NET Core repository
provides images that are built for running ASP.NET Core apps in production.
For more information about using .NET in a Docker container, see Introduction to .NET and Docker and Samples.
Next steps
How to check if .NET is already installed.
Working with macOS Catalina notarization.
Tutorial: Get started on macOS.
Tutorial: Create a new app with Visual Studio Code.
Tutorial: Containerize a .NET app.
Install .NET on Linux
9/10/2022 • 2 minutes to read • Edit Online
This article details how to install .NET on various Linux distributions, manually and via a package manager.
Typically, stable .NET versions are available in a package manager, and Preview versions are not.
Manual installation
You can install .NET manually in the following ways:
Download tarballs
Scripted install
Manual binary extraction
You may need to install .NET dependencies if you install .NET manually.
Microsoft packages
.NET is also available via packages.microsoft.com.
CentOS
Debian
Fedora
openSUSE
SLES
Ubuntu
These packages are supported by Microsoft.
You're encouraged to install .NET from the official archive for your distribution if it's available there, even if it's
also available at packages.microsoft.com.
Other distributions
Installation information is also provided for other distributions.
Alpine
Containers
Snap
Next steps
How to check if .NET is already installed.
Tutorial: Create a new app with Visual Studio Code.
Tutorial: Containerize a .NET app.
Install the .NET SDK or the .NET Runtime on
Ubuntu
9/10/2022 • 11 minutes to read • Edit Online
.NET is supported on Ubuntu. This article describes how to install .NET on Ubuntu. When an Ubuntu version falls
out of support, .NET is no longer supported with that version.
Install the SDK (which includes the runtime) if you want to develop .NET apps. Or, if you only need to run apps,
install the Runtime. If you're installing the Runtime, we suggest you install the ASP.NET Core Runtime as it
includes both .NET and ASP.NET Core runtimes.
If you've already installed the SDK or Runtime, use the dotnet --list-sdks and dotnet --list-runtimes
commands to see which versions are installed. For more information, see How to check that .NET is already
installed.
IMPORTANT
Package manager installs are only supported on the x64 architecture. Other architectures, such as Arm , must install .NET
by some other means such as with Snap, an installer script, or through a manual binary installation.
For more information on installing .NET without a package manager , see one of the following articles:
Alternatively install .NET with Snap.
Alternatively install .NET with install-dotnet script.
Manually install .NET
Supported distributions
The following table is a list of currently supported .NET releases and the versions of Ubuntu they're supported
on.
UB UN T U . N ET
22.04 (LTS) 6+
22.04
WARNING
If you've previously installed .NET 6 from packages.microsoft.com , see the Advisory on installing .NET 6 on Ubuntu
22.04.
As an alternative to the ASP.NET Core Runtime, you can install the .NET Runtime, which doesn't include ASP.NET
Core support: replace aspnetcore-runtime-6.0 in the previous command with dotnet-runtime-6.0 :
Installing with APT can be done with a few commands. Before you install .NET, run the following commands to
add the Microsoft package signing key to your list of trusted keys and add the package repository.
Open a terminal and run the following commands:
IMPORTANT
If you receive an error message similar to Unable to locate package dotnet-sdk-6.0 , see the APT troubleshooting
section.
IMPORTANT
If you receive an error message similar to Unable to locate package aspnetcore-runtime-6.0 , see the APT
troubleshooting section.
As an alternative to the ASP.NET Core Runtime, you can install the .NET Runtime, which doesn't include ASP.NET
Core support: replace aspnetcore-runtime-6.0 in the previous command with dotnet-runtime-6.0 :
20.04
Installing with APT can be done with a few commands. Before you install .NET, run the following commands to
add the Microsoft package signing key to your list of trusted keys and add the package repository.
Open a terminal and run the following commands:
IMPORTANT
If you receive an error message similar to Unable to locate package dotnet-sdk-6.0 , see the APT troubleshooting
section.
IMPORTANT
If you receive an error message similar to Unable to locate package aspnetcore-runtime-6.0 , see the APT
troubleshooting section.
As an alternative to the ASP.NET Core Runtime, you can install the .NET Runtime, which doesn't include ASP.NET
Core support: replace aspnetcore-runtime-6.0 in the previous command with dotnet-runtime-6.0 :
18.04
Installing with APT can be done with a few commands. Before you install .NET, run the following commands to
add the Microsoft package signing key to your list of trusted keys and add the package repository.
Open a terminal and run the following commands:
IMPORTANT
If you receive an error message similar to Unable to locate package dotnet-sdk-6.0 , see the APT troubleshooting
section.
IMPORTANT
If you receive an error message similar to Unable to locate package aspnetcore-runtime-6.0 , see the APT
troubleshooting section.
As an alternative to the ASP.NET Core Runtime, you can install the .NET Runtime, which doesn't include ASP.NET
Core support: replace aspnetcore-runtime-6.0 in the previous command with dotnet-runtime-6.0 :
16.04
Installing with APT can be done with a few commands. Before you install .NET, run the following commands to
add the Microsoft package signing key to your list of trusted keys and add the package repository.
Open a terminal and run the following commands:
wget https://packages.microsoft.com/config/ubuntu/16.04/packages-microsoft-prod.deb -O packages-microsoft-
prod.deb
sudo dpkg -i packages-microsoft-prod.deb
rm packages-microsoft-prod.deb
IMPORTANT
If you receive an error message similar to Unable to locate package dotnet-sdk-6.0 , see the APT troubleshooting
section.
IMPORTANT
If you receive an error message similar to Unable to locate package aspnetcore-runtime-6.0 , see the APT
troubleshooting section.
As an alternative to the ASP.NET Core Runtime, you can install the .NET Runtime, which doesn't include ASP.NET
Core support: replace aspnetcore-runtime-6.0 in the previous command with dotnet-runtime-6.0 :
product
The type of .NET product to install. Valid options are:
dotnet
aspnetcore
type
Chooses the SDK or the runtime. Valid options are:
sdk
runtime
version
The version of the SDK or runtime to install. This article will always give the instructions for the latest
supported version. Valid options are any released version, such as:
5.0
3.1
3.0
2.1
It's possible the SDK/runtime you're trying to download is not available for your Linux distribution. For a
list of supported distributions, see Install .NET on Linux.
Examples
Install the ASP.NET Core 5.0 runtime: aspnetcore-runtime-5.0
Install the .NET Core 2.1 runtime: dotnet-runtime-2.1
Install the .NET 5 SDK: dotnet-sdk-5.0
Install the .NET Core 3.1 SDK: dotnet-sdk-3.1
Package missing
If the package-version combination doesn't work, it's not available. For example, there isn't an ASP.NET Core
SDK, the SDK components are included with the .NET SDK. The value aspnetcore-sdk-2.2 is incorrect and should
be dotnet-sdk-2.2 . For a list of Linux distributions supported by .NET, see .NET dependencies and requirements.
If you've upgraded your Linux distribution since installing .NET, you may need to reconfigure the Microsoft
package repository. Run the installation instructions for your current distribution version to upgrade to the
appropriate package repository for .NET updates.
APT troubleshooting
This section provides information on common errors you may get while using APT to install .NET.
Unable to find package
IMPORTANT
Package manager installs are only supported on the x64 architecture. Other architectures, such as Arm , must install .NET
by some other means such as with Snap, an installer script, or through a manual binary installation.
For more information on installing .NET without a package manager , see one of the following articles:
Alternatively install .NET with Snap.
Alternatively install .NET with install-dotnet script.
Manually install .NET
Unable to locate \ Some packages could not be installed
NOTE
This information only applies when .NET is installed from the Microsoft package feed.
If you receive an error message similar to Unable to locate package {dotnet-package} or Some packages
could not be installed , run the following commands.
There are two placeholders in the following set of commands.
{dotnet-package}
This represents the .NET package you're installing, such as aspnetcore-runtime-3.1 . This is used in the
following sudo apt-get install command.
{os-version}
This represents the distribution version you're on. This is used in the wget command below. The
distribution version is the numerical value, such as 20.04 on Ubuntu or 10 on Debian.
First, try purging the package list:
Then, try to install .NET again. If that doesn't work, you can run a manual install with the following commands:
Failed to fetch
While installing the .NET package, you may see an error similar to
Failed to fetch ... File has unexpected size ... Mirror sync in progress? . This error could mean that the
package feed for .NET is being upgraded with newer package versions, and that you should try again later.
During an upgrade, the package feed shouldn't be unavailable for more than 30 minutes. If you continually
receive this error for more than 30 minutes, please file an issue at https://github.com/dotnet/core/issues.
Dependencies
When you install with a package manager, these libraries are installed for you. But, if you manually install .NET
or you publish a self-contained app, you'll need to make sure these libraries are installed:
libc6
libgcc1
libgssapi-krb5-2
libicu52 (for 14.x)
libicu55 (for 16.x)
libicu60 (for 18.x)
libicu66 (for 20.x)
libssl1.0.0 (for 14.x, 16.x)
libssl1.1 (for 18.x, 20.x)
libstdc++6
zlib1g
For .NET apps that use the System.Drawing.Common assembly, you also need the following dependency:
libgdiplus (version 6.0.1 or later)
WARNING
You can install a recent version of libgdiplus by adding the Mono repository to your system. For more
information, see https://www.mono-project.com/download/stable/.
Next steps
How to enable TAB completion for the .NET CLI
Tutorial: Create a console application with .NET SDK using Visual Studio Code
Install the .NET SDK or the .NET Runtime on Alpine
9/10/2022 • 2 minutes to read • Edit Online
This article describes how to install .NET on Alpine. When an Alpine version falls out of support, .NET is no
longer supported with that version. However, these instructions may help you to get .NET running on those
versions, even though it isn't supported.
Install the SDK (which includes the runtime) if you want to develop .NET apps. Or, if you only need to run apps,
install the Runtime. If you're installing the Runtime, we suggest you install the ASP.NET Core Runtime as it
includes both .NET and ASP.NET Core runtimes.
If you've already installed the SDK or Runtime, use the dotnet --list-sdks and dotnet --list-runtimes
commands to see which versions are installed. For more information, see How to check that .NET is already
installed.
Install
Installers aren't available for Alpine Linux. You must install .NET in one of the following ways:
Scripted install with install-dotnet.sh
Manual binary extraction
Supported distributions
The following table is a list of currently supported .NET releases and the versions of Alpine they're supported on.
These versions remain supported until either the version of .NET reaches end-of-support or the version of
Alpine reaches end-of-life.
A✔️ indicates that the version of Alpine or .NET is still supported.
A ❌ indicates that the version of Alpine or .NET isn't supported on that Alpine release.
When both a version of Alpine and a version of .NET have ✔ ️ , that OS and .NET combination is supported.
A L P IN E . N ET C O RE 3. 1 . N ET 6
️ 3.15
✔ ️ 3.1
✔ ️ 6.0
✔
️ 3.14
✔ ️ 3.1
✔ ️ 6.0
✔
️ 3.13
✔ ️ 3.1
✔ ️ 6.0
✔
️ 3.12
✔ ️ 3.1
✔ ️ 6.0
✔
❌ 3.11 ️ 3.1
✔ ❌ 6.0
❌ 3.10 ️ 3.1
✔ ❌ 6.0
❌ 3.9 ️ 3.1
✔ ❌ 6.0
❌ 3.8 ️ 3.1
✔ ❌ 6.0
Dependencies
.NET on Alpine Linux requires the following dependencies installed:
icu-libs
krb5-libs
libgcc
libgdiplus (if the .NET app requires the System.Drawing.Common assembly)
libintl
libssl1.1 (Alpine v3.9 or greater)
libssl1.0 (Alpine v3.8 or lower)
libstdc++
zlib
To install the needed requirements, run the following command:
apk add bash icu-libs krb5-libs libgcc libintl libssl1.1 libstdc++ zlib
Next steps
How to enable TAB completion for the .NET CLI
Tutorial: Create a console application with .NET SDK using Visual Studio Code
Install the .NET SDK or the .NET Runtime on
CentOS
9/10/2022 • 7 minutes to read • Edit Online
.NET is supported on CentOS. This article describes how to install .NET on CentOS. If you need to install .NET On
CentOS Stream, see Install the .NET SDK or the .NET Runtime on RHEL and CentOS Stream.
Install the SDK (which includes the runtime) if you want to develop .NET apps. Or, if you only need to run apps,
install the Runtime. If you're installing the Runtime, we suggest you install the ASP.NET Core Runtime as it
includes both .NET and ASP.NET Core runtimes.
If you've already installed the SDK or Runtime, use the dotnet --list-sdks and dotnet --list-runtimes
commands to see which versions are installed. For more information, see How to check that .NET is already
installed.
IMPORTANT
Package manager installs are only supported on the x64 architecture. Other architectures, such as Arm , must install .NET
by some other means such as with Snap, an installer script, or through a manual binary installation.
For more information on installing .NET without a package manager , see one of the following articles:
Alternatively install .NET with Snap.
Alternatively install .NET with install-dotnet script.
Manually install .NET
Supported distributions
The following table is a list of currently supported .NET releases on both CentOS 7 and CentOS 8. These versions
remain supported until either the version of .NET reaches end-of-support or the version of CentOS is no longer
supported.
A✔️ indicates that the version of CentOS or .NET is still supported.
A ❌ indicates that the version of CentOS or .NET isn't supported on that CentOS release.
When both a version of CentOS and a version of .NET have ✔ ️ , that OS and .NET combination is supported.
C EN TO S . N ET C O RE 3. 1 . N ET 6
️ 7
✔ ️ 3.1
✔ ️ 6.0
✔
❌ 8* ️ 3.1
✔ ❌ 6.0
WARNING
*CentOS 8 reached an early End Of Life (EOL) on December 31st, 2021. For more information, see the official CentOS
Linux EOL page. Because of this, .NET 6 won't be supported on CentOS Linux 8.
IMPORTANT
Package manager installs are only supported on the x64 architecture. Other architectures, such as Arm , must install .NET
by some other means such as with Snap, an installer script, or through a manual binary installation.
For more information on installing .NET without a package manager , see one of the following articles:
Alternatively install .NET with Snap.
Alternatively install .NET with install-dotnet script.
Manually install .NET
CentOS 7 ✔
️
Before you install .NET, run the following commands to add the Microsoft package signing key to your list of
trusted keys and add the Microsoft package repository. Open a terminal and run the following commands:
As an alternative to the ASP.NET Core Runtime, you can install the .NET Runtime, which doesn't include ASP.NET
Core support: replace aspnetcore-runtime-6.0 in the previous command with dotnet-runtime-6.0 :
CentOS 8 ✔
️
WARNING
*CentOS 8 will reach an early End Of Life (EOL) on December 31st, 2021. For more information, see the official CentOS
Linux EOL page. Because of this, .NET 6 won't be supported on CentOS Linux 8.
As an alternative to the ASP.NET Core Runtime, you can install the .NET Runtime, which doesn't include ASP.NET
Core support: replace aspnetcore-runtime-5.0 in the previous command with dotnet-runtime-5.0 :
product
The type of .NET product to install. Valid options are:
dotnet
aspnetcore
type
Chooses the SDK or the runtime. Valid options are:
sdk
runtime
version
The version of the SDK or runtime to install. This article will always give the instructions for the latest
supported version. Valid options are any released version, such as:
5.0
3.1
3.0
2.1
It's possible the SDK/runtime you're trying to download is not available for your Linux distribution. For a
list of supported distributions, see Install .NET on Linux.
Examples
Install the ASP.NET Core 5.0 runtime: aspnetcore-runtime-5.0
Install the .NET Core 2.1 runtime: dotnet-runtime-2.1
Install the .NET 5 SDK: dotnet-sdk-5.0
Install the .NET Core 3.1 SDK: dotnet-sdk-3.1
Package missing
If the package-version combination doesn't work, it's not available. For example, there isn't an ASP.NET Core
SDK, the SDK components are included with the .NET SDK. The value aspnetcore-sdk-2.2 is incorrect and should
be dotnet-sdk-2.2 . For a list of Linux distributions supported by .NET, see .NET dependencies and requirements.
IMPORTANT
Package manager installs are only supported on the x64 architecture. Other architectures, such as Arm , must install .NET
by some other means such as with Snap, an installer script, or through a manual binary installation.
For more information on installing .NET without a package manager , see one of the following articles:
Alternatively install .NET with Snap.
Alternatively install .NET with install-dotnet script.
Manually install .NET
Failed to fetch
While installing the .NET package, you may see an error similar to
signature verification failed for file 'repomd.xml' from repository 'packages-microsoft-com-prod' . Generally
speaking, this error means that the package feed for .NET is being upgraded with newer package versions, and
that you should try again later. During an upgrade, the package feed should not be unavailable for more than 2
hours. If you continually receive this error for more than 2 hours, please file an issue at
https://github.com/dotnet/core/issues.
Errors related to missing fxr , libhostfxr.so , or FrameworkList.xml
For more information about solving these problems, see Troubleshoot fxr , libhostfxr.so , and
FrameworkList.xml errors.
Dependencies
When you install with a package manager, these libraries are installed for you. But, if you manually install .NET
Core or you publish a self-contained app, you'll need to make sure these libraries are installed:
krb5-libs
libicu
openssl-libs
zlib
If the target runtime environment's OpenSSL version is 1.1 or newer, you'll need to install compat-openssl10 .
For more information about the dependencies, see Self-contained Linux apps.
For .NET Core apps that use the System.Drawing.Common assembly, you'll also need the following dependency:
libgdiplus (version 6.0.1 or later)
WARNING
You can install a recent version of libgdiplus by adding the Mono repository to your system. For more
information, see https://www.mono-project.com/download/stable/.
Next steps
How to enable TAB completion for the .NET CLI
Tutorial: Create a console application with .NET SDK using Visual Studio Code
Install the .NET SDK or the .NET Runtime on RHEL
and CentOS Stream
9/10/2022 • 8 minutes to read • Edit Online
.NET is supported on Red Hat Enterprise Linux (RHEL). This article describes how to install .NET on RHEL and
CentOS Stream.
Install the SDK (which includes the runtime) if you want to develop .NET apps. Or, if you only need to run apps,
install the Runtime. If you're installing the Runtime, we suggest you install the ASP.NET Core Runtime as it
includes both .NET and ASP.NET Core runtimes.
If you've already installed the SDK or Runtime, use the dotnet --list-sdks and dotnet --list-runtimes
commands to see which versions are installed. For more information, see How to check that .NET is already
installed.
IMPORTANT
This doesn't apply to CentOS Stream.
Supported distributions
The following table is a list of currently supported .NET releases on both RHEL and CentOS Stream. These
versions remain supported until either the version of .NET reaches end-of-support or the Linux distribution is no
longer supported.
A✔️ indicates that the version of RHEL or .NET is still supported.
A ❌ indicates that the version of RHEL or .NET isn't supported on that RHEL release.
When both a version of Linux distribution and a version of .NET have ✔
️ , that OS and .NET combination is
supported.
DIST RIB UT IO N . N ET C O RE 3. 1 . N ET 6
️ RHEL 8
✔ ️ 3.1
✔ ️ 6.0
✔
️ RHEL 7
✔ ️ 3.1
✔ ️ 6.0
✔
️ CentOS Stream 9
✔ ❌ 3.1 ️ 6.0
✔
️ CentOS Stream 8
✔ ️ 3.1
✔ ️ 6.0
✔
RHEL 8 ✔
️
.NET is included in the AppStream repositories for RHEL 8.
Install the SDK
The .NET SDK allows you to develop apps with .NET. If you install the .NET SDK, you don't need to install the
corresponding runtime. To install the .NET SDK, run the following command:
As an alternative to the ASP.NET Core Runtime, you can install the .NET Runtime, which doesn't include ASP.NET
Core support: replace aspnetcore-runtime-6.0 in the previous command with dotnet-runtime-6.0 :
RHEL 7 ✔
️ .NET 6.0
The following command installs the scl-utils package:
Red Hat does not recommend permanently enabling rh-dotnet60 because it may affect other programs. If you
want to enable rh-dotnet permanently, add the following line to your ~/.bashrc file.
Red Hat does not recommend permanently enabling rh-dotnet60 because it may affect other programs. If you
want to enable rh-dotnet60 permanently, add the following line to your ~/.bashrc file.
As an alternative to the ASP.NET Core Runtime, you can install the .NET Runtime that doesn't include ASP.NET
Core support: replace rh-dotnet60-aspnetcore-runtime-6.0 in the preceding command with
rh-dotnet60-dotnet-runtime-6.0 .
RHEL 7 ✔
️ .NET 5.0
The following command installs the scl-utils package:
Red Hat does not recommend permanently enabling rh-dotnet50 because it may affect other programs. If you
want to enable rh-dotnet permanently, add the following line to your ~/.bashrc file.
Red Hat does not recommend permanently enabling rh-dotnet50 because it may affect other programs. If you
want to enable rh-dotnet50 permanently, add the following line to your ~/.bashrc file.
As an alternative to the ASP.NET Core Runtime, you can install the .NET Runtime that doesn't include ASP.NET
Core support: replace rh-dotnet50-aspnetcore-runtime-5.0 in the commands above with
rh-dotnet50-dotnet-runtime-5.0 .
RHEL 7 ✔
️ .NET Core 3.1
Before you install .NET, run the following commands to add the Microsoft package signing key to your list of
trusted keys and add the Microsoft package repository. Open a terminal and run the following commands:
The following command installs the scl-utils package:
Red Hat does not recommend permanently enabling rh-dotnet31 because it may affect other programs. For
example, rh-dotnet31 includes a version of libcurl that differs from the base RHEL version. This may lead to
issues in programs that do not expect a different version of libcurl . If you want to enable rh-dotnet
permanently, add the following line to your ~/.bashrc file.
Red Hat does not recommend permanently enabling rh-dotnet31 because it may affect other programs. For
example, rh-dotnet31 includes a version of libcurl that differs from the base RHEL version. This may lead to
issues in programs that do not expect a different version of libcurl . If you want to enable rh-dotnet31
permanently, add the following line to your ~/.bashrc file.
As an alternative to the ASP.NET Core Runtime, you can install the .NET Core Runtime that doesn't include
ASP.NET Core support: replace rh-dotnet31-aspnetcore-runtime-3.1 in the commands above with
rh-dotnet31-dotnet-runtime-3.1 .
CentOS Stream 9 ✔
️
.NET is included in the AppStream repositories for CentOS Stream 9. However, .NET Core 3.1 and .NET 5 have
been removed from CentOS Stream 9 and you should use .NET 6. For more information, see the blog post Using
.NET with OpenSSL in CentOS Stream 9 | Omair Majid.
Install the SDK
The .NET SDK allows you to develop apps with .NET. If you install the .NET SDK, you don't need to install the
corresponding runtime. To install the .NET SDK, run the following command:
As an alternative to the ASP.NET Core Runtime, you can install the .NET Runtime, which doesn't include ASP.NET
Core support: replace aspnetcore-runtime-6.0 in the previous command with dotnet-runtime-6.0 :
CentOS Stream 8 ✔
️
.NET is included in the AppStream repositories for CentOS Stream 8.
Install the SDK
The .NET SDK allows you to develop apps with .NET. If you install the .NET SDK, you don't need to install the
corresponding runtime. To install the .NET SDK, run the following command:
Dependencies
When you install with a package manager, these libraries are installed for you. But, if you manually install .NET
Core or you publish a self-contained app, you'll need to make sure these libraries are installed:
krb5-libs
libicu
openssl-libs
zlib
If the target runtime environment's OpenSSL version is 1.1 or newer, you'll need to install compat-openssl10 .
For more information about the dependencies, see Self-contained Linux apps.
For .NET Core apps that use the System.Drawing.Common assembly, you'll also need the following dependency:
libgdiplus (version 6.0.1 or later)
WARNING
You can install a recent version of libgdiplus by adding the Mono repository to your system. For more
information, see https://www.mono-project.com/download/stable/.
For more information about solving these problems, see Troubleshoot fxr , libhostfxr.so , and
FrameworkList.xml errors.
Next steps
How to enable TAB completion for the .NET CLI
Tutorial: Create a console application with .NET SDK using Visual Studio Code
Install the .NET SDK or the .NET Runtime on
Debian
9/10/2022 • 10 minutes to read • Edit Online
This article describes how to install .NET on Debian. When a Debian version falls out of support, .NET is no
longer supported with that version. However, these instructions may help you to get .NET running on those
versions, even though it isn't supported.
Install the SDK (which includes the runtime) if you want to develop .NET apps. Or, if you only need to run apps,
install the Runtime. If you're installing the Runtime, we suggest you install the ASP.NET Core Runtime as it
includes both .NET and ASP.NET Core runtimes.
If you've already installed the SDK or Runtime, use the dotnet --list-sdks and dotnet --list-runtimes
commands to see which versions are installed. For more information, see How to check that .NET is already
installed.
IMPORTANT
Package manager installs are only supported on the x64 architecture. Other architectures, such as Arm , must install .NET
by some other means such as with Snap, an installer script, or through a manual binary installation.
For more information on installing .NET without a package manager , see one of the following articles:
Alternatively install .NET with Snap.
Alternatively install .NET with install-dotnet script.
Manually install .NET
Supported distributions
The following table is a list of currently supported .NET releases and the versions of Debian they're supported
on. These versions remain supported until either the version of .NET reaches end-of-support or the version of
Debian reaches end-of-life.
A✔️ indicates that the version of Debian or .NET is still supported.
A ❌ indicates that the version of Debian or .NET isn't supported on that Debian release.
When both a version of Debian and a version of .NET have ✔ ️ , that OS and .NET combination is supported.
DEB IA N . N ET C O RE 3. 1 . N ET 6
️ 11
✔ ️ 3.1
✔ ️ 6.0
✔
️ 10
✔ ️ 3.1
✔ ️ 6.0
✔
️ 9
✔ ️ 3.1
✔ ️ 6.0
✔
❌8 ❌ 3.1 ❌ 6.0
Debian 11 ✔
️
Installing with APT can be done with a few commands. Before you install .NET, run the following commands to
add the Microsoft package signing key to your list of trusted keys and add the package repository.
Open a terminal and run the following commands:
IMPORTANT
If you receive an error message similar to Unable to locate package dotnet-sdk-6.0 , see the APT troubleshooting
section.
IMPORTANT
If you receive an error message similar to Unable to locate package aspnetcore-runtime-6.0 , see the APT
troubleshooting section.
As an alternative to the ASP.NET Core Runtime, you can install the .NET Runtime, which doesn't include ASP.NET
Core support: replace aspnetcore-runtime-6.0 in the previous command with dotnet-runtime-6.0 :
Debian 10 ✔
️
Installing with APT can be done with a few commands. Before you install .NET, run the following commands to
add the Microsoft package signing key to your list of trusted keys and add the package repository.
Open a terminal and run the following commands:
IMPORTANT
If you receive an error message similar to Unable to locate package dotnet-sdk-6.0 , see the APT troubleshooting
section.
IMPORTANT
If you receive an error message similar to Unable to locate package aspnetcore-runtime-6.0 , see the APT
troubleshooting section.
As an alternative to the ASP.NET Core Runtime, you can install the .NET Runtime, which doesn't include ASP.NET
Core support: replace aspnetcore-runtime-6.0 in the previous command with dotnet-runtime-6.0 :
Debian 9 ✔
️
Installing with APT can be done with a few commands. Before you install .NET, run the following commands to
add the Microsoft package signing key to your list of trusted keys and add the package repository.
Open a terminal and run the following commands:
IMPORTANT
If you receive an error message similar to Unable to locate package dotnet-sdk-6.0 , see the APT troubleshooting
section.
IMPORTANT
If you receive an error message similar to Unable to locate package aspnetcore-runtime-6.0 , see the APT
troubleshooting section.
As an alternative to the ASP.NET Core Runtime, you can install the .NET Runtime, which doesn't include ASP.NET
Core support: replace aspnetcore-runtime-6.0 in the previous command with dotnet-runtime-6.0 :
IMPORTANT
If you receive an error message similar to Unable to locate package dotnet-sdk-2.1 , see the APT troubleshooting
section.
IMPORTANT
If you receive an error message similar to Unable to locate package aspnetcore-runtime-2.1 , see the APT
troubleshooting section.
As an alternative to the ASP.NET Core Runtime, you can install the .NET Core Runtime, which doesn't include
ASP.NET Core support: replace aspnetcore-runtime-2.1 in the previous command with dotnet-runtime-2.1 .
product
The type of .NET product to install. Valid options are:
dotnet
aspnetcore
type
Chooses the SDK or the runtime. Valid options are:
sdk
runtime
version
The version of the SDK or runtime to install. This article will always give the instructions for the latest
supported version. Valid options are any released version, such as:
5.0
3.1
3.0
2.1
It's possible the SDK/runtime you're trying to download is not available for your Linux distribution. For a
list of supported distributions, see Install .NET on Linux.
Examples
Install the ASP.NET Core 5.0 runtime: aspnetcore-runtime-5.0
Install the .NET Core 2.1 runtime: dotnet-runtime-2.1
Install the .NET 5 SDK: dotnet-sdk-5.0
Install the .NET Core 3.1 SDK: dotnet-sdk-3.1
Package missing
If the package-version combination doesn't work, it's not available. For example, there isn't an ASP.NET Core
SDK, the SDK components are included with the .NET SDK. The value aspnetcore-sdk-2.2 is incorrect and should
be dotnet-sdk-2.2 . For a list of Linux distributions supported by .NET, see .NET dependencies and requirements.
If you've upgraded your Linux distribution since installing .NET, you may need to reconfigure the Microsoft
package repository. Run the installation instructions for your current distribution version to upgrade to the
appropriate package repository for .NET updates.
APT troubleshooting
This section provides information on common errors you may get while using APT to install .NET.
Unable to find package
IMPORTANT
Package manager installs are only supported on the x64 architecture. Other architectures, such as Arm , must install .NET
by some other means such as with Snap, an installer script, or through a manual binary installation.
For more information on installing .NET without a package manager , see one of the following articles:
Alternatively install .NET with Snap.
Alternatively install .NET with install-dotnet script.
Manually install .NET
Unable to locate \ Some packages could not be installed
If you receive an error message similar to Unable to locate package {dotnet-package} or Some packages
could not be installed , run the following commands.
There are two placeholders in the following set of commands.
{dotnet-package}
This represents the .NET package you're installing, such as aspnetcore-runtime-3.1 . This is used in the
following sudo apt-get install command.
{os-version}
This represents the distribution version you're on. This is used in the wget command below. The
distribution version is the numerical value, such as 20.04 on Ubuntu or 10 on Debian.
Then, try to install .NET again. If that doesn't work, you can run a manual install with the following commands:
Failed to fetch
While installing the .NET package, you may see an error similar to
Failed to fetch ... File has unexpected size ... Mirror sync in progress? . This error could mean that the
package feed for .NET is being upgraded with newer package versions, and that you should try again later.
During an upgrade, the package feed shouldn't be unavailable for more than 30 minutes. If you continually
receive this error for more than 30 minutes, please file an issue at https://github.com/dotnet/core/issues.
Dependencies
When you install with a package manager, these libraries are installed for you. But, if you manually install .NET
Core or you publish a self-contained app, you'll need to make sure these libraries are installed:
libc6
libgcc-s1
libgssapi-krb5-2
libicu52 (for 8.x)
libicu57 (for 9.x)
libicu63 (for 10.x)
libicu67 (for 11.x)
libssl1.0.0 (for 8.x)
libssl1.1 (for 9.x-11.x)
libstdc++6
zlib1g
For .NET Core apps that use the System.Drawing.Common assembly, you also need the following dependency:
libgdiplus (version 6.0.1 or later)
WARNING
You can install a recent version of libgdiplus by adding the Mono repository to your system. For more
information, see https://www.mono-project.com/download/stable/.
Next steps
How to enable TAB completion for the .NET CLI
Tutorial: Create a console application with .NET SDK using Visual Studio Code
Install the .NET SDK or the .NET Runtime on Fedora
9/10/2022 • 7 minutes to read • Edit Online
.NET is supported on Fedora and this article describes how to install .NET on Fedora. When a Fedora version
falls out of support, .NET is no longer supported with that version.
Install the SDK (which includes the runtime) if you want to develop .NET apps. Or, if you only need to run apps,
install the Runtime. If you're installing the Runtime, we suggest you install the ASP.NET Core Runtime as it
includes both .NET and ASP.NET Core runtimes.
If you've already installed the SDK or Runtime, use the dotnet --list-sdks and dotnet --list-runtimes
commands to see which versions are installed. For more information, see How to check that .NET is already
installed.
For more information on installing .NET without a package manager, see one of the following articles:
Install the .NET SDK or the .NET Runtime with Snap.
Install the .NET SDK or the .NET Runtime with a script.
Install the .NET SDK or the .NET Runtime manually.
Install .NET 6
Install the SDK
The .NET SDK allows you to develop apps with .NET. If you install the .NET SDK, you don't need to install the
corresponding runtime. To install the .NET SDK, run the following command:
As an alternative to the ASP.NET Core Runtime, you can install the .NET Runtime, which doesn't include ASP.NET
Core support: replace aspnetcore-runtime-6.0 in the previous command with dotnet-runtime-6.0 :
As an alternative to the ASP.NET Core Runtime, you can install the .NET Core Runtime, which doesn't include
ASP.NET Core support: replace aspnetcore-runtime-3.1 in the previous command with dotnet-runtime-3.1 .
Supported distributions
The following table is a list of currently supported .NET releases and the versions of Fedora they're supported
on. These versions remain supported until either the version of .NET reaches end-of-support or the version of
Fedora reaches end-of-life.
A✔️ indicates that the version of Fedora or .NET is still supported.
A ❌ indicates that the version of Fedora or .NET isn't supported on that Fedora release.
When both a version of Fedora and a version of .NET have ✔ ️ , that OS and .NET combination is supported.
. N ET F EDO R
VERSIO A 36
N ️
✔ 35 ✔
️ 34 ❌ 33 ❌ 32 ❌ 31 ❌ 30 ❌ 29 ❌ 28 ❌ 27 ❌
.NET 6 ️
✔ ️
✔ ️
✔ ❌ ❌ ❌ ❌ ❌ ❌ ❌
.NET ️
✔ ️
✔ ️
✔ ️
✔ ️
✔ ️
✔ ️
✔ ️
✔ ❌ ❌
Core
3.1
Dependencies
When you install with a package manager, these libraries are installed for you. But, if you manually install .NET
Core or you publish a self-contained app, you'll need to make sure these libraries are installed:
krb5-libs
libicu
openssl-libs
zlib
If the target runtime environment's OpenSSL version is 1.1 or newer, you'll need to install compat-openssl10 .
For more information about the dependencies, see Self-contained Linux apps.
For .NET Core apps that use the System.Drawing.Common assembly, you'll also need the following dependency:
libgdiplus (version 6.0.1 or later)
WARNING
You can install a recent version of libgdiplus by adding the Mono repository to your system. For more
information, see https://www.mono-project.com/download/stable/.
2. Next, add the Microsoft package repository. The source of the repository is based on your version of
Fedora.
33 https://packages.microsoft.com/config/fedora/33/prod.repo
32 https://packages.microsoft.com/config/fedora/32/prod.repo
31 https://packages.microsoft.com/config/fedora/31/prod.repo
30 https://packages.microsoft.com/config/fedora/30/prod.repo
29 https://packages.microsoft.com/config/fedora/29/prod.repo
28 https://packages.microsoft.com/config/fedora/28/prod.repo
27 https://packages.microsoft.com/config/fedora/27/prod.repo
sudo wget -O /etc/yum.repos.d/microsoft-prod.repo
https://packages.microsoft.com/config/fedora/31/prod.repo
As an alternative to the ASP.NET Core Runtime, you can install the .NET Core Runtime, which doesn't include
ASP.NET Core support: replace aspnetcore-runtime-3.1 in the previous command with dotnet-runtime-3.1 .
product
The type of .NET product to install. Valid options are:
dotnet
aspnetcore
type
Chooses the SDK or the runtime. Valid options are:
sdk
runtime
version
The version of the SDK or runtime to install. This article will always give the instructions for the latest
supported version. Valid options are any released version, such as:
5.0
3.1
3.0
2.1
It's possible the SDK/runtime you're trying to download is not available for your Linux distribution. For a
list of supported distributions, see Install .NET on Linux.
Examples
Install the ASP.NET Core 5.0 runtime: aspnetcore-runtime-5.0
Install the .NET Core 2.1 runtime: dotnet-runtime-2.1
Install the .NET 5 SDK: dotnet-sdk-5.0
Install the .NET Core 3.1 SDK: dotnet-sdk-3.1
Package missing
If the package-version combination doesn't work, it's not available. For example, there isn't an ASP.NET Core
SDK, the SDK components are included with the .NET SDK. The value aspnetcore-sdk-2.2 is incorrect and should
be dotnet-sdk-2.2 . For a list of Linux distributions supported by .NET, see .NET dependencies and requirements.
For more information about solving these problems, see Troubleshoot fxr , libhostfxr.so , and
FrameworkList.xml errors.
Next steps
How to enable TAB completion for the .NET CLI
Tutorial: Create a console application with .NET SDK using Visual Studio Code
Install the .NET SDK or the .NET Runtime on
openSUSE
9/10/2022 • 5 minutes to read • Edit Online
.NET is supported on openSUSE. This article describes how to install .NET on openSUSE.
Install the SDK (which includes the runtime) if you want to develop .NET apps. Or, if you only need to run apps,
install the Runtime. If you're installing the Runtime, we suggest you install the ASP.NET Core Runtime as it
includes both .NET and ASP.NET Core runtimes.
If you've already installed the SDK or Runtime, use the dotnet --list-sdks and dotnet --list-runtimes
commands to see which versions are installed. For more information, see How to check that .NET is already
installed.
IMPORTANT
Package manager installs are only supported on the x64 architecture. Other architectures, such as Arm , must install .NET
by some other means such as with Snap, an installer script, or through a manual binary installation.
For more information on installing .NET without a package manager , see one of the following articles:
Alternatively install .NET with Snap.
Alternatively install .NET with install-dotnet script.
Manually install .NET
Supported distributions
The following table is a list of currently supported .NET releases on openSUSE 15. These versions remain
supported until either the version of .NET reaches end-of-support or the version of openSUSE is no longer
supported.
A✔️ indicates that the version of openSUSE or .NET is still supported.
A ❌ indicates that the version of openSUSE or .NET isn't supported on that openSUSE release.
When both a version of openSUSE and a version of .NET have ✔ ️ , that OS and .NET combination is
supported.
O P EN SUSE . N ET C O RE 3. 1 . N ET 6
️ 15
✔ ️ 3.1
✔ ️ 6.0
✔
openSUSE 15 ✔
️
Before you install .NET, run the following commands to add the Microsoft package signing key to your list of
trusted keys and add the Microsoft package repository. Open a terminal and run the following commands:
As an alternative to the ASP.NET Core Runtime, you can install the .NET Runtime, which doesn't include ASP.NET
Core support: replace aspnetcore-runtime-6.0 in the previous command with dotnet-runtime-6.0 :
IMPORTANT
Package manager installs are only supported on the x64 architecture. Other architectures, such as Arm , must install .NET
by some other means such as with Snap, an installer script, or through a manual binary installation.
For more information on installing .NET without a package manager , see one of the following articles:
Alternatively install .NET with Snap.
Alternatively install .NET with install-dotnet script.
Manually install .NET
Failed to fetch
While installing the .NET package, you may see an error similar to
signature verification failed for file 'repomd.xml' from repository 'packages-microsoft-com-prod' . Generally
speaking, this error means that the package feed for .NET is being upgraded with newer package versions, and
that you should try again later. During an upgrade, the package feed should not be unavailable for more than 2
hours. If you continually receive this error for more than 2 hours, please file an issue at
https://github.com/dotnet/core/issues.
Dependencies
When you install with a package manager, these libraries are installed for you. But, if you manually install .NET
or you publish a self-contained app, you'll need to make sure these libraries are installed:
krb5
libicu
libopenssl1_0_0
If the target runtime environment's OpenSSL version is 1.1 or newer, you'll need to install compat-openssl10 .
For more information about the dependencies, see Self-contained Linux apps.
For .NET apps that use the System.Drawing.Common assembly, you'll also need the following dependency:
libgdiplus (version 6.0.1 or later)
WARNING
You can install a recent version of libgdiplus by adding the Mono repository to your system. For more
information, see https://www.mono-project.com/download/stable/.
Next steps
How to enable TAB completion for the .NET CLI
Tutorial: Create a console application with .NET SDK using Visual Studio Code
Install the .NET SDK or the .NET Runtime on RHEL
and CentOS Stream
9/10/2022 • 8 minutes to read • Edit Online
.NET is supported on Red Hat Enterprise Linux (RHEL). This article describes how to install .NET on RHEL and
CentOS Stream.
Install the SDK (which includes the runtime) if you want to develop .NET apps. Or, if you only need to run apps,
install the Runtime. If you're installing the Runtime, we suggest you install the ASP.NET Core Runtime as it
includes both .NET and ASP.NET Core runtimes.
If you've already installed the SDK or Runtime, use the dotnet --list-sdks and dotnet --list-runtimes
commands to see which versions are installed. For more information, see How to check that .NET is already
installed.
IMPORTANT
This doesn't apply to CentOS Stream.
Supported distributions
The following table is a list of currently supported .NET releases on both RHEL and CentOS Stream. These
versions remain supported until either the version of .NET reaches end-of-support or the Linux distribution is no
longer supported.
A✔️ indicates that the version of RHEL or .NET is still supported.
A ❌ indicates that the version of RHEL or .NET isn't supported on that RHEL release.
When both a version of Linux distribution and a version of .NET have ✔
️ , that OS and .NET combination is
supported.
DIST RIB UT IO N . N ET C O RE 3. 1 . N ET 6
️ RHEL 8
✔ ️ 3.1
✔ ️ 6.0
✔
️ RHEL 7
✔ ️ 3.1
✔ ️ 6.0
✔
️ CentOS Stream 9
✔ ❌ 3.1 ️ 6.0
✔
️ CentOS Stream 8
✔ ️ 3.1
✔ ️ 6.0
✔
RHEL 8 ✔
️
.NET is included in the AppStream repositories for RHEL 8.
Install the SDK
The .NET SDK allows you to develop apps with .NET. If you install the .NET SDK, you don't need to install the
corresponding runtime. To install the .NET SDK, run the following command:
As an alternative to the ASP.NET Core Runtime, you can install the .NET Runtime, which doesn't include ASP.NET
Core support: replace aspnetcore-runtime-6.0 in the previous command with dotnet-runtime-6.0 :
RHEL 7 ✔
️ .NET 6.0
The following command installs the scl-utils package:
Red Hat does not recommend permanently enabling rh-dotnet60 because it may affect other programs. If you
want to enable rh-dotnet permanently, add the following line to your ~/.bashrc file.
Red Hat does not recommend permanently enabling rh-dotnet60 because it may affect other programs. If you
want to enable rh-dotnet60 permanently, add the following line to your ~/.bashrc file.
As an alternative to the ASP.NET Core Runtime, you can install the .NET Runtime that doesn't include ASP.NET
Core support: replace rh-dotnet60-aspnetcore-runtime-6.0 in the preceding command with
rh-dotnet60-dotnet-runtime-6.0 .
RHEL 7 ✔
️ .NET 5.0
The following command installs the scl-utils package:
Red Hat does not recommend permanently enabling rh-dotnet50 because it may affect other programs. If you
want to enable rh-dotnet permanently, add the following line to your ~/.bashrc file.
Red Hat does not recommend permanently enabling rh-dotnet50 because it may affect other programs. If you
want to enable rh-dotnet50 permanently, add the following line to your ~/.bashrc file.
As an alternative to the ASP.NET Core Runtime, you can install the .NET Runtime that doesn't include ASP.NET
Core support: replace rh-dotnet50-aspnetcore-runtime-5.0 in the commands above with
rh-dotnet50-dotnet-runtime-5.0 .
RHEL 7 ✔
️ .NET Core 3.1
Before you install .NET, run the following commands to add the Microsoft package signing key to your list of
trusted keys and add the Microsoft package repository. Open a terminal and run the following commands:
The following command installs the scl-utils package:
Red Hat does not recommend permanently enabling rh-dotnet31 because it may affect other programs. For
example, rh-dotnet31 includes a version of libcurl that differs from the base RHEL version. This may lead to
issues in programs that do not expect a different version of libcurl . If you want to enable rh-dotnet
permanently, add the following line to your ~/.bashrc file.
Red Hat does not recommend permanently enabling rh-dotnet31 because it may affect other programs. For
example, rh-dotnet31 includes a version of libcurl that differs from the base RHEL version. This may lead to
issues in programs that do not expect a different version of libcurl . If you want to enable rh-dotnet31
permanently, add the following line to your ~/.bashrc file.
As an alternative to the ASP.NET Core Runtime, you can install the .NET Core Runtime that doesn't include
ASP.NET Core support: replace rh-dotnet31-aspnetcore-runtime-3.1 in the commands above with
rh-dotnet31-dotnet-runtime-3.1 .
CentOS Stream 9 ✔
️
.NET is included in the AppStream repositories for CentOS Stream 9. However, .NET Core 3.1 and .NET 5 have
been removed from CentOS Stream 9 and you should use .NET 6. For more information, see the blog post Using
.NET with OpenSSL in CentOS Stream 9 | Omair Majid.
Install the SDK
The .NET SDK allows you to develop apps with .NET. If you install the .NET SDK, you don't need to install the
corresponding runtime. To install the .NET SDK, run the following command:
As an alternative to the ASP.NET Core Runtime, you can install the .NET Runtime, which doesn't include ASP.NET
Core support: replace aspnetcore-runtime-6.0 in the previous command with dotnet-runtime-6.0 :
CentOS Stream 8 ✔
️
.NET is included in the AppStream repositories for CentOS Stream 8.
Install the SDK
The .NET SDK allows you to develop apps with .NET. If you install the .NET SDK, you don't need to install the
corresponding runtime. To install the .NET SDK, run the following command:
Dependencies
When you install with a package manager, these libraries are installed for you. But, if you manually install .NET
Core or you publish a self-contained app, you'll need to make sure these libraries are installed:
krb5-libs
libicu
openssl-libs
zlib
If the target runtime environment's OpenSSL version is 1.1 or newer, you'll need to install compat-openssl10 .
For more information about the dependencies, see Self-contained Linux apps.
For .NET Core apps that use the System.Drawing.Common assembly, you'll also need the following dependency:
libgdiplus (version 6.0.1 or later)
WARNING
You can install a recent version of libgdiplus by adding the Mono repository to your system. For more
information, see https://www.mono-project.com/download/stable/.
For more information about solving these problems, see Troubleshoot fxr , libhostfxr.so , and
FrameworkList.xml errors.
Next steps
How to enable TAB completion for the .NET CLI
Tutorial: Create a console application with .NET SDK using Visual Studio Code
Install the .NET SDK or the .NET Runtime on SLES
9/10/2022 • 5 minutes to read • Edit Online
.NET is supported on SLES. This article describes how to install .NET on SLES.
Install the SDK (which includes the runtime) if you want to develop .NET apps. Or, if you only need to run apps,
install the Runtime. If you're installing the Runtime, we suggest you install the ASP.NET Core Runtime as it
includes both .NET and ASP.NET Core runtimes.
If you've already installed the SDK or Runtime, use the dotnet --list-sdks and dotnet --list-runtimes
commands to see which versions are installed. For more information, see How to check that .NET is already
installed.
Supported distributions
The following table is a list of currently supported .NET releases on both SLES 12 SP2 and SLES 15. These
versions remain supported until either the version of .NET reaches end-of-support or the version of SLES is no
longer supported.
A✔️ indicates that the version of SLES or .NET is still supported.
A ❌ indicates that the version of SLES or .NET isn't supported on that SLES release.
When both a version of SLES and a version of .NET have ✔ ️ , that OS and .NET combination is supported.
SL ES . N ET C O RE 3. 1 . N ET 6
️ 15
✔ ️ 3.1
✔ ️ 6.0
✔
️ 12 SP2
✔ ️ 3.1
✔ ️ 6.0
✔
SLES 15 ✔
️
Before you install .NET, run the following commands to add the Microsoft package signing key to your list of
trusted keys and add the Microsoft package repository. Open a terminal and run the following commands:
Currently, the SLES 15 Microsoft repository setup package installs the microsoft-prod.repo file to the wrong
directory, preventing zypper from finding the .NET packages. To fix this problem, create a symlink in the correct
directory.
As an alternative to the ASP.NET Core Runtime, you can install the .NET Runtime, which doesn't include ASP.NET
Core support: replace aspnetcore-runtime-6.0 in the previous command with dotnet-runtime-6.0 :
SLES 12 ✔
️
.NET requires SP2 as a minimum for the SLES 12 family.
Before you install .NET, run the following commands to add the Microsoft package signing key to your list of
trusted keys and add the Microsoft package repository. Open a terminal and run the following commands:
As an alternative to the ASP.NET Core Runtime, you can install the .NET Runtime, which doesn't include ASP.NET
Core support: replace aspnetcore-runtime-6.0 in the previous command with dotnet-runtime-6.0 :
product
The type of .NET product to install. Valid options are:
dotnet
aspnetcore
type
Chooses the SDK or the runtime. Valid options are:
sdk
runtime
version
The version of the SDK or runtime to install. This article will always give the instructions for the latest
supported version. Valid options are any released version, such as:
5.0
3.1
3.0
2.1
It's possible the SDK/runtime you're trying to download is not available for your Linux distribution. For a
list of supported distributions, see Install .NET on Linux.
Examples
Install the ASP.NET Core 5.0 runtime: aspnetcore-runtime-5.0
Install the .NET Core 2.1 runtime: dotnet-runtime-2.1
Install the .NET 5 SDK: dotnet-sdk-5.0
Install the .NET Core 3.1 SDK: dotnet-sdk-3.1
Package missing
If the package-version combination doesn't work, it's not available. For example, there isn't an ASP.NET Core
SDK, the SDK components are included with the .NET SDK. The value aspnetcore-sdk-2.2 is incorrect and should
be dotnet-sdk-2.2 . For a list of Linux distributions supported by .NET, see .NET dependencies and requirements.
Troubleshoot the package manager
This section provides information on common errors you may get while using the package manager to install
.NET.
Failed to fetch
While installing the .NET package, you may see an error similar to
signature verification failed for file 'repomd.xml' from repository 'packages-microsoft-com-prod' . Generally
speaking, this error means that the package feed for .NET is being upgraded with newer package versions, and
that you should try again later. During an upgrade, the package feed should not be unavailable for more than 2
hours. If you continually receive this error for more than 2 hours, please file an issue at
https://github.com/dotnet/core/issues.
Dependencies
When you install with a package manager, these libraries are installed for you. But, if you manually install .NET
or you publish a self-contained app, you'll need to make sure these libraries are installed:
krb5
libicu
libopenssl1_1
If the target runtime environment's OpenSSL version is 1.1 or newer, you'll need to install compat-openssl10 .
For more information about the dependencies, see Self-contained Linux apps.
For .NET apps that use the System.Drawing.Common assembly, you'll also need the following dependency:
libgdiplus (version 6.0.1 or later)
WARNING
You can install a recent version of libgdiplus by adding the Mono repository to your system. For more
information, see https://www.mono-project.com/download/stable/.
Next steps
How to enable TAB completion for the .NET CLI
Tutorial: Create a console application with .NET SDK using Visual Studio Code
Install the .NET SDK or the .NET Runtime with Snap
9/10/2022 • 5 minutes to read • Edit Online
Use a Snap package to install the .NET SDK or .NET Runtime. Snaps are a great alternative to the package
manager built into your Linux distribution. This article describes how to install .NET through Snap.
A snap is a bundle of an app and its dependencies that works without modification across many different Linux
distributions. Snaps are discoverable and installable from the Snap Store. For more information about Snap, see
Getting started with Snap.
Cau t i on
Snap packages aren't supported in WSL2 on Windows 10. As an alternative, use the dotnet-install script or
the package manager for the particular WSL2 distribution. It's not recommended but you can try to enable snap
with an unsupported workaround from the snapcraft forums.
.NET releases
Only ✔️ supported versions of .NET SDK are available through Snap. All versions of the .NET Runtime are
available through snap starting with version 2.1. The following table lists the .NET (and .NET Core) releases:
️ SUP P O RT ED
✔ ❌ UN SUP P O RT ED
6 (LTS) 5
2.2
2.1
2.0
1.1
1.0
For more information about the life cycle of .NET releases, see .NET and .NET Core Support Policy.
SDK or Runtime
Install the SDK (which includes the runtime) if you want to develop .NET apps. Or, if you only need to run apps,
install the Runtime. If you're installing the Runtime, we suggest you install the ASP.NET Core Runtime as it
includes both .NET and ASP.NET Core runtimes.
If you've already installed the SDK or Runtime, use the dotnet --list-sdks and dotnet --list-runtimes
commands to see which versions are installed. For more information, see How to check that .NET is already
installed.
. N ET VERSIO N SN A P PA C K A GE O R C H A N N EL
5 5.0
Use the snap install command to install a .NET SDK snap package. Use the --channel parameter to indicate
which version to install. If this parameter is omitted, latest/stable is used. In this example, 6.0 is specified:
Next, register the dotnet command for the system with the snap alias command:
This command is formatted as: sudo snap alias {package}.{command} {alias} . You can choose any {alias}
name you would like. For example, you could name the command after the specific version installed by snap:
sudo snap alias dotnet-sdk.dotnet dotnet60 . When you use the command dotnet60 , you'll invoke this specific
version of .NET. But choosing a different alias is incompatible with most tutorials and examples as they expect a
dotnet command to be used.
. N ET VERSIO N SN A P PA C K A GE
6 (LTS) dotnet-runtime-60
5 dotnet-runtime-50
3.0 dotnet-runtime-30
2.2 dotnet-runtime-22
2.1 dotnet-runtime-21
Use the snap install command to install a .NET Runtime snap package. In this example, .NET 6 is installed:
Next, register the dotnet command for the system with the snap alias command:
sudo snap alias dotnet-runtime-60.dotnet dotnet
The command is formatted as: sudo snap alias {package}.{command} {alias} . You can choose any {alias}
name you would like. For example, you could name the command after the specific version installed by snap:
sudo snap alias dotnet-runtime-60.dotnet dotnet60 . When you use the command dotnet60 , you'll invoke a
specific version of .NET. But choosing a different alias is incompatible with most tutorials and examples as they
expect a dotnet command to be available.
export DOTNET_ROOT=/snap/dotnet-sdk/current
TIP
The preceding export command only sets the environment variable for the terminal session in which it was run.
You can edit your shell profile to permanently add the commands. There are a number of different shells available for
Linux and each has a different profile. For example:
Bash Shell: ~/.bash_profile, ~/.bashrc
Korn Shell: ~/.kshrc or .profile
Z Shell: ~/.zshrc or .zprofile
Edit the appropriate source file for your shell and add export DOTNET_ROOT=/snap/dotnet-sdk/current .
export SSL_CERT_FILE=[path-to-certificate-file]
export SSL_CERT_DIR=/dev/null
The certificate location will vary by distro. Here are the locations for the distros where the issue has been
experienced.
DIST RIB UT IO N LO C AT IO N
Fedora /etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem
OpenSUSE /etc/ssl/ca-bundle.pem
Solus /etc/ssl/certs/ca-certificates.crt
ln -s /snap/dotnet-sdk/current/dotnet /usr/local/bin/dotnet
You can also review these GitHub issues for information about these problems:
SDK resolver doesn't work with snap installations of SDK on Linux
It wasn't possible to find any installed .NET SDKs
The dotnet alias
It's possible that if you created the dotnet alias for the snap-installed .NET, you'll have a conflict. Use the
snap unalias dotnet command to remove it, and then add a different alias if you want.
Next steps
How to enable TAB completion for the .NET CLI
Tutorial: Create a console application with .NET SDK using Visual Studio Code
Install .NET on Linux by using an install script or by
extracting binaries
9/10/2022 • 4 minutes to read • Edit Online
This article demonstrates how to install the .NET SDK or the .NET Runtime on Linux by using the install script or
by extracting the binaries. For a list of distributions that support the built-in package manager, see Install .NET on
Linux.
You can also install .NET with snap. For more information, see Install the .NET SDK or the .NET Runtime with
Snap.
Install the SDK (which includes the runtime) if you want to develop .NET apps. Or, if you only need to run apps,
install the Runtime. If you're installing the Runtime, we suggest you install the ASP.NET Core Runtime as it
includes both .NET and ASP.NET Core runtimes.
If you've already installed the SDK or Runtime, use the dotnet --list-sdks and dotnet --list-runtimes
commands to see which versions are installed. For more information, see How to check that .NET is already
installed.
.NET releases
The following table lists the .NET (and .NET Core) releases:
️ SUP P O RT ED
✔ ❌ UN SUP P O RT ED
6 (LTS) 5
2.2
2.1
2.0
1.1
1.0
For more information about the life cycle of .NET releases, see .NET and .NET Core Support Policy.
Dependencies
It's possible that when you install .NET, specific dependencies may not be installed, such as when manually
installing. The following list details Linux distributions that are supported by Microsoft and have dependencies
you may need to install. Check the distribution page for more information:
Alpine
Debian
CentOS
Fedora
RHEL and CentOS Stream
SLES
Ubuntu
For generic information about the dependencies, see Self-contained Linux apps.
RPM dependencies
If your distribution wasn't previously listed, and is RPM-based, you may need the following dependencies:
krb5-libs
libicu
openssl-libs
If the target runtime environment's OpenSSL version is 1.1 or newer, you'll need to install compat-openssl10 .
DEB dependencies
If your distribution wasn't previously listed, and is debian-based, you may need the following dependencies:
libc6
libgcc1
libgssapi-krb5-2
libicu67
libssl1.1
libstdc++6
zlib1g
Common dependencies
For .NET apps that use the System.Drawing.Common assembly, you'll also need the following dependency:
libgdiplus (version 6.0.1 or later)
WARNING
You can install a recent version of libgdiplus by adding the Mono repository to your system. For more
information, see https://www.mono-project.com/download/stable/.
Scripted install
The dotnet-install scripts are used for automation and non-admin installs of the SDK and Runtime . You can
download the script from https://dot.net/v1/dotnet-install.sh.
IMPORTANT
Bash is required to run the script.
Before running this script, you'll need to grant permission for this script to run as an executable:
The script defaults to installing the latest SDK long term support (LTS) version, which is .NET 6. To install the
current release, which may not be an (LTS) version, use the -c Current parameter.
./dotnet-install.sh -c Current
To install .NET Runtime instead of the SDK, use the --runtime parameter.
You can install a specific version by altering the -c parameter to indicate the specific version. The following
command installs .NET SDK 6.0.
./dotnet-install.sh -c 6.0
Manual install
As an alternative to the package managers, you can download and manually install the SDK and runtime.
Manual installation is commonly used as part of continuous integration testing or on an unsupported Linux
distribution. For a developer or user, it's better to use a package manager.
First, download a binar y release for either the SDK or the runtime from one of the following sites. If you install
the .NET SDK, you will not need to install the corresponding runtime:
✔ .NET 6 downloads
️
️ .NET Core 3.1 downloads
✔
All .NET Core downloads
Next, extract the downloaded file and use the export command to set DOTNET_ROOT to the extracted folder's
location and then ensure .NET is in PATH. This should make the .NET CLI commands available at the terminal.
Alternatively, after downloading the .NET binary, the following commands may be run from the directory where
the file is saved to extract the runtime. This will also make the .NET CLI commands available at the terminal and
set the required environment variables. Remember to change the DOTNET_FILE value to the name of the
downloaded binar y :
DOTNET_FILE=dotnet-sdk-6.0.100-linux-x64.tar.gz
export DOTNET_ROOT=$(pwd)/.dotnet
export PATH=$PATH:$DOTNET_ROOT:$DOTNET_ROOT/tools
This approach lets you install different versions into separate locations and choose explicitly which one to use by
which application.
Set environment variables system-wide
If you used the previous install script, the variables set only apply to your current terminal session. Add them to
your shell profile. There are a number of different shells available for Linux and each has a different profile. For
example:
Bash Shell : ~/.bash_profile, ~/.bashrc
Korn Shell : ~/.kshrc or .profile
Z Shell : ~/.zshrc or .zprofile
Set the following two environment variables in your shell profile:
DOTNET_ROOT
This variable is set to the folder .NET was installed to, such as $HOME/.dotnet :
export DOTNET_ROOT=$HOME/.dotnet
PATH
This variable should include both the DOTNET_ROOT folder and the user's .dotnet/tools folder:
export PATH=$PATH:$HOME/.dotnet:$HOME/.dotnet/tools
Next steps
How to enable TAB completion for the .NET CLI
Tutorial: Create a console application with .NET SDK using Visual Studio Code
How to remove the .NET Runtime and SDK
9/10/2022 • 6 minutes to read • Edit Online
Over time, as you install updated versions of the .NET runtime and SDK, you may want to remove outdated
versions of .NET from your machine. Removing older versions of the runtime may change the runtime chosen to
run shared framework applications, as detailed in the article on .NET version selection.
Uninstall .NET
.NET uses the Windows Apps & features dialog to remove versions of the .NET runtime and SDK. The
following figure shows the Apps & features dialog. You can search for core or .net to filter and show installed
versions of .NET.
Select any versions you want to remove from your computer and click Uninstall .
The best way for you to uninstall .NET is to mirror the action you used to install .NET. The specifics depend on
your chosen Linux distribution and the installation method.
IMPORTANT
For Red Hat installations, consult the Red Hat Product Documentation for .NET.
There's no need to first uninstall the .NET SDK when upgrading it using a package manager, unless you're
upgrading from a preview version that was manually installed. The package manager update or refresh
commands will automatically remove the older version upon the successful installation of a newer version. If
you have a preview version installed, uninstall it.
If you installed .NET using a package manager, use that same package manager to uninstall the .NET SDK or
runtime. .NET installations support most popular package managers. Consult the documentation for your
distribution's package manager for the precise syntax in your environment:
apt-get(8) is used by Debian based systems, including Ubuntu.
yum(8) is used on Fedora, CentOS, and Oracle Linux.
zypper(8) is used on openSUSE and SUSE Linux Enterprise System (SLES).
dnf(8) is used on Fedora.
In almost all cases, the command to remove a package is remove .
The package name for the .NET SDK installation for most package managers is dotnet-sdk , followed by the
version number. Starting with the version 2.1.300 of the .NET SDK and version 2.1 of the runtime, only the
major and minor version numbers are necessary: for example, the .NET SDK version 2.1.300 can be referenced
as the package dotnet-sdk-2.1 . Prior versions require the entire version string: for example,
dotnet-sdk-2.1.200 would be required for version 2.1.200 of the .NET SDK.
For machines that have installed only the runtime, and not the SDK, the package name is
dotnet-runtime-<version> for the .NET runtime, and aspnetcore-runtime-<version> for the entire runtime stack.
TIP
.NET Core installations earlier than 2.0 didn't uninstall the host application when the SDK was uninstalled using the
package manager. Using apt-get , the command is:
If you installed using a tarball, you must remove .NET using the manual method.
On Linux, you must remove the SDKs and runtimes separately, by removing the versioned directories. These
directories may vary depending on your Linux distribution. Removing them deletes the SDK and runtime from
disk. For example, to remove the 1.0.1 SDK and runtime, you would use the following bash commands:
version="1.0.1"
sudo rm -rf /usr/share/dotnet/sdk/$version
sudo rm -rf /usr/share/dotnet/shared/Microsoft.NETCore.App/$version
sudo rm -rf /usr/share/dotnet/shared/Microsoft.AspNetCore.All/$version
sudo rm -rf /usr/share/dotnet/shared/Microsoft.AspNetCore.App/$version
sudo rm -rf /usr/share/dotnet/host/fxr/$version
IMPORTANT
The version folders may not match the "version" you're uninstalling. The individual runtimes and SDKs that are installed
with a single .NET release may have different versions. For example, you may have installed ASP.NET Core 5 Runtime,
which installed the 5.0.2 ASP.NET Core runtime and the 5.0.8 .NET runtime. Each has a different versioned folder. For more
information, see Overview of how .NET is versioned.
The parent directories for the SDK and runtime are listed in the output from the dotnet --list-sdks and
dotnet --list-runtimes command, as shown in the earlier table.
On Mac, you must remove the SDKs and runtimes separately, by removing the versioned directories. Removing
them deletes the SDK and runtime from disk. For example, to remove the 1.0.1 SDK and runtime, you would use
the following bash commands:
version="1.0.1"
sudo rm -rf /usr/local/share/dotnet/sdk/$version
sudo rm -rf /usr/local/share/dotnet/shared/Microsoft.NETCore.App/$version
sudo rm -rf /usr/local/share/dotnet/shared/Microsoft.AspNetCore.All/$version
sudo rm -rf /usr/local/share/dotnet/shared/Microsoft.AspNetCore.App/$version
sudo rm -rf /usr/local/share/dotnet/host/fxr/$version
IMPORTANT
The version folders may not match the "version" you're uninstalling. The individual runtimes and SDKs that are installed
with .NET may have different versions. For example, you may have installed .NET 5 Runtime, which installed the 5.0.2
ASP.NET Core runtime and the 5.0.8 .NET runtime. For more information, see Overview of how .NET is versioned.
IMPORTANT
If you're using an Arm-based Mac, such as one with an M1 chip, review the folder paths described in Install .NET on Arm-
based Macs.
The parent directories for the SDK and runtime are listed in the output from the dotnet --list-sdks and
dotnet --list-runtimes command, as shown in the earlier table.
Visual Studio 2019 version 16.2 .NET Core SDK 2.2.4xx, 2.1.8xx
Visual Studio 2019 version 16.1 .NET Core SDK 2.2.3xx, 2.1.7xx
Visual Studio 2019 version 16.0 .NET Core SDK 2.2.2xx, 2.1.6xx
Visual Studio 2017 version 15.9 .NET Core SDK 2.2.1xx, 2.1.5xx
Starting with Visual Studio 2019 version 16.3, Visual Studio is in charge of its own copy of the .NET SDK. For that
reason, you no longer see those SDK versions in the Apps & features dialog.
.NET Core provides a template system that enables users to install or uninstall templates from NuGet, a NuGet
package file, or a file system directory. This article describes how to manage .NET Core templates through the
.NET SDK CLI.
For more information about creating templates, see Tutorial: Create templates.
Install template
Templates are installed through the dotnet new SDK command with the -i parameter. You can either provide
the NuGet package identifier of a template, or a folder that contains the template files.
NuGet hosted package
.NET CLI templates are uploaded to NuGet for wide distribution. Templates can also be installed from a private
feed. Instead of uploading a template to a NuGet feed, nupkg template files can be distributed and manually
installed, as described in the Local NuGet package section.
For more information about configuring NuGet feeds, see dotnet nuget add source.
To install a template pack from the default NuGet feed, use the dotnet new -i {package-id} command:
To install a template pack from the default NuGet feed with a specific version, use the
dotnet new -i {package-id}::{version} command:
Folder
As an alternative to installing template from a nupkg file, you can also install templates from a folder directly
with the dotnet new -i {folder-path} command. The folder specified is treated as the template pack identifier
for any template found. Any template found in the specified folder's hierarchy is installed.
dotnet new -u
Template Instantiation Commands for .NET CLI
c:\code\nuget-packages\some-folder
Templates:
A Template Console Class (templateconsole) C#
Project for some technology (contosoproject) C#
Uninstall Command:
dotnet new -u c:\code\nuget-packages\some-folder
dotnet new -u
Template Instantiation Commands for .NET CLI
/home/username/code/templates
Templates:
A Template Console Class (templateconsole) C#
Project for some technology (contosoproject) C#
Uninstall Command:
dotnet new -u /home/username/code/templates
Uninstall template
Templates are uninstalled through the dotnet new SDK command with the -u parameter. You can either provide
the NuGet package identifier of a template, or a folder that contains the template files.
NuGet package
After a NuGet template pack is installed, either from a NuGet feed or a nupkg file, you can uninstall it by
referencing the NuGet package identifier.
To uninstall a template pack, use the dotnet new -u {package-id} command:
Folder
When templates are installed through a folder path, the folder path becomes the template pack identifier.
To uninstall a template pack, use the dotnet new -u {package-folder-path} command:
dotnet new -u
Template Instantiation Commands for .NET CLI
c:\code\nuget-packages\some-folder
Templates:
A Template Console Class (templateconsole) C#
Project for some technology (contosoproject) C#
Uninstall Command:
dotnet new -u c:\code\nuget-packages\some-folder
Couldn't find an installed template that matches the input, searching online for one that does...
And you should see a message indicating the project was created.
See also
Tutorial: Create an item template
dotnet new
dotnet nuget add source
macOS Catalina Notarization and the impact on
.NET downloads and projects
9/10/2022 • 4 minutes to read • Edit Online
Beginning with macOS Catalina (version 10.15), all software built after June 1, 2019, and distributed with
Developer ID, must be notarized. This requirement applies to the .NET runtime, .NET SDK, and software created
with .NET. This article describes the common scenarios you may face with .NET and macOS notarization.
Installing .NET
The installers for .NET (both runtime and SDK) have been notarized since February 18, 2020. Prior released
versions aren't notarized. You can manually install a non-notarized version of .NET by first downloading the
installer, and then using the sudo installer command. For more information, see Download and manually
install for macOS.
Native appHost
In .NET SDK 7 and later versions, an appHost , which is a native Mach-O executable, is produced for your app.
This executable is usually invoked by .NET when your project compiles, publishes, or is run with the dotnet run
command. The non-appHost version of your app is a dll file that can be invoked by the dotnet <app.dll>
command.
When run locally, the SDK signs the apphost using ad hoc signing, which allows the app to run locally. When
distributing your app, you'll need to properly sign your app according to Apple guidance.
You can also distribute your app without the apphost and rely on users to run your app using dotnet . To turn
off appHost generation, add the UseAppHost boolean setting in the project file and set it to false . You can also
toggle the appHost with the -p:UseAppHost parameter on the command line for the specific dotnet command
you run:
Project file
<PropertyGroup>
<UseAppHost>false</UseAppHost>
</PropertyGroup>
Command-line parameter
An appHost is required when you publish your app self-contained and you cannot disable it.
For more information about the UseAppHost setting, see MSBuild properties for Microsoft.NET.Sdk.
Context of the appHost
When the appHost is enabled in your project, and you use the dotnet run command to run your app, the app is
invoked in the context of the appHost and not the default host (the default host is the dotnet command). If the
appHost is disabled in your project, the dotnet run command runs your app in the context of the default host.
Even if the appHost is disabled, publishing your app as self-contained generates an appHost executable, and
users use that executable to run your app. Running your app with dotnet <filename.dll> invokes the app with
the default host, the shared runtime.
When an app using the appHost is invoked, the certificate partition accessed by the app is different from the
notarized default host. If your app must access the certificates installed through the default host, use the
dotnet run command to run your app from its project file, or use the dotnet <filename.dll> command to start
the app directly.
More information about this scenario is provided in the ASP.NET Core and macOS and certificates section.
Default entitlements
.NET's default host (the dotnet command) has a set of default entitlements. These entitlements are required for
proper operation of .NET. It's possible that your application may need additional entitlements, in which case
you'll need to generate and use an appHost and then add the necessary entitlements locally.
Default set of entitlements for .NET:
com.apple.security.cs.allow-jit
com.apple.security.cs.allow-unsigned-executable-memory
com.apple.security.cs.allow-dyld-environment-variables
com.apple.security.cs.disable-library-validation
Next steps
Install .NET on macOS.
Troubleshoot fxr, libhostfxr.so, and
FrameworkList.xml errors
9/10/2022 • 3 minutes to read • Edit Online
When you try to use .NET 5+ (and .NET Core), commands such as dotnet new and dotnet run may fail with a
message related to something not being found. Some of the error messages may be similar to the following:
System.IO.FileNotFoundException
A fatal error occurred. The required library libhostfxr.so could not be found.
or
or
A fatal error occurred, the folder [/usr/share/dotnet/host/fxr] does not contain any version-numbered
child folders.
What's going on
This generally happens when two Linux package repositories provide .NET packages. While Microsoft provides a
Linux package repository to source .NET packages, some Linux distributions also provide .NET packages, such as:
Arch
CentOS
CentOS Stream
Fedora
RHEL
Mixing .NET packages from two different sources will most likely lead to issues since the packages may place
things at different paths, and may be compiled differently.
Solutions
The solution to these problems is to use .NET from one package repository. Which repository to pick, and how
to do it, varies by use-case and the Linux distribution.
If your distribution provides .NET packages, it's recommended that you use that package repository instead of
Microsoft's.
1. I only use .NET and no other packages from the Microsoft repositor y, and my distribution
provides .NET packages.
If you only use the Microsoft repository for .NET packages and not for any other Microsoft package such
as mdatp , powershell , or mssql , then:
a. Remove the Microsoft repository
b. Remove the .NET related packages from your OS
c. Install the .NET packages from the distribution repository
For Fedora, CentOS 8+, RHEL 8+, use the following bash commands:
2. I want to use the distribution provided .NET packages, but I also use the Microsoft
repositor y for other packages.
If you use the Microsoft repository for Microsoft packages such as mdatp , powershell , or mssql , but
you don't want to use the repository for .NET, then:
a. Configure the Microsoft repository to exclude any .NET package
b. Remove the .NET related packages from your OS
c. Install the .NET packages from the distribution repository
For Fedora, CentOS 8+, RHEL 8+, use the following bash commands:
3. I need a recent version of .NET that's not provided by the Linux distribution repositories.
In this case, keep the Microsoft repository, but configure it so .NET packages from the Microsoft
repository are considered a higher priority. Then, remove the already-installed .NET packages and then
re-install the .NET packages from the Microsoft repository.
For Fedora, CentOS 8+, RHEL 8+, use the following bash commands:
4. I've encountered a bug in the Linux distribution version of .NET, I need the latest Microsoft
version.
Use solution 3 to solve this problem.
Online references
Many of these problems have been reported by users such as yourself. The following is a list of those issues. You
can read through them for insights on what may be happening:
System.IO.FileNotFoundException and
'/usr/share/dotnet/packs/Microsoft.NETCore.App.Ref/5.0.0/data/FrameworkList.xml'
SDK #15785: unable to build brand new project after upgrading to 5.0.3
SDK #15863: "MSB4018 ResolveTargetingPackAssets task failed unexpectedly" after updating to
5.0.103
SDK #17411: dotnet build always throwing error
SDK #12075: dotnet 3.1.301 on Fedora 32 unable to find FrameworkList.xml because it doesn't exist
Fatal error: libhostfxr.so couldn't be found
SDK #17570: After updating Fedora 33 to 34 and dotnet 5.0.5 to 5.0.6 I get error regarding
libhostfxr.so:
Fatal error: folder /host/fxr doesn't exist
Core #5746: The folder does not exist when installing 3.1 on CentOS 8 with packages.microsoft.com
repo enabled
SDK #15476: A fatal error occurred. The folder [/usr/share/dotnet/host/fxr] does not exist:
Fatal error: folder /host/fxr doesn't contain any version-numbered child folders
Installer #9254: Error when install dotnet/core/aspnet:3.1 on CentOS 8 - Folder does not contain any
version-numbered child folders
StackOverflow: Error when install dotnet/core/aspnet:3.1 on CentOS 8 - Folder does not contain any
version-numbered child folders
Generic errors without clear messages
Core #4605: cannot run "dotnet new console"
Core #4644: Cannot install .NET Core SDK 2.1 on Fedora 32
Runtime #49375: After updating to 5.0.200-1 using package manager, it appears that no sdks are
installed
Next steps
Install .NET on Linux
How to remove the .NET Runtime and SDK
Tutorial: Create a new app with Visual Studio Code.
Tutorial: Containerize a .NET app.
How to check that .NET is already installed
9/10/2022 • 2 minutes to read • Edit Online
This article teaches you how to check which versions of the .NET runtime and SDK are installed on your
computer. If you have an integrated development environment, such as Visual Studio or Visual Studio for Mac,
.NET may have already been installed.
Installing an SDK installs the corresponding runtime.
If any command in this article fails, you don't have the runtime or SDK installed. For more information, see the
install articles for Windows, macOS, or Linux.
dotnet --list-sdks
2.1.500 [/home/user/dotnet/sdk]
2.1.502 [/home/user/dotnet/sdk]
2.1.504 [/home/user/dotnet/sdk]
2.1.600 [/home/user/dotnet/sdk]
2.1.602 [/home/user/dotnet/sdk]
3.1.100 [/home/user/dotnet/sdk]
5.0.100 [/home/user/dotnet/sdk]
6.0.100 [/home/user/dotnet/sdk]
2.1.500 [/usr/local/share/dotnet/sdk]
2.1.502 [/usr/local/share/dotnet/sdk]
2.1.504 [/usr/local/share/dotnet/sdk]
2.1.600 [/usr/local/share/dotnet/sdk]
2.1.602 [/usr/local/share/dotnet/sdk]
3.1.100 [/usr/local/share/dotnet/sdk]
5.0.100 [/usr/local/share/dotnet/sdk]
6.0.100 [/usr/local/share/dotnet/sdk]
More information
You can see both the SDK versions and runtime versions with the command dotnet --info . You'll also get other
environmental related information, such as the operating system version and runtime identifier (RID).
Next steps
Install the .NET Runtime and SDK for Windows.
Install the .NET Runtime and SDK for macOS.
Install the .NET Runtime and SDK for Linux.
See also
Determine which .NET Framework versions are installed
How to install localized IntelliSense files for .NET
9/10/2022 • 3 minutes to read • Edit Online
IntelliSense is a code-completion aid that's available in different integrated development environments (IDEs),
such as Visual Studio. By default, when you're developing .NET projects, the SDK only includes the English
version of the IntelliSense files. This article explains:
How to install the localized version of those files.
How to modify the Visual Studio installation to use a different language.
Prerequisites
.NET Core 3.1 SDK or a later version, such as the .NET 6 SDK.
Visual Studio 2019 version 16.3 or a later version.
SDK T Y P E PAT H
c. Navigate to the version you want to install the localized IntelliSense for. For example, 6.0.0.
d. Open the ref folder.
e. Open the moniker folder. For example, net6.0.
So, the full path that you'd navigate to would look similar to C:\Program
Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.0\ref\net6.0.
5. Create a subfolder inside the moniker folder you just opened. The name of the folder indicates which
language you want to use. The following table specifies the different options:
L A N GUA GE F O L DER N A M E
French fr
German de
Italian it
Japanese ja
Korean ko
Russian ru
Spanish es
6. Copy the .xml files you extracted in step 3 to this new folder. The .xml files are broken down by SDK
folders, so copy them to the matching SDK you chose in step 4.
IMPORTANT
To install, update, or modify Visual Studio, you must log on with an account that has administrator permission. For more
information, see User permissions and Visual Studio.
You might have to update the installer before continuing. If so, follow the prompts.
2. In the installer, look for the edition of Visual Studio that you want to add the language pack to, and then
choose Modify .
IMPORTANT
If you don't see a Modify button but you see an Update one instead, you need to update your Visual Studio
before you can modify your installation. After the update is finished, the Modify button should appear.
3. In the Language packs tab, select or deselect the languages you want to install or uninstall.
4. Choose Modify . The update starts.
Modify language settings in Visual Studio
Once you've installed the desired language packs, modify your Visual Studio settings to use a different language:
1. Open Visual Studio.
2. On the start window, choose Continue without code .
3. On the menu bar, select Tools > Options . The Options dialog opens.
4. Under the Environment node, choose International Settings .
5. On the Language drop-down, select the desired language. Choose OK .
6. A dialog informs you that you have to restart Visual Studio for the changes to take effect. Choose OK .
7. Restart Visual Studio.
After this, your IntelliSense should work as expected when you open a .NET project that targets the version of
the IntelliSense files you just installed.
See also
IntelliSense in Visual Studio
What is .NET? Introduction and overview
9/10/2022 • 8 minutes to read • Edit Online
.NET is a free, cross-platform, open source developer platform for building many kinds of applications. .NET is
built on a high-performance runtime that is used in production by many high-scale apps.
Cloud apps
Cloud native apps
Console apps
Serverless functions in the cloud
Web apps, web APIs, and microservices
Cross-platform client apps
Desktop apps
Games
Mobile apps
Windows apps
Windows Desktop apps
Windows Forms
Windows WPF
Universal Windows Platform (UWP)
Windows services
Other app types
Machine learning
Internet of Things (IoT)
Features
.NET features allow developers to productively write reliable and performant code.
Asynchronous code
Attributes
Reflection
Code analyzers
Delegates and lambdas
Events
Exceptions
Garbage collection
Generic types
LINQ (Language Integrated Query).
Parallel programming
Type inference - C#, F#, Visual Basic.
Type system
Unsafe code
Using .NET
.NET apps and libraries are built from source code and a project file, using the .NET CLI or an Integrated
Development Environment (IDE) like Visual Studio.
The following example is a minimal .NET app:
Project file:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
</PropertyGroup>
</Project>
Source code:
Console.WriteLine("Hello, World!");
The app can be built and run with the .NET CLI:
% dotnet run
Hello, World!
It can also be built and run as two separate steps. The following example is for an app that is named app:
% dotnet build
% ./bin/Debug/net6.0/app
Hello, World!
Binary distributions
.NET SDK -- Set of tools, libraries, and runtimes for development, building, and testing apps.
.NET Runtimes -- Set of runtimes and libraries, for running apps.
You can download .NET from:
The Microsoft download site.
Containers.
Linux package managers.
Support
Microsoft supports .NET on Android, Apple, Linux, and Windows operating systems. It can be used on Arm64,
x64, and x86 architectures. It's also supported in emulated environments, like macOS Rosetta 2.
New versions of .NET are released annually in November. .NET releases in odd-numbered years are Long-term
Support (LTS) releases and are supported for three years. Releases in even-numbered years are Short-term
Support (STS) releases and are supported for 18 months. The quality level, breaking change policies, and all
other aspects of the releases are the same. For more information, see Releases and support.
The .NET Team at Microsoft works collaboratively with other organizations to distribute and support .NET in
various ways.
Red Hat supports .NET on Red Hat Enterprise Linux (RHEL).
Samsung supports .NET on Tizen platforms.
Runtime
The Common Language Runtime (CLR) is the foundation all .NET apps are built on. The fundamental features of
the runtime are:
Garbage collection.
Memory safety and type safety.
High level support for programming languages.
Cross-platform design.
.NET is sometimes called a "managed code" runtime. It's called managed primarily because it uses a garbage
collector for memory management and because it enforces type and memory safety. The CLR virtualizes (or
abstracts) various operating system and hardware concepts, such as memory, threads, and exceptions.
The CLR was designed to be a cross-platform runtime from its inception. It has been ported to multiple
operating systems and architectures. Cross-platform .NET code typically does not need to be recompiled to run
in new environments. Instead, you just need to install a different runtime to run your app.
The runtime exposes various diagnostics services and APIs for debuggers, dumps and tracing tools, and
observability. The observability implementation is primarily built around OpenTelemetry, enabling flexible
application monitoring and site reliability engineering (SRE).
The runtime offers low-level C-style interop functionality, via a combination of P/Invoke, value types, and the
ability to blit values across the native/managed-code boundary.
Languages
The runtime is designed to support multiple programming languages. C#, F#, and Visual Basic languages are
supported by Microsoft and are designed in collaboration with the community.
C# is a modern, object-oriented, and type-safe programming language. It has its roots in the C family of
languages and will be immediately familiar to C, C++, Java, and JavaScript programmers.
F# is an interoperable programming language for writing succinct, robust, and performant code. F#
programming is data-oriented, where code involves transforming data with functions.
Visual Basic uses a more verbose syntax that is closer to ordinary human language. It can be an easier
language to learn for people new to programming.
Compilation
.NET apps (as written in a high-level language like C#) are compiled to an Intermediate Language (IL). IL is a
compact code format that can be supported on any operating system or architecture. Most .NET apps use APIs
that are supported in multiple environments, requiring only the .NET runtime to run.
IL needs to be compiled to native code in order to execute on a CPU, for example Arm64 or x64. .NET supports
both Ahead-Of-Time (AOT) and Just-In-Time (JIT) compilation models.
On Android, Linux, macOS, and Linux, JIT compilation is the default, and AOT is optional (for example, with
ReadyToRun).
On iOS, AOT is mandatory (except when running in the simulator).
In WebAssembly (Wasm) environments, AOT is mandatory.
The advantage of the JIT is that it can compile an app (unmodified) to the CPU instructions and calling
conventions in a given environment, per the underlying operating system and hardware. It can also compile
code at higher or lower levels of quality to enable better startup and steady-state throughput performance.
The advantage of AOT is that it provides the best app startup and can (in some cases) result in smaller
deployments. The primary downside is that binaries must be built for each separate deployment target (the
same as any other native code). AOT code is not compatible with some reflection patterns.
Runtime libraries
.NET has a comprehensive standard set of class libraries. These libraries provide implementations for many
general-purpose and workload-specific types and utility functionality.
Here are some examples of types defined in the .NET runtime libraries:
Every .NET type derives from the System.Object type.
Primitive value types, such as System.Boolean and System.Int32.
Collections, such as System.Collections.Generic.List<T> and
System.Collections.Generic.Dictionary<TKey,TValue>.
Data types, such as System.Data.DataSet and System.Data.DataTable.
Network utility types, such as System.Net.Http.HttpClient.
File and stream I/O utility types, such as System.IO.FileStream and System.IO.TextWriter.
Serialization utility types, such as System.Text.Json.JsonSerializer and System.Xml.Serialization.XmlSerializer.
High-performance types, such as System.Span<T>, System.Numerics.Vector, and Pipelines.
For more information, see the Runtime libraries overview.
Tools
The .NET SDK is a set of libraries and tools for developing and running .NET applications. It includes the MSBuild
build engine, the Roslyn (C# and Visual Basic) compiler, and the F# compiler. Most commands are run by using
the dotnet command. The CLI tools can be used for local development and continuous integration.
The Visual Studio family of IDEs offer excellent support for .NET and the C#, F#, and Visual Basic languages.
GitHub Codespaces and GitHub security features support .NET.
Notebooks
.NET Interactive is a group of CLI tools and APIs that enable users to create interactive experiences across the
web, markdown, and notebooks.
For more information, see the following resources:
.NET In-Browser Tutorial
Using .NET notebooks with Jupyter on your machine
.NET Interactive documentation
CI/CD
MSBuild and the .NET CLI can be used with various continuous integration tools and environments, such as:
GitHub Actions
Azure DevOps
CAKE for C#
FAKE for F#
For more information, see Use the .NET SDK in Continuous Integration (CI) environments.
Deployment models
.NET apps can be published in two different modes:
Self-contained apps include the .NET runtime and dependent libraries. They can be single-file or multi-file.
Users of the application can run it on a machine that doesn't have the .NET runtime installed. Self-contained
apps always target a single operating system and architecture configuration.
Framework-dependent apps require a compatible version of the .NET runtime, typically installed globally.
Framework-dependent apps can be published for a single operating system and architecture configuration or
as "portable," targeting all supported configurations.
.NET apps are launched with a native executable, by default. The executable is both operating system and
architecture-specific. Apps can also be launched with the dotnet command.
Apps can be deployed in containers. Microsoft provides container images for various target environments.
.NET history
In 2002, Microsoft released .NET Framework, a development platform for creating Windows apps. Today .NET
Framework is at version 4.8 and remains fully supported by Microsoft.
In 2014, Microsoft introduced .NET Core as a cross-platform, open-source successor to .NET Framework. This
new implementation of .NET kept the name .NET Core through version 3.1. The next version after .NET Core 3.1
was named .NET 5.
New .NET versions continue to be released annually, each a major version number higher. They include
significant new features and often enable new scenarios.
.NET ecosystem
There are multiple variants of .NET, each supporting a different type of app. The reason for multiple variants is
part historical, part technical.
.NET implementations (historical order):
.NET Framework -- It provides access to the broad capabilities of Windows and Windows Server. Also
extensively used for Windows-based cloud computing. The original .NET.
Mono -- A cross-platform implementation of .NET Framework. The original community and open source
.NET. Used for Android, iOS, and Wasm apps.
.NET (Core) -- A cross-platform and open source implementation of .NET, rethought for the cloud age while
remaining significantly compatible with .NET Framework. Used for Linux, macOS, and Windows apps.
Next steps
Choose a .NET tutorial
Try .NET in your browser
Take a tour of C#
Take a tour of F#
.NET implementations
9/10/2022 • 2 minutes to read • Edit Online
A .NET app is developed for one or more implementations of .NET. Implementations of .NET include .NET
Framework, .NET 5+ (and .NET Core), and Mono.
Each implementation of .NET includes the following components:
One or more runtimes—for example, .NET Framework CLR and .NET 5 CLR.
A class library—for example, .NET Framework Base Class Library and .NET 5 Base Class Library.
Optionally, one or more application frameworks—for example, ASP.NET, Windows Forms, and Windows
Presentation Foundation (WPF) are included in .NET Framework and .NET 5+.
Optionally, development tools. Some development tools are shared among multiple implementations.
There are four .NET implementations that Microsoft supports:
.NET 5 (and .NET Core) and later versions
.NET Framework
Mono
UWP
.NET 6 is currently the primary implementation, and the one that's the focus of ongoing development. .NET 6 is
built on a single code base that supports multiple platforms and many workloads, such as Windows desktop
apps and cross-platform console apps, cloud services, and websites. Some workloads, such as .NET
WebAssembly build tools, are available as optional installations.
.NET Framework
.NET Framework is the original .NET implementation that has existed since 2002. Versions 4.5 and later
implement .NET Standard, so code that targets .NET Standard can run on those versions of .NET Framework. It
contains additional Windows-specific APIs, such as APIs for Windows desktop development with Windows
Forms and WPF. .NET Framework is optimized for building Windows desktop applications.
For more information, see the .NET Framework guide.
Mono
Mono is a .NET implementation that is mainly used when a small runtime is required. It is the runtime that
powers Xamarin applications on Android, macOS, iOS, tvOS, and watchOS and is focused primarily on a small
footprint. Mono also powers games built using the Unity engine.
It supports all of the currently published .NET Standard versions.
Historically, Mono implemented the larger API of .NET Framework and emulated some of the most popular
capabilities on Unix. It is sometimes used to run .NET applications that rely on those capabilities on Unix.
Mono is typically used with a just-in-time compiler, but it also features a full static compiler (ahead-of-time
compilation) that is used on platforms like iOS.
For more information, see the Mono documentation.
Class libraries are the shared library concept for .NET. They enable you to componentize useful functionality into
modules that can be used by multiple applications. They can also be used as a means of loading functionality
that is not needed or not known at application startup. Class libraries are described using the .NET Assembly file
format.
There are three types of class libraries that you can use:
Platform-specific class libraries have access to all the APIs in a given platform (for example, .NET
Framework on Windows, Xamarin iOS), but can only be used by apps and libraries that target that platform.
Por table class libraries have access to a subset of APIs, and can be used by apps and libraries that target
multiple platforms.
.NET Standard class libraries are a merger of the platform-specific and portable library concept into a
single model that provides the best of both.
.NET Standard is a formal specification of .NET APIs that are available on multiple .NET implementations. The
motivation behind .NET Standard was to establish greater uniformity in the .NET ecosystem. .NET 5 and later
versions adopt a different approach to establishing uniformity that eliminates the need for .NET Standard in
most scenarios. However, if you want to share code between .NET Framework and any other .NET
implementation, such as .NET Core, your library should target .NET Standard 2.0. No new versions of .NET
Standard will be released, but .NET 5, .NET 6, and all future versions will continue to support .NET Standard 2.1
and earlier.
For information about choosing between .NET 5+ and .NET Standard, see .NET 5+ and .NET Standard later in this
article.
.NET and .NET Core 1.0, 1.1, 2.0, 2.1, 2.2, 3.0, 3.1, 5.0, 6.0
.NET Framework 4.5, 4.5.1, 4.5.2, 4.6, 4.6.1, 4.6.2, 4.7, 4.7.1, 4.7.2, 4.8
Unity 2018.1
For more information, see .NET Standard 1.0. For an interactive table, see .NET Standard versions.
Which .NET Standard version to target
We recommend you target .NET Standard 2.0, unless you need to support an earlier version. Most general-
purpose libraries should not need APIs outside of .NET Standard 2.0. .NET Standard 2.0 is supported by all
modern platforms and is the recommended way to support multiple platforms with one target.
If you need to support .NET Standard 1.x, we recommend that you also target .NET Standard 2.0. .NET Standard
1.x is distributed as a granular set of NuGet packages, which creates a large package dependency graph and
results in developers downloading a lot of packages when building. For more information, see Cross-platform
targeting and .NET 5+ and .NET Standard later in this article.
.NET Standard versioning rules
There are two primary versioning rules:
Additive: .NET Standard versions are logically concentric circles: higher versions incorporate all APIs from
previous versions. There are no breaking changes between versions.
Immutable: Once shipped, .NET Standard versions are frozen.
There will be no new .NET Standard versions after 2.1. For more information, see .NET 5+ and .NET Standard
later in this article.
Specification
The .NET Standard specification is a standardized set of APIs. The specification is maintained by .NET
implementers, specifically Microsoft (includes .NET Framework, .NET Core, and Mono) and Unity.
Official artifacts
The official specification is a set of .cs files that define the APIs that are part of the standard. The ref directory in
the (now archived) dotnet/standard repository defines the .NET Standard APIs.
The NETStandard.Library metapackage (source) describes the set of libraries that define (in part) one or more
.NET Standard versions.
A given component, like System.Runtime , describes:
Part of .NET Standard ( just its scope).
Multiple versions of .NET Standard, for that scope.
Derivative artifacts are provided to enable more convenient reading and to enable certain developer scenarios
(for example, using a compiler).
API list in markdown.
Reference assemblies, distributed as NuGet packages and referenced by the NETStandard.Library
metapackage.
Package representation
The primary distribution vehicle for the .NET Standard reference assemblies is NuGet packages.
Implementations are delivered in a variety of ways, appropriate for each .NET implementation.
NuGet packages target one or more frameworks. .NET Standard packages target the ".NET Standard" framework.
You can target the .NET Standard framework using the netstandard compact TFM (for example, netstandard1.4
). Libraries that are intended to run on multiple implementations of .NET should target this framework. For the
broadest set of APIs, target netstandard2.0 since the number of available APIs more than doubled between .NET
Standard 1.6 and 2.0.
The NETStandard.Library metapackage references the complete set of NuGet packages that define .NET
Standard. The most common way to target netstandard is by referencing this metapackage. It describes and
provides access to the ~40 .NET libraries and associated APIs that define .NET Standard. You can reference
additional packages that target netstandard to get access to additional APIs.
Versioning
The specification is not singular, but a linearly versioned set of APIs. The first version of the standard establishes
a baseline set of APIs. Subsequent versions add APIs and inherit APIs defined by previous versions. There is no
established provision for removing APIs from the Standard.
.NET Standard is not specific to any one .NET implementation, nor does it match the versioning scheme of any of
those implementations.
As noted earlier, there will be no new .NET Standard versions after 2.1.
This TFM is for code that runs everywhere. With a few exceptions, it includes only technologies that work
cross-platform. For .NET 5 code, net5.0 replaces both netcoreapp and netstandard TFMs.
net5.0-windows
This is an example of an OS-specific TFM that add OS-specific functionality to everything that net5.0
refers to.
When to target net5.0 or net6.0 vs. netstandard
For existing code that targets netstandard , there's no need to change the TFM to net5.0 or net6.0 . .NET 5 and
.NET 6 implement .NET Standard 2.1 and earlier. The only reason to retarget from .NET Standard to .NET 5+
would be to gain access to more runtime features, language features, or APIs. For example, in order to use C# 9,
you need to target .NET 5 or a later version. You can multitarget .NET 5 or .NET 6 and .NET Standard to get access
to newer features and still have your library available to other .NET implementations.
Here are some guidelines for new code for .NET 5+:
App components
If you're using libraries to break down an application into several components, we recommend you target
net5.0 or net6.0 . For simplicity, it's best to keep all projects that make up your application on the same
version of .NET. Then you can assume the same BCL features everywhere.
Reusable libraries
If you're building reusable libraries that you plan to ship on NuGet, consider the trade-off between reach
and available feature set. .NET Standard 2.0 is the latest version that's supported by .NET Framework, so it
gives good reach with a fairly large feature set. We don't recommend targeting .NET Standard 1.x, as
you'd limit the available feature set for a minimal increase in reach.
If you don't need to support .NET Framework, you could go with .NET Standard 2.1 or .NET 5/6. We
recommend you skip .NET Standard 2.1 and go straight to .NET 6. Most widely used libraries will multi-
target for both .NET Standard 2.0 and .NET 5+. Supporting .NET Standard 2.0 gives you the most reach,
while supporting .NET 5+ ensures you can leverage the latest platform features for customers that are
already on .NET 5+.
.NET Standard problems
Here are some problems with .NET Standard that help explain why .NET 5 and later versions are the better way
to share code across platforms and workloads:
Slowness to add new APIs
.NET Standard was created as an API set that all .NET implementations would have to support, so there
was a review process for proposals to add new APIs. The goal was to standardize only APIs that could be
implemented in all current and future .NET platforms. The result was that if a feature missed a particular
release, you might have to wait for a couple of years before it got added to a version of the Standard.
Then you'd wait even longer for the new version of .NET Standard to be widely supported.
Solution in .NET 5+: When a feature is implemented, it's already available for every .NET 5+ app and
library because the code base is shared. And since there's no difference between the API specification and
its implementation, you're able to take advantage of new features much quicker than with .NET Standard.
Complex versioning
The separation of the API specification from its implementations results in complex mapping between API
specification versions and implementation versions. This complexity is evident in the table shown earlier
in this article and the instructions for how to interpret it.
Solution in .NET 5+: There's no separation between a .NET 5+ API specification and its implementation.
The result is a simplified TFM scheme. There's one TFM prefix for all workloads: net5.0 or net6.0 is
used for libraries, console apps, and web apps. The only variation is a suffix that specifies platform-
specific APIs for a particular platform, such as net5.0-windows or net6.0-windows . Thanks to this TFM
naming convention, you can easily tell whether a given app can use a given library. No version number
equivalents table, like the one for .NET Standard, is needed.
Platform-unsupported exceptions at run time
.NET Standard exposes platform-specific APIs. Your code might compile without errors and appear to be
portable to any platform even if it isn't portable. When it runs on a platform that doesn't have an
implementation for a given API, you get run-time errors.
Solution in .NET 5+: The .NET 5+ SDKs include code analyzers that are enabled by default. The
platform compatibility analyzer detects unintentional use of APIs that aren't supported on the platforms
you intend to run on. For more information, see Platform compatibility analyzer.
.NET Standard not deprecated
.NET Standard is still needed for libraries that can be used by multiple .NET implementations. We recommend
you target .NET Standard in the following scenarios:
Use netstandard2.0 to share code between .NET Framework and all other implementations of .NET.
Use netstandard2.1 to share code between Mono, Xamarin, and .NET Core 3.x.
See also
.NET Standard versions (source)
.NET Standard versions (interactive UI)
Build a .NET Standard library
Cross-platform targeting
Releases and support for .NET (.NET 5+ and .NET
Core)
9/10/2022 • 7 minutes to read • Edit Online
Microsoft ships major releases, minor releases, and servicing updates (patches) for .NET 5 (and .NET Core) and
later versions. This article explains release types, servicing updates, SDK feature bands, support periods, and
support options.
Release types
Information about the type of each release is encoded in the version number in the form major.minor.patch.
For example:
.NET 5 and NET 6 are major releases.
.NET Core 3.1 is the first minor release after the .NET Core 3.0 major release.
.NET Core 5.0.15 is the fifteenth patch for .NET 5.
Major releases
Major releases include new features, new public API surface area, and bug fixes. Examples include .NET 5 and
.NET 6. Due to the nature of the changes, these releases are expected to have breaking changes. Major releases
install side by side with previous major releases.
Minor releases
Minor releases also include new features, public API surface area, and bug fixes, and may also have breaking
changes. An example is .NET Core 3.1. The difference between these and major releases is that the magnitude of
the changes is smaller. An application upgrading from .NET Core 3.0 to 3.1 has a smaller jump to move forward.
Minor releases install side by side with previous minor releases.
Servicing updates
Servicing updates (patches) ship almost every month, and these updates carry both security and non-security
bug fixes. For example, .NET 5.0.8 is the eighth update for .NET 5. When these updates include security fixes,
they're released on "patch Tuesday", which is always the second Tuesday of the month. Servicing updates are
expected to maintain compatibility. Starting with .NET Core 3.1, servicing updates are upgrades that remove the
preceding update. For example, the latest servicing update for 3.1 removes the previous 3.1 update upon
successful installation.
Feature bands (SDK only)
Versioning for the .NET SDK works slightly differently from the .NET runtime. To align with new Visual Studio
releases, .NET SDK updates sometimes include new features or new versions of components like MSBuild and
NuGet. These new features or components may be incompatible with the versions that shipped in previous SDK
updates for the same major or minor version.
To differentiate such updates, the .NET SDK uses the concept of feature bands. For example, the first .NET 5 SDK
was 5.0.100. This release corresponds to the 3.1.1xx feature band. Feature bands are defined in the hundreds
groups in the third section of the version number. For example, 5.0.101 and 5.0.201 are versions in two different
feature bands while 5.0.101 and 5.0.199 are in the same feature band. When .NET SDK 5.0.101 is installed, .NET
SDK 5.1.100 is removed from the machine if it exists. When .NET SDK 5.0.200 is installed on the same machine,
.NET SDK 5.0.101 isn't removed.
Runtime roll-forward and compatibility
Major and minor updates install side by side with previous versions. An application built to target a specific
major.minor version continues to use that targeted runtime even if a newer version is installed. The app doesn't
automatically roll forward to use a newer major.minor version of the runtime unless you opt in for this behavior.
An application that was built to target .NET Core 3.0 doesn't automatically start running on .NET Core 3.1. We
recommend rebuilding the app and testing against a newer major or minor runtime version before deploying to
production. For more information, see Framework-dependent apps roll forward and Self-contained deployment
runtime roll forward.
Servicing updates are treated differently from major and minor releases. An application built to target .NET 5.0.0
runs on the 5.0.0 runtime by default. It automatically rolls forward to use a newer 5.0.1 runtime when that
servicing update is installed. This behavior is the default because we want security fixes to be used as soon as
they're installed without any other action needed. You can opt out from this default roll forward behavior.
End of support
End of support refers to the date after which Microsoft no longer provides fixes, updates, or technical assistance
for a product version. Before this date, make sure you have moved to using a supported version. Versions that
are out of support no longer receive security updates that protect your applications and data.
Get support
You have a choice between Microsoft assisted support and Community support.
Microsoft support
For assisted support, contact a Microsoft Support Professional.
You need to be on a supported servicing level (the latest available servicing update) to be eligible for support. If
a system is running .NET 5 and the 5.0.8 servicing update has been released, then 5.0.8 needs to be installed as a
first step.
Community support
For community support, see the Community page.
See also
For more information, including supported date ranges for each version of .NET, see the Support Policy.
Ecma standards
9/10/2022 • 2 minutes to read • Edit Online
The C# Language and the Common Language Infrastructure (CLI) specifications are standardized through Ecma
International®. The first editions of these standards were published by Ecma in December 2001.
Subsequent revisions to the standards have been developed by the TC49-TG2 (C#) and TC49-TG3 (CLI) task
groups within the Programming Languages Technical Committee (TC49), and adopted by the Ecma General
Assembly and subsequently by ISO/IEC JTC 1 via the ISO Fast-Track process.
Latest standards
The following official Ecma documents are available for C# and the CLI (TR-84):
The C# Language Standard (version 5.0) : ECMA-334.pdf
The Common Language Infrastructure : ECMA-335.pdf.
Information Derived from the Par tition IV XML File : ECMA-084.pdf format.
The official ISO/IEC documents are available from the ISO/IEC Publicly Available Standards page. These links are
direct from that page:
Information technology - Programming languages - C# : ISO/IEC 23270:2018
Information technology — Common Language Infrastructure (CLI) Par titions I to VI : ISO/IEC
23271:2012
Information technology — Common Language Infrastructure (CLI) — Technical Repor t on
Information Derived from Par tition IV XML File : ISO/IEC TR 23272:2011
.NET Glossary
9/10/2022 • 14 minutes to read • Edit Online
The primary goal of this glossary is to clarify meanings of selected terms and acronyms that appear frequently
in the .NET documentation.
AOT
Ahead-of-time compiler.
Similar to JIT, this compiler also translates IL to machine code. In contrast to JIT compilation, AOT compilation
happens before the application is executed and is usually performed on a different machine. Because AOT tool
chains don't compile at run time, they don't have to minimize time spent compiling. That means they can spend
more time optimizing. Since the context of AOT is the entire application, the AOT compiler also performs cross-
module linking and whole-program analysis, which means that all references are followed and a single
executable is produced.
See CoreRT and .NET Native.
app model
A workload-specific API. Here are some examples:
ASP.NET
ASP.NET Web API
Entity Framework (EF)
Windows Presentation Foundation (WPF)
Windows Communication Foundation (WCF)
Windows Workflow Foundation (WF)
Windows Forms (WinForms)
ASP.NET
The original ASP.NET implementation that ships with the .NET Framework, also known as ASP.NET 4.x.
Sometimes ASP.NET is an umbrella term that refers to both the original ASP.NET and ASP.NET Core. The meaning
that the term carries in any given instance is determined by context. Refer to ASP.NET 4.x when you want to
make it clear that you're not using ASP.NET to mean both implementations.
See ASP.NET documentation.
ASP.NET Core
A cross-platform, high-performance, open-source implementation of ASP.NET.
See ASP.NET Core documentation.
assembly
A .dll or .exe file that can contain a collection of APIs that can be called by applications or other assemblies.
An assembly may include types such as interfaces, classes, structures, enumerations, and delegates. Assemblies
in a project's bin folder are sometimes referred to as binaries. See also library.
BCL
Base Class Library.
A set of libraries that comprise the System.* (and to a limited extent Microsoft.*) namespaces. The BCL is a
general purpose, lower-level framework that higher-level application frameworks, such as ASP.NET Core, build
on.
The source code of the BCL for .NET 5 (and .NET Core) and later versions is contained in the .NET runtime
repository. Most of these BCL APIs are also available in .NET Framework, so you can think of this source code as
a fork of the .NET Framework BCL source code.
The following terms often refer to the same collection of APIs that BCL refers to:
core .NET libraries
framework libraries
runtime libraries
shared framework
CLR
Common Language Runtime.
The exact meaning depends on the context. Common Language Runtime usually refers to the runtime of .NET
Framework or the runtime of .NET 5 (and .NET Core) and later versions.
A CLR handles memory allocation and management. A CLR is also a virtual machine that not only executes apps
but also generates and compiles code on-the-fly using a JIT compiler.
The CLR implementation for .NET Framework is Windows only.
The CLR implementation for .NET 5 and later versions (also known as the Core CLR) is built from the same code
base as the .NET Framework CLR. Originally, the Core CLR was the runtime of Silverlight and was designed to
run on multiple platforms, specifically Windows and OS X. It's still a cross-platform runtime, now including
support for many Linux distributions.
See also runtime.
Core CLR
The Common Language Runtime for .NET 5 (and .NET Core) and later versions.
See CLR.
CoreRT
In contrast to the CLR, CoreRT is not a virtual machine, which means it doesn't include the facilities to generate
and run code on-the-fly because it doesn't include a JIT. It does, however, include the GC and the ability for run-
time type identification (RTTI) and reflection. However, its type system is designed so that metadata for reflection
isn't required. Not requiring metadata enables having an AOT tool chain that can link away superfluous
metadata and (more importantly) identify code that the app doesn't use. CoreRT is in development.
See Intro to CoreRT and .NET Runtime Lab.
cross-platform
The ability to develop and execute an application that can be used on multiple different operating systems, such
as Linux, Windows, and iOS, without having to rewrite specifically for each one. This enables code reuse and
consistency between applications on different platforms.
See platform.
ecosystem
All of the runtime software, development tools, and community resources that are used to build and run
applications for a given technology.
The term ".NET ecosystem" differs from similar terms such as ".NET stack" in its inclusion of third-party apps
and libraries. Here's an example in a sentence:
"The motivation behind .NET Standard was to establish greater uniformity in the .NET ecosystem."
framework
In general, a comprehensive collection of APIs that facilitates development and deployment of applications that
are based on a particular technology. In this general sense, ASP.NET Core and Windows Forms are examples of
application frameworks. The words framework and library are often used synonymously.
The word "framework" has a different meaning in the following terms:
framework libraries
.NET Framework
shared framework
target framework
TFM (target framework moniker)
framework-dependent app
Sometimes "framework" refers to an implementation of .NET. For example, an article may call .NET 5+ a
framework.
framework libraries
Meaning depends on context. May refer to the framework libraries for .NET 5 (and .NET Core) and later versions,
in which case it refers to the same libraries that BCL refers to. It may also refer to the ASP.NET Core framework
libraries, which build on the BCL and provide additional APIs for web apps.
GC
Garbage collector.
The garbage collector is an implementation of automatic memory management. The GC frees memory occupied
by objects that are no longer in use.
See Garbage Collection.
IL
Intermediate language.
Higher-level .NET languages, such as C#, compile down to a hardware-agnostic instruction set, which is called
Intermediate Language (IL). IL is sometimes referred to as MSIL (Microsoft IL) or CIL (Common IL).
JIT
Just-in-time compiler.
Similar to AOT, this compiler translates IL to machine code that the processor understands. Unlike AOT, JIT
compilation happens on demand and is performed on the same machine that the code needs to run on. Since
JIT compilation occurs during execution of the application, compile time is part of the run time. Thus, JIT
compilers have to balance time spent optimizing code against the savings that the resulting code can produce.
But a JIT knows the actual hardware and can free developers from having to ship different implementations.
implementation of .NET
An implementation of .NET includes:
One or more runtimes. Examples: CLR, CoreRT.
A class library that implements a version of .NET Standard and may include additional APIs. Examples: the
BCLs for .NET Framework and .NET 5 (and .NET Core) and later versions.
Optionally, one or more application frameworks. Examples: ASP.NET, Windows Forms, and WPF are included
in .NET Framework and .NET 5+.
Optionally, development tools. Some development tools are shared among multiple implementations.
Examples of .NET implementations:
.NET Framework
.NET 5 (and .NET Core) and later versions
Universal Windows Platform (UWP)
Mono
For more information, see .NET implementations.
library
A collection of APIs that can be called by apps or other libraries. A .NET library is composed of one or more
assemblies.
The words library and framework are often used synonymously.
Mono
Mono is an open source, cross-platform .NET implementation that is mainly used when a small runtime is
required. It is the runtime that powers Xamarin applications on Android, Mac, iOS, tvOS, and watchOS and is
focused primarily on apps that require a small footprint.
It supports all of the currently published .NET Standard versions.
Historically, Mono implemented the larger API of the .NET Framework and emulated some of the most popular
capabilities on Unix. It is sometimes used to run .NET applications that rely on those capabilities on Unix.
Mono is typically used with a just-in-time compiler, but it also features a full static compiler (ahead-of-time
compilation) that is used on platforms like iOS.
See the Mono documentation.
.NET
In general, .NET is the umbrella term for .NET Standard and all .NET implementations and workloads.
More specifically, .NET refers to the implementation of .NET that is recommended for all new development:
.NET 5 (and .NET Core) and later versions.
For example, the first meaning is intended in phrases such as "implementations of .NET" or "the .NET
development platform." The second meaning is intended in names such as .NET SDK and .NET CLI.
.NET is always fully capitalized, never ".Net".
See .NET documentation
.NET 5+
The plus sign after a version number means "and later versions." See .NET 5 and later versions.
.NET CLI
A cross-platform toolchain for developing applications and libraries for .NET 5 (and .NET Core) and later
versions. Also known as the .NET Core CLI.
See .NET CLI.
.NET Core
See .NET 5 and later versions.
.NET Framework
An implementation of .NET that runs only on Windows. Includes the Common Language Runtime (CLR), the
Base Class Library (BCL), and application framework libraries such as ASP.NET, Windows Forms, and WPF.
See .NET Framework Guide.
.NET Native
A compiler tool chain that produces native code ahead-of-time (AOT), as opposed to just-in-time (JIT).
Compilation happens on the developer's machine similar to the way a C++ compiler and linker works. It
removes unused code and spends more time optimizing it. It extracts code from libraries and merges them into
the executable. The result is a single module that represents the entire app.
UWP is the application framework supported by .NET Native.
See .NET Native documentation.
.NET SDK
A set of libraries and tools that allow developers to create .NET applications and libraries for .NET 5 (and .NET
Core) and later versions. Also known as the .NET Core SDK.
Includes the .NET CLI for building apps, .NET libraries and runtime for building and running apps, and the dotnet
executable (dotnet.exe) that runs CLI commands and runs applications.
See .NET SDK Overview.
.NET Standard
A formal specification of .NET APIs that are available in each .NET implementation.
The .NET Standard specification is sometimes called a library. Because a library includes API implementations,
not only specifications (interfaces), it's misleading to call .NET Standard a "library."
See .NET Standard.
NGEN
Native (image) generation.
You can think of this technology as a persistent JIT compiler. It usually compiles code on the machine where the
code is executed, but compilation typically occurs at install time.
package
A NuGet package—or just a package—is a .zip file with one or more assemblies of the same name along with
additional metadata such as the author name.
The .zip file has a .nupkg extension and may contain assets, such as .dll files and .xml files, for use with multiple
target frameworks and versions. When installed in an app or library, the appropriate assets are selected based
on the target framework specified by the app or library. The assets that define the interface are in the ref folder,
and the assets that define the implementation are in the lib folder.
platform
An operating system and the hardware it runs on, such as Windows, macOS, Linux, iOS, and Android.
Here are examples of usage in sentences:
".NET Core is a cross-platform implementation of .NET."
"PCL profiles represent Microsoft platforms, while .NET Standard is agnostic to platform."
Legacy .NET documentation sometimes uses ".NET platform" to mean either an implementation of .NET or the
.NET stack including all implementations. Both of these usages tend to get confused with the primary
(OS/hardware) meaning, so we try to avoid these usages.
"Platform" has a different meaning in the phrase "developer platform," which refers to software that provides
tools and libraries for building and running apps. .NET is a cross-platform, open-source developer platform for
building many different types of applications.
POCO
A POCO—or a plain old class/CLR object—is a .NET data structure that contains only public properties or fields.
A POCO shouldn't contain any other members, such as:
methods
events
delegates
These objects are used primarily as data transfer objects (DTOs). A pure POCO will not inherit another object, or
implement an interface. It's common for POCOs to be used with serialization.
runtime
In general, the execution environment for a managed program. The OS is part of the runtime environment but is
not part of the .NET runtime. Here are some examples of .NET runtimes in this sense of the word:
Common Language Runtime (CLR)
.NET Native (for UWP)
Mono runtime
The word "runtime" has a different meaning in some contexts:
.NET runtime on the .NET 5 download page.
You can download the .NET runtime or other runtimes, such as the ASP.NET Core runtime. A runtime in
this usage is the set of components that must be installed on a machine to run a framework-dependent
app on the machine. The .NET runtime includes the CLR and the .NET shared framework, which provides
the BCL.
.NET runtime libraries
Refers to the same libraries that BCL refers to. However, other runtimes, such as the ASP.NET Core
runtime, have different shared frameworks, with additional libraries that build on the BCL.
Runtime Identifier (RID).
Runtime here means the OS platform and CPU architecture that a .NET app runs on, for example:
linux-x64 .
Sometimes "runtime" is used in the sense of an implementation of .NET, as in the following examples:
"The various .NET runtimes implement specific versions of .NET Standard. … Each .NET runtime version
advertises the highest .NET Standard version it supports …"
"Libraries that are intended to run on multiple runtimes should target this framework." (referring to
.NET Standard)
shared framework
Meaning depends on context. The .NET shared framework refers to the libraries included in the .NET runtime. In
this case, the shared framework for .NET 5 (and .NET Core) and later versions refers to the same libraries that
BCL refers to.
There are other shared frameworks. The ASP.NET Core shared framework refers to the libraries included in the
ASP.NET Core runtime, which includes the BCL plus additional APIs for use by web apps.
For framework-dependent apps, the shared framework consists of libraries that are contained in assemblies
installed in a folder on the machine that runs the app. For self-contained apps, the shared framework assemblies
are included with the app.
For more information, see Deep-dive into .NET Core primitives, part 2: the shared framework.
stack
A set of programming technologies that are used together to build and run applications.
"The .NET stack" refers to .NET Standard and all .NET implementations. The phrase "a .NET stack" may refer to
one implementation of .NET.
target framework
The collection of APIs that a .NET app or library relies on.
An app or library can target a version of .NET Standard (for example, .NET Standard 2.0), which is a specification
for a standardized set of APIs across all .NET implementations. An app or library can also target a version of a
specific .NET implementation, in which case it gets access to implementation-specific APIs. For example, an app
that targets Xamarin.iOS gets access to Xamarin-provided iOS API wrappers.
For some target frameworks (for example, .NET Framework) the available APIs are defined by the assemblies
that a .NET implementation installs on a system, which may include application framework APIs (for example,
ASP.NET, WinForms). For package-based target frameworks, the framework APIs are defined by the packages
installed in the app or library.
See Target Frameworks.
TFM
Target framework moniker.
A standardized token format for specifying the target framework of a .NET app or library. Target frameworks are
typically referenced by a short name, such as net462 . Long-form TFMs (such as .NETFramework,Version=4.6.2)
exist but are not generally used to specify a target framework.
See Target Frameworks.
UWP
Universal Windows Platform.
An implementation of .NET that is used for building touch-enabled Windows applications and software for the
Internet of Things (IoT). It's designed to unify the different types of devices that you may want to target,
including PCs, tablets, phones, and even the Xbox. UWP provides many services, such as a centralized app store,
an execution environment (AppContainer), and a set of Windows APIs to use instead of Win32 (WinRT). Apps
can be written in C++, C#, Visual Basic, and JavaScript. When using C# and Visual Basic, the .NET APIs are
provided by .NET 5 (and .NET Core) and later versions.
workload
A type of app someone is building. More generic than app model. For example, at the top of every .NET
documentation page, including this one, is a drop-down list for Workloads , which lets you switch to
documentation for Web , Mobile , Cloud , Desktop , and Machine Learning & Data .
In some contexts, workload refers to a collection of Visual Studio features that you can choose to install to
support a particular type of app. For an example, see Select a workload.
See also
.NET fundamentals
.NET Framework Guide
ASP.NET Overview
ASP.NET Core Overview
.NET 6 C# console app template generates top-
level statements
9/10/2022 • 5 minutes to read • Edit Online
Starting with .NET 6, the project template for new C# console apps generates the following code in the
Program.cs file:
The new output uses recent C# features that simplify the code you need to write for a program. For .NET 5 and
earlier versions, the console app template generates the following code:
using System;
These two forms represent the same program. Both are valid with C# 10.0. When you use the newer version,
you only need to write the body of the Main method. The compiler synthesizes a Program class with a Main
method and places all your top level statements in that Main method. You don't need to include the other
program elements, the compiler generates them for you. You can learn more about the code the compiler
generates when you use top level statements in the article on top level statements in the C# Guide's
fundamentals section.
You have two options to work with tutorials that haven't been updated to use .NET 6+ templates:
Use the new program style, adding new top-level statements as you add features.
Convert the new program style to the older style, with a Program class and a Main method.
If you want to use the old templates, see Use the old program style later in this article.
The term top-level statements means the compiler generates the class and method elements for your main
program. The compiler generated class and Main method are declared in the global namespace. You can look at
the code for the new application and imagine that it contains the statements inside the Main method generated
by earlier templates, but in the global namespace.
You can add more statements to the program, just like you can add more statements to your Main method in
the traditional style. You can access args (command-line arguments), use await , and set the exit code. You can
even add functions. They're created as local functions nested inside the generated Main method. Local functions
can't include any access modifiers (for example, public or protected ).
Both top-level statements and implicit using directives simplify the code that makes up your application. To
follow an existing tutorial, add any new statements to the Program.cs file generated by the template. You can
imagine that the statements you write are between the open and closing braces in the Main method in the
instructions of the tutorial.
If you'd prefer to use the older format, you can copy the code from the second example in this article, and
continue the tutorial as before.
You can learn more about top-level statements in the tutorial exploration on top-level statements.
Other application types include more namespaces that are common for those application types.
If you need using directives that aren't implicitly included, you can add them to the .cs file that contains top-
level statements or to other .cs files. For using directives that you need in all of the .cs files in an application,
use global using directives.
Disable implicit using directives
If you want to remove this behavior and manually control all namespaces in your project, add
<ImplicitUsings>disable</ImplicitUsings> to your project file in the <PropertyGroup> element, as shown in the
following example:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
...
<ImplicitUsings>disable</ImplicitUsings>
</PropertyGroup>
</Project>
<ItemGroup>
<Using Remove="System.Net.Http" />
</ItemGroup>
IMPORTANT
Creating a project that targets .NET 5 requires the .NET 5 templates. The .NET 5 templates can be installed manually with
the dotnet new --install command or by installing the .NET 5 SDK.
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
- <TargetFramework>net5.0</TargetFramework>
+ <TargetFramework>net6.0</TargetFramework>
</PropertyGroup>
</Project>
3. Optional step: you can still use some of the newer .NET 6 and C# features by adding the properties for
implicit using directives and nullable context to the project file.
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
+ <ImplicitUsings>enable</ImplicitUsings>
+ <Nullable>enable</Nullable>
</PropertyGroup>
</Project>
2. After your project is created, find the Project Explorer pane. Double-click on the project file and change
<TargetFramework>net5.0</TargetFramework> to <TargetFramework>net6.0</TargetFramework> .
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
- <TargetFramework>net5.0</TargetFramework>
+ <TargetFramework>net6.0</TargetFramework>
</PropertyGroup>
</Project>
Alternatively, you can right-click on the project in the Solution Explorer pane, and select Proper ties .
This opens up a settings page where you can change the Target framework .
3. Optional step: you can still use some of the newer .NET 6 and C# features by adding the properties for
implicit using directives and nullable context to the project file.
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
+ <ImplicitUsings>enable</ImplicitUsings>
+ <Nullable>enable</Nullable>
</PropertyGroup>
</Project>
Template feedback
Top-level statements is a new feature in .NET 6. Add an up or down vote in GitHub issue #27420 to let us know if
you support the use of this feature in project templates.
Tutorial: Create a .NET console application using
Visual Studio
9/10/2022 • 7 minutes to read • Edit Online
This tutorial shows how to create and run a .NET console application in Visual Studio 2022.
Prerequisites
Visual Studio 2022 version 17.1 or later with the .NET desktop development workload installed. The
.NET 6 SDK is automatically installed when you select this workload.
For more information, see Install the .NET SDK with Visual Studio.
3. On the Create a new project page, enter console in the search box. Next, choose C# or Visual Basic
from the language list, and then choose All platforms from the platform list. Choose the Console
Application template, and then choose Next .
TIP
If you don't see the .NET templates, you're probably missing the required workload. Under the Not finding what
you're looking for? message, choose the Install more tools and features link. The Visual Studio Installer
opens. Make sure you have the .NET desktop development workload installed.
4. In the Configure your new project dialog, enter HelloWorld in the Project name box. Then choose
Next .
5. In the Additional information dialog, select .NET 6 (Long-term suppor t) , and then select Create .
The template creates a simple application that displays "Hello World" in the console window. The code is
in the Program.cs or Program.vb file:
Console.WriteLine("Hello, World!");
Imports System
Module Program
Sub Main(args As String())
Console.WriteLine("Hello World!")
End Sub
End Module
If the language you want to use is not shown, change the language selector at the top of the page.
6. For C#, the code is just a line that calls the Console.WriteLine(String) method to display "Hello World!" in
the console window. Replace the contents of Program.cs with the following code:
namespace HelloWorld
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
}
}
}
The code defines a class, Program , with a single method, Main , that takes a String array as an argument.
Main is the application entry point, the method that's called automatically by the runtime when it
launches the application. Any command-line arguments supplied when the application is launched are
available in the args array.
In the latest version of C#, a new feature named top-level statements lets you omit the Program class and
the Main method. Most existing C# programs don't use top-level statements, so this tutorial doesn't use
this new feature. But it's available in C# 10, and whether you use it in your programs is a matter of style
preference.
This code displays a prompt in the console window and waits until the user enters a string followed by
the Enter key. It stores this string in a variable named name . It also retrieves the value of the
DateTime.Now property, which contains the current local time, and assigns it to a variable named
currentDate . And it displays these values in the console window. Finally, it displays a prompt in the
console window and calls the Console.ReadKey(Boolean) method to wait for user input.
Environment.NewLine is a platform-independent and language-independent way to represent a line
break. Alternatives are \n in C# and vbCrLf in Visual Basic.
The dollar sign ( $ ) in front of a string lets you put expressions such as variable names in curly braces in
the string. The expression value is inserted into the string in place of the expression. This syntax is
referred to as interpolated strings.
2. Press Ctrl+F5 to run the program without debugging.
3. Respond to the prompt by entering a name and pressing the Enter key.
Additional resources
Current releases and long-term support releases
Next steps
In this tutorial, you created a .NET console application. In the next tutorial, you debug the app.
Debug a .NET console application using Visual Studio
This tutorial shows how to create and run a .NET console application in Visual Studio 2019.
Prerequisites
Visual Studio 2019 version 16.9.2 or a later version with the .NET Core cross-platform development
workload installed. The .NET 5.0 SDK is automatically installed when you select this workload.
For more information, see Install the .NET SDK with Visual Studio.
3. On the Create a new project page, enter console in the search box. Next, choose C# or Visual Basic
from the language list, and then choose All platforms from the platform list. Choose the Console
Application template, and then choose Next .
TIP
If you don't see the .NET templates, you're probably missing the required workload. Under the Not finding what
you're looking for? message, choose the Install more tools and features link. The Visual Studio Installer
opens. Make sure you have the .NET Core cross-platform development workload installed.
4. In the Configure your new project dialog, enter HelloWorld in the Project name box. Then choose
Next .
5. In the Additional information dialog, select .NET 5.0 (Current) , and then select Create .
The template creates a simple "Hello World" application. It calls the Console.WriteLine(String) method to display
"Hello World!" in the console window.
The template code defines a class, Program , with a single method, Main , that takes a String array as an
argument:
using System;
namespace HelloWorld
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
}
}
}
Imports System
Module Program
Sub Main(args As String())
Console.WriteLine("Hello World!")
End Sub
End Module
Main is the application entry point, the method that's called automatically by the runtime when it launches the
application. Any command-line arguments supplied when the application is launched are available in the args
array.
If the language you want to use is not shown, change the language selector at the top of the page.
This code displays a prompt in the console window and waits until the user enters a string followed by
the Enter key. It stores this string in a variable named name . It also retrieves the value of the
DateTime.Now property, which contains the current local time, and assigns it to a variable named
currentDate . And it displays these values in the console window. Finally, it displays a prompt in the
console window and calls the Console.ReadKey(Boolean) method to wait for user input.
Environment.NewLine is a platform-independent and language-independent way to represent a line
break. Alternatives are \n in C# and vbCrLf in Visual Basic.
The dollar sign ( $ ) in front of a string lets you put expressions such as variable names in curly braces in
the string. The expression value is inserted into the string in place of the expression. This syntax is
referred to as interpolated strings.
2. Press Ctrl+F5 to run the program without debugging.
3. Respond to the prompt by entering a name and pressing the Enter key.
4. Press any key to close the console window.
Additional resources
Current releases and long-term support releases
Next steps
In this tutorial, you created a .NET console application. In the next tutorial, you debug the app.
Debug a .NET console application using Visual Studio
This tutorial is only available for .NET 5 and .NET 6. Select one of those options at the top of the page.
Tutorial: Debug a .NET console application using
Visual Studio
9/10/2022 • 13 minutes to read • Edit Online
Prerequisites
This tutorial works with the console app that you create in Create a .NET console application using Visual
Studio.
Set a breakpoint
A breakpoint temporarily interrupts the execution of the application before the line with the breakpoint is
executed.
1. Set a breakpoint on the line that displays the name, date, and time, by clicking in the left margin of the
code window on that line. The left margin is to the left of the line numbers. Other ways to set a
breakpoint are by placing the cursor in the line of code and then pressing F9 or choosing Debug >
Toggle Breakpoint from the menu bar.
As the following image shows, Visual Studio indicates the line on which the breakpoint is set by
highlighting it and displaying a red dot in the left margin.
2. Press F5 to run the program in Debug mode. Another way to start debugging is by choosing Debug >
Star t Debugging from the menu.
3. Enter a string in the console window when the program prompts for a name, and then press Enter.
4. Program execution stops when it reaches the breakpoint and before the Console.WriteLine method
executes. The Locals window displays the values of variables that are defined in the currently executing
method.
4. Press F5 to continue program execution. Another way to continue is by choosing Debug > Continue
from the menu.
The values displayed in the console window correspond to the changes you made in the Immediate
window.
String.IsNullOrEmpty(name)
String.IsNullOrEmpty(name)
Each time the breakpoint is hit, the debugger calls the String.IsNullOrEmpty(name) method, and it breaks
on this line only if the method call returns true .
Instead of a conditional expression, you can specify a hit count, which interrupts program execution
before a statement is executed a specified number of times. Another option is to specify a filter condition,
which interrupts program execution based on such attributes as a thread identifier, process name, or
thread name.
3. Select Close to close the dialog.
4. Start the program with debugging by pressing F5.
5. In the console window, press the Enter key when prompted to enter your name.
6. Because the condition you specified ( name is either null or String.Empty) has been satisfied, program
execution stops when it reaches the breakpoint and before the Console.WriteLine method executes.
7. Select the Locals window, which shows the values of variables that are local to the currently executing
method. In this case, Main is the currently executing method. Observe that the value of the name
variable is "" , or String.Empty.
8. Confirm the value is an empty string by entering the following statement in the Immediate window and
pressing Enter. The result is true .
? name == String.Empty
? String.IsNullOrEmpty(name)
Visual Basic
At this point, the Locals window shows that the args array is empty, and name and currentDate have
default values. In addition, Visual Studio has opened a blank console window.
2. Press F11. Visual Studio now highlights the next line of execution. The Locals window is unchanged, and
the console window remains blank.
C#
Visual Basic
3. Press F11. Visual Studio highlights the statement that includes the name variable assignment. The Locals
window shows that name is null , and the console window displays the string "What is your name?".
4. Respond to the prompt by entering a string in the console window and pressing Enter. The console is
unresponsive, and the string you entered isn't displayed in the console window, but the Console.ReadLine
method will nevertheless capture your input.
5. Press F11. Visual Studio highlights the statement that includes the currentDate variable assignment. The
Locals window shows the value returned by the call to the Console.ReadLine method. The console
window also displays the string you entered at the prompt.
6. Press F11. The Locals window shows the value of the currentDate variable after the assignment from
the DateTime.Now property. The console window is unchanged.
7. Press F11. Visual Studio calls the Console.WriteLine(String, Object, Object) method. The console window
displays the formatted string.
8. Choose Debug > Step Out . Another way to stop step-by-step execution is by pressing Shift+F11.
The console window displays a message and waits for you to press a key.
9. Press any key to close the console window and stop debugging.
When you press F5 or choose Build Solution from the Build menu, Visual Studio compiles the Release version
of the application. You can test it as you did the Debug version.
Next steps
In this tutorial, you used Visual Studio debugging tools. In the next tutorial, you publish a deployable version of
the app.
Publish a .NET console application using Visual Studio
This tutorial introduces the debugging tools available in Visual Studio.
Prerequisites
This tutorial works with the console app that you create in Create a .NET console application using Visual
Studio.
Set a breakpoint
A breakpoint temporarily interrupts the execution of the application before the line with the breakpoint is
executed.
1. Set a breakpoint on the line that displays the name, date, and time, by clicking in the left margin of the
code window on that line. The left margin is to the left of the line numbers. Other ways to set a
breakpoint are by placing the cursor in the line of code and then pressing F9 or choosing Debug >
Toggle Breakpoint from the menu bar.
As the following image shows, Visual Studio indicates the line on which the breakpoint is set by
highlighting it and displaying a red dot in the left margin.
2. Press F5 to run the program in Debug mode. Another way to start debugging is by choosing Debug >
Star t Debugging from the menu.
3. Enter a string in the console window when the program prompts for a name, and then press Enter.
4. Program execution stops when it reaches the breakpoint and before the Console.WriteLine method
executes. The Locals window displays the values of variables that are defined in the currently executing
method.
Use the Immediate window
The Immediate window lets you interact with the application you're debugging. You can interactively change
the value of variables to see how it affects your program.
1. If the Immediate window is not visible, display it by choosing Debug > Windows > Immediate .
2. Enter name = "Gracie" in the Immediate window and press the Enter key.
3. Enter currentDate = DateTime.Parse("2019-11-16T17:25:00Z").ToUniversalTime() in the Immediate
window and press the Enter key.
The Immediate window displays the value of the string variable and the properties of the DateTime
value. In addition, the values of the variables are updated in the Locals window.
4. Press F5 to continue program execution. Another way to continue is by choosing Debug > Continue
from the menu.
The values displayed in the console window correspond to the changes you made in the Immediate
window.
2. For the Conditional Expression , enter the following code in the field that shows example code that
tests if x is 5. If the language you want to use is not shown, change the language selector at the top of
the page.
String.IsNullOrEmpty(name)
String.IsNullOrEmpty(name)
Each time the breakpoint is hit, the debugger calls the String.IsNullOrEmpty(name) method, and it breaks
on this line only if the method call returns true .
Instead of a conditional expression, you can specify a hit count, which interrupts program execution
before a statement is executed a specified number of times. Another option is to specify a filter condition,
which interrupts program execution based on such attributes as a thread identifier, process name, or
thread name.
3. Select Close to close the dialog.
4. Start the program with debugging by pressing F5.
5. In the console window, press the Enter key when prompted to enter your name.
6. Because the condition you specified ( name is either null or String.Empty) has been satisfied, program
execution stops when it reaches the breakpoint and before the Console.WriteLine method executes.
7. Select the Locals window, which shows the values of variables that are local to the currently executing
method. In this case, Main is the currently executing method. Observe that the value of the name
variable is "" , or String.Empty.
8. Confirm the value is an empty string by entering the following statement in the Immediate window and
pressing Enter. The result is true .
? name == String.Empty
? String.IsNullOrEmpty(name)
At this point, the Locals window shows that the args array is empty, and name and currentDate have
default values. In addition, Visual Studio has opened a blank console window.
2. Press F11. Visual Studio now highlights the next line of execution. The Locals window is unchanged, and
the console window remains blank.
C#
Visual Basic
3. Press F11. Visual Studio highlights the statement that includes the name variable assignment. The Locals
window shows that name is null , and the console window displays the string "What is your name?".
4. Respond to the prompt by entering a string in the console window and pressing Enter. The console is
unresponsive, and the string you entered isn't displayed in the console window, but the Console.ReadLine
method will nevertheless capture your input.
5. Press F11. Visual Studio highlights the statement that includes the currentDate variable assignment. The
Locals window shows the value returned by the call to the Console.ReadLine method. The console
window also displays the string you entered at the prompt.
6. Press F11. The Locals window shows the value of the currentDate variable after the assignment from
the DateTime.Now property. The console window is unchanged.
7. Press F11. Visual Studio calls the Console.WriteLine(String, Object, Object) method. The console window
displays the formatted string.
8. Choose Debug > Step Out . Another way to stop step-by-step execution is by pressing Shift+F11.
The console window displays a message and waits for you to press a key.
9. Press any key to close the console window and stop debugging.
When you press F5 or choose Build Solution from the Build menu, Visual Studio compiles the Release version
of the application. You can test it as you did the Debug version.
Next steps
In this tutorial, you used Visual Studio debugging tools. In the next tutorial, you publish a deployable version of
the app.
Publish a .NET console application using Visual Studio
This tutorial is only available for .NET 5 and .NET 6. Select one of those options at the top of the page.
Tutorial: Publish a .NET console application using
Visual Studio
9/10/2022 • 5 minutes to read • Edit Online
This tutorial shows how to publish a console app so that other users can run it. Publishing creates the set of files
that are needed to run your application. To deploy the files, copy them to the target machine.
Prerequisites
This tutorial works with the console app that you create in Create a .NET console application using Visual
Studio.
4. Right-click on the HelloWorld project (not the HelloWorld solution) and select Publish from the menu.
5. On the Target tab of the Publish page, select Folder , and then select Next .
6. On the Specific Target tab of the Publish page, select Folder , and then select Next .
cd C:\Projects\HelloWorld\bin\Release\net6.0\publish\
Additional resources
.NET application deployment
Next steps
In this tutorial, you published a console app. In the next tutorial, you create a class library.
Create a .NET class library using Visual Studio
This tutorial shows how to publish a console app so that other users can run it. Publishing creates the set of files
that are needed to run your application. To deploy the files, copy them to the target machine.
Prerequisites
This tutorial works with the console app that you create in Create a .NET console application using Visual
Studio.
4. Right-click on the HelloWorld project (not the HelloWorld solution) and select Publish from the menu.
5. On the Target tab of the Publish page, select Folder , and then select Next .
6. On the Specific Target tab of the Publish page, select Folder , and then select Next .
7. On the Location tab of the Publish page, select Finish .
cd C:\Projects\HelloWorld\bin\Release\net5.0\publish\
Additional resources
.NET application deployment
Next steps
In this tutorial, you published a console app. In the next tutorial, you create a class library.
Create a .NET class library using Visual Studio
This tutorial is only available for .NET 5 and .NET 6. Select one of those options at the top of the page.
Tutorial: Create a .NET class library using Visual
Studio
9/10/2022 • 12 minutes to read • Edit Online
In this tutorial, you create a simple class library that contains a single string-handling method.
A class library defines types and methods that are called by an application. If the library targets .NET Standard
2.0, it can be called by any .NET implementation (including .NET Framework) that supports .NET Standard 2.0. If
the library targets .NET 6, it can be called by any application that targets .NET 6. This tutorial shows how to
target .NET 6.
When you create a class library, you can distribute it as a NuGet package or as a component bundled with the
application that uses it.
Prerequisites
Visual Studio 2022 version 17.0.0 Preview with the .NET desktop development workload installed. The
.NET 6 SDK is automatically installed when you select this workload.
For more information, see Install the .NET SDK with Visual Studio.
Create a solution
Start by creating a blank solution to put the class library project in. A Visual Studio solution serves as a container
for one or more projects. You'll add additional, related projects to the same solution.
To create the blank solution:
1. Start Visual Studio.
2. On the start window, choose Create a new project .
3. On the Create a new project page, enter solution in the search box. Choose the Blank Solution
template, and then choose Next .
4. On the Configure your new project page, enter ClassLibrar yProjects in the Solution name box.
Then choose Create .
namespace UtilityLibraries;
char ch = str[0];
return char.IsUpper(ch);
}
}
Imports System.Runtime.CompilerServices
Namespace UtilityLibraries
Public Module StringLibrary
<Extension>
Public Function StartsWithUpper(str As String) As Boolean
If String.IsNullOrWhiteSpace(str) Then
Return False
End If
using UtilityLibraries;
class Program
{
static void Main(string[] args)
{
int row = 0;
do
{
if (row == 0 || row >= 25)
ResetConsole();
Module Program
Dim row As Integer = 0
Sub Main()
Do
If row = 0 OrElse row >= 25 Then ResetConsole()
The code uses the row variable to maintain a count of the number of rows of data written to the console
window. Whenever it's greater than or equal to 25, the code clears the console window and displays a
message to the user.
The program prompts the user to enter a string. It indicates whether the string starts with an uppercase
character. If the user presses the Enter key without entering a string, the application ends, and the
console window closes.
3. Try out the program by entering strings and pressing Enter, then press Enter to exit.
Additional resources
Develop libraries with the .NET CLI
.NET Standard versions and the platforms they support.
Next steps
In this tutorial, you created a class library. In the next tutorial, you learn how to unit test the class library.
Unit test a .NET class library using Visual Studio
Or you can skip automated unit testing and learn how to share the library by creating a NuGet package:
Create and publish a package using Visual Studio
Or learn how to publish a console app. If you publish the console app from the solution you created in this
tutorial, the class library goes with it as a .dll file.
Publish a .NET console application using Visual Studio
In this tutorial, you create a simple class library that contains a single string-handling method.
A class library defines types and methods that are called by an application. If the library targets .NET Standard
2.0, it can be called by any .NET implementation (including .NET Framework) that supports .NET Standard 2.0. If
the library targets .NET 5, it can be called by any application that targets .NET 5. This tutorial shows how to
target .NET 5.
When you create a class library, you can distribute it as a NuGet package or as a component bundled with the
application that uses it.
Prerequisites
Visual Studio 2019 version 16.8 or a later version with the .NET Core cross-platform development
workload installed. The .NET 5.0 SDK is automatically installed when you select this workload. This tutorial
assumes you have enabled Show all .NET Core templates in the New project , as shown in Tutorial:
Create a .NET console application using Visual Studio.
Create a solution
Start by creating a blank solution to put the class library project in. A Visual Studio solution serves as a container
for one or more projects. You'll add additional, related projects to the same solution.
To create the blank solution:
1. Start Visual Studio.
2. On the start window, choose Create a new project .
3. On the Create a new project page, enter solution in the search box. Choose the Blank Solution
template, and then choose Next .
4. On the Configure your new project page, enter ClassLibrar yProjects in the Project name box.
Then choose Create .
For each project, Visual Basic automatically creates a namespace that corresponds to the project name. In
this tutorial, you define a top-level namespace by using the namespace keyword in the code file.
4. Replace the code in the code window for Class1.cs or Class1.vb with the following code, and save the file.
If the language you want to use is not shown, change the language selector at the top of the page.
using System;
namespace UtilityLibraries
{
public static class StringLibrary
{
public static bool StartsWithUpper(this string str)
{
if (string.IsNullOrWhiteSpace(str))
return false;
char ch = str[0];
return char.IsUpper(ch);
}
}
}
Imports System.Runtime.CompilerServices
Namespace UtilityLibraries
Public Module StringLibrary
<Extension>
Public Function StartsWithUpper(str As String) As Boolean
If String.IsNullOrWhiteSpace(str) Then
Return False
End If
using System;
using UtilityLibraries;
class Program
{
static void Main(string[] args)
{
int row = 0;
do
{
if (row == 0 || row >= 25)
ResetConsole();
Module Program
Dim row As Integer = 0
Sub Main()
Do
If row = 0 OrElse row >= 25 Then ResetConsole()
The code uses the row variable to maintain a count of the number of rows of data written to the console
window. Whenever it's greater than or equal to 25, the code clears the console window and displays a
message to the user.
The program prompts the user to enter a string. It indicates whether the string starts with an uppercase
character. If the user presses the Enter key without entering a string, the application ends, and the
console window closes.
3. Try out the program by entering strings and pressing Enter, then press Enter to exit.
Additional resources
Develop libraries with the .NET CLI
.NET Standard versions and the platforms they support.
Next steps
In this tutorial, you created a class library. In the next tutorial, you learn how to unit test the class library.
Unit test a .NET class library using Visual Studio
Or you can skip automated unit testing and learn how to share the library by creating a NuGet package:
Create and publish a package using Visual Studio
Or learn how to publish a console app. If you publish the console app from the solution you created in this
tutorial, the class library goes with it as a .dll file.
Publish a .NET console application using Visual Studio
This tutorial is only available for .NET 5 and .NET 6. Select one of those options at the top of the page.
Tutorial: Test a .NET class library with .NET using
Visual Studio
9/10/2022 • 18 minutes to read • Edit Online
This tutorial shows how to automate unit testing by adding a test project to a solution.
Prerequisites
This tutorial works with the solution that you create in Create a .NET class library using Visual Studio.
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace StringLibraryTest
{
[TestClass]
public class UnitTest1
{
[TestMethod]
public void TestMethod1()
{
}
}
}
Imports Microsoft.VisualStudio.TestTools.UnitTesting
Namespace StringLibraryTest
<TestClass>
Public Class UnitTest1
<TestMethod>
Sub TestSub()
End Sub
End Class
End Namespace
The source code created by the unit test template does the following:
It imports the Microsoft.VisualStudio.TestTools.UnitTesting namespace, which contains the types used
for unit testing.
It applies the TestClassAttribute attribute to the UnitTest1 class.
It applies the TestMethodAttribute attribute to define TestMethod1 in C# or TestSub in Visual Basic.
Each method tagged with [TestMethod] in a test class tagged with [TestClass] is executed automatically
when the unit test is run.
A SSERT M ET H O DS F UN C T IO N
Assert.AreEqual Verifies that two values or objects are equal. The assert fails
if the values or objects aren't equal.
Assert.AreSame Verifies that two object variables refer to the same object.
The assert fails if the variables refer to different objects.
Assert.IsNotNull Verifies that an object isn't null . The assert fails if the
object is null .
You can also use the Assert.ThrowsException method in a test method to indicate the type of exception it's
expected to throw. The test fails if the specified exception isn't thrown.
In testing the StringLibrary.StartsWithUpper method, you want to provide a number of strings that begin with
an uppercase character. You expect the method to return true in these cases, so you can call the Assert.IsTrue
method. Similarly, you want to provide a number of strings that begin with something other than an uppercase
character. You expect the method to return false in these cases, so you can call the Assert.IsFalse method.
Since your library method handles strings, you also want to make sure that it successfully handles an empty
string ( String.Empty ), a valid string that has no characters and whose Length is 0, and a null string that hasn't
been initialized. You can call StartsWithUpper directly as a static method and pass a single String argument. Or
you can call StartsWithUpper as an extension method on a string variable assigned to null .
You'll define three methods, each of which calls an Assert method for each element in a string array. You'll call a
method overload that lets you specify an error message to be displayed in case of test failure. The message
identifies the string that caused the failure.
To create the test methods:
1. In the UnitTest1.cs or UnitTest1.vb code window, replace the code with the following code:
using Microsoft.VisualStudio.TestTools.UnitTesting;
using UtilityLibraries;
namespace StringLibraryTest
{
[TestClass]
public class UnitTest1
{
[TestMethod]
public void TestStartsWithUpper()
{
// Tests that we expect to return true.
string[] words = { "Alphabet", "Zebra", "ABC", "Αθήνα", "Москва" };
foreach (var word in words)
{
bool result = word.StartsWithUpper();
Assert.IsTrue(result,
string.Format("Expected for '{0}': true; Actual: {1}",
word, result));
}
}
[TestMethod]
public void TestDoesNotStartWithUpper()
{
// Tests that we expect to return false.
string[] words = { "alphabet", "zebra", "abc", "αυτοκινητοβιομηχανία", "государство",
"1234", ".", ";", " " };
foreach (var word in words)
{
bool result = word.StartsWithUpper();
Assert.IsFalse(result,
string.Format("Expected for '{0}': false; Actual: {1}",
word, result));
}
}
[TestMethod]
public void DirectCallWithNullOrEmpty()
{
// Tests that we expect to return false.
string?[] words = { string.Empty, null };
foreach (var word in words)
{
bool result = StringLibrary.StartsWithUpper(word ?? string.Empty);
Assert.IsFalse(result,
string.Format("Expected for '{0}': false; Actual: {1}",
word == null ? "<null>" : word, result));
}
}
}
}
Imports Microsoft.VisualStudio.TestTools.UnitTesting
Imports UtilityLibraries
Namespace StringLibraryTest
<TestClass>
Public Class UnitTest1
<TestMethod>
Public Sub TestStartsWithUpper()
' Tests that we expect to return true.
Dim words() As String = {"Alphabet", "Zebra", "ABC", "Αθήνα", "Москва"}
For Each word In words
Dim result As Boolean = word.StartsWithUpper()
Assert.IsTrue(result,
$"Expected for '{word}': true; Actual: {result}")
Next
End Sub
<TestMethod>
Public Sub TestDoesNotStartWithUpper()
' Tests that we expect to return false.
Dim words() As String = {"alphabet", "zebra", "abc", "αυτοκινητοβιομηχανία",
"государство",
"1234", ".", ";", " "}
For Each word In words
Dim result As Boolean = word.StartsWithUpper()
Assert.IsFalse(result,
$"Expected for '{word}': false; Actual: {result}")
Next
End Sub
<TestMethod>
Public Sub DirectCallWithNullOrEmpty()
' Tests that we expect to return false.
Dim words() As String = {String.Empty, Nothing}
For Each word In words
Dim result As Boolean = StringLibrary.StartsWithUpper(word)
Assert.IsFalse(result,
$"Expected for '{If(word Is Nothing, "<null>", word)}': false; Actual:
{result}")
Next
End Sub
End Class
End Namespace
The test of uppercase characters in the TestStartsWithUpper method includes the Greek capital letter
alpha (U+0391) and the Cyrillic capital letter EM (U+041C). The test of lowercase characters in the
TestDoesNotStartWithUpper method includes the Greek small letter alpha (U+03B1) and the Cyrillic small
letter Ghe (U+0433).
2. On the menu bar, select File > Save UnitTest1.cs As or File > Save UnitTest1.vb As . In the Save File
As dialog, select the arrow beside the Save button, and select Save with Encoding .
3. In the Confirm Save As dialog, select the Yes button to save the file.
4. In the Advanced Save Options dialog, select Unicode (UTF-8 with signature) - Codepage 65001
from the Encoding drop-down list and select OK .
If you fail to save your source code as a UTF8-encoded file, Visual Studio may save it as an ASCII file.
When that happens, the runtime doesn't accurately decode the UTF8 characters outside of the ASCII
range, and the test results won't be correct.
5. On the menu bar, select Test > Run All Tests . If the Test Explorer window doesn't open, open it by
choosing Test > Test Explorer . The three tests are listed in the Passed Tests section, and the Summar y
section reports the result of the test run.
Handle test failures
If you're doing test-driven development (TDD), you write tests first and they fail the first time you run them. Then
you add code to the app that makes the test succeed. For this tutorial, you created the test after writing the app
code that it validates, so you haven't seen the test fail. To validate that a test fails when you expect it to fail, add
an invalid value to the test input.
1. Modify the words array in the TestDoesNotStartWithUpper method to include the string "Error". You don't
need to save the file because Visual Studio automatically saves open files when a solution is built to run
tests.
2. Run the test by selecting Test > Run All Tests from the menu bar. The Test Explorer window indicates
that two tests succeeded and one failed.
4. Remove the string "Error" that you added in step 1. Rerun the test and the tests pass.
2. In Solution Explorer , right-click the StringLibrar y project and select Build from the context menu to
recompile the library.
3. Run the unit tests by choosing Test > Run All Tests from the menu bar. The tests pass.
Debug tests
If you're using Visual Studio as your IDE, you can use the same process shown in Tutorial: Debug a .NET console
application using Visual Studio to debug code using your unit test project. Instead of starting the ShowCase app
project, right-click the StringLibrar yTests project, and select Debug Tests from the context menu.
Visual Studio starts the test project with the debugger attached. Execution will stop at any breakpoint you've
added to the test project or the underlying library code.
Additional resources
Unit test basics - Visual Studio
Unit testing in .NET
Next steps
In this tutorial, you unit tested a class library. You can make the library available to others by publishing it to
NuGet as a package. To learn how, follow a NuGet tutorial:
Create and publish a NuGet package using Visual Studio
If you publish a library as a NuGet package, others can install and use it. To learn how, follow a NuGet tutorial:
Install and use a package in Visual Studio
A library doesn't have to be distributed as a package. It can be bundled with a console app that uses it. To learn
how to publish a console app, see the earlier tutorial in this series:
Publish a .NET console application using Visual Studio
This tutorial shows how to automate unit testing by adding a test project to a solution.
Prerequisites
This tutorial works with the solution that you create in Create a .NET class library using Visual Studio.
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace StringLibraryTest
{
[TestClass]
public class UnitTest1
{
[TestMethod]
public void TestMethod1()
{
}
}
}
Imports Microsoft.VisualStudio.TestTools.UnitTesting
Namespace StringLibraryTest
<TestClass>
Public Class UnitTest1
<TestMethod>
Sub TestSub()
End Sub
End Class
End Namespace
The source code created by the unit test template does the following:
It imports the Microsoft.VisualStudio.TestTools.UnitTesting namespace, which contains the types used
for unit testing.
It applies the TestClassAttribute attribute to the UnitTest1 class.
It applies the TestMethodAttribute attribute to define TestMethod1 in C# or TestSub in Visual Basic.
Each method tagged with [TestMethod] in a test class tagged with [TestClass] is executed automatically
when the unit test is run.
A SSERT M ET H O DS F UN C T IO N
Assert.AreEqual Verifies that two values or objects are equal. The assert fails
if the values or objects aren't equal.
Assert.AreSame Verifies that two object variables refer to the same object.
The assert fails if the variables refer to different objects.
Assert.IsNotNull Verifies that an object isn't null . The assert fails if the
object is null .
You can also use the Assert.ThrowsException method in a test method to indicate the type of exception it's
expected to throw. The test fails if the specified exception isn't thrown.
In testing the StringLibrary.StartsWithUpper method, you want to provide a number of strings that begin with
an uppercase character. You expect the method to return true in these cases, so you can call the Assert.IsTrue
method. Similarly, you want to provide a number of strings that begin with something other than an uppercase
character. You expect the method to return false in these cases, so you can call the Assert.IsFalse method.
Since your library method handles strings, you also want to make sure that it successfully handles an empty
string ( String.Empty ), a valid string that has no characters and whose Length is 0, and a null string that hasn't
been initialized. You can call StartsWithUpper directly as a static method and pass a single String argument. Or
you can call StartsWithUpper as an extension method on a string variable assigned to null .
You'll define three methods, each of which calls an Assert method for each element in a string array. You'll call a
method overload that lets you specify an error message to be displayed in case of test failure. The message
identifies the string that caused the failure.
To create the test methods:
1. In the UnitTest1.cs or UnitTest1.vb code window, replace the code with the following code:
using Microsoft.VisualStudio.TestTools.UnitTesting;
using UtilityLibraries;
namespace StringLibraryTest
{
[TestClass]
public class UnitTest1
{
[TestMethod]
public void TestStartsWithUpper()
{
// Tests that we expect to return true.
string[] words = { "Alphabet", "Zebra", "ABC", "Αθήνα", "Москва" };
foreach (var word in words)
{
bool result = word.StartsWithUpper();
Assert.IsTrue(result,
string.Format("Expected for '{0}': true; Actual: {1}",
word, result));
}
}
[TestMethod]
public void TestDoesNotStartWithUpper()
{
// Tests that we expect to return false.
string[] words = { "alphabet", "zebra", "abc", "αυτοκινητοβιομηχανία", "государство",
"1234", ".", ";", " " };
foreach (var word in words)
{
bool result = word.StartsWithUpper();
Assert.IsFalse(result,
string.Format("Expected for '{0}': false; Actual: {1}",
word, result));
}
}
[TestMethod]
public void DirectCallWithNullOrEmpty()
{
// Tests that we expect to return false.
string?[] words = { string.Empty, null };
foreach (var word in words)
{
bool result = StringLibrary.StartsWithUpper(word ?? string.Empty);
Assert.IsFalse(result,
string.Format("Expected for '{0}': false; Actual: {1}",
word == null ? "<null>" : word, result));
}
}
}
}
Imports Microsoft.VisualStudio.TestTools.UnitTesting
Imports UtilityLibraries
Namespace StringLibraryTest
<TestClass>
Public Class UnitTest1
<TestMethod>
Public Sub TestStartsWithUpper()
' Tests that we expect to return true.
Dim words() As String = {"Alphabet", "Zebra", "ABC", "Αθήνα", "Москва"}
For Each word In words
Dim result As Boolean = word.StartsWithUpper()
Assert.IsTrue(result,
$"Expected for '{word}': true; Actual: {result}")
Next
End Sub
<TestMethod>
Public Sub TestDoesNotStartWithUpper()
' Tests that we expect to return false.
Dim words() As String = {"alphabet", "zebra", "abc", "αυτοκινητοβιομηχανία",
"государство",
"1234", ".", ";", " "}
For Each word In words
Dim result As Boolean = word.StartsWithUpper()
Assert.IsFalse(result,
$"Expected for '{word}': false; Actual: {result}")
Next
End Sub
<TestMethod>
Public Sub DirectCallWithNullOrEmpty()
' Tests that we expect to return false.
Dim words() As String = {String.Empty, Nothing}
For Each word In words
Dim result As Boolean = StringLibrary.StartsWithUpper(word)
Assert.IsFalse(result,
$"Expected for '{If(word Is Nothing, "<null>", word)}': false; Actual:
{result}")
Next
End Sub
End Class
End Namespace
The test of uppercase characters in the TestStartsWithUpper method includes the Greek capital letter
alpha (U+0391) and the Cyrillic capital letter EM (U+041C). The test of lowercase characters in the
TestDoesNotStartWithUpper method includes the Greek small letter alpha (U+03B1) and the Cyrillic small
letter Ghe (U+0433).
2. On the menu bar, select File > Save UnitTest1.cs As or File > Save UnitTest1.vb As . In the Save File
As dialog, select the arrow beside the Save button, and select Save with Encoding .
3. In the Confirm Save As dialog, select the Yes button to save the file.
4. In the Advanced Save Options dialog, select Unicode (UTF-8 with signature) - Codepage 65001
from the Encoding drop-down list and select OK .
If you fail to save your source code as a UTF8-encoded file, Visual Studio may save it as an ASCII file.
When that happens, the runtime doesn't accurately decode the UTF8 characters outside of the ASCII
range, and the test results won't be correct.
5. On the menu bar, select Test > Run All Tests . If the Test Explorer window doesn't open, open it by
choosing Test > Test Explorer . The three tests are listed in the Passed Tests section, and the Summar y
section reports the result of the test run.
Handle test failures
If you're doing test-driven development (TDD), you write tests first and they fail the first time you run them. Then
you add code to the app that makes the test succeed. For this tutorial, you created the test after writing the app
code that it validates, so you haven't seen the test fail. To validate that a test fails when you expect it to fail, add
an invalid value to the test input.
1. Modify the words array in the TestDoesNotStartWithUpper method to include the string "Error". You don't
need to save the file because Visual Studio automatically saves open files when a solution is built to run
tests.
2. Run the test by selecting Test > Run All Tests from the menu bar. The Test Explorer window indicates
that two tests succeeded and one failed.
4. Remove the string "Error" that you added in step 1. Rerun the test and the tests pass.
2. In Solution Explorer , right-click the StringLibrar y project and select Build from the context menu to
recompile the library.
3. Run the unit tests by choosing Test Run > All Tests from the menu bar. The tests pass.
Debug tests
If you're using Visual Studio as your IDE, you can use the same process shown in Tutorial: Debug a .NET console
application using Visual Studio to debug code using your unit test project. Instead of starting the ShowCase app
project, right-click the StringLibrar yTests project, and select Debug Tests from the context menu.
Visual Studio starts the test project with the debugger attached. Execution will stop at any breakpoint you've
added to the test project or the underlying library code.
Additional resources
Unit test basics - Visual Studio
Unit testing in .NET
Next steps
In this tutorial, you unit tested a class library. You can make the library available to others by publishing it to
NuGet as a package. To learn how, follow a NuGet tutorial:
Create and publish a NuGet package using Visual Studio
If you publish a library as a NuGet package, others can install and use it. To learn how, follow a NuGet tutorial:
Install and use a package in Visual Studio
A library doesn't have to be distributed as a package. It can be bundled with a console app that uses it. To learn
how to publish a console app, see the earlier tutorial in this series:
Publish a .NET console application using Visual Studio
This tutorial is only available for .NET 5 and .NET 6. Select one of those options at the top of the page.
Tutorial: Create a .NET console application using
Visual Studio Code
9/10/2022 • 7 minutes to read • Edit Online
This tutorial shows how to create and run a .NET console application by using Visual Studio Code and the .NET
CLI. Project tasks, such as creating, compiling, and running a project are done by using the .NET CLI. You can
follow this tutorial with a different code editor and run commands in a terminal if you prefer.
Prerequisites
Visual Studio Code with the C# extension installed. For information about how to install extensions on Visual
Studio Code, see VS Code Extension Marketplace.
The .NET 6 SDK.
The project template creates a simple application that displays "Hello World" in the console window by
calling the Console.WriteLine(String) method in Program.cs.
Console.WriteLine("Hello, World!");
The first time you edit a .cs file, Visual Studio Code prompts you to add the missing assets to build and
debug your app. Select Yes , and Visual Studio Code creates a .vscode folder with launch.json and
tasks.json files.
NOTE
If you don't get the prompt, or if you accidentally dismiss it without selecting Yes , do the following steps to create
launch.json and tasks.json:
Select Run > Add Configuration from the menu.
Select .NET 5+ and .NET Core at the Select environment prompt.
The code defines a class, Program , with a single method, Main , that takes a String array as an argument.
Main is the application entry point, the method that's called automatically by the runtime when it
launches the application. Any command-line arguments supplied when the application is launched are
available in the args array.
In the latest version of C#, a new feature named top-level statements lets you omit the Program class and
the Main method. Most existing C# programs don't use top-level statements, so this tutorial doesn't use
this new feature. But it's available in C# 10, and whether you use it in your programs is a matter of style
preference.
dotnet run
This code displays a prompt in the console window and waits until the user enters a string followed by
the Enter key. It stores this string in a variable named name . It also retrieves the value of the
DateTime.Now property, which contains the current local time, and assigns it to a variable named
currentDate . And it displays these values in the console window. Finally, it displays a prompt in the
console window and calls the Console.ReadKey(Boolean) method to wait for user input.
NewLine is a platform-independent and language-independent way to represent a line break.
Alternatives are \n in C# and vbCrLf in Visual Basic.
The dollar sign ( $ ) in front of a string lets you put expressions such as variable names in curly braces in
the string. The expression value is inserted into the string in place of the expression. This syntax is
referred to as interpolated strings.
3. Save your changes.
IMPORTANT
In Visual Studio Code, you have to explicitly save changes. Unlike Visual Studio, file changes are not automatically
saved when you build and run an app.
dotnet run
5. Respond to the prompt by entering a name and pressing the Enter key.
Additional resources
Setting up Visual Studio Code
Next steps
In this tutorial, you created a .NET console application. In the next tutorial, you debug the app.
Debug a .NET console application using Visual Studio Code
This tutorial shows how to create and run a .NET console application by using Visual Studio Code and the .NET
CLI. Project tasks, such as creating, compiling, and running a project are done by using the .NET CLI. You can
follow this tutorial with a different code editor and run commands in a terminal if you prefer.
Prerequisites
1. Visual Studio Code with the C# extension installed. For information about how to install extensions on Visual
Studio Code, see VS Code Extension Marketplace.
2. The .NET 5 SDK. If you install the .NET 6 SDK, install the .NET 5 SDK also, or some of the tutorial instructions
won't work. For more information, see New C# templates generate top-level statements.
The template creates a simple "Hello World" application. It calls the Console.WriteLine(String) method to display
"Hello World!" in the console window.
The template code defines a class, Program , with a single method, Main , that takes a String array as an
argument:
using System;
namespace HelloWorld
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
}
}
}
Main is the application entry point, the method that's called automatically by the runtime when it launches the
application. Any command-line arguments supplied when the application is launched are available in the args
array.
dotnet run
2. Select Yes when Visual Studio Code prompts you to add the missing assets to build and debug your app.
3. Replace the contents of the Main method in Program.cs, which is the line that calls Console.WriteLine ,
with the following code:
This code displays a prompt in the console window and waits until the user enters a string followed by
the Enter key. It stores this string in a variable named name . It also retrieves the value of the
DateTime.Now property, which contains the current local time, and assigns it to a variable named
currentDate . And it displays these values in the console window. Finally, it displays a prompt in the
console window and calls the Console.ReadKey(Boolean) method to wait for user input.
NewLine is a platform-independent and language-independent way to represent a line break.
Alternatives are \n in C# and vbCrLf in Visual Basic.
The dollar sign ( $ ) in front of a string lets you put expressions such as variable names in curly braces in
the string. The expression value is inserted into the string in place of the expression. This syntax is
referred to as interpolated strings.
4. Save your changes.
IMPORTANT
In Visual Studio Code, you have to explicitly save changes. Unlike Visual Studio, file changes are not automatically
saved when you build and run an app.
dotnet run
6. Respond to the prompt by entering a name and pressing the Enter key.
7. Press any key to exit the program.
Additional resources
Setting up Visual Studio Code
Next steps
In this tutorial, you created a .NET console application. In the next tutorial, you debug the app.
Debug a .NET console application using Visual Studio Code
This tutorial is only available for .NET 5 and .NET 6. Select one of those options at the top of the page.
Tutorial: Debug a .NET console application using
Visual Studio Code
9/10/2022 • 13 minutes to read • Edit Online
This tutorial introduces the debugging tools available in Visual Studio Code for working with .NET apps.
Prerequisites
This tutorial works with the console app that you create in Create a .NET console application using Visual
Studio Code.
Set a breakpoint
A breakpoint temporarily interrupts the execution of the application before the line with the breakpoint is run.
1. Open the Program.cs file.
2. Set a breakpoint on the line that displays the name, date, and time, by clicking in the left margin of the
code window. The left margin is to the left of the line numbers. Other ways to set a breakpoint are by
pressing F9 or choosing Run > Toggle Breakpoint from the menu while the line of code is selected.
Visual Studio Code indicates the line on which the breakpoint is set by displaying a red dot in the left
margin.
Set up for terminal input
The breakpoint is located after a Console.ReadLine method call. The Debug Console doesn't accept terminal
input for a running program. To handle terminal input while debugging, you can use the integrated terminal
(one of the Visual Studio Code windows) or an external terminal. For this tutorial, you use the integrated
terminal.
1. Open .vscode/launch.json.
2. Change the console setting from internalConsole to integratedTerminal :
"console": "integratedTerminal",
Start debugging
1. Open the Debug view by selecting the Debugging icon on the left side menu.
2. Select the green arrow at the top of the pane, next to .NET Core Launch (console) . Other ways to start
the program in debugging mode are by pressing F5 or choosing Run > Star t Debugging from the
menu.
3. Select the Terminal tab to see the "What is your name?" prompt that the program displays before
waiting for a response.
4. Enter a string in the Terminal window in response to the prompt for a name, and then press Enter.
Program execution stops when it reaches the breakpoint and before the Console.WriteLine method runs.
The Locals section of the Variables window displays the values of variables that are defined in the
currently running method.
2. Select Expression in the drop-down, enter the following conditional expression, and press Enter.
String.IsNullOrEmpty(name)
Each time the breakpoint is hit, the debugger calls the String.IsNullOrEmpty(name) method, and it breaks
on this line only if the method call returns true .
Instead of a conditional expression, you can specify a hit count, which interrupts program execution
before a statement is run a specified number of times. Another option is to specify a filter condition,
which interrupts program execution based on such attributes as a thread identifier, process name, or
thread name.
3. Start the program with debugging by pressing F5.
4. In the Terminal tab, press the Enter key when prompted to enter your name.
Because the condition you specified ( name is either null or String.Empty) has been satisfied, program
execution stops when it reaches the breakpoint and before the Console.WriteLine method runs.
The Variables window shows that the value of the name variable is "" , or String.Empty.
5. Confirm the value is an empty string by entering the following statement at the Debug Console prompt
and pressing Enter. The result is true .
name == String.Empty
6. Respond to the prompt by entering a string in the Terminal tab and pressing Enter.
The Terminal tab might not display the string you enter while you're entering it, but the
Console.ReadLine method will capture your input.
7. Select Run > Step Into or press F11.
Visual Studio Code highlights the currentDate variable assignment. The Variables window shows the
value returned by the call to the Console.ReadLine method. The Terminal tab displays the string you
entered at the prompt.
8. Select Run > Step Into or press F11.
The Variables window shows the value of the currentDate variable after the assignment from the
DateTime.Now property.
9. Select Run > Step Into or press F11.
Visual Studio Code calls the Console.WriteLine(String, Object, Object) method. The console window
displays the formatted string.
10. Select Run > Step Out or press Shift+F11.
Additional resources
Debugging in Visual Studio Code
Next steps
In this tutorial, you used Visual Studio Code debugging tools. In the next tutorial, you publish a deployable
version of the app.
Publish a .NET console application using Visual Studio Code
This tutorial introduces the debugging tools available in Visual Studio Code for working with .NET apps.
Prerequisites
This tutorial works with the console app that you create in Create a .NET console application using Visual
Studio Code.
Set a breakpoint
A breakpoint temporarily interrupts the execution of the application before the line with the breakpoint is
executed.
1. Open the Program.cs file.
2. Set a breakpoint on the line that displays the name, date, and time, by clicking in the left margin of the
code window. The left margin is to the left of the line numbers. Other ways to set a breakpoint are by
pressing F9 or choosing Run > Toggle Breakpoint from the menu while the line of code is selected.
Visual Studio Code indicates the line on which the breakpoint is set by displaying a red dot in the left
margin.
Set up for terminal input
The breakpoint is located after a Console.ReadLine method call. The Debug Console doesn't accept terminal
input for a running program. To handle terminal input while debugging, you can use the integrated terminal
(one of the Visual Studio Code windows) or an external terminal. For this tutorial, you use the integrated
terminal.
1. Open .vscode/launch.json.
2. Change the console setting from internalConsole to integratedTerminal :
"console": "integratedTerminal",
Start debugging
1. Open the Debug view by selecting the Debugging icon on the left side menu.
2. Select the green arrow at the top of the pane, next to .NET Core Launch (console) . Other ways to start
the program in debugging mode are by pressing F5 or choosing Run > Star t Debugging from the
menu.
3. Select the Terminal tab to see the "What is your name?" prompt that the program displays before
waiting for a response.
4. Enter a string in the Terminal window in response to the prompt for a name, and then press Enter.
Program execution stops when it reaches the breakpoint and before the Console.WriteLine method
executes. The Locals section of the Variables window displays the values of variables that are defined in
the currently executing method.
2. Select Expression in the drop-down, enter the following conditional expression, and press Enter.
String.IsNullOrEmpty(name)
Each time the breakpoint is hit, the debugger calls the String.IsNullOrEmpty(name) method, and it breaks
on this line only if the method call returns true .
Instead of a conditional expression, you can specify a hit count, which interrupts program execution
before a statement is executed a specified number of times. Another option is to specify a filter condition,
which interrupts program execution based on such attributes as a thread identifier, process name, or
thread name.
3. Start the program with debugging by pressing F5.
4. In the Terminal tab, press the Enter key when prompted to enter your name.
Because the condition you specified ( name is either null or String.Empty) has been satisfied, program
execution stops when it reaches the breakpoint and before the Console.WriteLine method executes.
The Variables window shows that the value of the name variable is "" , or String.Empty.
5. Confirm the value is an empty string by entering the following statement at the Debug Console prompt
and pressing Enter. The result is true .
name == String.Empty
6. Respond to the prompt by entering a string in the Terminal tab and pressing Enter.
The Terminal tab might not display the string you enter while you're entering it, but the
Console.ReadLine method will capture your input.
7. Select Run > Step Into or press F11.
Visual Studio Code highlights the currentDate variable assignment. The Variables window shows the
value returned by the call to the Console.ReadLine method. The Terminal tab displays the string you
entered at the prompt.
8. Select Run > Step Into or press F11.
The Variables window shows the value of the currentDate variable after the assignment from the
DateTime.Now property.
9. Select Run > Step Into or press F11.
Visual Studio Code calls the Console.WriteLine(String, Object, Object) method. The console window
displays the formatted string.
10. Select Run > Step Out or press Shift+F11.
Additional resources
Debugging in Visual Studio Code
Next steps
In this tutorial, you used Visual Studio Code debugging tools. In the next tutorial, you publish a deployable
version of the app.
Publish a .NET console application using Visual Studio Code
This tutorial is only available for .NET 5 and .NET 6. Select one of those options at the top of the page.
Tutorial: Publish a .NET console application using
Visual Studio Code
9/10/2022 • 6 minutes to read • Edit Online
This tutorial shows how to publish a console app so that other users can run it. Publishing creates the set of files
that are needed to run an application. To deploy the files, copy them to the target machine.
The .NET CLI is used to publish the app, so you can follow this tutorial with a code editor other than Visual
Studio Code if you prefer.
Prerequisites
This tutorial works with the console app that you create in Create a .NET console application using Visual
Studio Code.
The default build configuration is Debug, so this command specifies the Release build configuration. The
output from the Release build configuration has minimal symbolic debug information and is fully
optimized.
The command output is similar to the following example:
As the image shows, the published output includes the following files:
HelloWorld.deps.json
This is the application's runtime dependencies file. It defines the .NET components and the libraries
(including the dynamic link library that contains your application) needed to run the app. For more
information, see Runtime configuration files.
HelloWorld.dll
This is the framework-dependent deployment version of the application. To run this dynamic link
library, enter dotnet HelloWorld.dll at a command prompt. This method of running the app
works on any platform that has the .NET runtime installed.
HelloWorld.exe (HelloWorld on Linux, not created on macOS.)
This is the framework-dependent executable version of the application. The file is operating-
system-specific.
HelloWorld.pdb (optional for deployment)
This is the debug symbols file. You aren't required to deploy this file along with your application,
although you should save it in the event that you need to debug the published version of your
application.
HelloWorld.runtimeconfig.json
This is the application's runtime configuration file. It identifies the version of .NET that your
application was built to run on. You can also add configuration options to it. For more information,
see .NET runtime configuration settings.
Additional resources
.NET application deployment
Next steps
In this tutorial, you published a console app. In the next tutorial, you create a class library.
Create a .NET class library using Visual Studio Code
This tutorial shows how to publish a console app so that other users can run it. Publishing creates the set of files
that are needed to run an application. To deploy the files, copy them to the target machine.
The .NET CLI is used to publish the app, so you can follow this tutorial with a code editor other than Visual
Studio Code if you prefer.
Prerequisites
This tutorial works with the console app that you create in Create a .NET console application using Visual
Studio Code.
The default build configuration is Debug, so this command specifies the Release build configuration. The
output from the Release build configuration has minimal symbolic debug information and is fully
optimized.
The command output is similar to the following example:
As the image shows, the published output includes the following files:
HelloWorld.deps.json
This is the application's runtime dependencies file. It defines the .NET components and the libraries
(including the dynamic link library that contains your application) needed to run the app. For more
information, see Runtime configuration files.
HelloWorld.dll
This is the framework-dependent deployment version of the application. To execute this dynamic
link library, enter dotnet HelloWorld.dll at a command prompt. This method of running the app
works on any platform that has the .NET runtime installed.
HelloWorld.exe (HelloWorld on Linux, not created on macOS.)
This is the framework-dependent executable version of the application. The file is operating-
system-specific.
HelloWorld.pdb (optional for deployment)
This is the debug symbols file. You aren't required to deploy this file along with your application,
although you should save it in the event that you need to debug the published version of your
application.
HelloWorld.runtimeconfig.json
This is the application's runtime configuration file. It identifies the version of .NET that your
application was built to run on. You can also add configuration options to it. For more information,
see .NET runtime configuration settings.
Additional resources
.NET application deployment
Next steps
In this tutorial, you published a console app. In the next tutorial, you create a class library.
Create a .NET class library using Visual Studio Code
This tutorial is only available for .NET 5 and .NET 6. Select one of those options at the top of the page.
Tutorial: Create a .NET class library using Visual
Studio Code
9/10/2022 • 11 minutes to read • Edit Online
In this tutorial, you create a simple utility library that contains a single string-handling method.
A class library defines types and methods that are called by an application. If the library targets .NET Standard
2.0, it can be called by any .NET implementation (including .NET Framework) that supports .NET Standard 2.0. If
the library targets .NET 6, it can be called by any application that targets .NET 6. This tutorial shows how to
target .NET 6.
When you create a class library, you can distribute it as a third-party component or as a bundled component
with one or more applications.
Prerequisites
Visual Studio Code with the C# extension installed. For information about how to install extensions on Visual
Studio Code, see VS Code Extension Marketplace.
The .NET 6 SDK.
Create a solution
Start by creating a blank solution to put the class library project in. A solution serves as a container for one or
more projects. You'll add additional, related projects to the same solution.
1. Start Visual Studio Code.
2. Select File > Open Folder (Open... on macOS) from the main menu
3. In the Open Folder dialog, create a ClassLibraryProjects folder and click Select Folder (Open on
macOS).
4. Open the Terminal in Visual Studio Code by selecting View > Terminal from the main menu.
The Terminal opens with the command prompt in the ClassLibraryProjects folder.
5. In the Terminal , enter the following command:
The -o or --output command specifies the location to place the generated output.
The terminal output looks like the following example:
2. Run the following command to add the library project to the solution:
3. Check to make sure that the library targets .NET 6. In Explorer , open StringLibrary/StringLibrary.csproj.
The TargetFramework element shows that the project targets .NET 6.0.
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
</PropertyGroup>
</Project>
4. Open Class1.cs and replace the code with the following code.
namespace UtilityLibraries;
char ch = str[0];
return char.IsUpper(ch);
}
}
dotnet build
2. Run the following command to add the console app project to the solution:
3. Open ShowCase/Program.cs and replace all of the code with the following code.
using UtilityLibraries;
class Program
{
static void Main(string[] args)
{
int row = 0;
do
{
if (row == 0 || row >= 25)
ResetConsole();
The code uses the row variable to maintain a count of the number of rows of data written to the console
window. Whenever it's greater than or equal to 25, the code clears the console window and displays a
message to the user.
The program prompts the user to enter a string. It indicates whether the string starts with an uppercase
character. If the user presses the Enter key without entering a string, the application ends, and the
console window closes.
4. Save your changes.
2. Try out the program by entering strings and pressing Enter, then press Enter to exit.
The terminal output looks like the following example:
Press <Enter> only to exit; otherwise, enter a string and press <Enter>:
Additional resources
Develop libraries with the .NET CLI
.NET Standard versions and the platforms they support.
Next steps
In this tutorial, you created a solution, added a library project, and added a console app project that uses the
library. In the next tutorial, you add a unit test project to the solution.
Test a .NET class library with .NET using Visual Studio Code
In this tutorial, you create a simple utility library that contains a single string-handling method.
A class library defines types and methods that are called by an application. If the library targets .NET Standard
2.0, it can be called by any .NET implementation (including .NET Framework) that supports .NET Standard 2.0. If
the library targets .NET 5, it can be called by any application that targets .NET 5. This tutorial shows how to
target .NET 5.
When you create a class library, you can distribute it as a third-party component or as a bundled component
with one or more applications.
Prerequisites
1. Visual Studio Code with the C# extension installed. For information about how to install extensions on Visual
Studio Code, see VS Code Extension Marketplace.
2. The .NET 5.0 SDK or later
Create a solution
Start by creating a blank solution to put the class library project in. A solution serves as a container for one or
more projects. You'll add additional, related projects to the same solution.
1. Start Visual Studio Code.
2. Select File > Open Folder (Open... on macOS) from the main menu
3. In the Open Folder dialog, create a ClassLibraryProjects folder and click Select Folder (Open on
macOS).
4. Open the Terminal in Visual Studio Code by selecting View > Terminal from the main menu.
The Terminal opens with the command prompt in the ClassLibraryProjects folder.
5. In the Terminal , enter the following command:
The -o or --output command specifies the location to place the generated output.
The terminal output looks like the following example:
2. Run the following command to add the library project to the solution:
3. Check to make sure that the library targets .NET 5. In Explorer , open StringLibrary/StringLibrary.csproj.
The TargetFramework element shows that the project targets .NET 5.0.
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
</PropertyGroup>
</Project>
4. Open Class1.cs and replace the code with the following code.
using System;
namespace UtilityLibraries
{
public static class StringLibrary
{
public static bool StartsWithUpper(this string str)
{
if (string.IsNullOrWhiteSpace(str))
return false;
char ch = str[0];
return char.IsUpper(ch);
}
}
}
dotnet build
2. Run the following command to add the console app project to the solution:
3. Open ShowCase/Program.cs and replace all of the code with the following code.
using System;
using UtilityLibraries;
class Program
{
static void Main(string[] args)
{
int row = 0;
do
{
if (row == 0 || row >= 25)
ResetConsole();
The code uses the row variable to maintain a count of the number of rows of data written to the console
window. Whenever it's greater than or equal to 25, the code clears the console window and displays a
message to the user.
The program prompts the user to enter a string. It indicates whether the string starts with an uppercase
character. If the user presses the Enter key without entering a string, the application ends, and the
console window closes.
4. Save your changes.
2. Try out the program by entering strings and pressing Enter, then press Enter to exit.
The terminal output looks like the following example:
Press <Enter> only to exit; otherwise, enter a string and press <Enter>:
Additional resources
Develop libraries with the .NET CLI
.NET Standard versions and the platforms they support.
Next steps
In this tutorial, you created a solution, added a library project, and added a console app project that uses the
library. In the next tutorial, you add a unit test project to the solution.
Test a .NET class library with .NET using Visual Studio Code
This tutorial is only available for .NET 5 and .NET 6. Select one of those options at the top of the page.
Tutorial: Test a .NET class library using Visual Studio
Code
9/10/2022 • 14 minutes to read • Edit Online
This tutorial shows how to automate unit testing by adding a test project to a solution.
Prerequisites
This tutorial works with the solution that you create in Create a .NET class library using Visual Studio Code.
The project template creates a UnitTest1.cs file with the following code:
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace StringLibraryTest
{
[TestClass]
public class UnitTest1
{
[TestMethod]
public void TestMethod1()
{
}
}
}
The source code created by the unit test template does the following:
It imports the Microsoft.VisualStudio.TestTools.UnitTesting namespace, which contains the types used
for unit testing.
It applies the TestClassAttribute attribute to the UnitTest1 class.
It applies the TestMethodAttribute attribute to define TestMethod1 .
Each method tagged with [TestMethod] in a test class tagged with [TestClass] is run automatically when
the unit test is invoked.
4. Add the test project to the solution.
dotnet sln add StringLibraryTest/StringLibraryTest.csproj
A SSERT M ET H O DS F UN C T IO N
Assert.AreEqual Verifies that two values or objects are equal. The assert fails
if the values or objects aren't equal.
Assert.AreSame Verifies that two object variables refer to the same object.
The assert fails if the variables refer to different objects.
Assert.IsNotNull Verifies that an object isn't null . The assert fails if the
object is null .
You can also use the Assert.ThrowsException method in a test method to indicate the type of exception it's
expected to throw. The test fails if the specified exception isn't thrown.
In testing the StringLibrary.StartsWithUpper method, you want to provide a number of strings that begin with
an uppercase character. You expect the method to return true in these cases, so you can call the Assert.IsTrue
method. Similarly, you want to provide a number of strings that begin with something other than an uppercase
character. You expect the method to return false in these cases, so you can call the Assert.IsFalse method.
Since your library method handles strings, you also want to make sure that it successfully handles an empty
string ( String.Empty ) and a null string. An empty string is one that has no characters and whose Length is 0. A
null string is one that hasn't been initialized. You can call StartsWithUpper directly as a static method and pass
a single String argument. Or you can call StartsWithUpper as an extension method on a string variable
assigned to null .
You'll define three methods, each of which calls an Assert method for each element in a string array. You'll call a
method overload that lets you specify an error message to be displayed in case of test failure. The message
identifies the string that caused the failure.
To create the test methods:
1. Open StringLibraryTest/UnitTest1.cs and replace all of the code with the following code.
using Microsoft.VisualStudio.TestTools.UnitTesting;
using UtilityLibraries;
namespace StringLibraryTest;
[TestClass]
public class UnitTest1
{
[TestMethod]
public void TestStartsWithUpper()
{
// Tests that we expect to return true.
string[] words = { "Alphabet", "Zebra", "ABC", "Αθήνα", "Москва" };
foreach (var word in words)
{
bool result = word.StartsWithUpper();
Assert.IsTrue(result,
string.Format("Expected for '{0}': true; Actual: {1}",
word, result));
}
}
[TestMethod]
public void TestDoesNotStartWithUpper()
{
// Tests that we expect to return false.
string[] words = { "alphabet", "zebra", "abc", "αυτοκινητοβιομηχανία", "государство",
"1234", ".", ";", " " };
foreach (var word in words)
{
bool result = word.StartsWithUpper();
Assert.IsFalse(result,
string.Format("Expected for '{0}': false; Actual: {1}",
word, result));
}
}
[TestMethod]
public void DirectCallWithNullOrEmpty()
{
// Tests that we expect to return false.
string?[] words = { string.Empty, null };
foreach (var word in words)
{
bool result = StringLibrary.StartsWithUpper(word);
Assert.IsFalse(result,
string.Format("Expected for '{0}': false; Actual: {1}",
word == null ? "<null>" : word, result));
}
}
}
The test of uppercase characters in the TestStartsWithUpper method includes the Greek capital letter
alpha (U+0391) and the Cyrillic capital letter EM (U+041C). The test of lowercase characters in the
TestDoesNotStartWithUpper method includes the Greek small letter alpha (U+03B1) and the Cyrillic small
letter Ghe (U+0433).
2. Save your changes.
3. Run the tests:
dotnet test StringLibraryTest/StringLibraryTest.csproj
The terminal output shows that one test fails, and it provides an error message for the failed test:
"Assert.IsFalse failed. Expected for 'Error': false; actual: True". Because of the failure, no strings in the array
after "Error" were tested.
3. Remove the string "Error" that you added in step 1. Rerun the test and the tests pass.
Debug tests
If you're using Visual Studio Code as your IDE, you can use the same process shown in Debug a .NET console
application using Visual Studio Code to debug code using your unit test project. Instead of starting the
ShowCase app project, open StringLibraryTest/UnitTest1.cs, and select Debug All Tests between lines 7 and 8. If
you're unable to find it, press Ctrl+Shift+P to open the command palette and enter Reload Window .
Visual Studio Code starts the test project with the debugger attached. Execution will stop at any breakpoint
you've added to the test project or the underlying library code.
Additional resources
Unit testing in .NET
Next steps
In this tutorial, you unit tested a class library. You can make the library available to others by publishing it to
NuGet as a package. To learn how, follow a NuGet tutorial:
Create and publish a package using the dotnet CLI
If you publish a library as a NuGet package, others can install and use it. To learn how, follow a NuGet tutorial:
Install and use a package using the dotnet CLI
A library doesn't have to be distributed as a package. It can be bundled with a console app that uses it. To learn
how to publish a console app, see the earlier tutorial in this series:
Publish a .NET console application using Visual Studio Code
This tutorial shows how to automate unit testing by adding a test project to a solution.
Prerequisites
This tutorial works with the solution that you create in Create a .NET class library using Visual Studio Code.
The project template creates a UnitTest1.cs file with the following code:
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace StringLibraryTest
{
[TestClass]
public class UnitTest1
{
[TestMethod]
public void TestMethod1()
{
}
}
}
The source code created by the unit test template does the following:
It imports the Microsoft.VisualStudio.TestTools.UnitTesting namespace, which contains the types used
for unit testing.
It applies the TestClassAttribute attribute to the UnitTest1 class.
It applies the TestMethodAttribute attribute to define TestMethod1 .
Each method tagged with [TestMethod] in a test class tagged with [TestClass] is executed automatically
when the unit test is run.
4. Add the test project to the solution.
A SSERT M ET H O DS F UN C T IO N
Assert.AreEqual Verifies that two values or objects are equal. The assert fails
if the values or objects aren't equal.
Assert.AreSame Verifies that two object variables refer to the same object.
The assert fails if the variables refer to different objects.
A SSERT M ET H O DS F UN C T IO N
Assert.IsNotNull Verifies that an object isn't null . The assert fails if the
object is null .
You can also use the Assert.ThrowsException method in a test method to indicate the type of exception it's
expected to throw. The test fails if the specified exception isn't thrown.
In testing the StringLibrary.StartsWithUpper method, you want to provide a number of strings that begin with
an uppercase character. You expect the method to return true in these cases, so you can call the Assert.IsTrue
method. Similarly, you want to provide a number of strings that begin with something other than an uppercase
character. You expect the method to return false in these cases, so you can call the Assert.IsFalse method.
Since your library method handles strings, you also want to make sure that it successfully handles an empty
string ( String.Empty ) and a null string. An empty string is one that has no characters and whose Length is 0. A
null string is one that hasn't been initialized. You can call StartsWithUpper directly as a static method and pass
a single String argument. Or you can call StartsWithUpper as an extension method on a string variable
assigned to null .
You'll define three methods, each of which calls an Assert method for each element in a string array. You'll call a
method overload that lets you specify an error message to be displayed in case of test failure. The message
identifies the string that caused the failure.
To create the test methods:
1. Open StringLibraryTest/UnitTest1.cs and replace all of the code with the following code.
using Microsoft.VisualStudio.TestTools.UnitTesting;
using UtilityLibraries;
namespace StringLibraryTest
{
[TestClass]
public class UnitTest1
{
[TestMethod]
public void TestStartsWithUpper()
{
// Tests that we expect to return true.
string[] words = { "Alphabet", "Zebra", "ABC", "Αθήνα", "Москва" };
foreach (var word in words)
{
bool result = word.StartsWithUpper();
Assert.IsTrue(result,
string.Format("Expected for '{0}': true; Actual: {1}",
word, result));
}
}
[TestMethod]
public void TestDoesNotStartWithUpper()
{
// Tests that we expect to return false.
string[] words = { "alphabet", "zebra", "abc", "αυτοκινητοβιομηχανία", "государство",
"1234", ".", ";", " " };
foreach (var word in words)
{
bool result = word.StartsWithUpper();
Assert.IsFalse(result,
string.Format("Expected for '{0}': false; Actual: {1}",
word, result));
}
}
[TestMethod]
public void DirectCallWithNullOrEmpty()
{
// Tests that we expect to return false.
string?[] words = { string.Empty, null };
foreach (var word in words)
{
bool result = StringLibrary.StartsWithUpper(word ?? string.Empty);
Assert.IsFalse(result,
string.Format("Expected for '{0}': false; Actual: {1}",
word == null ? "<null>" : word, result));
}
}
}
}
The test of uppercase characters in the TestStartsWithUpper method includes the Greek capital letter
alpha (U+0391) and the Cyrillic capital letter EM (U+041C). The test of lowercase characters in the
TestDoesNotStartWithUpper method includes the Greek small letter alpha (U+03B1) and the Cyrillic small
letter Ghe (U+0433).
2. Save your changes.
3. Run the tests:
The terminal output shows that one test fails, and it provides an error message for the failed test:
"Assert.IsFalse failed. Expected for 'Error': false; actual: True". Because of the failure, no strings in the array
after "Error" were tested.
3. Remove the string "Error" that you added in step 1. Rerun the test and the tests pass.
Additional resources
Unit testing in .NET
Next steps
In this tutorial, you unit tested a class library. You can make the library available to others by publishing it to
NuGet as a package. To learn how, follow a NuGet tutorial:
Create and publish a package using the dotnet CLI
If you publish a library as a NuGet package, others can install and use it. To learn how, follow a NuGet tutorial:
Install and use a package using the dotnet CLI
A library doesn't have to be distributed as a package. It can be bundled with a console app that uses it. To learn
how to publish a console app, see the earlier tutorial in this series:
Publish a .NET console application using Visual Studio Code
This tutorial is only available for .NET 5 and .NET 6. Select one of those options at the top of the page.
Tutorial: Create a .NET console application using
Visual Studio for Mac
9/10/2022 • 3 minutes to read • Edit Online
This tutorial shows how to create and run a .NET console application using Visual Studio for Mac.
NOTE
Your feedback is highly valued. There are two ways you can provide feedback to the development team on Visual Studio
for Mac:
In Visual Studio for Mac, select Help > Repor t a Problem from the menu or Repor t a Problem from the Welcome
screen, which will open a window for filing a bug report. You can track your feedback in the Developer Community
portal.
To make a suggestion, select Help > Provide a Suggestion from the menu or Provide a Suggestion from the
Welcome screen, which will take you to the Visual Studio for Mac Developer Community webpage.
Prerequisites
Visual Studio for Mac version 8.8 or later. Select the option to install .NET Core. Installing Xamarin is
optional for .NET development. For more information, see the following resources:
Tutorial: Install Visual Studio for Mac.
Supported macOS versions.
.NET versions supported by Visual Studio for Mac.
3. In the New Project dialog, select App under the Web and Console node. Select the Console
Application template, and select Next .
4. In the Target Framework drop-down of the Configure your new Console Application dialog, select
.NET 5.0 , and select Next .
5. Type "HelloWorld" for the Project Name , and select Create .
The template creates a simple "Hello World" application. It calls the Console.WriteLine(String) method to display
"Hello World!" in the terminal window.
The template code defines a class, Program , with a single method, Main , that takes a String array as an
argument:
using System;
namespace HelloWorld
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
}
}
}
Main is the application entry point, the method that's called automatically by the runtime when it launches the
application. Any command-line arguments supplied when the application is launched are available in the args
array.
This code displays a prompt in the console window and waits until the user enters a string followed by
the enter key. It stores this string in a variable named name . It also retrieves the value of the
DateTime.Now property, which contains the current local time, and assigns it to a variable named
currentDate . And it displays these values in the console window. Finally, it displays a prompt in the
console window and calls the Console.ReadKey(Boolean) method to wait for user input.
NewLine is a platform-independent and language-independent way to represent a line break.
Alternatives are \n in C# and vbCrLf in Visual Basic.
The dollar sign ( $ ) in front of a string lets you put expressions such as variable names in curly braces in
the string. The expression value is inserted into the string in place of the expression. This syntax is
referred to as interpolated strings.
2. Press ⌘↵ (option+command+enter) to run the app.
Next steps
In this tutorial, you created a .NET console application. In the next tutorial, you debug the app.
Debug a .NET console application using Visual Studio for Mac
Tutorial: Debug a .NET console application using
Visual Studio for Mac
9/10/2022 • 6 minutes to read • Edit Online
This tutorial introduces the debugging tools available in Visual Studio for Mac.
Prerequisites
This tutorial works with the console app that you create in Create a .NET console application using Visual
Studio for Mac.
Set a breakpoint
A breakpoint temporarily interrupts the execution of the application before the line with the breakpoint is
executed.
1. Set a breakpoint on the line that displays the name, date, and time. To do that, place the cursor in the line
of code and press ⌘\ (command+\). Another way to set a breakpoint is by selecting Run > Toggle
Breakpoint from the menu.
Visual Studio indicates the line on which the breakpoint is set by highlighting it and displaying a red dot
in the left margin.
2. Press ⌘↵ (command+enter) to start the program in debugging mode. Another way to start debugging
is by choosing Run > Star t Debugging from the menu.
3. Enter a string in the terminal window when the program prompts for a name, and then press enter.
4. Program execution stops when it reaches the breakpoint, before the Console.WriteLine method executes.
String.IsNullOrEmpty(name)
Each time the breakpoint is hit, the debugger calls the String.IsNullOrEmpty(name) method, and it breaks
on this line only if the method call returns true .
Instead of a conditional expression, you can specify a hit count, which interrupts program execution
before a statement is executed a specified number of times.
3. Press ⌘↵ (command+enter) to start debugging.
4. In the terminal window, press enter when prompted to enter your name.
Because the condition you specified ( name is either null or String.Empty) has been satisfied, program
execution stops when it reaches the breakpoint.
5. Select the Locals window, which shows the values of variables that are local to the currently executing
method. In this case, Main is the currently executing method. Observe that the value of the name
variable is "" , that is, String.Empty.
6. You can also see that the value is an empty string by entering the name variable name in the Immediate
window and pressing enter.
7. Press ⌘↵ (command+enter) to continue debugging.
8. In the terminal window, press any key to exit the program.
9. Close the terminal window.
10. Clear the breakpoint by clicking on the red dot in the left margin of the code window. Another way to
clear a breakpoint is by choosing Run > Toggle Breakpoint while the line of code is selected.
Next steps
In this tutorial, you used Visual Studio debugging tools. In the next tutorial, you publish a deployable version of
the app.
Publish a .NET console application using Visual Studio for Mac
Tutorial: Publish a .NET console application using
Visual Studio for Mac
9/10/2022 • 2 minutes to read • Edit Online
This tutorial shows how to publish a console app so that other users can run it. Publishing creates the set of files
that are needed to run your application. To deploy the files, copy them to the target machine.
Prerequisites
This tutorial works with the console app that you create in Create a .NET console application using Visual
Studio for Mac.
6. Select the gear icon, and select Copy "publish" as Pathname from the context menu.
cd ~/Projects/HelloWorld/HelloWorld/bin/Release/net5.0/publish/
Additional resources
.NET application deployment
Next steps
In this tutorial, you published a console app. In the next tutorial, you create a class library.
Create a .NET library using Visual Studio for Mac
Tutorial: Create a .NET class library using Visual
Studio for Mac
9/10/2022 • 4 minutes to read • Edit Online
In this tutorial, you create a class library that contains a single string-handling method.
A class library defines types and methods that are called by an application. If the library targets .NET Standard
2.0, it can be called by any .NET implementation (including .NET Framework) that supports .NET Standard 2.0. If
the library targets .NET 5, it can be called by any application that targets .NET 5. This tutorial shows how to
target .NET 5.
NOTE
Your feedback is highly valued. There are two ways you can provide feedback to the development team on Visual Studio
for Mac:
In Visual Studio for Mac, select Help > Repor t a Problem from the menu or Repor t a Problem from the Welcome
screen, which opens a window for filing a bug report. You can track your feedback in the Developer Community portal.
To make a suggestion, select Help > Provide a Suggestion from the menu or Provide a Suggestion from the
Welcome screen, which takes you to the Visual Studio for Mac Developer Community webpage.
Prerequisites
Install Visual Studio for Mac version 8.8 or later. Select the option to install .NET Core. Installing Xamarin
is optional for .NET development. For more information, see the following resources:
Tutorial: Install Visual Studio for Mac.
Supported macOS versions.
.NET versions supported by Visual Studio for Mac.
6. From the main menu, select View > Solution , and select the dock icon to keep the pad open.
7. In the Solution pad, expand the StringLibrary node to reveal the class file provided by the template,
Class1.cs. ctrl-click the file, select Rename from the context menu, and rename the file to
StringLibrary.cs. Open the file and replace the contents with the following code:
using System;
namespace UtilityLibraries
{
public static class StringLibrary
{
public static bool StartsWithUpper(this string str)
{
if (string.IsNullOrWhiteSpace(str))
return false;
char ch = str[0];
return char.IsUpper(ch);
}
}
}
4. Open the Program.cs file. Replace the code with the following code:
using System;
using UtilityLibraries;
class Program
{
static void Main(string[] args)
{
int row = 0;
do
{
if (row == 0 || row >= 25)
ResetConsole();
The program prompts the user to enter a string. It indicates whether the string starts with an uppercase
character. If the user presses the enter key without entering a string, the application ends, and the
console window closes.
The code uses the row variable to maintain a count of the number of rows of data written to the console
window. Whenever it's greater than or equal to 25, the code clears the console window and displays a
message to the user.
Next steps
In this tutorial, you created a solution and a library project, and added a console app project that uses the library.
In the next tutorial, you add a unit test project to the solution.
Test a .NET class library using Visual Studio for Mac
Test a .NET class library using Visual Studio
9/10/2022 • 7 minutes to read • Edit Online
This tutorial shows how to automate unit testing by adding a test project to a solution.
Prerequisites
This tutorial works with the solution that you create in Create a .NET class library using Visual Studio for Mac.
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace StringLibraryTest
{
[TestClass]
public class UnitTest1
{
[TestMethod]
public void TestMethod1()
{
}
}
}
The source code created by the unit test template does the following:
It imports the Microsoft.VisualStudio.TestTools.UnitTesting namespace, which contains the types used
for unit testing.
It applies the TestClassAttribute attribute to the UnitTest1 class.
It applies the TestMethodAttribute attribute to TestMethod1 .
Each method tagged with [TestMethod] in a test class tagged with [TestClass] is executed automatically
when the unit test is run.
A SSERT M ET H O DS F UN C T IO N
Assert.AreEqual Verifies that two values or objects are equal. The assert fails
if the values or objects aren't equal.
Assert.AreSame Verifies that two object variables refer to the same object.
The assert fails if the variables refer to different objects.
Assert.IsNotNull Verifies that an object isn't null . The assert fails if the
object is null .
You can also use the Assert.ThrowsException method in a test method to indicate the type of exception it's
expected to throw. The test fails if the specified exception isn't thrown.
In testing the StringLibrary.StartsWithUpper method, you want to provide a number of strings that begin with
an uppercase character. You expect the method to return true in these cases, so you can call the Assert.IsTrue
method. Similarly, you want to provide a number of strings that begin with something other than an uppercase
character. You expect the method to return false in these cases, so you can call the Assert.IsFalse method.
Since your library method handles strings, you also want to make sure that it successfully handles an empty
string ( String.Empty ), a valid string that has no characters and whose Length is 0, and a null string that hasn't
been initialized. You can call StartsWithUpper directly as a static method and pass a single String argument. Or
you can call StartsWithUpper as an extension method on a string variable assigned to null .
You'll define three methods, each of which calls an Assert method for each element in a string array. You'll call a
method overload that lets you specify an error message to be displayed in case of test failure. The message
identifies the string that caused the failure.
To create the test methods:
1. Open the UnitTest1.cs file and replace the code with the following code:
using Microsoft.VisualStudio.TestTools.UnitTesting;
using UtilityLibraries;
namespace StringLibraryTest
{
[TestClass]
public class UnitTest1
{
[TestMethod]
public void TestStartsWithUpper()
{
// Tests that we expect to return true.
string[] words = { "Alphabet", "Zebra", "ABC", "Αθήνα", "Москва" };
foreach (var word in words)
{
bool result = word.StartsWithUpper();
Assert.IsTrue(result,
string.Format("Expected for '{0}': true; Actual: {1}",
word, result));
}
}
[TestMethod]
public void TestDoesNotStartWithUpper()
{
// Tests that we expect to return false.
string[] words = { "alphabet", "zebra", "abc", "αυτοκινητοβιομηχανία", "государство",
"1234", ".", ";", " " };
foreach (var word in words)
{
bool result = word.StartsWithUpper();
Assert.IsFalse(result,
string.Format("Expected for '{0}': false; Actual: {1}",
word, result));
}
}
[TestMethod]
public void DirectCallWithNullOrEmpty()
{
// Tests that we expect to return false.
string?[] words = { string.Empty, null };
foreach (var word in words)
{
bool result = StringLibrary.StartsWithUpper(word ?? string.Empty);
Assert.IsFalse(result,
string.Format("Expected for '{0}': false; Actual: {1}",
word == null ? "<null>" : word, result));
}
}
}
}
The test of uppercase characters in the TestStartsWithUpper method includes the Greek capital letter
alpha (U+0391) and the Cyrillic capital letter EM (U+041C). The test of lowercase characters in the
TestDoesNotStartWithUpper method includes the Greek small letter alpha (U+03B1) and the Cyrillic small
letter Ghe (U+0433).
2. On the menu bar, select File > Save As . In the dialog, make sure that Encoding is set to Unicode (UTF-
8) .
3. When you're asked if you want to replace the existing file, select Replace .
If you fail to save your source code as a UTF8-encoded file, Visual Studio may save it as an ASCII file.
When that happens, the runtime doesn't accurately decode the UTF8 characters outside of the ASCII
range, and the test results won't be correct.
4. Open the Unit Tests panel on the right side of the screen. Select View > Tests from the menu.
5. Click the Dock icon to keep the panel open.
3. ctrl-click the failed test, TestDoesNotStartWithUpper , and select Show Results Pad from the context
menu.
The Results pad displays the message produced by the assert: "Assert.IsFalse failed. Expected for 'Error':
false; actual: True". Because of the failure, no strings in the array after "Error" were tested.
4. Remove the string "Error" that you added in step 1. Rerun the test and the tests pass.
2. In the Solution pad, ctrl-click the StringLibrar y project and select Build from the context menu to
recompile the library.
Debug tests
If you're using Visual Studio for Mac as your IDE, you can use the same process shown in Tutorial: Debug a .NET
console application using Visual Studio for Mac to debug code using your unit test project. Instead of starting
the ShowCase app project, ctrl-click the StringLibrar yTests project, and select Star t Debugging Project
from the context menu.
Visual Studio starts the test project with the debugger attached. Execution will stop at any breakpoint you've
added to the test project or the underlying library code.
Additional resources
Unit testing in .NET
Next steps
In this tutorial, you unit tested a class library. You can make the library available to others by publishing it to
NuGet as a package. To learn how, follow a NuGet tutorial:
Create and publish a package (dotnet CLI)
If you publish a library as a NuGet package, others can install and use it. To learn how, follow a NuGet tutorial:
Install and use a package in Visual Studio for Mac
A library doesn't have to be distributed as a package. It can be bundled with a console app that uses it. To learn
how to publish a console app, see the earlier tutorial in this series:
Publish a .NET console application using Visual Studio for Mac
Learn .NET and the .NET SDK tools by exploring
these tutorials
9/10/2022 • 2 minutes to read • Edit Online
The following tutorials show how to develop console apps and libraries for .NET Core, .NET 5, and later versions.
For other types of applications, see Tutorials for getting started with .NET.
Advanced topics
How to create libraries
Unit test an app with xUnit
Unit test using C#/VB/F# with NUnit/xUnit/MSTest
Live unit test with Visual Studio
Create templates for the CLI
Create and use tools for the CLI
Create an app with plugins
What's new in .NET 6
9/10/2022 • 12 minutes to read • Edit Online
.NET 6 delivers the final parts of the .NET unification plan that started with .NET 5. .NET 6 unifies the SDK, base
libraries, and runtime across mobile, desktop, IoT, and cloud apps. In addition to this unification, the .NET 6
ecosystem offers:
Simplified development : Getting started is easy. New language features in C# 10 reduce the amount
of code you need to write. And investments in the web stack and minimal APIs make it easy to quickly
write smaller, faster microservices.
Better performance : .NET 6 is the fastest full stack web framework, which lowers compute costs if
you're running in the cloud.
Ultimate productivity : .NET 6 and Visual Studio 2022 provide hot reload, new git tooling, intelligent
code editing, robust diagnostics and testing tools, and better team collaboration.
.NET 6 will be supported for three years as a long-term support (LTS) release.
Preview features are disabled by default. They are also not supported for use in production and may be
removed in a future version. The new RequiresPreviewFeaturesAttribute is used to annotate preview APIs, and a
corresponding analyzer alerts you if you're using these preview APIs.
.NET 6 is supported by Visual Studio 2022 and Visual Studio 2022 for Mac (and later versions).
This article does not cover all of the new features of .NET 6. To see all of the new features, and for further
information about the features listed in this article, see the Announcing .NET 6 blog post.
Performance
.NET 6 includes numerous performance improvements. This section lists some of the improvements—in
FileStream, profile-guided optimization, and AOT compilation. For detailed information, see the Performance
improvements in .NET 6 blog post.
FileStream
The System.IO.FileStream type has been rewritten for .NET 6 to provide better performance and reliability on
Windows. Now, FileStream never blocks when created for asynchronous I/O on Windows. For more information,
see the File IO improvements in .NET 6 blog post.
Profile -guided optimization
Profile-guided optimization (PGO) is where the JIT compiler generates optimized code in terms of the types and
code paths that are most frequently used. .NET 6 introduces dynamic PGO. Dynamic PGO works hand-in-hand
with tiered compilation to further optimize code based on additional instrumentation that's put in place during
tier 0. Dynamic PGO is disabled by default, but you can enable it with the DOTNET_TieredPGO environment
variable. For more information, see JIT performance improvements.
Crossgen2
.NET 6 introduces Crossgen2, the successor to Crossgen, which has been removed. Crossgen and Crossgen2 are
tools that provide ahead-of-time (AOT) compilation to improve the startup time of an app. Crossgen2 is written
in C# instead of C++, and can perform analysis and optimization that weren't possible with the previous version.
For more information, see Conversation about Crossgen2.
Arm64 support
The .NET 6 release includes support for macOS Arm64 (or "Apple Silicon") and Windows Arm64 operating
systems, for both native Arm64 execution and x64 emulation. In addition, the x64 and Arm64 .NET installers
now install side by side. For more information, see .NET Support for macOS 11 and Windows 11 for Arm64 and
x64.
Hot reload
Hot reload is a feature that lets you modify your app's source code and instantly apply those changes to your
running app. The feature's purpose is to increase your productivity by avoiding app restarts between edits. Hot
reload is available in Visual Studio 2022 and the dotnet watch command-line tool. Hot reload works with most
types of .NET apps, and for C#, Visual Basic, and C++ source code. For more information, see the Hot reload
blog post.
.NET MAUI
.NET Multi-platform App UI (.NET MAUI) is still in preview , with a release candidate coming in the first quarter of
2022 and general availability (GA) in the second quarter of 2022. .NET MAUI makes it possible to build native
client apps for desktop and mobile operating systems with a single codebase. For more information, see the
Update on .NET Multi-platform App UI blog post.
C# 10 and templates
C# 10 includes innovations such as global using directives, file-scoped namespace declarations, and record
structs. For more information, see What's new in C# 10.
In concert with that work, the .NET SDK project templates for C# have been modernized to use some of the new
language features:
async Main method
Top-level statements
Target-typed new expressions
Implicit global using directives
File-scoped namespaces
Nullable reference types
By adding these new language features to the project templates, new code starts with the features enabled.
However, existing code isn't affected when you upgrade to .NET 6. For more information about these template
changes, see the .NET SDK: C# project templates modernized blog post.
SDK Workloads
To keep the size of the .NET SDK smaller, some components have been placed in new, optional SDK workloads.
These components include .NET MAUI and Blazor WebAssembly AOT. If you use Visual Studio, it will take care of
installing any SDK workloads that you need. If you use the .NET CLI, you can manage workloads using the new
dotnet workload commands:
C OMMAND DESC RIP T IO N
System.Text.Json APIs
Many improvements have been made in System.Text.Json in .NET 6, such that it is now an "industrial strength"
serialization solution.
Source generator
.NET 6 adds a new source generator for System.Text.Json. Source generation works with JsonSerializer and can
be configured in multiple ways. It can improve performance, reduce memory usage, and facilitate assembly
trimming. For more information, see How to choose reflection or source generation in System.Text.Json and
How to use source generation in System.Text.Json.
Writeable DOM
A new, writeable document object model (DOM) has been added, which supplements the pre-existing read-only
DOM. The new API provides a lightweight serialization alternative for cases when use of plain old CLR object
(POCO) types isn't possible. It also allows you to efficiently navigate to a subsection of a large JSON tree and
read an array or deserialize a POCO from that subsection. The following new types have been added to support
the writeable DOM:
JsonNode
JsonArray
JsonObject
JsonValue
For more information, see JSON DOM choices.
IAsyncEnumerable serialization
System.Text.Json now supports serialization and deserialization with IAsyncEnumerable<T> instances.
Asynchronous serialization methods enumerate any IAsyncEnumerable<T> instances in an object graph and
then serialize them as JSON arrays. For deserialization, the new method
JsonSerializer.DeserializeAsyncEnumerable<TValue>(Stream, JsonSerializerOptions, CancellationToken) was
added. For more information, see IAsyncEnumerable serialization.
Other new APIs
New serialization interfaces for validation and defaulting values:
IJsonOnDeserialized
IJsonOnDeserializing
IJsonOnSerialized
IJsonOnSerializing
For more information, see Callbacks.
New property ordering attribute:
JsonPropertyOrderAttribute
For more information, see Configure the order of serialized properties.
New method to write "raw" JSON:
Utf8JsonWriter.WriteRawValue
For more information, see Write Raw JSON.
Synchronous serialization and deserialization to a stream:
JsonSerializer.Deserialize(Stream, Type, JsonSerializerOptions)
JsonSerializer.Deserialize(Stream, Type, JsonSerializerContext)
JsonSerializer.Deserialize<TValue>(Stream, JsonSerializerOptions)
JsonSerializer.Deserialize<TValue>(Stream, JsonTypeInfo<TValue>)
JsonSerializer.Serialize(Stream, Object, Type, JsonSerializerOptions)
JsonSerializer.Serialize(Stream, Object, Type, JsonSerializerContext)
JsonSerializer.Serialize<TValue>(Stream, TValue, JsonSerializerOptions)
JsonSerializer.Serialize<TValue>(Stream, TValue, JsonTypeInfo<TValue>)
New option to ignore an object when a reference cycle is detected during serialization:
ReferenceHandler.IgnoreCycles
For more information, see Ignore circular references.
For more information about serializing and deserializing with System.Text.Json , see JSON serialization and
deserialization in .NET.
HTTP/3
.NET 6 includes preview support for HTTP/3, a new version of HTTP. HTTP/3 solves some existing functional and
performance challenges by using a new underlying connection protocol called QUIC. QUIC establishes
connections more quickly, and connections are independent of the IP address, allowing mobile clients to roam
between Wi-fi and cellular networks. For more information, see Use HTTP/3 with HttpClient.
ASP.NET Core
ASP.NET Core includes improvements in minimal APIs, ahead-of-time (AOT) compilation for Blazor
WebAssembly apps, and single-page apps. In addition, Blazorcomponents can now be rendered from JavaScript
and integrated with existing JavaScript based apps. For more information, see What's new in ASP.NET Core 6.
OpenTelemetry
.NET 6 brings improved support for OpenTelemetry, which is a collection of tools, APIs, and SDKs that help you
analyze your software's performance and behavior. APIs in the System.Diagnostics.Metrics namespace
implement the OpenTelemetry Metrics API specification. For example, there are four instrument classes to
support different metrics scenarios. The instrument classes are:
Counter<T>
Histogram<T>
ObservableCounter<T>
ObservableGauge<T>
Security
.NET 6 adds preview support for two key security mitigations: Control-flow Enforcement Technology (CET) and
"write exclusive execute" (W^X).
CET is an Intel technology available in some newer Intel and AMD processors. It adds capabilities to the
hardware that protect against some control-flow hijacking attacks. .NET 6 provides support for CET for Windows
x64 apps, and you must explicitly enable it. For more information, see .NET 6 compatibility with Intel CET
shadow stacks.
W^X is available all operating systems with .NET 6 but only enabled by default on Apple Silicon. W^X blocks the
simplest attack path by disallowing memory pages to be writeable and executable at the same time.
IL trimming
Trimming of self-contained deployments is improved. In .NET 5, only unused assemblies were trimmed. .NET 6
adds trimming of unused types and members too. In addition, trim warnings, which alert you to places where
trimming may remove code that's used at run time, are now enabled by default. For more information, see Trim
self-contained deployments and executables.
Code analysis
The .NET 6 SDK includes a handful of new code analyzers that concern API compatibility, platform compatibility,
trimming safety, use of span in string concatenation and splitting, faster string APIs, and faster collection APIs.
For a full list of new (and removed) analyzers, see Analyzer releases - .NET 6.
Windows Forms
Application.SetDefaultFont(Font) is a new method in .NET 6 that sets the default font across your application.
The templates for C# Windows Forms apps have been updated to support global using directives, file-scoped
namespaces, and nullable reference types. In addition, they include application bootstrap code, which reduces
boilerplate code and allows the Windows Forms designer to render the design surface in the preferred font. The
bootstrap code is a call to ApplicationConfiguration.Initialize() , which is a source-generated method that
emits calls to other configuration methods, such as Application.EnableVisualStyles(). Additionally, if you set a
non-default font via the ApplicationDefaultFont MSBuild property, ApplicationConfiguration.Initialize() emits
a call to SetDefaultFont(Font).
For more information, see the What's new in Windows Forms blog post.
Source build
The source tarball, which contains all the source for the .NET SDK, is now a product of the .NET SDK build. Other
organizations, such as Red Hat, can build their own version of the SDK using this source tarball.
Generic math
In preview is the ability to use operators on generic types in .NET 6. .NET 6 introduces numerous interfaces that
make use of C# 10's new preview feature, static abstract interface members. These interfaces correspond to
different operators, for example, IAdditionOperators represents the + operator. The interfaces are available in
the System.Runtime.Experimental NuGet package. For more information, see the Generic math blog post.
Reflection APIs
.NET 6 introduces the following new APIs that inspect code and provide nullability information:
System.Reflection.NullabilityInfo
System.Reflection.NullabilityInfoContext
System.Reflection.NullabilityState
These APIs are useful for reflection-based tools and serializers.
Microsoft.Extensions APIs
Several extensions namespaces have improvements in .NET 6, as the following table shows.
N A M ESPA C E IM P RO VEM EN T S
M ET H O D DESC RIP T IO N
Enumerable.MaxBy and Enumerable.MinBy Finds maximal or minimal elements using a key selector.
Enumerable.FirstOrDefault<TSource> New overloads let you specify a default value to use if the
(IEnumerable<TSource>, TSource) and sequence is empty.
Enumerable.FirstOrDefault<TSource>
(IEnumerable<TSource>, Func<TSource,Boolean>, TSource)
Enumerable.LastOrDefault<TSource>
(IEnumerable<TSource>, TSource) and
Enumerable.LastOrDefault<TSource>
(IEnumerable<TSource>, Func<TSource,Boolean>, TSource)
Enumerable.SingleOrDefault<TSource>
(IEnumerable<TSource>, TSource) and
Enumerable.SingleOrDefault<TSource>
(IEnumerable<TSource>, Func<TSource,Boolean>, TSource)
PriorityQueue class
The new PriorityQueue<TElement,TPriority> class represents a collection of items that have both a value and a
priority. Items are dequeued in increasing priority order—that is, the item with the lowest priority value is
dequeued first. This class implements a min heap data structure.
See also
What's new in C# 10
What's new in F# 6
What's new in EF Core 6
What's new in ASP.NET Core 6
Release notes for .NET 6
Release notes for Visual Studio 2022
Blog: Announcing .NET 6
Blog: Try the new System.Text.Json source generator
Breaking changes in .NET 6
9/10/2022 • 5 minutes to read • Edit Online
If you're migrating an app to .NET 6, the breaking changes listed here might affect you. Changes are grouped by
technology area, such as ASP.NET Core or Windows Forms.
This article categorizes each breaking change as binary incompatible or source incompatible:
Binar y incompatible - Existing binaries may encounter a breaking change in behavior, such as failure to
load or execute, or different run-time behavior.
Source incompatible - Source code may encounter a breaking change in behavior when targeting the new
runtime or using the new SDK or component. Behavior changes can include compile errors or different run-
time behavior.
NOTE
This article is a work-in-progress. It's not a complete list of breaking changes in .NET 6. To query breaking changes that
are still pending publication, see Issues of .NET.
ASP.NET Core
T IT L E B IN A RY C O M PAT IB L E SO URC E C O M PAT IB L E IN T RO DUC ED
ActionResult<T> sets ️
✔ ❌
StatusCode to 200
AddDataAnnotationsValidat ️
✔ ❌
ion method made obsolete
Blazor: ❌ ❌
WebEventDescriptor.EventA
rgsType property replaced
Changed MessagePack ❌ ️
✔
library in
@microsoft/signalr-
protocol-msgpack
T IT L E B IN A RY C O M PAT IB L E SO URC E C O M PAT IB L E IN T RO DUC ED
ClientCertificate property ️
✔ ❌
doesn't trigger
renegotiation for HttpSys
EndpointName metadata ️
✔ ❌ RC 2
not set automatically
Microsoft.AspNetCore.Http. ❌ ️
✔
Features split
Middleware: HTTPS ️
✔ ❌
Redirection Middleware
throws exception on
ambiguous HTTPS ports
PreserveCompilationContex ❌ ️
✔
t not configured by default
Containers
T IT L E B IN A RY C O M PAT IB L E SO URC E C O M PAT IB L E IN T RO DUC ED
For information on other breaking changes for containers in .NET 6, see .NET 6 Container Release Notes.
Changes to nullable ️
✔ ❌ Preview 1-2
reference type annotations
Conditional string ️
✔ ❌ RC 1
evaluation in Debug
methods
Environment.ProcessorCou ️
✔ ❌ Preview 2
nt behavior on Windows
New System.Linq.Queryable ️
✔ ❌ Preview 3-4
method overloads
Parameter names in ️
✔ ❌ Preview 1
Stream-derived types
StringBuilder.Append ❌ ️
✔ RC 1
overloads and evaluation
order
System.Drawing.Common ❌ ❌ Preview 7
only supported on
Windows
System.Security.SecurityCon ️
✔ ❌ RC 1
text is marked obsolete
Cryptography
T IT L E B IN A RY C O M PAT IB L E SO URC E C O M PAT IB L E IN T RO DUC ED
CreateEncryptor methods ❌ ️
✔ Preview 7
throw exception for
incorrect feedback size
Deployment
T IT L E B IN A RY C O M PAT IB L E SO URC E C O M PAT IB L E IN T RO DUC ED
Extensions
T IT L E B IN A RY C O M PAT IB L E SO URC E C O M PAT IB L E IN T RO DUC ED
FileConfigurationProvider.Lo ️
✔ ❌ RC 1
ad throws
InvalidDataException
Resolving disposed ️
✔ ❌ RC 1
ServiceProvider throws
exception
Globalization
T IT L E B IN A RY C O M PAT IB L E SO URC E C O M PAT IB L E IN T RO DUC ED
Interop
T IT L E B IN A RY C O M PAT IB L E SO URC E C O M PAT IB L E IN T RO DUC ED
JIT compiler
T IT L E B IN A RY C O M PAT IB L E SO URC E C O M PAT IB L E IN T RO DUC ED
Networking
T IT L E B IN A RY C O M PAT IB L E SO URC E C O M PAT IB L E IN T RO DUC ED
WebRequest, WebClient, ️
✔ ❌ Preview 1
and ServicePoint are
obsolete
SDK
T IT L E B IN A RY C O M PAT IB L E SO URC E C O M PAT IB L E IN T RO DUC ED
-p option for ️
✔ ❌ Preview 6
dotnet run is deprecated
GetTargetFrameworkProper ❌ ️
✔ Preview 1
ties and
GetNearestTargetFramewor
k removed from
ProjectReference protocol
OutputType not ️
✔ ❌ RC 1
automatically set to WinExe
runtimeconfig.dev.json file ❌ ️
✔ 6.0.100
not generated
RuntimeIdentifier warning if ️
✔ ❌ RC 1
self-contained is unspecified
Serialization
T IT L E B IN A RY C O M PAT IB L E SO URC E C O M PAT IB L E IN T RO DUC ED
IAsyncEnumerable ️
✔ ❌ Preview 4
serialization
JSON source-generation ❌ ️
✔ RC 2
API refactoring
JsonNumberHandlingAttrib ❌ ️
✔ RC 1
ute on collection properties
Windows Forms
T IT L E B IN A RY C O M PAT IB L E SO URC E C O M PAT IB L E IN T RO DUC ED
C# templates use ️
✔ ❌ RC 1
application bootstrap
Selected ❌ ️
✔ Preview 1
TableLayoutSettings
properties throw
InvalidEnumArgumentExcep
tion
DataGridView-related APIs ❌ ️
✔ Preview 4
now throw
InvalidOperationException
ListViewGroupCollection ❌ ️
✔ RC 2
methods throw new
InvalidOperationException
NotifyIcon.Text maximum ❌ ️
✔ Preview 1
text length increased
TreeNodeCollection.Item ❌ ️
✔ Preview 1
throws exception if node is
assigned elsewhere
XmlDocument.XmlResolver ❌ ️
✔ RC 1
nullability change
XNodeReader.GetAttribute ️
✔ ❌ Preview 2
behavior for invalid index
What's new in .NET 5
9/10/2022 • 4 minutes to read • Edit Online
.NET 5 is the next major release of .NET Core following 3.1. We named this new release .NET 5 instead of .NET
Core 4 for two reasons:
We skipped version numbers 4.x to avoid confusion with .NET Framework 4.x.
We dropped "Core" from the name to emphasize that this is the main implementation of .NET going forward.
.NET 5 supports more types of apps and more platforms than .NET Core or .NET Framework.
ASP.NET Core 5.0 is based on .NET 5 but retains the name "Core" to avoid confusing it with ASP.NET MVC 5.
Likewise, Entity Framework Core 5.0 retains the name "Core" to avoid confusing it with Entity Framework 5 and
6.
.NET 5 includes the following improvements and new features compared to .NET Core 3.1:
C# updates
F# updates
Visual Basic updates
System.Text.Json new features
Single file apps
App trimming
Windows Arm64 and Arm64 intrinsics
Tooling support for dump debugging
The runtime libraries are 80% annotated for nullable reference types
Performance improvements:
Garbage Collection (GC)
System.Text.Json
System.Text.RegularExpressions
Async ValueTask pooling
Container size optimizations
Many more areas
C# updates
Developers writing .NET 5 apps will have access to the latest C# version and features. .NET 5 is paired with C# 9,
which brings many new features to the language. Here are a few highlights:
Records : Reference types with value-based equality semantics and non-destructive mutation supported
by a new with expression.
Relational pattern matching : Extends pattern matching capabilities to relational operators for
comparative evaluations and expressions, including logical patterns - new keywords and , or , and not .
Top-level statements : As a means for accelerating the adoption and learning of C#, the Main method
can be omitted, and an application as simple as the following example is valid:
System.Console.Write("Hello world!");
Function pointers : Language constructs that expose the following intermediate language (IL) opcodes:
ldftn and calli .
F# updates
F# is the .NET functional programming language, and with .NET 5, developers have access to F# 5. One of the
new features is interpolated strings, similar to interpolated strings in C#, and even JavaScript.
let name = "David"
let age = 36
let message = $"{name} is {age} years old."
In addition to basic string interpolation, there's typed interpolation. With typed interpolation, a given type must
match the format specifier.
This format is similar to the sprintf function that formats a string based on type-safe inputs.
For more information, see What's new in F# 5.
For more information on project templates from the .NET CLI, see dotnet new .
See also
The Journey to one .NET
Performance improvements in .NET 5
Download the .NET SDK
Breaking changes in .NET 5
9/10/2022 • 5 minutes to read • Edit Online
If you're migrating an app to .NET 5, the breaking changes listed here might affect you. Changes are grouped by
technology area, such as ASP.NET Core or cryptography.
This article categorizes each breaking change as binary incompatible or source incompatible:
Binar y incompatible - Existing binaries may encounter a breaking change in behavior, such as failure to
load or execute, or different run-time behavior.
Source incompatible - Source code may encounter a breaking change in behavior when targeting the new
runtime or using the new SDK or component. Behavior changes can include compile errors or different run-
time behavior.
ASP.NET Core
T IT L E B IN A RY C O M PAT IB L E SO URC E C O M PAT IB L E
Blazor: ProtectedBrowserStorage ️
✔ ❌
feature moved to shared framework
T IT L E B IN A RY C O M PAT IB L E SO URC E C O M PAT IB L E
Obsolete properties on ️
✔ ❌
ConsoleLoggerOptions
ResourceManagerWithCultureStringLo ️
✔ ❌
calizer class and WithCulture interface
member removed
Code analysis
T IT L E B IN A RY C O M PAT IB L E SO URC E C O M PAT IB L E
CA1416 warning ️
✔ ❌
CA1417 warning ️
✔ ❌
CA1831 warning ️
✔ ❌
CA2013 warning ️
✔ ❌
CA2014 warning ️
✔ ❌
CA2015 warning ️
✔ ❌
CA2200 warning ️
✔ ❌
CA2247 warning ️
✔ ❌
CreateCounterSetInstance throws ️
✔ ❌
InvalidOperationException
Obsolete properties on ️
✔ ❌
ConsoleLoggerOptions
Microsoft.DotNet.PlatformAbstractions ❌ ️
✔
package removed
PrincipalPermissionAttribute is ️
✔ ❌
obsolete
Thread.Abort is obsolete ️
✔ ❌
Vector<T> throws ❌ ️
✔
NotSupportedException
Cryptography
T IT L E B IN A RY C O M PAT IB L E SO URC E C O M PAT IB L E
Cryptography.Oid is init-only ️
✔ ❌
Globalization
T IT L E B IN A RY C O M PAT IB L E SO URC E C O M PAT IB L E
Interop
T IT L E B IN A RY C O M PAT IB L E SO URC E C O M PAT IB L E
Networking
T IT L E B IN A RY C O M PAT IB L E SO URC E C O M PAT IB L E
SDK
T IT L E B IN A RY C O M PAT IB L E SO URC E C O M PAT IB L E
Directory.Packages.props files ❌ ️
✔
imported by default
Security
T IT L E B IN A RY C O M PAT IB L E SO URC E C O M PAT IB L E
PrincipalPermissionAttribute is ️
✔ ❌
obsolete
Serialization
T IT L E B IN A RY C O M PAT IB L E SO URC E C O M PAT IB L E
BinaryFormatter.Deserialize rewraps ️
✔ ❌
exceptions
JsonSerializer.Deserialize requires ️
✔ ❌
single-character string
JsonSerializer.Serialize throws ️
✔ ❌
ArgumentNullException
Non-public, parameterless ️
✔ ❌
constructors not used for
deserialization
Windows Forms
T IT L E B IN A RY C O M PAT IB L E SO URC E C O M PAT IB L E
Methods throw ️
✔ ❌
ArgumentNullException
Properties throw ️
✔ ❌
ArgumentOutOfRangeException
TextFormatFlags.ModifyString is ️
✔ ❌
obsolete
WPF
T IT L E B IN A RY C O M PAT IB L E SO URC E C O M PAT IB L E
This article describes what is new in .NET Core 3.1. This release contains minor improvements to .NET Core 3.0,
focusing on small, but important, fixes. The most important feature about .NET Core 3.1 is that it's a long-term
support (LTS) release.
If you're using Visual Studio 2019, you must update to Visual Studio 2019 version 16.4 or later to work with
.NET Core 3.1 projects. For information on what's new in Visual Studio version 16.4, see What's New in Visual
Studio 2019 version 16.4.
Visual Studio for Mac also supports and includes .NET Core 3.1 in Visual Studio for Mac 8.4.
For more information about the release, see the .NET Core 3.1 announcement.
Download and get started with .NET Core 3.1 on Windows, macOS, or Linux.
Long-term support
.NET Core 3.1 is an LTS release with support from Microsoft for three years after its release. It's highly
recommended that you move your apps to the latest LTS release. See the .NET and .NET Core support policy
page for a list of supported releases.
REL EA SE EN D O F L IF E DAT E
For more information, see the .NET and .NET Core support policy.
You can either configure the appHost at the project level, or toggle the appHost for a specific dotnet command
with the -p:UseAppHost parameter:
Project file
<PropertyGroup>
<UseAppHost>true</UseAppHost>
</PropertyGroup>
Command-line parameter
For more information about the UseAppHost setting, see MSBuild properties for Microsoft.NET.Sdk.
Windows Forms
Windows only
WARNING
There are breaking changes in Windows Forms.
Legacy controls were included in Windows Forms that have been unavailable in the Visual Studio Designer
Toolbox for some time. These were replaced with new controls back in .NET Framework 2.0. These have been
removed from the Desktop SDK for .NET Core 3.1.
ContextMenu ContextMenuStrip
MainMenu MenuStrip
MenuItem ToolStripMenuItem
We recommend you update your applications to .NET Core 3.1 and move to the replacement controls. Replacing
the controls is a straightforward process, essentially "find and replace" on the type.
C++/CLI
Windows only
Support has been added for creating C++/CLI (also known as "managed C++") projects. Binaries produced
from these projects are compatible with .NET Core 3.0 and later versions.
To add support for C++/CLI in Visual Studio 2019 version 16.4, install the Desktop development with C++
workload. This workload adds two templates to Visual Studio:
CLR Class Library (.NET Core)
CLR Empty Project (.NET Core)
Next steps
Review the breaking changes between .NET Core 3.0 and 3.1.
Review the breaking changes in .NET Core 3.1 for Windows Forms apps.
Breaking changes in .NET Core 3.1
9/10/2022 • 8 minutes to read • Edit Online
If you're migrating to version 3.1 of .NET Core or ASP.NET Core, the breaking changes listed in this article may
affect your app.
ASP.NET Core
HTTP: Browser SameSite changes impact authentication
HTTP: Browser SameSite changes impact authentication
Some browsers, such as Chrome and Firefox, made breaking changes to their implementations of SameSite for
cookies. The changes impact remote authentication scenarios, such as OpenID Connect and WS-Federation,
which must opt out by sending SameSite=None . However, SameSite=None breaks on iOS 12 and some older
versions of other browsers. The app needs to sniff these versions and omit SameSite .
For discussion on this issue, see dotnet/aspnetcore#14996.
Version introduced
3.1 Preview 1
Old behavior
SameSite is a 2016 draft standard extension to HTTP cookies. It's intended to mitigate Cross-Site Request
Forgery (CSRF). This was originally designed as a feature the servers would opt into by adding the new
parameters. ASP.NET Core 2.0 added initial support for SameSite .
New behavior
Google proposed a new draft standard that isn't backwards compatible. The standard changes the default mode
to Lax and adds a new entry None to opt out. Lax suffices for most app cookies; however, it breaks cross-site
scenarios like OpenID Connect and WS-Federation login. Most OAuth logins aren't affected because of
differences in how the request flows. The new None parameter causes compatibility problems with clients that
implemented the prior draft standard (for example, iOS 12). Chrome 80 will include the changes. See SameSite
Updates for the Chrome product launch timeline.
ASP.NET Core 3.1 has been updated to implement the new SameSite behavior. The update redefines the
behavior of SameSiteMode.None to emit SameSite=None and adds a new value SameSiteMode.Unspecified to omit
the SameSite attribute. All cookie APIs now default to Unspecified , though some components that use cookies
set values more specific to their scenarios such as the OpenID Connect correlation and nonce cookies.
For other recent changes in this area, see HTTP: Some cookie SameSite defaults changed to None. In ASP.NET
Core 3.0, most defaults were changed from SameSiteMode.Lax to SameSiteMode.None (but still using the prior
standard).
Reason for change
Browser and specification changes as outlined in the preceding text.
Recommended action
Apps that interact with remote sites, such as through third-party login, need to:
Test those scenarios on multiple browsers.
Apply the cookie policy browser sniffing mitigation discussed in Support older browsers.
For testing and browser sniffing instructions, see the following section.
D e t e r m i n e i f y o u ' r e a ffe c t e d
Test your web app using a client version that can opt into the new behavior. Chrome, Firefox, and Microsoft Edge
Chromium all have new opt-in feature flags that can be used for testing. Verify that your app is compatible with
older client versions after you've applied the patches, especially Safari. For more information, see Support older
browsers.
Ch r om e
Chrome 78 and later yield misleading test results. Those versions have a temporary mitigation in place and
allow cookies less than two minutes old. With the appropriate test flags enabled, Chrome 76 and 77 yield more
accurate results. To test the new behavior, toggle chrome://flags/#same-site-by-default-cookies to enabled.
Chrome 75 and earlier are reported to fail with the new None setting. For more information, see Support older
browsers.
Google doesn't make older Chrome versions available. You can, however, download older versions of
Chromium, which will suffice for testing. Follow the instructions at Download Chromium.
Chromium 76 Win64
Chromium 74 Win64
Sa fa r i
Safari 12 strictly implemented the prior draft and fails if it sees the new None value in cookies. This must be
avoided via the browser sniffing code shown in Support older browsers. Ensure you test Safari 12 and 13 as
well as WebKit-based, OS-style logins using Microsoft Authentication Library (MSAL), Active Directory
Authentication Library (ADAL), or whichever library you're using. The problem is dependent on the underlying
OS version. OSX Mojave 10.14 and iOS 12 are known to have compatibility problems with the new behavior.
Upgrading to OSX Catalina 10.15 or iOS 13 fixes the problem. Safari doesn't currently have an opt-in flag for
testing the new specification behavior.
F i r e fo x
Firefox support for the new standard can be tested on version 68 and later by opting in on the about:config
page with the feature flag network.cookie.sameSite.laxByDefault . No compatibility issues have been reported on
older versions of Firefox.
M i c r o so ft Ed g e
While Microsoft Edge supports the old SameSite standard, as of version 44 it didn't have any compatibility
problems with the new standard.
M i c r o so ft Ed g e C h r o m i u m
Versions of Electron include older versions of Chromium. For example, the version of Electron used by Microsoft
Teams is Chromium 66, which exhibits the older behavior. Perform your own compatibility testing with the
version of Electron your product uses. For more information, see Support older browsers.
Su p p o r t o l d e r b r o w se r s
The 2016 SameSite standard mandated that unknown values be treated as SameSite=Strict values.
Consequently, any older browsers that support the original standard may break when they see a SameSite
property with a value of None . Web apps must implement browser sniffing if they intend to support these old
browsers. ASP.NET Core doesn't implement browser sniffing for you because User-Agent request header values
are highly unstable and change on a weekly basis. Instead, an extension point in the cookie policy allows you to
add User-Agent -specific logic.
In Startup.cs, add the following code:
private void CheckSameSite(HttpContext httpContext, CookieOptions options)
{
if (options.SameSite == SameSiteMode.None)
{
var userAgent = httpContext.Request.Headers["User-Agent"].ToString();
// TODO: Use your User Agent library of choice here.
if (/* UserAgent doesn't support new behavior */)
{
options.SameSite = SameSiteMode.Unspecified;
}
}
}
app.UseAuthentication();
// code omitted for brevity
}
O p t - o u t sw i t c h e s
The Microsoft.AspNetCore.SuppressSameSiteNone compatibility switch enables you to temporarily opt out of the
new ASP.NET Core cookie behavior. Add the following JSON to a runtimeconfig.template.json file in your project:
{
"configProperties": {
"Microsoft.AspNetCore.SuppressSameSiteNone": "true"
}
}
O t h e r Ve r si o n s
Category
ASP.NET
Affected APIs
Microsoft.AspNetCore.Builder.CookiePolicyOptions.MinimumSameSitePolicy
Microsoft.AspNetCore.Http.CookieBuilder.SameSite
Microsoft.AspNetCore.Http.CookieOptions.SameSite
Microsoft.AspNetCore.Http.SameSiteMode
Microsoft.Net.Http.Headers.SameSiteMode
Microsoft.Net.Http.Headers.SetCookieHeaderValue.SameSite
Deployment
x86 host path on 64-bit Windows
MSBuild
Design-time builds only return top-level package references
Design-time builds only return top-level package references
Starting in .NET Core SDK 3.1.400, only top-level package references are returned by the
RunResolvePackageDependencies target.
Version introduced
.NET Core SDK 3.1.400
Change description
In previous versions of the .NET Core SDK, the RunResolvePackageDependencies target created the following
MSBuild items that contained information from the NuGet assets file:
PackageDefinitions
PackageDependencies
TargetDefinitions
FileDefinitions
FileDependencies
This data is used by Visual Studio to populate the Dependencies node in Solution Explorer. However, it can be a
large amount of data, and the data isn't needed unless the Dependencies node is expanded.
Starting in the .NET Core SDK version 3.1.400, most of these items aren't generated by default. Only items of
type Package are returned. If Visual Studio needs the items to populate the Dependencies node, it reads the
information directly from the assets file.
Reason for change
This changed was introduced to improve solution-load performance inside of Visual Studio. Previously, all
package references would be loaded, which involved loading many references that most users would never
view.
Recommended action
If you have MSBuild logic that depends on these items being created, set the EmitLegacyAssetsFileItems
property to true in your project file. This setting enables the previous behavior where all the items are created.
Category
MSBuild
Affected APIs
N/A
Windows Forms
Removed controls
CellFormatting event not raised if tooltip is shown
Removed controls
Starting in .NET Core 3.1, some Windows Forms controls are no longer available.
Change description
Starting with .NET Core 3.1, various Windows Forms controls are no longer available. Replacement controls that
have better design and support were introduced in .NET Framework 2.0. The deprecated controls were
previously removed from designer toolboxes but were still available to be used.
The following types are no longer available:
ContextMenu
DataGrid
DataGrid.HitTestType
DataGridBoolColumn
DataGridCell
DataGridColumnStyle
DataGridLineStyle
DataGridParentRowsLabelStyle
DataGridPreferredColumnWidthTypeConverter
DataGridTableStyle
DataGridTextBox
DataGridTextBoxColumn
GridColumnStylesCollection
GridTablesFactory
GridTableStylesCollection
IDataGridEditingService
IMenuEditorService
MainMenu
Menu
Menu.MenuItemCollection
MenuItem
ToolBar
ToolBarAppearance
ToolBarButton
ToolBar.ToolBarButtonCollection
ToolBarButtonClickEventArgs
ToolBarButtonStyle
ToolBarTextAlign
Version introduced
3.1
Recommended action
Each removed control has a recommended replacement control. Refer to the following table:
A SSO C IAT ED A P IS T H AT A RE
REM O VED C O N T RO L ( A P I) REC O M M EN DED REP L A C EM EN T REM O VED
ContextMenu ContextMenuStrip
A SSO C IAT ED A P IS T H AT A RE
REM O VED C O N T RO L ( A P I) REC O M M EN DED REP L A C EM EN T REM O VED
MainMenu MenuStrip
MenuItem ToolStripMenuItem
Category
Windows Forms
Affected APIs
System.Windows.Forms.ContextMenu
System.Windows.Forms.GridColumnStylesCollection
System.Windows.Forms.GridTablesFactory
System.Windows.Forms.GridTableStylesCollection
System.Windows.Forms.IDataGridEditingService
System.Windows.Forms.MainMenu
System.Windows.Forms.Menu
System.Windows.Forms.Menu.MenuItemCollection
System.Windows.Forms.MenuItem
System.Windows.Forms.ToolBar
System.Windows.Forms.ToolBar.ToolBarButtonCollection
System.Windows.Forms.ToolBarAppearance
System.Windows.Forms.ToolBarButton
System.Windows.Forms.ToolBarButtonClickEventArgs
System.Windows.Forms.ToolBarButtonStyle
System.Windows.Forms.ToolBarTextAlign
System.Windows.Forms.DataGrid
System.Windows.Forms.DataGrid.HitTestType
System.Windows.Forms.DataGridBoolColumn
System.Windows.Forms.DataGridCell
System.Windows.Forms.DataGridColumnStyle
System.Windows.Forms.DataGridLineStyle
System.Windows.Forms.DataGridParentRowsLabelStyle
System.Windows.Forms.DataGridPreferredColumnWidthTypeConverter
System.Windows.Forms.DataGridTableStyle
System.Windows.Forms.DataGridTextBox
System.Windows.Forms.DataGridTextBoxColumn
System.Windows.Forms.Design.IMenuEditorService
This article describes what is new in .NET Core 3.0. One of the biggest enhancements is support for Windows
desktop applications (Windows only). By using the .NET Core 3.0 SDK component Windows Desktop, you can
port your Windows Forms and Windows Presentation Foundation (WPF) applications. To be clear, the Windows
Desktop component is only supported and included on Windows. For more information, see the Windows
desktop section later in this article.
.NET Core 3.0 adds support for C# 8.0. It's highly recommended that you use Visual Studio 2019 version 16.3 or
newer, Visual Studio for Mac 8.3 or newer, or Visual Studio Code with the latest C# extension .
Download and get started with .NET Core 3.0 right now on Windows, macOS, or Linux.
For more information about the release, see the .NET Core 3.0 announcement.
.NET Core 3.0 RC 1 was considered production ready by Microsoft and was fully supported. If you're using a
preview release, you must move to the RTM version for continued support.
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.1</TargetFramework>
</PropertyGroup>
</Project>
If you're using Visual Studio, you need Visual Studio 2019, as Visual Studio 2017 doesn't support .NET
Standard 2.1 or .NET Core 3.0 .
Compile/Deploy
Default executables
.NET Core now builds framework-dependent executables by default. This behavior is new for applications that
use a globally installed version of .NET Core. Previously, only self-contained deployments would produce an
executable.
During dotnet build or dotnet publish , an executable (known as the appHost ) is created that matches the
environment and platform of the SDK you're using. You can expect the same things with these executables as
you would other native executables, such as:
You can double-click on the executable.
You can launch the application from a command prompt directly, such as myapp.exe on Windows, and
./myapp on Linux and macOS.
You can either configure the appHost at the project level, or toggle the appHost for a specific dotnet command
with the -p:UseAppHost parameter:
Project file
<PropertyGroup>
<UseAppHost>true</UseAppHost>
</PropertyGroup>
Command-line parameter
For more information about the UseAppHost setting, see MSBuild properties for Microsoft.NET.Sdk.
Single -file executables
The dotnet publish command supports packaging your app into a platform-specific single-file executable. The
executable is self-extracting and contains all dependencies (including native) that are required to run your app.
When the app is first run, the application is extracted to a directory based on the app name and build identifier.
Startup is faster when the application is run again. The application doesn't need to extract itself a second time
unless a new version was used.
To publish a single-file executable, set the PublishSingleFile in your project or on the command line with the
dotnet publish command:
<PropertyGroup>
<RuntimeIdentifier>win10-x64</RuntimeIdentifier>
<PublishSingleFile>true</PublishSingleFile>
</PropertyGroup>
-or-
For more information about single-file publishing, see the single-file bundler design document.
Assembly trimming
The .NET core 3.0 SDK comes with a tool that can reduce the size of apps by analyzing IL and trimming unused
assemblies.
Self-contained apps include everything needed to run your code, without requiring .NET to be installed on the
host computer. However, many times the app only requires a small subset of the framework to function, and
other unused libraries could be removed.
.NET Core now includes a setting that will use the IL Trimmer tool to scan the IL of your app. This tool detects
what code is required, and then trims unused libraries. This tool can significantly reduce the deployment size of
some apps.
To enable this tool, add the <PublishTrimmed> setting in your project and publish a self-contained app:
<PropertyGroup>
<PublishTrimmed>true</PublishTrimmed>
</PropertyGroup>
As an example, the basic "hello world" new console project template that is included, when published, hits about
70 MB in size. By using <PublishTrimmed> , that size is reduced to about 30 MB.
It's important to consider that applications or frameworks (including ASP.NET Core and WPF) that use reflection
or related dynamic features, will often break when trimmed. This breakage occurs because the trimmer doesn't
know about this dynamic behavior and can't determine which framework types are required for reflection. The
IL Trimmer tool can be configured to be aware of this scenario.
Above all else, be sure to test your app after trimming.
For more information about the IL Trimmer tool, see the documentation or visit the mono/linker repo.
Tiered compilation
Tiered compilation (TC) is on by default with .NET Core 3.0. This feature enables the runtime to more adaptively
use the just-in-time (JIT) compiler to achieve better performance.
The main benefit of tiered compilation is to provide two ways of jitting methods: in a lower-quality-but-faster
tier or a higher-quality-but-slower tier. The quality refers to how well the method is optimized. TC helps to
improve the performance of an application as it goes through various stages of execution, from startup through
steady state. When tiered compilation is disabled, every method is compiled in a single way that's biased to
steady-state performance over startup performance.
When TC is enabled, the following behavior applies for method compilation when an app starts up:
If the method has ahead-of-time-compiled code, or ReadyToRun, the pregenerated code is used.
Otherwise, the method is jitted. Typically, these methods are generics over value types.
Quick JIT produces lower-quality (or less optimized) code more quickly. In .NET Core 3.0, Quick JIT is
enabled by default for methods that don't contain loops and is preferred during startup.
The fully optimizing JIT produces higher-quality (or more optimized) code more slowly. For methods
where Quick JIT would not be used (for example, if the method is attributed with
MethodImplOptions.AggressiveOptimization), the fully optimizing JIT is used.
For frequently called methods, the just-in-time compiler eventually creates fully optimized code in the
background. The optimized code then replaces the pre-compiled code for that method.
Code generated by Quick JIT may run slower, allocate more memory, or use more stack space. If there are issues,
you can disabled Quick JIT using this MSBuild property in the project file:
<PropertyGroup>
<TieredCompilationQuickJit>false</TieredCompilationQuickJit>
</PropertyGroup>
<PropertyGroup>
<TieredCompilation>false</TieredCompilation>
</PropertyGroup>
TIP
If you change these settings in the project file, you may need to perform a clean build for the new settings to be reflected
(delete the obj and bin directories and rebuild).
For more information about configuring compilation at run time, see Runtime configuration options for
compilation.
ReadyToRun images
You can improve the startup time of your .NET Core application by compiling your application assemblies as
ReadyToRun (R2R) format. R2R is a form of ahead-of-time (AOT) compilation.
R2R binaries improve startup performance by reducing the amount of work the just-in-time (JIT) compiler
needs to do as your application loads. The binaries contain similar native code compared to what the JIT would
produce. However, R2R binaries are larger because they contain both intermediate language (IL) code, which is
still needed for some scenarios, and the native version of the same code. R2R is only available when you publish
a self-contained app that targets specific runtime environments (RID) such as Linux x64 or Windows x64.
To compile your project as ReadyToRun, do the following:
1. Add the <PublishReadyToRun> setting to your project:
<PropertyGroup>
<PublishReadyToRun>true</PublishReadyToRun>
</PropertyGroup>
2. Publish a self-contained app. For example, this command creates a self-contained app for the 64-bit
version of Windows:
dotnet publish -c Release -r win-x64 --self-contained
Runtime/SDK
Major-version runtime roll forward
.NET Core 3.0 introduces an opt-in feature that allows your app to roll forward to the latest major version of
.NET Core. Additionally, a new setting has been added to control how roll forward is applied to your app. This
can be configured in the following ways:
Project file property: RollForward
Runtime configuration file property: rollForward
Environment variable: DOTNET_ROLL_FORWARD
Command-line argument: --roll-forward
One of the following values must be specified. If the setting is omitted, Minor is the default.
LatestPatch
Roll forward to the highest patch version. This disables minor version roll forward.
Minor
Roll forward to the lowest higher minor version, if requested minor version is missing. If the requested minor
version is present, then the LatestPatch policy is used.
Major
Roll forward to lowest higher major version, and lowest minor version, if requested major version is missing.
If the requested major version is present, then the Minor policy is used.
LatestMinor
Roll forward to highest minor version, even if requested minor version is present. Intended for component
hosting scenarios.
LatestMajor
Roll forward to highest major and highest minor version, even if requested major is present. Intended for
component hosting scenarios.
Disable
Don't roll forward. Only bind to specified version. This policy isn't recommended for general use because it
disables the ability to roll forward to the latest patches. This value is only recommended for testing.
Besides the Disable setting, all settings will use the highest available patch version.
By default, if the requested version (as specified in .runtimeconfig.json for the application) is a release version,
only release versions are considered for roll forward. Any pre-release versions are ignored. If there is no
matching release version, then pre-release versions are taken into account. This behavior can be changed by
setting DOTNET_ROLL_FORWARD_TO_PRERELEASE=1 , in which case all versions are always considered.
Build copies dependencies
The dotnet build command now copies NuGet dependencies for your application from the NuGet cache to the
build output folder. Previously, dependencies were only copied as part of dotnet publish .
There are some operations, like trimming and razor page publishing, that will still require publishing.
Local tools
.NET Core 3.0 introduces local tools. Local tools are similar to global tools but are associated with a particular
location on disk. Local tools aren't available globally and are distributed as NuGet packages.
Local tools rely on a manifest file name dotnet-tools.json in your current directory. This manifest file defines
the tools to be available at that folder and below. You can distribute the manifest file with your code to ensure
that anyone who works with your code can restore and use the same tools.
For both global and local tools, a compatible version of the runtime is required. Many tools currently on
NuGet.org target .NET Core Runtime 2.1. To install these tools globally or locally, you would still need to install
the NET Core 2.1 Runtime.
New global.json options
The global.json file has new options that provide more flexibility when you're trying to define which version of
the .NET Core SDK is used. The new options are:
allowPrerelease : Indicates whether the SDK resolver should consider prerelease versions when selecting the
SDK version to use.
rollForward : Indicates the roll-forward policy to use when selecting an SDK version, either as a fallback
when a specific SDK version is missing or as a directive to use a higher version.
For more information about the changes including default values, supported values, and new matching rules,
see global.json overview.
Smaller Garbage Collection heap sizes
The Garbage Collector's default heap size has been reduced resulting in .NET Core using less memory. This
change better aligns with the generation 0 allocation budget with modern processor cache sizes.
Garbage Collection Large Page support
Large Pages (also known as Huge Pages on Linux) is a feature where the operating system is able to establish
memory regions larger than the native page size (often 4K) to improve performance of the application
requesting these large pages.
The Garbage Collector can now be configured with the GCLargePages setting as an opt-in feature to choose to
allocate large pages on Windows.
Visual Studio 2019 adds New Project templates for .NET Core 3.0 Windows Forms and WPF.
For more information about how to port an existing .NET Framework application, see Port WPF projects and
Port Windows Forms projects.
WinForms high DPI
.NET Core Windows Forms applications can set high DPI mode with
Application.SetHighDpiMode(HighDpiMode). The SetHighDpiMode method sets the corresponding high DPI
mode unless the setting has been set by other means like App.Manifest or P/Invoke before Application.Run .
The possible highDpiMode values, as expressed by the System.Windows.Forms.HighDpiMode enum are:
DpiUnaware
SystemAware
PerMonitor
PerMonitorV2
DpiUnawareGdiScaled
For more information about high DPI modes, see High DPI Desktop Application Development on Windows.
Create COM components
On Windows, you can now create COM-callable managed components. This capability is critical to use .NET Core
with COM add-in models and also to provide parity with .NET Framework.
Unlike .NET Framework where the mscoree.dll was used as the COM server, .NET Core will add a native launcher
dll to the bin directory when you build your COM component.
For an example of how to create a COM component and consume it, see the COM Demo.
Windows Native Interop
Windows offers a rich native API in the form of flat C APIs, COM, and WinRT. While .NET Core supports
P/Invoke , .NET Core 3.0 adds the ability to CoCreate COM APIs and Activate WinRT APIs . For a code
example, see the Excel Demo.
MSIX Deployment
MSIX is a new Windows application package format. It can be used to deploy .NET Core 3.0 desktop applications
to Windows 10.
The Windows Application Packaging Project, available in Visual Studio 2019, allows you to create MSIX packages
with self-contained .NET Core applications.
The .NET Core project file must specify the supported runtimes in the <RuntimeIdentifiers> property:
<RuntimeIdentifiers>win-x86;win-x64</RuntimeIdentifiers>
Linux improvements
SerialPort for Linux
.NET Core 3.0 provides basic support for System.IO.Ports.SerialPort on Linux.
Previously, .NET Core only supported using SerialPort on Windows.
For more information about the limited support for the serial port on Linux, see GitHub issue #33146.
Docker and cgroup memory Limits
Running .NET Core 3.0 on Linux with Docker works better with cgroup memory limits. Running a Docker
container with memory limits, such as with docker run -m , changes how .NET Core behaves.
Default Garbage Collector (GC) heap size: maximum of 20 mb or 75% of the memory limit on the container.
Explicit size can be set as an absolute number or percentage of cgroup limit.
Minimum reserved segment size per GC heap is 16 mb. This size reduces the number of heaps that are
created on machines.
GPIO Support for Raspberry Pi
Two packages have been released to NuGet that you can use for GPIO programming:
System.Device.Gpio
Iot.Device.Bindings
The GPIO packages include APIs for GPIO, SPI, I2C, and PWM devices. The IoT bindings package includes device
bindings. For more information, see the devices GitHub repo.
Arm64 Linux support
.NET Core 3.0 adds support for Arm64 for Linux. The primary use case for Arm64 is currently with IoT scenarios.
For more information, see .NET Core Arm64 Status.
Docker images for .NET Core on Arm64 are available for Alpine, Debian, and Ubuntu.
NOTE
Support for the macOS Arm64 (or "Apple Silicon") and Windows Arm64 operating systems was later added in .NET 6.
Security
TLS 1.3 & OpenSSL 1.1.1 on Linux
.NET Core now takes advantage of TLS 1.3 support in OpenSSL 1.1.1, when it's available in a given environment.
With TLS 1.3:
Connection times are improved with reduced round trips required between the client and server.
Improved security because of the removal of various obsolete and insecure cryptographic algorithms.
When available, .NET Core 3.0 uses OpenSSL 1.1.1 , OpenSSL 1.1.0 , or OpenSSL 1.0.2 on a Linux system.
When OpenSSL 1.1.1 is available, both System.Net.Security.SslStream and System.Net.Http.HttpClient types
will use TLS 1.3 (assuming both the client and server support TLS 1.3 ).
IMPORTANT
Windows and macOS do not yet support TLS 1.3 .
The following C# 8.0 example demonstrates .NET Core 3.0 on Ubuntu 18.10 connecting to
https://www.cloudflare.com:
using System;
using System.Net.Security;
using System.Net.Sockets;
using System.Threading.Tasks;
namespace whats_new
{
public static class TLS
{
public static async Task ConnectCloudFlare()
{
var targetHost = "www.cloudflare.com";
await sslStream.AuthenticateAsClientAsync(targetHost);
await Console.Out.WriteLineAsync($"Connected to {targetHost} with {sslStream.SslProtocol}");
}
}
}
Cryptography ciphers
.NET Core 3.0 adds support for AES-GCM and AES-CCM ciphers, implemented with
System.Security.Cryptography.AesGcm and System.Security.Cryptography.AesCcm respectively. These
algorithms are both Authenticated Encryption with Association Data (AEAD) algorithms.
The following code demonstrates using AesGcm cipher to encrypt and decrypt random data.
using System;
using System.Linq;
using System.Security.Cryptography;
namespace whats_new
{
public static class Cipher
{
public static void Run()
{
// key should be: pre-known, derived, or transported via another channel, such as RSA encryption
byte[] key = new byte[16];
RandomNumberGenerator.Fill(key);
using System;
using System.Security.Cryptography;
namespace whats_new
{
public static class RSATest
{
public static void Run(string keyFile)
{
using var rsa = RSA.Create();
There's also the System.Range type, which consists of two Index values, one for the start and one for the end,
and can be written with a x..y range expression (C#). You can then index with a Range , which produces a slice:
In addition to being able to await foreach , you can also create async iterators, for example, an iterator that
returns an IAsyncEnumerable/IAsyncEnumerator that you can both await and yield in. For objects that need to
be disposed, you can use IAsyncDisposable , which various BCL types implement, such as Stream and Timer .
For more information, see the async streams tutorial.
IEEE Floating-point
Floating point APIs are being updated to comply with IEEE 754-2008 revision. The goal of these changes is to
expose all required operations and ensure that they're behaviorally compliant with the IEEE spec. For more
information about floating-point improvements, see the Floating-Point Parsing and Formatting improvements in
.NET Core 3.0 blog post.
Parsing and formatting fixes include:
Correctly parse and round inputs of any length.
Correctly parse and format negative zero.
Correctly parse Infinity and NaN by doing a case-insensitive check and allowing an optional preceding +
where applicable.
New System.Math APIs include:
BitIncrement(Double) and BitDecrement(Double)
Corresponds to the nextUp and nextDown IEEE operations. They return the smallest floating-point
number that compares greater or lesser than the input (respectively). For example,
Math.BitIncrement(0.0) would return double.Epsilon .
Log2(Double)
Corresponds to the log2 IEEE operation, it returns the base-2 logarithm. It minimizes rounding error.
FusedMultiplyAdd(Double, Double, Double)
Corresponds to the fma IEEE operation, it performs a fused multiply add. That is, it does (x * y) + z as
a single operation, thereby minimizing the rounding error. An example is
FusedMultiplyAdd(1e308, 2.0, -1e308) , which returns 1e308 . The regular (1e308 * 2.0) - 1e308 returns
double.PositiveInfinity .
CopySign(Double, Double)
Corresponds to the copySign IEEE operation, it returns the value of x , but with the sign of y .
.NET Platform-Dependent Intrinsics
APIs have been added that allow access to certain perf-oriented CPU instructions, such as the SIMD or Bit
Manipulation instruction sets. These instructions can help achieve significant performance improvements in
certain scenarios, such as processing data efficiently in parallel.
Where appropriate, the .NET libraries have begun using these instructions to improve performance.
For more information, see .NET Platform-Dependent Intrinsics.
Improved .NET Core Version APIs
Starting with .NET Core 3.0, the version APIs provided with .NET Core now return the information you expect.
For example:
System.Console.WriteLine($"Environment.Version: {System.Environment.Version}");
// Old result
// Environment.Version: 4.0.30319.42000
//
// New result
// Environment.Version: 3.0.0
System.Console.WriteLine($"RuntimeInformation.FrameworkDescription:
{System.Runtime.InteropServices.RuntimeInformation.FrameworkDescription}");
// Old result
// RuntimeInformation.FrameworkDescription: .NET Core 4.6.27415.71
//
// New result (notice the value includes any preview release information)
// RuntimeInformation.FrameworkDescription: .NET Core 3.0.0-preview4-27615-11
WARNING
Breaking change. This is technically a breaking change because the versioning scheme has changed.
// HTTP/1.1 request
using (var response = await client.GetAsync("/"))
Console.WriteLine(response.Content);
// HTTP/2 request
using (var request = new HttpRequestMessage(HttpMethod.Get, "/") { Version = new Version(2, 0) })
using (var response = await client.SendAsync(request))
Console.WriteLine(response.Content);
// HTTP/2 is default
using (var response = await client.GetAsync("/"))
Console.WriteLine(response.Content);
Many times when you're developing an application, you want to use an unencrypted connection. If you know the
target endpoint will be using HTTP/2, you can turn on unencrypted connections for HTTP/2. You can turn it on
by setting the DOTNET_SYSTEM_NET_HTTP_SOCKETSHTTPHANDLER_HTTP2UNENCRYPTEDSUPPORT environment variable to 1
or by enabling it in the app context:
AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true);
Next steps
Review the breaking changes between .NET Core 2.2 and 3.0.
Review the breaking changes in .NET Core 3.0 for Windows Forms apps.
Breaking changes in .NET Core 3.0
9/10/2022 • 69 minutes to read • Edit Online
If you're migrating to version 3.0 of .NET Core, ASP.NET Core, or EF Core, the breaking changes listed in this
article may affect your app.
ASP.NET Core
Obsolete Antiforgery, CORS, Diagnostics, MVC, and Routing APIs removed
"Pubternal" APIs removed
Authentication: Google+ deprecation
Authentication: HttpContext.Authentication property removed
Authentication: Newtonsoft.Json types replaced
Authentication: OAuthHandler ExchangeCodeAsync signature changed
Authorization: AddAuthorization overload moved to different assembly
Authorization: IAllowAnonymous removed from AuthorizationFilterContext.Filters
Authorization: IAuthorizationPolicyProvider implementations require new method
Caching: CompactOnMemoryPressure property removed
Caching: Microsoft.Extensions.Caching.SqlServer uses new SqlClient package
Caching: ResponseCaching "pubternal" types changed to internal
Data Protection: DataProtection.Blobs uses new Azure Storage APIs
Hosting: AspNetCoreModule V1 removed from Windows Hosting Bundle
Hosting: Generic host restricts Startup constructor injection
Hosting: HTTPS redirection enabled for IIS out-of-process apps
Hosting: IHostingEnvironment and IApplicationLifetime types replaced
Hosting: ObjectPoolProvider removed from WebHostBuilder dependencies
HTTP: DefaultHttpContext extensibility removed
HTTP: HeaderNames fields changed to static readonly
HTTP: Response body infrastructure changes
HTTP: Some cookie SameSite default values changed
HTTP: Synchronous IO disabled by default
Identity: AddDefaultUI method overload removed
Identity: UI Bootstrap version change
Identity: SignInAsync throws exception for unauthenticated identity
Identity: SignInManager constructor accepts new parameter
Identity: UI uses static web assets feature
Kestrel: Connection adapters removed
Kestrel: Empty HTTPS assembly removed
Kestrel: Request trailer headers moved to new collection
Kestrel: Transport abstraction layer changes
Localization: APIs marked obsolete
Logging: DebugLogger class made internal
MVC: Controller action Async suffix removed
MVC: JsonResult moved to Microsoft.AspNetCore.Mvc.Core
MVC: Precompilation tool deprecated
MVC: Types changed to internal
MVC: Web API compatibility shim removed
Razor: RazorTemplateEngine API removed
Razor: Runtime compilation moved to a package
Session state: Obsolete APIs removed
Shared framework: Assembly removal from Microsoft.AspNetCore.App
Shared framework: Microsoft.AspNetCore.All removed
SignalR: HandshakeProtocol.SuccessHandshakeData replaced
SignalR: HubConnection methods removed
SignalR: HubConnectionContext constructors changed
SignalR: JavaScript client package name change
SignalR: Obsolete APIs
SPAs: SpaServices and NodeServices marked obsolete
SPAs: SpaServices and NodeServices console logger fallback default change
Target framework: .NET Framework not supported
Obsolete Antiforgery, CORS, Diagnostics, MVC, and Routing APIs removed
Obsolete members and compatibility switches in ASP.NET Core 2.2 were removed.
Version introduced
3.0
Reason for change
Improvement of API surface over time.
Recommended action
While targeting .NET Core 2.2, follow the guidance in the obsolete build messages to adopt new APIs instead.
Category
ASP.NET Core
Affected APIs
The following types and members were marked as obsolete for ASP.NET Core 2.1 and 2.2:
Types
Microsoft.AspNetCore.Diagnostics.Views.WelcomePage
Microsoft.AspNetCore.DiagnosticsViewPage.Views.AttributeValue
Microsoft.AspNetCore.DiagnosticsViewPage.Views.BaseView
Microsoft.AspNetCore.DiagnosticsViewPage.Views.HelperResult
Microsoft.AspNetCore.Mvc.Formatters.Xml.ProblemDetails21Wrapper
Microsoft.AspNetCore.Mvc.Formatters.Xml.ValidationProblemDetails21Wrapper
Microsoft.AspNetCore.Mvc.Razor.Compilation.ViewsFeatureProvider
Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageArgumentBinder
Microsoft.AspNetCore.Routing.IRouteValuesAddressMetadata
Microsoft.AspNetCore.Routing.RouteValuesAddressMetadata
Constructors
Microsoft.AspNetCore.Cors.Infrastructure.CorsService(IOptions{CorsOptions})
Microsoft.AspNetCore.Routing.Tree.TreeRouteBuilder(ILoggerFactory,UrlEncoder,ObjectPool{UriBuildingContext},IInlineConstraintResolver)
Microsoft.AspNetCore.Mvc.Formatters.OutputFormatterCanWriteContext
Microsoft.AspNetCore.Mvc.ApiExplorer.DefaultApiDescriptionProvider(IOptions{MvcOptions},IInlineConstraintResolver,IModelMetadataProvider)
Microsoft.AspNetCore.Mvc.ApiExplorer.DefaultApiDescriptionProvider(IOptions{MvcOptions},IInlineConstraintResolver,IModelMetadataProvider,IActionResul
Microsoft.AspNetCore.Mvc.Formatters.FormatFilter(IOptions{MvcOptions})
Microsoft.AspNetCore.Mvc.ModelBinding.Binders.ArrayModelBinder`1(IModelBinder)
Microsoft.AspNetCore.Mvc.ModelBinding.Binders.ByteArrayModelBinder
Microsoft.AspNetCore.Mvc.ModelBinding.Binders.CollectionModelBinder`1(IModelBinder)
Microsoft.AspNetCore.Mvc.ModelBinding.Binders.ComplexTypeModelBinder(IDictionary`2)
Microsoft.AspNetCore.Mvc.ModelBinding.Binders.DictionaryModelBinder`2(IModelBinder,IModelBinder)
Microsoft.AspNetCore.Mvc.ModelBinding.Binders.DoubleModelBinder(System.Globalization.NumberStyles)
Microsoft.AspNetCore.Mvc.ModelBinding.Binders.FloatModelBinder(System.Globalization.NumberStyles)
Microsoft.AspNetCore.Mvc.ModelBinding.Binders.FormCollectionModelBinder
Microsoft.AspNetCore.Mvc.ModelBinding.Binders.FormFileModelBinder
Microsoft.AspNetCore.Mvc.ModelBinding.Binders.HeaderModelBinder
Microsoft.AspNetCore.Mvc.ModelBinding.Binders.KeyValuePairModelBinder`2(IModelBinder,IModelBinder)
Microsoft.AspNetCore.Mvc.ModelBinding.Binders.SimpleTypeModelBinder(System.Type)
Microsoft.AspNetCore.Mvc.ModelBinding.ModelAttributes(IEnumerable{System.Object})
Microsoft.AspNetCore.Mvc.ModelBinding.ModelAttributes(IEnumerable{System.Object},IEnumerable{System.Object})
Microsoft.AspNetCore.Mvc.ModelBinding.ModelBinderFactory(IModelMetadataProvider,IOptions{MvcOptions})
Microsoft.AspNetCore.Mvc.ModelBinding.ParameterBinder(IModelMetadataProvider,IModelBinderFactory,IObjectModelValidator)
Microsoft.AspNetCore.Mvc.Routing.KnownRouteValueConstraint()
Microsoft.AspNetCore.Mvc.Formatters.XmlDataContractSerializerInputFormatter
Microsoft.AspNetCore.Mvc.Formatters.XmlDataContractSerializerInputFormatter(System.Boolean)
Microsoft.AspNetCore.Mvc.Formatters.XmlDataContractSerializerInputFormatter(MvcOptions)
Microsoft.AspNetCore.Mvc.Formatters.XmlSerializerInputFormatter
Microsoft.AspNetCore.Mvc.Formatters.XmlSerializerInputFormatter(System.Boolean)
Microsoft.AspNetCore.Mvc.Formatters.XmlSerializerInputFormatter(MvcOptions)
Microsoft.AspNetCore.Mvc.TagHelpers.ImageTagHelper(IHostingEnvironment,IMemoryCache,HtmlEncoder,IUrlHelperFactory)
Microsoft.AspNetCore.Mvc.TagHelpers.LinkTagHelper(IHostingEnvironment,IMemoryCache,HtmlEncoder,JavaScriptEncoder,IUrlHelperFactory)
Microsoft.AspNetCore.Mvc.TagHelpers.ScriptTagHelper(IHostingEnvironment,IMemoryCache,HtmlEncoder,JavaScriptEncoder,IUrlHelperFactory)
Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.RazorPageAdapter(RazorPageBase)
Proper ties
Microsoft.AspNetCore.Antiforgery.AntiforgeryOptions.CookieDomain
Microsoft.AspNetCore.Antiforgery.AntiforgeryOptions.CookieName
Microsoft.AspNetCore.Antiforgery.AntiforgeryOptions.CookiePath
Microsoft.AspNetCore.Antiforgery.AntiforgeryOptions.RequireSsl
Microsoft.AspNetCore.Mvc.ApiBehaviorOptions.AllowInferringBindingSourceForCollectionTypesAsFromQuery
Microsoft.AspNetCore.Mvc.ApiBehaviorOptions.SuppressUseValidationProblemDetailsForInvalidModelStateResponses
Microsoft.AspNetCore.Mvc.CookieTempDataProviderOptions.CookieName
Microsoft.AspNetCore.Mvc.CookieTempDataProviderOptions.Domain
Microsoft.AspNetCore.Mvc.CookieTempDataProviderOptions.Path
Microsoft.AspNetCore.Mvc.DataAnnotations.MvcDataAnnotationsLocalizationOptions.AllowDataAnnotationsLocalizationForEnumDisplayAttributes
Microsoft.AspNetCore.Mvc.Formatters.Xml.MvcXmlOptions.AllowRfc7807CompliantProblemDetailsFormat
Microsoft.AspNetCore.Mvc.MvcOptions.AllowBindingHeaderValuesToNonStringModelTypes
Microsoft.AspNetCore.Mvc.MvcOptions.AllowCombiningAuthorizeFilters
Microsoft.AspNetCore.Mvc.MvcOptions.AllowShortCircuitingValidationWhenNoValidatorsArePresent
Microsoft.AspNetCore.Mvc.MvcOptions.AllowValidatingTopLevelNodes
Microsoft.AspNetCore.Mvc.MvcOptions.InputFormatterExceptionPolicy
Microsoft.AspNetCore.Mvc.MvcOptions.SuppressBindingUndefinedValueToEnumType
Microsoft.AspNetCore.Mvc.MvcViewOptions.AllowRenderingMaxLengthAttribute
Microsoft.AspNetCore.Mvc.MvcViewOptions.SuppressTempDataAttributePrefix
Microsoft.AspNetCore.Mvc.RazorPages.RazorPagesOptions.AllowAreas
Microsoft.AspNetCore.Mvc.RazorPages.RazorPagesOptions.AllowDefaultHandlingForOptionsRequests
Microsoft.AspNetCore.Mvc.RazorPages.RazorPagesOptions.AllowMappingHeadRequestsToGetHandler
Methods
Microsoft.AspNetCore.Mvc.LocalRedirectResult.ExecuteResult(ActionContext)
Microsoft.AspNetCore.Mvc.RedirectResult.ExecuteResult(ActionContext)
Microsoft.AspNetCore.Mvc.RedirectToActionResult.ExecuteResult(ActionContext)
Microsoft.AspNetCore.Mvc.RedirectToPageResult.ExecuteResult(ActionContext)
Microsoft.AspNetCore.Mvc.RedirectToRouteResult.ExecuteResult(ActionContext)
Microsoft.AspNetCore.Mvc.ModelBinding.ParameterBinder.BindModelAsync(ActionContext,IValueProvider,ParameterDescriptor)
Microsoft.AspNetCore.Mvc.ModelBinding.ParameterBinder.BindModelAsync(ActionContext,IValueProvider,ParameterDescriptor,Object)
HttpContext.Request.EnableRewind();
In an ASP.NET Core 3.0 project, replace the EnableRewind call with a call to the EnableBuffering extension
method. The request buffering feature works as it did in the past. EnableBuffering calls the now internal API.
HttpContext.Request.EnableBuffering();
Category
ASP.NET Core
Affected APIs
All APIs in the Microsoft.AspNetCore.* and Microsoft.Extensions.* namespaces that have an Internal
segment in the namespace name. For example:
Microsoft.AspNetCore.Authentication.Internal
Microsoft.AspNetCore.Builder.Internal
Microsoft.AspNetCore.DataProtection.Cng.Internal
Microsoft.AspNetCore.DataProtection.Internal
Microsoft.AspNetCore.Hosting.Internal
Microsoft.AspNetCore.Http.Internal
Microsoft.AspNetCore.Mvc.Core.Infrastructure
Microsoft.AspNetCore.Mvc.Core.Internal
Microsoft.AspNetCore.Mvc.Cors.Internal
Microsoft.AspNetCore.Mvc.DataAnnotations.Internal
Microsoft.AspNetCore.Mvc.Formatters.Internal
Microsoft.AspNetCore.Mvc.Formatters.Json.Internal
Microsoft.AspNetCore.Mvc.Formatters.Xml.Internal
Microsoft.AspNetCore.Mvc.Internal
Microsoft.AspNetCore.Mvc.ModelBinding.Internal
Microsoft.AspNetCore.Mvc.Razor.Internal
Microsoft.AspNetCore.Mvc.RazorPages.Internal
Microsoft.AspNetCore.Mvc.TagHelpers.Internal
Microsoft.AspNetCore.Mvc.ViewFeatures.Internal
Microsoft.AspNetCore.Rewrite.Internal
Microsoft.AspNetCore.Routing.Internal
Microsoft.AspNetCore.Server.Kestrel.Core.Adapter.Internal
Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure
Microsoft.AspNetCore.Server.Kestrel.Https.Internal
For Microsoft.Owin 3.1.0 and later, a temporary mitigation is outlined here. Apps should complete testing with
the mitigation to check for changes in the data format. There are plans to release Microsoft.Owin 4.0.1 with a fix.
Apps using any prior version should update to version 4.0.1.
A SP.N E T C o r e 1 .x
The mitigation in Owin with ASP.NET Web Forms and MVC can be adapted to ASP.NET Core 1.x. NuGet package
patches aren't planned because 1.x has reached end of life status.
A SP.N E T C o r e 2 .x
.AddGoogle(o =>
{
o.ClientId = Configuration["Authentication:Google:ClientId"];
o.ClientSecret = Configuration["Authentication:Google:ClientSecret"];
o.UserInformationEndpoint = "https://www.googleapis.com/oauth2/v2/userinfo";
o.ClaimActions.Clear();
o.ClaimActions.MapJsonKey(ClaimTypes.NameIdentifier, "id");
o.ClaimActions.MapJsonKey(ClaimTypes.Name, "name");
o.ClaimActions.MapJsonKey(ClaimTypes.GivenName, "given_name");
o.ClaimActions.MapJsonKey(ClaimTypes.Surname, "family_name");
o.ClaimActions.MapJsonKey("urn:google:profile", "link");
o.ClaimActions.MapJsonKey(ClaimTypes.Email, "email");
});
The February 2.1 and 2.2 patches incorporated the preceding reconfiguration as the new default. No patch is
planned for ASP.NET Core 2.0 since it has reached end of life.
A SP.N E T C o r e 3 .0
The mitigation given for ASP.NET Core 2.x can also be used for ASP.NET Core 3.0. In future 3.0 previews, the
Microsoft.AspNetCore.Authentication.Google package may be removed. Users would be directed to
Microsoft.AspNetCore.Authentication.OpenIdConnect instead. The following code shows how to replace
AddGoogle with AddOpenIdConnect in Startup.ConfigureServices . This replacement can be used with ASP.NET
Core 2.0 and later and can be adapted for ASP.NET Core 1.x as needed.
.AddOpenIdConnect("Google", o =>
{
o.ClientId = Configuration["Authentication:Google:ClientId"];
o.ClientSecret = Configuration["Authentication:Google:ClientSecret"];
o.Authority = "https://accounts.google.com";
o.ResponseType = OpenIdConnectResponseType.Code;
o.CallbackPath = "/signin-google"; // Or register the default "/signin-oidc"
o.Scope.Add("email");
});
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
Category
ASP.NET Core
Affected APIs
Microsoft.AspNetCore.Authentication.Google
To:
For questions about the Azure Storage APIs, use https://github.com/Azure/azure-storage-net. For discussion on
this issue, see dotnet/aspnetcore#19570.
Version introduced
3.0
Old behavior
The package referenced the WindowsAzure.Storage NuGet package. The package references the
Microsoft.Azure.Storage.Blob NuGet package.
New behavior
The package references the Azure.Storage.Blob NuGet package.
Reason for change
This change allows Azure.Extensions.AspNetCore.DataProtection.Blobs to migrate to the recommended Azure
Storage packages.
Recommended action
If you still need to use the older Azure Storage APIs with ASP.NET Core 3.0, add a direct dependency to the
package WindowsAzure.Storage or Microsoft.Azure.Storage. This package can be installed alongside the new
Azure.Storage APIs.
In many cases, the upgrade only involves changing the using statements to use the new namespaces:
- using Microsoft.WindowsAzure.Storage;
- using Microsoft.WindowsAzure.Storage.Blob;
- using Microsoft.Azure.Storage;
- using Microsoft.Azure.Storage.Blob;
+ using Azure.Storage;
+ using Azure.Storage.Blobs;
Category
ASP.NET Core
Affected APIs
None
Change description
Prior to ASP.NET Core 3.0, constructor injection could be used for arbitrary types in the Startup class's
constructor. In ASP.NET Core 3.0, the web stack was replatformed onto the generic host library. You can see the
change in the Program.cs file of the templates:
ASP.NET Core 2.x:
https://github.com/dotnet/aspnetcore/blob/5cb615fcbe8559e49042e93394008077e30454c0/src/Templating/s
rc/Microsoft.DotNet.Web.ProjectTemplates/content/EmptyWeb-CSharp/Program.cs#L20-L22
ASP.NET Core 3.0:
https://github.com/dotnet/aspnetcore/blob/b1ca2c1155da3920f0df5108b9fedbe82efaa11c/src/ProjectTemplat
es/Web.ProjectTemplates/content/EmptyWeb-CSharp/Program.cs#L19-L24
Host uses one dependency injection (DI) container to build the app. WebHost uses two containers: one for the
host and one for the app. As a result, the Startup constructor no longer supports custom service injection. Only
IHostEnvironment , IWebHostEnvironment , and IConfiguration can be injected. This change prevents DI issues
such as the duplicate creation of a singleton service.
Version introduced
3.0
Reason for change
This change is a consequence of replatforming the web stack onto the generic host library.
Recommended action
Inject services into the Startup.Configure method signature. For example:
Category
ASP.NET Core
Affected APIs
None
Machines running ASP.NET Core 3.0.0 apps should install the ASP.NET Core 3.0.1 runtime before installing the
ASP.NET Core 3.1.0 Preview 3 ANCM. Doing so ensures that UseHttpsRedirection continues to operate as
expected for the ASP.NET Core 3.0 apps.
In Azure App Service, ANCM deploys on a separate schedule from the runtime because of its global nature.
ANCM was deployed to Azure with these changes after ASP.NET Core 3.0.1 and 3.1.0 were deployed.
Category
ASP.NET Core
Affected APIs
HttpsPolicyBuilderExtensions.UseHttpsRedirection(IApplicationBuilder)
Category
ASP.NET Core
Affected APIs
None
New behavior
If you replace HttpResponse.Body , it replaces the entire IHttpResponseBodyFeature with a wrapper around your
given stream using StreamResponseBodyFeature to provide default implementations for all of the expected APIs.
Setting back the original stream reverts this change.
Reason for change
The motivation is to combine the response body APIs into a single new feature interface.
Recommended action
Use IHttpResponseBodyFeature where you previously were using IHttpResponseFeature.Body ,
IHttpSendFileFeature , or .
IHttpBufferingFeature
Category
ASP.NET Core
Affected APIs
Microsoft.AspNetCore.Http.Features.IHttpBufferingFeature
Microsoft.AspNetCore.Http.Features.IHttpResponseFeature.Body
Microsoft.AspNetCore.Http.Features.IHttpSendFileFeature
New behavior
All the affected APIs default to SameSiteMode.None .
Reason for change
The default value was changed to make SameSite an opt-in feature.
Recommended action
Each component that emits cookies needs to decide if SameSite is appropriate for its scenarios. Review your
usage of the affected APIs and reconfigure SameSite as needed.
Category
ASP.NET Core
Affected APIs
IResponseCookies.Append(String, String, CookieOptions)
CookiePolicyOptions.MinimumSameSitePolicy
Each server has an AllowSynchronousIO option that controls this behavior and the default for all of them is now
false .
The behavior can also be overridden on a per-request basis as a temporary mitigation. For example:
If you have trouble with a TextWriter or another stream calling a synchronous API in Dispose , call the new
DisposeAsync API instead.
Category
ASP.NET Core
Affected APIs
Stream.Flush
Stream.Read
Stream.Write
<IdentityUIFrameworkVersion>Bootstrap3</IdentityUIFrameworkVersion>
Category
ASP.NET Core
Affected APIs
IdentityBuilderUIExtensions.AddDefaultUI(IdentityBuilder,UIFramework)
New behavior
The services.AddDefaultIdentity<IdentityUser>().AddDefaultUI(); method call is the same as
services.AddDefaultIdentity<IdentityUser>().AddDefaultUI(UIFramework.Bootstrap4);
services.AddDefaultIdentity<IdentityUser>().AddDefaultUI();
services.AddDefaultIdentity<IdentityUser>().AddDefaultUI(UIFramework.Bootstrap3);
Category
ASP.NET Core
Affected APIs
None
Recommended action
In ASP.NET Core 3.0 Preview 6, there's a RequireAuthenticatedSignIn flag on AuthenticationOptions that is true
by default. Set this flag to false to restore the old behavior.
Category
ASP.NET Core
Affected APIs
None
<IdentityUIFrameworkVersion>Bootstrap3</IdentityUIFrameworkVersion>
Category
ASP.NET Core
Affected APIs
IdentityBuilderUIExtensions.AddDefaultUI(IdentityBuilder, UIFramework)
Recommended action
Libraries referencing Microsoft.AspNetCore.Server.Kestrel.Https 2.0 should update all ASP.NET Core
dependencies to 2.1 or later. Otherwise, they may break when loaded into an ASP.NET Core 3.0 app.
Apps and libraries targeting ASP.NET Core 2.1 and later should remove any direct references to the
Microsoft.AspNetCore.Server.Kestrel.Https NuGet package.
Category
ASP.NET Core
Affected APIs
None
Category
ASP.NET Core
Affected APIs
ResourceManagerWithCultureStringLocalizer
ResourceManagerStringLocalizer.WithCulture
The action is routable via Product/ListAsync . Link generation requires specifying the Async suffix. For example:
New behavior
In ASP.NET Core 3.0, the action is routable via Product/List . Link generation code should omit the Async suffix.
For example:
This change doesn't affect names specified using the [ActionName] attribute. The new behavior can be disabled
by setting MvcOptions.SuppressAsyncSuffixInActionNames to false in Startup.ConfigureServices :
services.AddMvc(options =>
{
options.SuppressAsyncSuffixInActionNames = false;
});
services.AddMvc(options =>
{
options.SuppressAsyncSuffixInActionNames = false;
});
Category
ASP.NET Core
Affected APIs
None