0% found this document useful (0 votes)
2K views5,437 pages

Net

Uploaded by

s. .k
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
2K views5,437 pages

Net

Uploaded by

s. .k
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

Contents

.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:

dotnet new console -o sample1


cd sample1
dotnet run

You should see the following output:

Hello World!

Congratulations! You've created a simple .NET application.

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.

Tutorials for creating apps


Create a console app
using Visual Studio Code
using Visual Studio (Windows)
using Visual Studio for Mac (macOS)
Create a web app
with server-side web UI
with client-side web UI
Create a web API
Create a remote procedure call web app
Create a real-time web app
Create a serverless function in the cloud
Create a mobile app for Android and iOS (Windows)
Create a Windows desktop app
WPF
Windows Forms
Universal Windows Platform (UWP)
Create a game using Unity
Create a Windows service

Tutorials for creating class libraries


Create a class library
using Visual Studio Code
using Visual Studio (Windows)
using Visual Studio for Mac (macOS)

Resources for learning .NET languages


Get started with C#
Get started with F#
Get started with Visual Basic

Other get-started resources


The following resources are for getting started with developing .NET apps but aren't step-by-step tutorials:
Internet of Things (IoT)
Machine learning
Next steps
To learn more about .NET, see Introduction to .NET.
Install .NET on Windows
9/10/2022 • 11 minutes to read • Edit Online

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

Install with Windows Package Manager (winget)


You can install and manage .NET through the Windows Package Manager service, using the winget tool. For
more information about how to install and use winget , see Use the winget tool.
If you're installing .NET system-wide, install with administrative privileges.
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 runtimes. To install the .NET SDK, run the following command:

winget install Microsoft.DotNet.SDK.6

Install the runtime


For Windows, there are three .NET runtimes you can install. You should install both the .NET Desktop Runtime
and the ASP.NET Core Runtime to ensure that you're compatible with all types of .NET apps.
.NET Desktop Runtime
This runtime includes the base .NET runtime, and supports Windows Presentation Foundation (WPF) and
Windows Forms apps that are built with .NET. This isn't the same as .NET Framework, which comes with
Windows.

winget install Microsoft.DotNet.DesktopRuntime.6

ASP.NET Core Runtime


This runtime includes the base .NET runtime, and runs web server apps. The ASP.NET Core Runtime
allows you to run apps that were made with .NET that didn't provide the runtime. The following
commands install the ASP.NET Core Runtime, which is the most compatible runtime for .NET. In your
terminal, run the following commands:

winget install Microsoft.DotNet.AspNetCore.6

.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:

winget install Microsoft.DotNet.DesktopRuntime.Preview

Install alongside Visual Studio Code


Visual Studio Code is a powerful and lightweight source code editor that runs on your desktop. Visual Studio
Code is available for Windows, macOS, and Linux.
While Visual Studio Code doesn't come with an automated .NET Core installer like Visual Studio does, adding
.NET Core support is simple.
1. Download and install Visual Studio Code.
2. Download and install the .NET SDK.
3. Install the C# extension from the Visual Studio Code marketplace.

Install with Windows Installer


The download page for .NET provides Windows Installer executables.
When you use the Windows installers to install .NET, you can customize the installation path by setting the
DOTNETHOME_X64 and DOTNETHOME_X86 parameters:

dotnet-sdk-3.1.301-win-x64.exe DOTNETHOME_X64="F:\dotnet\x64" DOTNETHOME_X86="F:\dotnet\x86"

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.

dotnet-sdk-3.1.301-win-x64.exe /install /quiet /norestart

For more information, see Standard Installer Command-Line Options.

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 with PowerShell automation


The dotnet-install scripts are used for CI automation and non-admin installs of the runtime. You can download
the script from the dotnet-install script reference page.
The script defaults to installing the latest long term support (LTS) version, which is .NET 6. You can choose a
specific release by specifying the Channel switch. Include the Runtime switch to install a runtime. Otherwise,
the script installs the SDK.

dotnet-install.ps1 -Channel 6.0 -Runtime aspnetcore

Install the SDK by omitting the -Runtime switch. The -Channel switch is set in this example to Current , which
installs the latest supported version.

dotnet-install.ps1 -Channel Current

Install with Visual Studio


If you're using Visual Studio to develop .NET apps, the following table describes the minimum required version
of Visual Studio based on the target .NET SDK version.

. N ET SDK VERSIO N VISUA L ST UDIO VERSIO N

6.0 Visual Studio 2022 version 17.0 or higher.

5.0 Visual Studio 2019 version 16.8 or higher.

3.1 Visual Studio 2019 version 16.4 or higher.

3.0 Visual Studio 2019 version 16.3 or higher.

2.2 Visual Studio 2017 version 15.9 or higher.

2.1 Visual Studio 2017 version 15.7 or higher.

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 Server 2022 ️


✔ ️

Windows 10 Version 21H1 ️


✔ ️

Windows 10 / Windows Server, ️


✔ ️

Version 20H2

Windows 10 / Windows Server, ️


✔ ️

Version 2004

Windows 10 / Windows Server, ️


✔ ️

Version 1909

Windows 10 / Windows Server, ️


✔ ️

Version 1903

Windows 10, Version 1809 ️


✔ ️

O P ERAT IN G SY ST EM . N ET C O RE 3. 1 . N ET 6

Windows 10, Version 1803 ️


✔ ️

Windows 10, Version 1709 ️


✔ ️

Windows 10, Version 1607 ️


✔ ️

Windows 8.1 ️
✔ ️

Windows 7 SP1 ESU ️


✔ ️

Windows Server 2019 ️


✔ ️

Windows Server 2016
Windows Server 2012 R2
Windows Server 2012

Windows Server Core 2012 R2 ️


✔ ️

Windows Server Core 2012 ️


✔ ️

Nano Server, Version 1809+ ️


✔ ️

Nano Server, Version 1803 ️


✔ ❌

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

Arm-based Windows PCs


The following sections describe things you should consider when installing .NET on an Arm-based Windows PC.
What's supported
The following table describes which versions of .NET are supported on an Arm-based Windows PC:

. 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

6.0 Arm64 Yes Yes No

6.0 x64 Yes Yes No

5.0 Arm64 Yes Yes Yes

5.0 x64 No Yes Yes

3.1 Arm64 No No N/A

3.1 x64 No Yes Yes

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

The following Windows versions are supported with .NET 6:

NOTE
A + symbol represents the minimum version.

OS VERSIO N A RC H IT EC T URES

Windows 11 21H2 x64, Arm64

Windows 10 Client 1607+ x64, x86, Arm64

Windows Client 7 SP1+, 8.1 x64, x86

Windows Server 2012+ x64, x86

Windows Server Core 2012+ x64, x86

Nano Server 1809+ x64

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:

O P ERAT IN G SY ST EM P REREQ UISIT ES

Windows 7 SP1 ESU - Microsoft Visual C++ 2015-2019 Redistributable 64-bit /


32-bit
- KB3063858 64-bit / 32-bit
- Microsoft Root Certificate Authority 2011 (.NET Core 2.1
offline installer only)

Windows Vista SP 2 Microsoft Visual C++ 2015-2019 Redistributable 64-bit /


32-bit

Windows 8.1 Microsoft Visual C++ 2015-2019 Redistributable 64-bit /


32-bit

Windows Server 2008 R2 Microsoft Visual C++ 2015-2019 Redistributable 64-bit /


32-bit

Windows Server 2012 Microsoft Visual C++ 2015-2019 Redistributable 64-bit /


32-bit

Windows Server 2012 R2 Microsoft Visual C++ 2015-2019 Redistributable 64-bit /


32-bit
The previous requirements are also required if you receive an error related to either of the following dlls:
api-ms-win-crt-runtime-l1-1-0.dll
api-ms-win-cor-timezone-l1-1-0.dll
hostfxr.dll

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.

> where.exe dotnet


C:\Program Files (x86)\dotnet\dotnet.exe
C:\Program Files\dotnet\dotnet.exe

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

macOS 12.0 "Monterey" ️ 3.1


✔ ️ 6.0

macOS 11.0 "Big Sur" ️ 3.1


✔ ️ 6.0

macOS 10.15 "Catalina" ️ 3.1


✔ ️ 6.0

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

Install with an installer


macOS has standalone installers that can be used to install the .NET 6 SDK:
x64 and Arm64 CPUs
Download and manually install
As an alternative to the macOS installers for .NET, you can download and manually install the SDK and runtime.
Manual installation is usually performed as part of continuous integration testing. For a developer or user, it's
generally better to use an installer.
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 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-osx-x64.tar.gz
export DOTNET_ROOT=$(pwd)/dotnet

mkdir -p "$DOTNET_ROOT" && tar zxf "$DOTNET_FILE" -C "$DOTNET_ROOT"

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 .

Also, add export DOTNET_ROOT=$HOME/dotnet to the end of the file.

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

6.0 Arm64 Yes Yes No

6.0 x64 Yes Yes No

3.1 Arm64 No No N/A

3.1 x64 No Yes Yes

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.

Install with Visual Studio for Mac


Visual Studio for Mac installs the .NET SDK when the .NET workload is selected. To get started with .NET
development on macOS, see Install Visual Studio 2019 for Mac.

. N ET SDK VERSIO N VISUA L ST UDIO VERSIO N

6.0 Visual Studio 2022 for Mac Preview 3 17.0 or higher.

3.1 Visual Studio 2019 for Mac version 8.4 or higher.


Install alongside Visual Studio Code
Visual Studio Code is a powerful and lightweight source code editor that runs on your desktop. Visual Studio
Code is available for Windows, macOS, and Linux.
While Visual Studio Code doesn't come with an automated .NET installer like Visual Studio does, adding .NET
support is simple.
1. Download and install Visual Studio Code.
2. Download and install the .NET SDK.
3. Install the C# extension from the Visual Studio Code marketplace.

Install with bash automation


The dotnet-install scripts are used for automation and non-admin installs of the runtime. You can download the
script from the dotnet-install script reference page.
The script defaults to installing the latest long term support (LTS) version, which is .NET 6.0. You can choose a
specific release by specifying the current switch. Include the runtime switch to install a runtime. Otherwise,
the script installs the SDK.

./dotnet-install.sh --channel 6.0 --runtime aspnetcore

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.

Official package archives


.NET is available in the official package archives for various Linux distributions, including the following ones:
Alpine Linux
Arch Linux
Arch Linux User Repository
Fedora
Red Hat Enterprise Linux
Ubuntu
Microsoft collaborates with partners to ensure .NET works well on their Linux distributions. Support is provided
by those distributions. You can still open issues at dotnet/core if you run into problems.

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+

20.04 (LTS) 3.1, 6

18.04 (LTS) 3.1, 6

16.04 (LTS) 3.1, 6

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
Install preview versions
Preview and release candidate versions of .NET aren't available in package managers. You can install previews
and release candidates of .NET in one of the following ways:
Snap package
Scripted install with install-dotnet.sh
Manual binary extraction

Remove preview versions


When using a package manager to manage your installation of .NET, you may run into a conflict if you've
previously installed a preview release. The package manager may interpret the non-preview release as an earlier
version of .NET. To install the non-preview release, first uninstall the preview versions. For more information
about uninstalling .NET, see How to remove the .NET Runtime and SDK.

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.

.NET 6 is included in the Ubuntu 22.04 package manager feeds.


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 commands:

sudo apt-get update && \


sudo apt-get install -y dotnet6

Install the runtime


The ASP.NET Core Runtime allows you to run apps that were made with .NET that didn't provide the runtime. The
following commands install the ASP.NET Core Runtime, which is the most compatible runtime for .NET. In your
terminal, run the following commands:

sudo apt-get update && \


sudo apt-get install -y aspnetcore-runtime-6.0

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 :

sudo apt-get install -y dotnet-runtime-6.0

22.04 (Microsoft package feed)


NOTE
Warning: .NET 6 is included in Ubuntu 22.04. See the Advisory on installing .NET 6 on Ubuntu 22.04 if you want to use
.NET packages from packages.microsoft.com .

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/22.04/packages-microsoft-prod.deb -O packages-microsoft-


prod.deb
sudo dpkg -i packages-microsoft-prod.deb
rm packages-microsoft-prod.deb

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 commands:

sudo apt-get update && \


sudo apt-get install -y dotnet-sdk-6.0

IMPORTANT
If you receive an error message similar to Unable to locate package dotnet-sdk-6.0 , see the APT troubleshooting
section.

Install the runtime


The ASP.NET Core Runtime allows you to run apps that were made with .NET that didn't provide the runtime. The
following commands install the ASP.NET Core Runtime, which is the most compatible runtime for .NET. In your
terminal, run the following commands:

sudo apt-get update && \


sudo apt-get install -y aspnetcore-runtime-6.0

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 :

sudo apt-get install -y dotnet-runtime-6.0


NOTE
Ubuntu 22.04 includes OpenSSL 3 as the baseline version. .NET 6 supports OpenSSL 3 while earlier .NET versions don't.
Microsoft doesn't test or support using OpenSSL 1.x on Ubuntu 22.04. For more information, see .NET 6 Security
Improvements.

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:

wget https://packages.microsoft.com/config/ubuntu/20.04/packages-microsoft-prod.deb -O packages-microsoft-


prod.deb
sudo dpkg -i packages-microsoft-prod.deb
rm packages-microsoft-prod.deb

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 commands:

sudo apt-get update && \


sudo apt-get install -y dotnet-sdk-6.0

IMPORTANT
If you receive an error message similar to Unable to locate package dotnet-sdk-6.0 , see the APT troubleshooting
section.

Install the runtime


The ASP.NET Core Runtime allows you to run apps that were made with .NET that didn't provide the runtime. The
following commands install the ASP.NET Core Runtime, which is the most compatible runtime for .NET. In your
terminal, run the following commands:

sudo apt-get update && \


sudo apt-get install -y aspnetcore-runtime-6.0

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 :

sudo apt-get install -y 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:

wget https://packages.microsoft.com/config/ubuntu/18.04/packages-microsoft-prod.deb -O packages-microsoft-


prod.deb
sudo dpkg -i packages-microsoft-prod.deb
rm packages-microsoft-prod.deb

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 commands:

sudo apt-get update && \


sudo apt-get install -y dotnet-sdk-6.0

IMPORTANT
If you receive an error message similar to Unable to locate package dotnet-sdk-6.0 , see the APT troubleshooting
section.

Install the runtime


The ASP.NET Core Runtime allows you to run apps that were made with .NET that didn't provide the runtime. The
following commands install the ASP.NET Core Runtime, which is the most compatible runtime for .NET. In your
terminal, run the following commands:

sudo apt-get update && \


sudo apt-get install -y aspnetcore-runtime-6.0

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 :

sudo apt-get install -y 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

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 commands:

sudo apt-get update && \


sudo apt-get install -y dotnet-sdk-6.0

IMPORTANT
If you receive an error message similar to Unable to locate package dotnet-sdk-6.0 , see the APT troubleshooting
section.

Install the runtime


The ASP.NET Core Runtime allows you to run apps that were made with .NET that didn't provide the runtime. The
following commands install the ASP.NET Core Runtime, which is the most compatible runtime for .NET. In your
terminal, run the following commands:

sudo apt-get update && \


sudo apt-get install -y aspnetcore-runtime-6.0

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 :

sudo apt-get install -y dotnet-runtime-6.0

How to install other versions


All versions of .NET are available for download at https://dotnet.microsoft.com/download/dotnet, but require
manual installation. You can try and use the package manager to install a different version of .NET. However, the
requested version may not be available.
The packages added to package manager feeds are named in a hackable format, for example:
{product}-{type}-{version} .

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.

Use APT to update .NET


When a new patch release is available for .NET, you can simply upgrade it through APT with the following
commands:

sudo apt-get update


sudo apt-get upgrade

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:

sudo dpkg --purge packages-microsoft-prod && sudo dpkg -i packages-microsoft-prod.deb


sudo apt-get update

Then, try to install .NET again. If that doesn't work, you can run a manual install with the following commands:

sudo apt-get install -y gpg


wget -O - https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor -o microsoft.asc.gpg
sudo mv microsoft.asc.gpg /etc/apt/trusted.gpg.d/
wget https://packages.microsoft.com/config/ubuntu/{os-version}/prod.list
sudo mv prod.list /etc/apt/sources.list.d/microsoft-prod.list
sudo chown root:root /etc/apt/trusted.gpg.d/microsoft.asc.gpg
sudo chown root:root /etc/apt/sources.list.d/microsoft-prod.list
sudo apt-get update && \
sudo apt-get install -y {dotnet-package}

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

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

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

To install libgdiplus , you may need to specify a repository:

apk add libgdiplus --repository https://dl-3.alpinelinux.org/alpine/edge/testing/

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.

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

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

Install preview versions


Preview and release candidate versions of .NET aren't available in package managers. You can install previews
and release candidates of .NET in one of the following ways:
Snap package
Scripted install with install-dotnet.sh
Manual binary extraction

Remove preview versions


When using a package manager to manage your installation of .NET, you may run into a conflict if you've
previously installed a preview release. The package manager may interpret the non-preview release as an earlier
version of .NET. To install the non-preview release, first uninstall the preview versions. For more information
about uninstalling .NET, see How to remove the .NET Runtime and SDK.

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:

sudo rpm -Uvh https://packages.microsoft.com/config/centos/7/packages-microsoft-prod.rpm

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:

sudo yum install dotnet-sdk-6.0

Install the runtime


The ASP.NET Core Runtime allows you to run apps that were made with .NET that didn't provide the runtime. The
following command installs the ASP.NET Core Runtime, which is the most compatible runtime for .NET. In your
terminal, run the following command:
sudo yum install aspnetcore-runtime-6.0

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 :

sudo yum install 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.

.NET 5 is available in the default package repositories for CentOS 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:

sudo dnf install dotnet-sdk-5.0

Install the runtime


The ASP.NET Core Runtime allows you to run apps that were made with .NET that didn't provide the runtime. The
following command install the ASP.NET Core Runtime, which is the most compatible runtime for .NET. In your
terminal, run the following command:

sudo dnf install aspnetcore-runtime-5.0

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 :

sudo dnf install dotnet-runtime-5.0

How to install other versions


All versions of .NET are available for download at https://dotnet.microsoft.com/download/dotnet, but require
manual installation. You can try and use the package manager to install a different version of .NET. However, the
requested version may not be available.
The packages added to package manager feeds are named in a hackable format, for example:
{product}-{type}-{version} .

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

Register your Red Hat subscription


To install .NET from Red Hat on RHEL, you first need to register using the Red Hat Subscription Manager. If this
hasn't been done on your system, or if you're unsure, see the Red Hat Product Documentation for .NET.

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

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

Install preview versions


Preview and release candidate versions of .NET aren't available in package managers. You can install previews
and release candidates of .NET in one of the following ways:
Snap package
Scripted install with install-dotnet.sh
Manual binary extraction

Remove preview versions


When using a package manager to manage your installation of .NET, you may run into a conflict if you've
previously installed a preview release. The package manager may interpret the non-preview release as an earlier
version of .NET. To install the non-preview release, first uninstall the preview versions. For more information
about uninstalling .NET, see How to remove the .NET Runtime and SDK.

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:

sudo dnf install dotnet-sdk-6.0

Install the runtime


The ASP.NET Core Runtime allows you to run apps that were made with .NET that didn't provide the runtime. The
following command install the ASP.NET Core Runtime, which is the most compatible runtime for .NET. In your
terminal, run the following command:

sudo dnf install aspnetcore-runtime-6.0

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 :

sudo dnf install dotnet-runtime-6.0

RHEL 7 ✔
️ .NET 6.0
The following command installs the scl-utils package:

sudo yum install scl-utils

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 .NET SDK, run the following commands:

subscription-manager repos --enable=rhel-7-server-dotnet-rpms


yum install rh-dotnet60 -y
scl enable rh-dotnet60 bash

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.

source scl_source enable rh-dotnet60

Install the runtime


The .NET Runtime allows you to run apps that were made with .NET that didn't include the runtime. The
commands below install the ASP.NET Core Runtime, which is the most compatible runtime for .NET Core. In your
terminal, run the following commands.

subscription-manager repos --enable=rhel-7-server-dotnet-rpms


yum install rh-dotnet60-aspnetcore-runtime-6.0 -y
scl enable rh-dotnet60 bash

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.

source scl_source enable rh-dotnet60

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:

sudo yum install scl-utils

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 .NET SDK, run the following commands:

subscription-manager repos --enable=rhel-7-server-dotnet-rpms


yum install rh-dotnet50 -y
scl enable rh-dotnet50 bash

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.

source scl_source enable rh-dotnet50

Install the runtime


The .NET Runtime allows you to run apps that were made with .NET that didn't include the runtime. The
commands below install the ASP.NET Core Runtime, which is the most compatible runtime for .NET Core. In your
terminal, run the following commands.

subscription-manager repos --enable=rhel-7-server-dotnet-rpms


yum install rh-dotnet50-aspnetcore-runtime-5.0 -y
scl enable rh-dotnet50 bash

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.

source scl_source enable rh-dotnet50

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:

sudo yum install scl-utils

Install the SDK


.NET SDK allows you to develop apps with .NET Core. If you install .NET SDK, you don't need to install the
corresponding runtime. To install .NET SDK, run the following commands:

subscription-manager repos --enable=rhel-7-server-dotnet-rpms


yum install rh-dotnet31 -y
scl enable rh-dotnet31 bash

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.

source scl_source enable rh-dotnet31

Install the runtime


The .NET Core Runtime allows you to run apps that were made with .NET Core that didn't include the runtime.
The commands below install the ASP.NET Core Runtime, which is the most compatible runtime for .NET Core. In
your terminal, run the following commands.

subscription-manager repos --enable=rhel-7-server-dotnet-rpms


yum install rh-dotnet31-aspnetcore-runtime-3.1 -y
scl enable rh-dotnet31 bash

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.

source scl_source enable rh-dotnet31

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:

sudo dnf install dotnet-sdk-6.0

Install the runtime


The ASP.NET Core Runtime allows you to run apps that were made with .NET that didn't provide the runtime. The
following command install the ASP.NET Core Runtime, which is the most compatible runtime for .NET. In your
terminal, run the following command:

sudo dnf install aspnetcore-runtime-6.0

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 :

sudo dnf install 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:

sudo dnf install dotnet-sdk-6.0

Install the runtime


The ASP.NET Core Runtime allows you to run apps that were made with .NET that didn't provide the runtime. The
following command install the ASP.NET Core Runtime, which is the most compatible runtime for .NET. In your
terminal, run the following command:

sudo dnf install aspnetcore-runtime-6.0


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 :

sudo dnf install dotnet-runtime-6.0

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

How to install other versions


Consult the Red Hat documentation for .NET on the steps required to install other releases of .NET.

Troubleshoot the package manager


This section provides information on common errors you may get while using the package manager to install
.NET or .NET Core.
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.

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

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

Install preview versions


Preview and release candidate versions of .NET aren't available in package managers. You can install previews
and release candidates of .NET in one of the following ways:
Snap package
Scripted install with install-dotnet.sh
Manual binary extraction

Remove preview versions


When using a package manager to manage your installation of .NET, you may run into a conflict if you've
previously installed a preview release. The package manager may interpret the non-preview release as an earlier
version of .NET. To install the non-preview release, first uninstall the preview versions. For more information
about uninstalling .NET, see How to remove the .NET Runtime and SDK.

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:

wget https://packages.microsoft.com/config/debian/11/packages-microsoft-prod.deb -O packages-microsoft-


prod.deb
sudo dpkg -i packages-microsoft-prod.deb
rm packages-microsoft-prod.deb

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 commands:

sudo apt-get update && \


sudo apt-get install -y dotnet-sdk-6.0

IMPORTANT
If you receive an error message similar to Unable to locate package dotnet-sdk-6.0 , see the APT troubleshooting
section.

Install the runtime


The ASP.NET Core Runtime allows you to run apps that were made with .NET that didn't provide the runtime. The
following commands install the ASP.NET Core Runtime, which is the most compatible runtime for .NET. In your
terminal, run the following commands:
sudo apt-get update && \
sudo apt-get install -y aspnetcore-runtime-6.0

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 :

sudo apt-get install -y 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:

wget https://packages.microsoft.com/config/debian/10/packages-microsoft-prod.deb -O packages-microsoft-


prod.deb
sudo dpkg -i packages-microsoft-prod.deb
rm packages-microsoft-prod.deb

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 commands:

sudo apt-get update && \


sudo apt-get install -y dotnet-sdk-6.0

IMPORTANT
If you receive an error message similar to Unable to locate package dotnet-sdk-6.0 , see the APT troubleshooting
section.

Install the runtime


The ASP.NET Core Runtime allows you to run apps that were made with .NET that didn't provide the runtime. The
following commands install the ASP.NET Core Runtime, which is the most compatible runtime for .NET. In your
terminal, run the following commands:

sudo apt-get update && \


sudo apt-get install -y aspnetcore-runtime-6.0

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 :

sudo apt-get install -y 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:

wget -O - https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > microsoft.asc.gpg


sudo mv microsoft.asc.gpg /etc/apt/trusted.gpg.d/
wget https://packages.microsoft.com/config/debian/9/prod.list
sudo mv prod.list /etc/apt/sources.list.d/microsoft-prod.list
sudo chown root:root /etc/apt/trusted.gpg.d/microsoft.asc.gpg
sudo chown root:root /etc/apt/sources.list.d/microsoft-prod.list

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 commands:

sudo apt-get update && \


sudo apt-get install -y dotnet-sdk-6.0

IMPORTANT
If you receive an error message similar to Unable to locate package dotnet-sdk-6.0 , see the APT troubleshooting
section.

Install the runtime


The ASP.NET Core Runtime allows you to run apps that were made with .NET that didn't provide the runtime. The
following commands install the ASP.NET Core Runtime, which is the most compatible runtime for .NET. In your
terminal, run the following commands:

sudo apt-get update && \


sudo apt-get install -y aspnetcore-runtime-6.0

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 :

sudo apt-get install -y dotnet-runtime-6.0


Debian 8 ❌
❌ Please note that this version of Debian is no longer supported.
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 -O - https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > microsoft.asc.gpg


sudo mv microsoft.asc.gpg /etc/apt/trusted.gpg.d/
wget https://packages.microsoft.com/config/debian/8/prod.list
sudo mv prod.list /etc/apt/sources.list.d/microsoft-prod.list
sudo chown root:root /etc/apt/trusted.gpg.d/microsoft.asc.gpg
sudo chown root:root /etc/apt/sources.list.d/microsoft-prod.list

Install the SDK


The .NET Core SDK allows you to develop apps with .NET Core. If you install the .NET Core SDK, you don't need
to install the corresponding runtime. To install the .NET Core SDK, run the following commands:

sudo apt-get update && \


sudo apt-get install -y dotnet-sdk-2.1

IMPORTANT
If you receive an error message similar to Unable to locate package dotnet-sdk-2.1 , see the APT troubleshooting
section.

Install the runtime


The .NET Core Runtime allows you to run apps that were made with .NET Core that didn't include the runtime.
The following commands install the ASP.NET Core Runtime, which is the most compatible runtime for .NET Core.
In your terminal, run the following commands.

sudo apt-get update && \


sudo apt-get install -y aspnetcore-runtime-2.1

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 .

sudo apt-get install -y dotnet-runtime-2.1

How to install other versions


All versions of .NET are available for download at https://dotnet.microsoft.com/download/dotnet, but require
manual installation. You can try and use the package manager to install a different version of .NET. However, the
requested version may not be available.
The packages added to package manager feeds are named in a hackable format, for example:
{product}-{type}-{version} .

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.

Use APT to update .NET


When a new patch release is available for .NET, you can simply upgrade it through APT with the following
commands:

sudo apt-get update


sudo apt-get upgrade

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.

First, try purging the package list:

sudo dpkg --purge packages-microsoft-prod && sudo dpkg -i packages-microsoft-prod.deb


sudo apt-get update

Then, try to install .NET again. If that doesn't work, you can run a manual install with the following commands:

sudo apt-get install -y gpg


wget -O - https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor -o microsoft.asc.gpg
sudo mv microsoft.asc.gpg /etc/apt/trusted.gpg.d/
wget https://packages.microsoft.com/config/debian/{os-version}/prod.list
sudo mv prod.list /etc/apt/sources.list.d/microsoft-prod.list
sudo chown root:root /etc/apt/trusted.gpg.d/microsoft.asc.gpg
sudo chown root:root /etc/apt/sources.list.d/microsoft-prod.list
sudo apt-get update && \
sudo apt-get install -y {dotnet-package}

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:

sudo dnf install dotnet-sdk-6.0

Install the runtime


The ASP.NET Core Runtime allows you to run apps that were made with .NET that didn't provide the runtime. The
following command install the ASP.NET Core Runtime, which is the most compatible runtime for .NET. In your
terminal, run the following command:

sudo dnf install aspnetcore-runtime-6.0

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 :

sudo dnf install dotnet-runtime-6.0

Install .NET Core 3.1


Install the SDK
The .NET Core SDK allows you to develop apps with .NET Core. If you install the .NET Core SDK, you don't need
to install the corresponding runtime. To install the .NET Core SDK, run the following command:

sudo dnf install dotnet-sdk-3.1


Install the runtime
The .NET Core Runtime allows you to run apps that were made with .NET Core that didn't include the runtime.
The following command install the ASP.NET Core Runtime, which is the most compatible runtime for .NET Core.
In your terminal, run the following command.

sudo dnf install aspnetcore-runtime-3.1

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 .

sudo dnf install 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

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

Install preview versions


Preview and release candidate versions of .NET aren't available in package managers. You can install previews
and release candidates of .NET in one of the following ways:
Snap package
Scripted install with install-dotnet.sh
Manual binary extraction

Remove preview versions


When using a package manager to manage your installation of .NET, you may run into a conflict if you've
previously installed a preview release. The package manager may interpret the non-preview release as an earlier
version of .NET. To install the non-preview release, first uninstall the preview versions. For more information
about uninstalling .NET, see How to remove the .NET Runtime and SDK.

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

Install on older distributions


Older versions of Fedora don't contain .NET Core in the default package repositories. You can install .NET with
snap, through the dotnet-install.sh script, or use Microsoft's repository to install .NET:
1. First, add the Microsoft signing key to your list of trusted keys.

sudo rpm --import https://packages.microsoft.com/keys/microsoft.asc

2. Next, add the Microsoft package repository. The source of the repository is based on your version of
Fedora.

F EDO RA VERSIO N PA C K A GE REP O SITO RY

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

Install the SDK


The .NET Core SDK allows you to develop apps with .NET Core. If you install the .NET Core SDK, you don't need
to install the corresponding runtime. To install the .NET Core SDK, run the following command:

sudo dnf install dotnet-sdk-3.1

Install the runtime


The .NET Core Runtime allows you to run apps that were made with .NET Core that didn't include the runtime.
The following command install the ASP.NET Core Runtime, which is the most compatible runtime for .NET Core.
In your terminal, run the following command.

sudo dnf install aspnetcore-runtime-3.1

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 .

sudo dnf install dotnet-runtime-3.1

How to install other versions


All versions of .NET are available for download at https://dotnet.microsoft.com/download/dotnet, but require
manual installation. You can try and use the package manager to install a different version of .NET. However, the
requested version may not be available.
The packages added to package manager feeds are named in a hackable format, for example:
{product}-{type}-{version} .

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 or .NET Core.
Unable to find package
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.
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.

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

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

Install preview versions


Preview and release candidate versions of .NET aren't available in package managers. You can install previews
and release candidates of .NET in one of the following ways:
Snap package
Scripted install with install-dotnet.sh
Manual binary extraction

Remove preview versions


When using a package manager to manage your installation of .NET, you may run into a conflict if you've
previously installed a preview release. The package manager may interpret the non-preview release as an earlier
version of .NET. To install the non-preview release, first uninstall the preview versions. For more information
about uninstalling .NET, see How to remove the .NET Runtime and SDK.

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:

sudo zypper install libicu


sudo rpm --import https://packages.microsoft.com/keys/microsoft.asc
wget https://packages.microsoft.com/config/opensuse/15/prod.repo
sudo mv prod.repo /etc/zypp/repos.d/microsoft-prod.repo
sudo chown root:root /etc/zypp/repos.d/microsoft-prod.repo

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:

sudo zypper install dotnet-sdk-6.0

Install the runtime


The ASP.NET Core Runtime allows you to run apps that were made with .NET that didn't provide the runtime. The
following command installs the ASP.NET Core Runtime, which is the most compatible runtime for .NET. In your
terminal, run the following command:

sudo zypper install aspnetcore-runtime-6.0

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 :

sudo zypper install dotnet-runtime-6.0

How to install other versions


All versions of .NET are available for download at https://dotnet.microsoft.com/download/dotnet, but require
manual installation. You can try and use the package manager to install a different version of .NET. However, the
requested version may not be available.
The packages added to package manager feeds are named in a hackable format, for example:
{product}-{type}-{version} .
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.
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
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.

Register your Red Hat subscription


To install .NET from Red Hat on RHEL, you first need to register using the Red Hat Subscription Manager. If this
hasn't been done on your system, or if you're unsure, see the Red Hat Product Documentation for .NET.

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

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

Install preview versions


Preview and release candidate versions of .NET aren't available in package managers. You can install previews
and release candidates of .NET in one of the following ways:
Snap package
Scripted install with install-dotnet.sh
Manual binary extraction

Remove preview versions


When using a package manager to manage your installation of .NET, you may run into a conflict if you've
previously installed a preview release. The package manager may interpret the non-preview release as an earlier
version of .NET. To install the non-preview release, first uninstall the preview versions. For more information
about uninstalling .NET, see How to remove the .NET Runtime and SDK.

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:

sudo dnf install dotnet-sdk-6.0

Install the runtime


The ASP.NET Core Runtime allows you to run apps that were made with .NET that didn't provide the runtime. The
following command install the ASP.NET Core Runtime, which is the most compatible runtime for .NET. In your
terminal, run the following command:

sudo dnf install aspnetcore-runtime-6.0

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 :

sudo dnf install dotnet-runtime-6.0

RHEL 7 ✔
️ .NET 6.0
The following command installs the scl-utils package:

sudo yum install scl-utils

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 .NET SDK, run the following commands:

subscription-manager repos --enable=rhel-7-server-dotnet-rpms


yum install rh-dotnet60 -y
scl enable rh-dotnet60 bash

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.

source scl_source enable rh-dotnet60

Install the runtime


The .NET Runtime allows you to run apps that were made with .NET that didn't include the runtime. The
commands below install the ASP.NET Core Runtime, which is the most compatible runtime for .NET Core. In your
terminal, run the following commands.

subscription-manager repos --enable=rhel-7-server-dotnet-rpms


yum install rh-dotnet60-aspnetcore-runtime-6.0 -y
scl enable rh-dotnet60 bash

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.

source scl_source enable rh-dotnet60

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:

sudo yum install scl-utils

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 .NET SDK, run the following commands:

subscription-manager repos --enable=rhel-7-server-dotnet-rpms


yum install rh-dotnet50 -y
scl enable rh-dotnet50 bash

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.

source scl_source enable rh-dotnet50

Install the runtime


The .NET Runtime allows you to run apps that were made with .NET that didn't include the runtime. The
commands below install the ASP.NET Core Runtime, which is the most compatible runtime for .NET Core. In your
terminal, run the following commands.

subscription-manager repos --enable=rhel-7-server-dotnet-rpms


yum install rh-dotnet50-aspnetcore-runtime-5.0 -y
scl enable rh-dotnet50 bash

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.

source scl_source enable rh-dotnet50

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:

sudo yum install scl-utils

Install the SDK


.NET SDK allows you to develop apps with .NET Core. If you install .NET SDK, you don't need to install the
corresponding runtime. To install .NET SDK, run the following commands:

subscription-manager repos --enable=rhel-7-server-dotnet-rpms


yum install rh-dotnet31 -y
scl enable rh-dotnet31 bash

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.

source scl_source enable rh-dotnet31

Install the runtime


The .NET Core Runtime allows you to run apps that were made with .NET Core that didn't include the runtime.
The commands below install the ASP.NET Core Runtime, which is the most compatible runtime for .NET Core. In
your terminal, run the following commands.

subscription-manager repos --enable=rhel-7-server-dotnet-rpms


yum install rh-dotnet31-aspnetcore-runtime-3.1 -y
scl enable rh-dotnet31 bash

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.

source scl_source enable rh-dotnet31

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:

sudo dnf install dotnet-sdk-6.0

Install the runtime


The ASP.NET Core Runtime allows you to run apps that were made with .NET that didn't provide the runtime. The
following command install the ASP.NET Core Runtime, which is the most compatible runtime for .NET. In your
terminal, run the following command:

sudo dnf install aspnetcore-runtime-6.0

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 :

sudo dnf install 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:

sudo dnf install dotnet-sdk-6.0

Install the runtime


The ASP.NET Core Runtime allows you to run apps that were made with .NET that didn't provide the runtime. The
following command install the ASP.NET Core Runtime, which is the most compatible runtime for .NET. In your
terminal, run the following command:

sudo dnf install aspnetcore-runtime-6.0


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 :

sudo dnf install dotnet-runtime-6.0

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

How to install other versions


Consult the Red Hat documentation for .NET on the steps required to install other releases of .NET.

Troubleshoot the package manager


This section provides information on common errors you may get while using the package manager to install
.NET or .NET Core.
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.

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

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

Install preview versions


Preview and release candidate versions of .NET aren't available in package managers. You can install previews
and release candidates of .NET in one of the following ways:
Snap package
Scripted install with install-dotnet.sh
Manual binary extraction

Remove preview versions


When using a package manager to manage your installation of .NET, you may run into a conflict if you've
previously installed a preview release. The package manager may interpret the non-preview release as an earlier
version of .NET. To install the non-preview release, first uninstall the preview versions. For more information
about uninstalling .NET, see How to remove the .NET Runtime and SDK.

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:

sudo rpm -Uvh https://packages.microsoft.com/config/sles/15/packages-microsoft-prod.rpm

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.

sudo ln -s /etc/yum.repos.d/microsoft-prod.repo /etc/zypp/repos.d/microsoft-prod.repo

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:

sudo zypper install dotnet-sdk-6.0

Install the runtime


The ASP.NET Core Runtime allows you to run apps that were made with .NET that didn't provide the runtime. The
following command installs the ASP.NET Core Runtime, which is the most compatible runtime for .NET. In your
terminal, run the following command:

sudo zypper install aspnetcore-runtime-6.0

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 :

sudo zypper install 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:

sudo rpm -Uvh https://packages.microsoft.com/config/sles/12/packages-microsoft-prod.rpm

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:

sudo zypper install dotnet-sdk-6.0


Install the runtime
The ASP.NET Core Runtime allows you to run apps that were made with .NET that didn't provide the runtime. The
following command installs the ASP.NET Core Runtime, which is the most compatible runtime for .NET. In your
terminal, run the following command:

sudo zypper install aspnetcore-runtime-6.0

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 :

sudo zypper install dotnet-runtime-6.0

How to install other versions


All versions of .NET are available for download at https://dotnet.microsoft.com/download/dotnet, but require
manual installation. You can try and use the package manager to install a different version of .NET. However, the
requested version may not be available.
The packages added to package manager feeds are named in a hackable format, for example:
{product}-{type}-{version} .

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

3.1 (LTS) 3.0

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.

Install the SDK


Snap packages for the .NET SDK are all published under the same identifier: dotnet-sdk . A specific version of
the SDK can be installed by specifying the channel. The SDK includes the corresponding runtime. The following
table lists the channels:

. N ET VERSIO N SN A P PA C K A GE O R C H A N N EL

6 (LTS) 6.0 or latest/stable or lts/stable

5 5.0

3.1 (LTS) 3.1

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:

sudo snap install dotnet-sdk --classic --channel=6.0

Next, register the dotnet command for the system with the snap alias command:

sudo snap alias dotnet-sdk.dotnet dotnet

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.

Install the runtime


Snap packages for the .NET Runtime are each published under their own package identifier. The following table
lists the package identifiers:

. N ET VERSIO N SN A P PA C K A GE

6 (LTS) dotnet-runtime-60

5 dotnet-runtime-50

3.1 (LTS) dotnet-runtime-31

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:

sudo snap install dotnet-runtime-60 --classic

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 the install location


The DOTNET_ROOT environment variable is often used by tools to determine where .NET is installed. When .NET is
installed through Snap, this environment variable isn't configured. You should configure the DOTNET_ROOT
environment variable in your profile. The path to the snap uses the following format: /snap/{package}/current .
For example, if you installed the dotnet-sdk snap, use the following command to set the environment variable
to where .NET is located:

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 .

TLS/SSL Certificate errors


When .NET is installed through Snap, it's possible that on some distros the .NET TLS/SSL certificates may not be
found and you may receive an error during restore :

Processing post-creation actions...


Running 'dotnet restore' on /home/myhome/test/test.csproj...
Restoring packages for /home/myhome/test/test.csproj...
/snap/dotnet-sdk/27/sdk/2.2.103/NuGet.targets(114,5): error : Unable to load the service index for source
https://api.nuget.org/v3/index.json. [/home/myhome/test/test.csproj]
/snap/dotnet-sdk/27/sdk/2.2.103/NuGet.targets(114,5): error : The SSL connection could not be established,
see inner exception. [/home/myhome/test/test.csproj]
/snap/dotnet-sdk/27/sdk/2.2.103/NuGet.targets(114,5): error : The remote certificate is invalid according
to the validation procedure. [/home/myhome/test/test.csproj]

To resolve this problem, set a few environment variables:

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

Troubles resolving dotnet


It's common for other apps, such as the OmniSharp extension for Visual Studio Code, to try to resolve the
location of the .NET SDK. Typically, this is done by figuring out where the dotnet executable is located. A snap-
installed .NET SDK may confuse these apps. When these apps can't resolve the .NET SDK, you'll see an error
similar to one of the following messages:
The SDK 'Microsoft.NET.Sdk' specified could not be found
The SDK 'Microsoft.NET.Sdk.Web' specified could not be found
The SDK 'Microsoft.NET.Sdk.Razor' specified could not be found
To fix this problem, symlink the snap dotnet executable to the location that the program is looking for. Two
common paths the dotnet command is looking for are /usr/local/bin/dotnet and /usr/share/dotnet . For
example, to link the current .NET SDK snap package, use the following command:

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

3.1 (LTS) 3.0

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:

sudo chmod +x ./dotnet-install.sh

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.

./dotnet-install.sh -c Current --runtime aspnetcore

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

For more information, see dotnet-install scripts reference.

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

mkdir -p "$DOTNET_ROOT" && tar zxf "$DOTNET_FILE" -C "$DOTNET_ROOT"

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.

Should I remove a version?


The .NET version selection behaviors and the runtime compatibility of .NET across updates enables safe removal
of previous versions. .NET runtime updates are compatible within a major version band such as 6.x and 5.x.
Additionally, newer releases of the .NET SDK generally maintain the ability to build applications that target
previous versions of the runtime in a compatible manner.
In general, you only need the latest SDK and latest patch version of the runtimes required for your application.
Instances where you might want to keep older SDK or runtime versions include maintaining project.json-based
applications. Unless your application has specific reasons for earlier SDKs or runtimes, you may safely remove
older versions.

Determine what is installed


The .NET CLI has options you can use to list the versions of the SDK and runtime that are installed on your
computer. Use dotnet --list-sdks to see the list of installed SDKs and dotnet --list-runtimes for the list of
runtimes. For more information, see How to check that .NET is already installed.

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:

apt-get remove dotnet-host

There's no version attached to dotnet-host .

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.

.NET Uninstall Tool


The .NET Uninstall Tool ( dotnet-core-uninstall ) lets you remove .NET SDKs and runtimes from a system. A
collection of options is available to specify which versions should be uninstalled.

Visual Studio dependency on .NET SDK versions


Before Visual Studio 2019 version 16.3, Visual Studio installers called the standalone SDK installer for .NET Core
version 2.1 or 2.2. As a result, the SDK versions appear in the Windows Apps & features dialog. Removing
.NET SDKs that were installed by Visual Studio using the standalone installer may break Visual Studio. If Visual
Studio has problems after you uninstall SDKs, run Repair on that specific version of Visual Studio. The following
table shows some of the Visual Studio dependencies on .NET Core SDK versions:

VISUA L ST UDIO VERSIO N . N ET C O RE SDK VERSIO N

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

Visual Studio 2017 version 15.8 .NET Core SDK 2.1.4xx

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.

Remove the NuGet fallback folder


Before .NET Core 3.0 SDK, the .NET Core SDK installers used a folder named NuGetFallbackFolder to store a
cache of NuGet packages. This cache was used during operations such as dotnet restore or
dotnet build /t:Restore . The NuGetFallbackFolder is located at C:\Program Files\dotnet\sdk on Windows and
at /usr/local/share/dotnet/sdk on macOS.
You may want to remove this folder, if:
You're only developing using .NET Core 3.0 SDK or .NET 5 or later versions.
You're developing using .NET Core SDK versions earlier than 3.0, but you can work online.
If you want to remove the NuGet fallback folder, you can delete it, but you'll need administrative privileges to do
so.
It's not recommended to delete the dotnet folder. Doing so would remove any global tools you've previously
installed. Also, on Windows:
You'll break Visual Studio 2019 version 16.3 and later versions. You can run Repair to recover.
If there are .NET Core SDK entries in the Apps & features dialog, they'll be orphaned.
Manage .NET project and item templates
9/10/2022 • 4 minutes to read • Edit Online

.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:

dotnet new -i Microsoft.DotNet.Web.Spa.ProjectTemplates

To install a template pack from the default NuGet feed with a specific version, use the
dotnet new -i {package-id}::{version} command:

dotnet new -i Microsoft.DotNet.Web.Spa.ProjectTemplates::2.2.6

Local NuGet package


When a template pack is created, a nupkg file is generated. If you have a nupkg file containing templates, you
can install it with the dotnet new -i {path-to-package} command:

dotnet new -i c:\code\nuget-packages\Some.Templates.1.0.0.nupkg

dotnet new -i ~/code/nuget-packages/Some.Templates.1.0.0.nupkg

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 -i c:\code\nuget-packages\some-folder\

dotnet new -i ~/code/nuget-packages/some-folder/


The {folder-path} specified on the command becomes the template pack identifier for all templates found. As
specified in the List templates section, you can get a list of templates installed with the dotnet new -u
command. In this example, the template pack identifier is shown as the folder used for install:

dotnet new -u
Template Instantiation Commands for .NET CLI

Currently installed items:

... cut to save space ...

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

Currently installed items:

... cut to save space ...

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

dotnet new -u Microsoft.DotNet.Web.Spa.ProjectTemplates

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 c:\code\nuget-packages\some-folder

dotnet new -u /home/username/code/templates


List templates
By using the standard uninstall command without a package identifier, you can see a list of installed templates
along with the command that uninstalls each template.

dotnet new -u
Template Instantiation Commands for .NET CLI

Currently installed items:

... cut to save space ...

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

Install templates from other SDKs


If you've installed each version of the SDK sequentially, for example you installed SDK 2.0, then SDK 2.1, and so
on, you'll have every SDK's templates installed. However, if you start with a later SDK version, like 3.1, only the
templates for LTS (long term support) releases are included, which at the time of the SDK 3.1 release is SDK 2.1
and SDK 3.1. Templates for any other release aren't included.
The .NET Core templates are available on NuGet, and you can install them like any other template. For more
information, see Install NuGet hosted package.

SDK N UGET PA C K A GE IDEN T IF IER

.NET Core 2.1 Microsoft.DotNet.Common.ProjectTemplates.2.1

.NET Core 2.2 Microsoft.DotNet.Common.ProjectTemplates.2.2

.NET Core 3.0 Microsoft.DotNet.Common.ProjectTemplates.3.0

.NET Core 3.1 Microsoft.DotNet.Common.ProjectTemplates.3.1

.NET 5.0 Microsoft.DotNet.Common.ProjectTemplates.5.0

.NET 6.0 Microsoft.DotNet.Common.ProjectTemplates.6.0

ASP.NET Core 2.1 Microsoft.DotNet.Web.ProjectTemplates.2.1

ASP.NET Core 2.2 Microsoft.DotNet.Web.ProjectTemplates.2.2

ASP.NET Core 3.0 Microsoft.DotNet.Web.ProjectTemplates.3.0

ASP.NET Core 3.1 Microsoft.DotNet.Web.ProjectTemplates.3.1

ASP.NET Core 5.0 Microsoft.DotNet.Web.ProjectTemplates.5.0

ASP.NET Core 6.0 Microsoft.DotNet.Web.ProjectTemplates.6.0


For example, the .NET Core SDK includes templates for a console app targeting .NET Core 2.1 and .NET Core 3.1.
If you wanted to target .NET Core 3.0, you would need to install the 3.0 templates.
1. Try creating an app that targets .NET Core 3.0.

dotnet new console --framework netcoreapp3.0

If you see an error message, you need to install the templates.

Couldn't find an installed template that matches the input, searching online for one that does...

2. Install the .NET Core 3.0 project templates.

dotnet new -i Microsoft.DotNet.Common.ProjectTemplates.3.0

3. Try creating the app a second time.

dotnet new console --framework netcoreapp3.0

And you should see a message indicating the project was created.

The template "Console Application" was created successfully.


Processing post-creation actions... Running 'dotnet restore' on path-to-project-file.csproj...
Determining projects to restore... Restore completed in 1.05 sec for path-to-project-file.csproj.
Restore succeeded.

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

dotnet run -p:UseAppHost=false

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.

ASP.NET Core, macOS, and certificates


.NET provides the ability to manage certificates in the macOS Keychain with the
System.Security.Cryptography.X509Certificates class. Access to the macOS Keychain uses the applications
identity as the primary key when deciding which partition to consider. For example, unsigned applications store
secrets in the unsigned partition, but signed applications store their secrets in partitions only they can access.
The source of execution that invokes your app decides which partition to use.
.NET provides three sources of execution: appHost, default host (the dotnet command), and a custom host. Each
execution model may have different identities, either signed or unsigned, and has access to different partitions
within the Keychain. Certificates imported by one mode may not be accessible from another. For example, the
notarized versions of .NET have a default host that is signed. Certificates are imported into a secure partition
based on its identity. These certificates aren't accessible from a generated appHost, as the appHost is ad-hoc
signed.
Another example, by default, ASP.NET Core imports a default SSL certificate through the default host. ASP.NET
Core applications that use an appHost won't have access to this certificate and will receive an error when .NET
detects the certificate isn't accessible. The error message provides instructions on how to fix this problem.
If certificate sharing is required, macOS provides configuration options with the security utility.
For more information on how to troubleshoot ASP.NET Core certificate issues, see Enforce HTTPS in ASP.NET
Core.

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

Notarize a .NET app


If you want your application to run on macOS Catalina (version 10.15) or higher, you'll want to notarize your
app. The appHost you submit with your application for notarization should be used with at least the same
default entitlements for .NET Core.

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

System.IO.FileNotFoundException: Could not find file


'/usr/share/dotnet/packs/Microsoft.NETCore.App.Ref/5.0.0/data/FrameworkList.xml'.

A fatal error occurred.

A fatal error occurred. The required library libhostfxr.so could not be found.

or

A fatal error occurred. The folder [/usr/share/dotnet/host/fxr] does not exist.

or

A fatal error occurred, the folder [/usr/share/dotnet/host/fxr] does not contain any version-numbered
child folders.

Generic messages about dotnet not found


A general message may appear that indicates the SDK isn't found, or that the package has already been
installed.
One symptom of these problems is that both the /usr/lib64/dotnet and /usr/share/dotnet folders are on your
system.

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:

sudo dnf remove packages-microsoft-prod


sudo dnf remove 'dotnet*' 'aspnet*' 'netstandard*'
sudo dnf install dotnet-sdk-5.0

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:

echo 'excludepkgs=dotnet*,aspnet*,netstandard*' | sudo tee -a /etc/yum.repos.d/microsoft-prod.repo


sudo dnf remove 'dotnet*' 'aspnet*' 'netstandard*'
sudo dnf install dotnet-sdk-5.0

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:

echo 'priority=50' | sudo tee -a /etc/yum.repos.d/microsoft-prod.repo


sudo dnf remove 'dotnet*' 'aspnet*' 'netstandard*'
sudo dnf install dotnet-sdk-5.0

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.

Check SDK versions


You can see which versions of the .NET SDK are currently installed with a terminal. Open a terminal and run the
following command.

dotnet --list-sdks

You get output similar to the following.

2.1.500 [C:\program files\dotnet\sdk]


2.1.502 [C:\program files\dotnet\sdk]
2.1.504 [C:\program files\dotnet\sdk]
2.1.600 [C:\program files\dotnet\sdk]
2.1.602 [C:\program files\dotnet\sdk]
3.1.100 [C:\program files\dotnet\sdk]
5.0.100 [C:\program files\dotnet\sdk]
6.0.100 [C:\program files\dotnet\sdk]

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]

Check runtime versions


You can see which versions of the .NET runtime are currently installed with the following command.
dotnet --list-runtimes

You get output similar to the following.

Microsoft.AspNetCore.All 2.1.7 [c:\program files\dotnet\shared\Microsoft.AspNetCore.All]


Microsoft.AspNetCore.All 2.1.13 [c:\program files\dotnet\shared\Microsoft.AspNetCore.All]
Microsoft.AspNetCore.App 2.1.7 [c:\program files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 2.1.13 [c:\program files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 3.1.0 [c:\program files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 5.0.0 [c:\program files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 6.0.0 [c:\program files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.NETCore.App 2.1.7 [c:\program files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 2.1.13 [c:\program files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 3.1.0 [c:\program files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 5.0.0 [c:\program files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 6.0.0 [c:\program files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.WindowsDesktop.App 3.0.0 [c:\program files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 3.1.0 [c:\program files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 5.0.0 [c:\program files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 6.0.0 [c:\program files\dotnet\shared\Microsoft.WindowsDesktop.App]

Microsoft.AspNetCore.All 2.1.7 [/home/user/dotnet/shared/Microsoft.AspNetCore.All]


Microsoft.AspNetCore.All 2.1.13 [/home/user/dotnet/shared/Microsoft.AspNetCore.All]
Microsoft.AspNetCore.App 2.1.7 [/home/user/dotnet/shared/Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 2.1.13 [/home/user/dotnet/shared/Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 3.1.0 [/home/user/dotnet/shared/Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 5.0.0 [/home/user/dotnet/shared/Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 6.0.0 [/home/user/dotnet/shared/Microsoft.AspNetCore.App]
Microsoft.NETCore.App 2.1.7 [/home/user/dotnet/shared/Microsoft.NETCore.App]
Microsoft.NETCore.App 2.1.13 [/home/user/dotnet/shared/Microsoft.NETCore.App]
Microsoft.NETCore.App 3.1.0 [/home/user/dotnet/shared/Microsoft.NETCore.App]
Microsoft.NETCore.App 5.0.0 [/home/user/dotnet/shared/Microsoft.NETCore.App]
Microsoft.NETCore.App 6.0.0 [/home/user/dotnet/shared/Microsoft.NETCore.App]

Microsoft.AspNetCore.All 2.1.7 [/usr/local/share/dotnet/shared/Microsoft.AspNetCore.All]


Microsoft.AspNetCore.All 2.1.13 [/usr/local/share/dotnet/shared/Microsoft.AspNetCore.All]
Microsoft.AspNetCore.App 2.1.7 [/usr/local/share/dotnet/shared/Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 2.1.13 [/usr/local/share/dotnet/shared/Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 3.1.0 [/usr/local/share/dotnet/shared/Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 5.0.0 [/usr/local/share/dotnet/shared/Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 6.0.0 [/usr/local/share/dotnet/shared/Microsoft.AspNetCore.App]
Microsoft.NETCore.App 2.1.7 [/usr/local/share/dotnet/shared/Microsoft.NETCore.App]
Microsoft.NETCore.App 2.1.13 [/usr/local/share/dotnet/shared/Microsoft.NETCore.App]
Microsoft.NETCore.App 3.1.0 [/usr/local/share/dotnet/shared/Microsoft.NETCore.App]
Microsoft.NETCore.App 5.0.0 [/usr/local/share/dotnet/shared/Microsoft.NETCore.App]
Microsoft.NETCore.App 6.0.0 [/usr/local/share/dotnet/shared/Microsoft.NETCore.App]

Check for install folders


It's possible that .NET is installed but not added to the PATH variable for your operating system or user profile.
In this case, the commands from the previous sections may not work. As an alternative, you can check that the
.NET install folders exist.
When you install .NET from an installer or script, it's installed to a standard folder. Much of the time the installer
or script you're using to install .NET gives you an option to install to a different folder. If you choose to install to a
different folder, adjust the start of the folder path.
dotnet executable
C:\program files\dotnet\dotnet.exe
.NET SDK
C:\program files\dotnet\sdk\{version}\
.NET Runtime
C:\program files\dotnet\shared\{runtime-type}\{version}\
dotnet executable
/home/user/share/dotnet/dotnet
.NET SDK
/home/user/share/dotnet/sdk/{version}/
.NET Runtime
/home/user/share/dotnet/shared/{runtime-type}/{version}/
dotnet executable
/usr/local/share/dotnet/dotnet
.NET SDK
/usr/local/share/dotnet/sdk/{version}/
.NET Runtime
/usr/local/share/dotnet/shared/{runtime-type}/{version}/

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.

Download and install the localized IntelliSense files


IMPORTANT
This procedure requires that you have administrator permission to copy the IntelliSense files to the .NET installation folder.

1. Go to the Download IntelliSense files page.


2. Download the IntelliSense file for the language and version you'd like to use.
3. Extract the contents of the zip file.
4. Navigate to the .NET Intellisense folder.
a. Navigate to the .NET installation folder. By default, it's under %ProgramFiles%\dotnet\packs.
b. Choose which SDK you want to install the IntelliSense for, and navigate to the associated path. You
have the following options:

SDK T Y P E PAT H

.NET 5+ and .NET Core Microsoft.NETCore.App.Ref

Windows Desktop Microsoft.WindowsDesktop.App.Ref

.NET Standard NETStandard.Library.Ref

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

Brazilian Portuguese pt-br

Chinese (simplified) zh-hans

Chinese (traditional) zh-hant

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.

Modify Visual Studio language


For Visual Studio to use a different language for IntelliSense, install the appropriate language pack. This can be
done during installation or at a later time by modifying the Visual Studio installation. If you already have Visual
Studio configured to the language of your choice, your IntelliSense installation is ready.
Install the language pack
If you didn't install the desired language pack during setup, update Visual Studio as follows to install the
language pack:

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.

1. Find the Visual Studio Installer on your computer.


For example, on a computer running Windows 10, select Star t , and then scroll to the letter V , where it's
listed as Visual Studio Installer .
NOTE
You can also find the Visual Studio Installer in the following location:
C:\Program Files (x86)\Microsoft Visual Studio\Installer\vs_installer.exe

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.

Free and open source


.NET is free, open source, and is a .NET Foundation project. .NET is maintained by Microsoft and the community
on GitHub in several repositories.
.NET source and binaries are licensed with the MIT license. Additional licenses apply on Windows for binary
distributions.

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.

NuGet Package Manager


NuGet is the package manager for .NET. It enables developers to share compiled binaries with each other.
NuGet.org offers many popular packages from the community.

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 5 and later versions


.NET 5+, previously referred to as .NET Core, is a cross-platform implementation of .NET that's designed to
handle server and cloud workloads at scale. It also supports other workloads, including desktop apps. It runs on
Windows, macOS, and Linux. It implements .NET Standard, so code that targets .NET Standard can run on .NET
5+. ASP.NET Core, Windows Forms, and Windows Presentation Foundation (WPF) all run on .NET 5+.
.NET 6 is the latest version of this .NET implementation.
For more information, see the following resources:
.NET introduction
.NET vs. .NET Framework for server apps
.NET 5+ and .NET Standard

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

Universal Windows Platform (UWP)


UWP is an implementation of .NET that is used for building modern, 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.
For more information, see Introduction to the Universal Windows Platform.
.NET class libraries
9/10/2022 • 3 minutes to read • Edit Online

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.

Platform-specific class libraries


Platform-specific libraries are bound to a single .NET platform (for example, .NET Framework on Windows) and
can therefore take significant dependencies on a known execution environment. Such an environment exposes a
known set of APIs (.NET and OS APIs) and maintains and exposes expected state (for example, Windows
registry).
Developers who create platform-specific libraries can fully exploit the underlying platform. The libraries will only
ever run on that given platform, making platform checks or other forms of conditional code unnecessary
(modulo single sourcing code for multiple platforms).
Platform-specific libraries have been the primary class library type for the .NET Framework. Even as other .NET
implementations emerged, platform-specific libraries remained the dominant library type.

Portable class libraries


Portable libraries are supported on multiple .NET implementations. They can still take dependencies on a known
execution environment, however, the environment is a synthetic one that's generated by the intersection of a set
of concrete .NET implementations. Exposed APIs and platform assumptions are a subset of what would be
available to a platform-specific library.
You choose a platform configuration when you create a portable library. The platform configuration is the set of
platforms that you need to support (for example, .NET Framework 4.5+, Windows Phone 8.0+). The more
platforms you opt to support, the fewer APIs and fewer platform assumptions you can make, the lowest
common denominator. This characteristic can be confusing at first, since people often think "more is better" but
find that more supported platforms results in fewer available APIs.
Many library developers have switched from producing multiple platform-specific libraries from one source
(using conditional compilation directives) to portable libraries. There are several approaches for accessing
platform-specific functionality within portable libraries, with bait-and-switch being the most widely accepted
technique at this point.

.NET Standard class libraries


.NET Standard libraries are a replacement of the platform-specific and portable libraries concepts. They are
platform-specific in the sense that they expose all functionality from the underlying platform (no synthetic
platforms or platform intersections). They are portable in the sense that they work on all supporting platforms.
.NET Standard exposes a set of library contracts. .NET implementations must support each contract fully or not
at all. Each implementation, therefore, supports a set of .NET Standard contracts. The corollary is that each .NET
Standard class library is supported on the platforms that support its contract dependencies.
.NET Standard does not expose the entire functionality of .NET Framework (nor is that a goal), however, the
libraries do expose many more APIs than Portable Class Libraries.
The following implementations support .NET Standard libraries:
.NET Core
.NET Framework
Mono
Universal Windows Platform (UWP)
For more information, see .NET Standard.

Mono class libraries


Class libraries are supported on Mono, including the three types of libraries described previously. Mono is often
viewed as a cross-platform implementation of .NET Framework. In part, this is because platform-specific .NET
Framework libraries can run on the Mono runtime without modification or recompilation. This characteristic was
in place before the creation of portable class libraries, so was an obvious choice to enable binary portability
between .NET Framework and Mono (although it only worked in one direction).
.NET Standard
9/10/2022 • 14 minutes to read • Edit Online

.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 Standard versions


.NET Standard is versioned. Each new version adds more APIs. When a library is built against a certain version of
.NET Standard, it can run on any .NET implementation that implements that version of .NET Standard (or higher).
Targeting a higher version of .NET Standard allows a library to use more APIs but means it can only be used on
more recent versions of .NET. Targeting a lower version reduces the available APIs but means the library can run
in more places.
Select .NET Standard version
1.0
1.1
1.2
1.3
1.4
1.5
1.6
2.0
2.1

.NET Standard 1.0 has 7,949 of the 37,118 available APIs.

. N ET IM P L EM EN TAT IO N VERSIO N SUP P O RT

.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

Mono 4.6, 5.4, 6.4

Xamarin.iOS 10.0, 10.14, 12.16

Xamarin.Mac 3.0, 3.8, 5.16


. N ET IM P L EM EN TAT IO N VERSIO N SUP P O RT

Xamarin.Android 7.0, 8.0, 10.0

Universal Windows Platform 8.0, 8.1, 10.0, 10.0.16299, TBD

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.

Target .NET Standard


You can build .NET Standard Libraries using a combination of the netstandard framework and the
NETStandard.Library metapackage.

.NET Framework compatibility mode


Starting with .NET Standard 2.0, the .NET Framework compatibility mode was introduced. This compatibility
mode allows .NET Standard projects to reference .NET Framework libraries as if they were compiled for .NET
Standard. Referencing .NET Framework libraries doesn't work for all projects, such as libraries that use Windows
Presentation Foundation (WPF) APIs.
For more information, see .NET Framework compatibility mode.

.NET Standard libraries and Visual Studio


In order to build .NET Standard libraries in Visual Studio, make sure you have Visual Studio 2022, Visual Studio
2019, or Visual Studio 2017 version 15.3 or later installed on Windows, or Visual Studio for Mac version 7.1 or
later installed on macOS.
If you only need to consume .NET Standard 2.0 libraries in your projects, you can also do that in Visual Studio
2015. However, you need NuGet client 3.6 or higher installed. You can download the NuGet client for Visual
Studio 2015 from the NuGet downloads page.

.NET 5+ and .NET Standard


.NET 5 and .NET 6 are single products with a uniform set of capabilities and APIs that can be used for Windows
desktop apps and cross-platform console apps, cloud services, and websites. The .NET 5 TFMs, for example,
reflect this broad range of scenarios:
net5.0

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.

.NET version lifecycles


.NET Core, .NET 5, and later versions adopt the modern lifecycle rather than the fixed lifecycle that has been used
for .NET Framework releases. Products with fixed lifecycles provide a long fixed period of support, for example, 5
years of mainstream support and another 5 years of extended support. Mainstream support includes security
and non-security fixes, while extended support provides security fixes only. Products that adopt a modern
lifecycle have a more service-like support model, with shorter support periods and more frequent releases.
Release tracks
There are two support tracks for releases:
Current releases
These versions are supported until six months after the next major or minor release ships. Previously
(.NET Core 3.0 and earlier), these releases were supported for only three months after the next major or
minor release shipped.
Example:
.NET Core 3.0 shipped in September 2019 and was followed by .NET Core 3.1 in December 2019.
.NET Core 3.0 support ended in March 2020, 3 months after 3.1 shipped.
Long Term Support (LTS) releases
These versions are supported for a minimum of 3 years, or 1 year after the next LTS release ships if that
date is later.
Example:
.NET Core 3.1 is an LTS release and was released in December 2019. It's supported for 3 years, until
December, 2022.
.NET 5 is a Current release and was released in November 2020. It's supported for 18 months, until
May, 2022.
.NET 6 is an LTS release and was released in November, 2021. It's supported for 3 years, until
November, 2024.
Releases alternate between LTS and Current, so it's possible for an earlier release to be supported longer than a
later release. For example, .NET Core 3.1 is an LTS release with support through December 2022. The .NET 5
release shipped almost a year later but goes out of support earlier, in May 2022.
Servicing updates ship monthly and include both security and non-security (reliability, compatibility, and
stability) fixes. Servicing updates are supported until the next servicing update is released. Servicing updates
have runtime roll forward behavior. That means that applications default to running on the latest installed
runtime servicing update.

How to choose a release


If you're building a service and expect to continue updating it on a regular basis, then a Current release like .NET
5 may be your best option to stay up to date with the latest features .NET has to offer.
If you're building a client application that will be distributed to consumers, stability may be more important than
access to the latest features. Your application might need to be supported for a certain period before the
consumer can upgrade to the next version of the application. In that case, an LTS release like .NET 6 might be the
right option.
Servicing updates
.NET servicing updates are supported until the next servicing update is released. The release cadence is monthly.
You need to regularly install servicing updates to ensure that your apps are in a secure and supported state. For
example, if the latest servicing update for .NET 5 is 5.0.8 and we ship 5.0.9, then 5.0.8 is no longer the latest. The
supported servicing level for .NET 5 is then 5.0.9.
For information about the latest servicing updates for each major and minor version, see the .NET downloads
page.

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.

Supported operating systems


.NET 5 (and .NET Core) and later versions can be run on a range of operating systems. Each of these operating
systems has a lifecycle defined by its sponsor organization (for example, Microsoft, Red Hat, or Apple). We take
these lifecycle schedules into account when adding and removing support for operating system versions.
When an operating system version goes out of support, we stop testing that version and providing support for
that version. Users need to move forward to a supported operating system version to get support.
For more information, see the .NET OS Lifecycle Policy.

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 5 and later versions


A cross-platform, high-performance, open-source implementation of .NET. Also referred to as .NET 5+. Includes
a Common Language Runtime (CLR), an AOT runtime (CoreRT, in development), a Base Class Library (BCL), and
the .NET SDK.
Earlier versions of this .NET implementation are known as .NET Core. .NET 5 is the next version following .NET
Core 3.1. Version 4 was skipped to avoid confusing this newer implementation of .NET with the older
implementation that is known as .NET Framework. The current version of .NET Framework is 4.8.
See .NET documentation.

.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:

// See https://aka.ms/new-console-template for more information


Console.WriteLine("Hello, World!");

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;

namespace MyApp // Note: actual namespace depends on the project name.


{
internal class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
}
}
}

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.

Use the new program style


The features that make the new program simpler are top-level statements, global using directives, and implicit
using directives.

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.

Implicit using directives


The term implicit using directives means the compiler automatically adds a set of using directives based on
the project type. For console applications, the following directives are implicitly included in the application:
using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;

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>

Global using directives


A global using directive imports a namespace for your whole application instead of a single file. These global
directives can be added either by adding a <Using> item to the project file, or by adding the global using
directive to a code file.
You can also add a <Using> item with a Remove attribute to your project file to remove a specific implicit using
directive. For example, if the implicit directives feature is turned on with
using
<ImplicitUsings>enable</ImplicitUsings> , adding the following <Using> item removes the System.Net.Http
namespace from those that are implicitly imported:

<ItemGroup>
<Using Remove="System.Net.Http" />
</ItemGroup>

Use the old program style


While a .NET 6 console app template generates the new style of top-level statements programs, using .NET 5
doesn't. By creating a .NET 5 project, you'll receive the old program style. Then, you can edit the project file to
target .NET 6 but retain the old program style for the Program.cs file.

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.

1. Create a new project that targets .NET 5.

dotnet new console --framework net5.0

2. Open the project file in a text editor and change <TargetFramework>net5.0</TargetFramework> to


<TargetFramework>net6.0</TargetFramework> .

Here's a file diff that illustrates the changes:

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

Use the old program style in Visual Studio


When you create a new console project in Visual Studio, you're prompted with a dropdown box that identifies
which target framework you want to use. Change that value to 5.0 . After the project is created, edit the project
file to change it back to 6.0 .
1. When you create a new project, the setup steps will navigate to the Additional information setup page.
On this page, change the framework setting from .NET 6.0 (Long-term suppor t) to .NET 5.0 , and
then select the Create button.

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

Here's a file diff that illustrates the changes:

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

Create the app


Create a .NET console app project named "HelloWorld".
1. Start Visual Studio 2022.
2. On the start page, choose Create a new project .

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!");
}
}
}

' This step of the tutorial applies only to C#.

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.

Run the app


1. Press Ctrl+F5 to run the program without debugging.
A console window opens with the text "Hello World!" printed on the screen.

2. Press any key to close the console window.

Enhance the app


Enhance the application to prompt the user for their name and display it along with the date and time.
1. In Program.cs or Program.vb, replace the contents of the Main method, which is the line that calls
Console.WriteLine , with the following code:

Console.WriteLine("What is your name?");


var name = Console.ReadLine();
var currentDate = DateTime.Now;
Console.WriteLine($"{Environment.NewLine}Hello, {name}, on {currentDate:d} at {currentDate:t}!");
Console.Write($"{Environment.NewLine}Press any key to exit...");
Console.ReadKey(true);

Console.WriteLine("What is your name?")


Dim name = Console.ReadLine()
Dim currentDate = DateTime.Now
Console.WriteLine($"{Environment.NewLine}Hello, {name}, on {currentDate:d} at {currentDate:t}")
Console.Write($"{Environment.NewLine}Press any key to exit...")
Console.ReadKey(True)

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

Create the app


Create a .NET console app project named "HelloWorld".
1. Start Visual Studio 2019.
2. On the start page, choose Create a new project .

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.

Run the app


1. Press Ctrl+F5 to run the program without debugging.
A console window opens with the text "Hello World!" printed on the screen.

2. Press any key to close the console window.

Enhance the app


Enhance the application to prompt the user for their name and display it along with the date and time.
1. In Program.cs or Program.vb, replace the contents of the Main method, which is the line that calls
Console.WriteLine , with the following code:

Console.WriteLine("What is your name?");


var name = Console.ReadLine();
var currentDate = DateTime.Now;
Console.WriteLine($"{Environment.NewLine}Hello, {name}, on {currentDate:d} at {currentDate:t}!");
Console.Write($"{Environment.NewLine}Press any key to exit...");
Console.ReadKey(true);

Console.WriteLine("What is your name?")


Dim name = Console.ReadLine()
Dim currentDate = DateTime.Now
Console.WriteLine($"{Environment.NewLine}Hello, {name}, on {currentDate:d} at {currentDate:t}")
Console.Write($"{Environment.NewLine}Press any key to exit...")
Console.ReadKey(True)

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

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.

Use Debug build configuration


Debug and Release are Visual Studio's built-in build configurations. You use the Debug build configuration for
debugging and the Release configuration for the final release distribution.
In the Debug configuration, a program compiles with full symbolic debug information and no optimization.
Optimization complicates debugging, because the relationship between source code and generated instructions
is more complex. The release configuration of a program has no symbolic debug information and is fully
optimized.
By default, Visual Studio uses the Debug build configuration, so you don't need to change it before debugging.
1. Start Visual Studio.
2. Open the project that you created in Create a .NET console application using Visual Studio.
The current build configuration is shown on the toolbar. The following toolbar image shows that Visual
Studio is configured to compile the Debug version of the app:

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.

5. Press any key to exit the application and stop debugging.

Set a conditional breakpoint


The program displays the string that the user enters. What happens if the user doesn't enter anything? You can
test this with a useful debugging feature called a conditional breakpoint.
1. Right-click on the red dot that represents the breakpoint. In the context menu, select Conditions to open
the Breakpoint Settings dialog. Select the box for Conditions if it's not already selected.
2. For the Conditional Expression , enter the following code in the field that shows example code that
tests if x is 5.

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)

The question mark directs the immediate window to evaluate an expression.

9. Press F5 to continue program execution.


10. Press any key to close the console window and stop debugging.
11. Clear the breakpoint by clicking on the dot in the left margin of the code window. Other ways to clear a
breakpoint are by pressing F9 or choosing Debug > Toggle Breakpoint while the line of code is
selected.

Step through a program


Visual Studio also allows you to step line by line through a program and monitor its execution. Ordinarily, you'd
set a breakpoint and follow program flow through a small part of your program code. Since this program is
small, you can step through the entire program.
1. Choose Debug > Step Into . Another way to debug one statement at a time is by pressing F11.
Visual Studio highlights and displays an arrow beside the next line of execution.
C#

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.

Use Release build configuration


Once you've tested the Debug version of your application, you should also compile and test the Release version.
The Release version incorporates compiler optimizations that can sometimes negatively affect the behavior of
an application. For example, compiler optimizations that are designed to improve performance can create race
conditions in multithreaded applications.
To build and test the Release version of your console application, change the build configuration on the toolbar
from Debug to Release .

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.

Use Debug build configuration


Debug and Release are Visual Studio's built-in build configurations. You use the Debug build configuration for
debugging and the Release configuration for the final release distribution.
In the Debug configuration, a program compiles with full symbolic debug information and no optimization.
Optimization complicates debugging, because the relationship between source code and generated instructions
is more complex. The release configuration of a program has no symbolic debug information and is fully
optimized.
By default, Visual Studio uses the Debug build configuration, so you don't need to change it before debugging.
1. Start Visual Studio.
2. Open the project that you created in Create a .NET console application using Visual Studio.
The current build configuration is shown on the toolbar. The following toolbar image shows that Visual
Studio is configured to compile the Debug version of the app:

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.

5. Press any key to exit the application and stop debugging.

Set a conditional breakpoint


The program displays the string that the user enters. What happens if the user doesn't enter anything? You can
test this with a useful debugging feature called a conditional breakpoint.
1. Right-click on the red dot that represents the breakpoint. In the context menu, select Conditions to open
the Breakpoint Settings dialog. Select the box for Conditions if it's not already selected.

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)

The question mark directs the immediate window to evaluate an expression.

9. Press F5 to continue program execution.


10. Press any key to close the console window and stop debugging.
11. Clear the breakpoint by clicking on the dot in the left margin of the code window. Other ways to clear a
breakpoint are by pressing F9 or choosing Debug > Toggle Breakpoint while the line of code is
selected.

Step through a program


Visual Studio also allows you to step line by line through a program and monitor its execution. Ordinarily, you'd
set a breakpoint and follow program flow through a small part of your program code. Since this program is
small, you can step through the entire program.
1. Choose Debug > Step Into . Another way to debug one statement at a time is by pressing F11.
Visual Studio highlights and displays an arrow beside the next line of execution.
C#
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.

Use Release build configuration


Once you've tested the Debug version of your application, you should also compile and test the Release version.
The Release version incorporates compiler optimizations that can sometimes negatively affect the behavior of
an application. For example, compiler optimizations that are designed to improve performance can create race
conditions in multithreaded applications.
To build and test the Release version of your console application, change the build configuration on the toolbar
from Debug to Release .

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.

Publish the app


1. Start Visual Studio.
2. Open the HelloWorld project that you created in Create a .NET console application using Visual Studio.
3. Make sure that Visual Studio is using the Release build configuration. If necessary, change the build
configuration setting on the toolbar from Debug to Release .

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 .


8. On the Publish tab of the Publish window, select Publish .

Inspect the files


By default, the publishing process creates a framework-dependent deployment, which is a type of deployment
where the published application runs on machine that has the .NET runtime installed. Users can run the
published app by double-clicking the executable or issuing the dotnet HelloWorld.dll command from a
command prompt.
In the following steps, you'll look at the files created by the publish process.
1. In Solution Explorer , select Show all files .
2. In the project folder, expand bin/Release/net6.0/publish.
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
This is the framework-dependent executable version of the application. To run it, enter
HelloWorld.exe at a command prompt. 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.

Run the published app


1. In Solution Explorer , right-click the publish folder, and select Copy Full Path .
2. Open a command prompt and navigate to the publish folder. To do that, enter cd and then paste the full
path. For example:

cd C:\Projects\HelloWorld\bin\Release\net6.0\publish\

3. Run the app by using the executable:


a. Enter HelloWorld.exe and press Enter.
b. Enter a name in response to the prompt, and press any key to exit.
4. Run the app by using the dotnet command:
a. Enter dotnet HelloWorld.dll and press Enter.
b. Enter a name in response to the prompt, and press any key to exit.

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.

Publish the app


1. Start Visual Studio.
2. Open the HelloWorld project that you created in Create a .NET console application using Visual Studio.
3. Make sure that Visual Studio is using the Release build configuration. If necessary, change the build
configuration setting on the toolbar from Debug to Release .

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 .

8. On the Publish tab of the Publish window, select Publish .


Inspect the files
By default, the publishing process creates a framework-dependent deployment, which is a type of deployment
where the published application runs on machine that has the .NET runtime installed. Users can run the
published app by double-clicking the executable or issuing the dotnet HelloWorld.dll command from a
command prompt.
In the following steps, you'll look at the files created by the publish process.
1. In Solution Explorer , select Show all files .
2. In the project folder, expand bin/Release/net5.0/publish.
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
This is the framework-dependent executable version of the application. To run it, enter
HelloWorld.exe at a command prompt. 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.

Run the published app


1. In Solution Explorer , right-click the publish folder, and select Copy Full Path .
2. Open a command prompt and navigate to the publish folder. To do that, enter cd and then paste the full
path. For example:

cd C:\Projects\HelloWorld\bin\Release\net5.0\publish\

3. Run the app by using the executable:


a. Enter HelloWorld.exe and press Enter.
b. Enter a name in response to the prompt, and press any key to exit.
4. Run the app by using the dotnet command:
a. Enter dotnet HelloWorld.dll and press Enter.
b. Enter a name in response to the prompt, and press any key to exit.

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 .

Create a class library project


1. Add a new .NET class library project named "StringLibrary" to the solution.
a. Right-click on the solution in Solution Explorer and select Add > New Project .
b. On the Add a new project page, enter librar y in the search box. Choose C# or Visual Basic
from the Language list, and then choose All platforms from the Platform list. Choose the Class
Librar y template, and then choose Next .
c. On the Configure your new project page, enter StringLibrar y in the Project name box, and
then choose Next .
d. On the Additional information page, select .NET 6 (Long-term suppor t) , and then choose
Create .
2. Check to make sure that the library targets the correct version of .NET. Right-click on the library project in
Solution Explorer , and then select Proper ties . The Target Framework text box shows that the project
targets .NET 6.0.
3. If you're using Visual Basic, clear the text in the Root namespace text box.
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 isn't shown, change the language selector at the top of the page.

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

Dim ch As Char = str(0)


Return Char.IsUpper(ch)
End Function
End Module
End Namespace

The class library, UtilityLibraries.StringLibrary , contains a method named StartsWithUpper . This


method returns a Boolean value that indicates whether the current string instance begins with an
uppercase character. The Unicode standard distinguishes uppercase characters from lowercase
characters. The Char.IsUpper(Char) method returns true if a character is uppercase.
StartsWithUpper is implemented as an extension method so that you can call it as if it were a member of
the String class. The question mark ( ? ) after string in the C# code indicates that the string may be null.
5. On the menu bar, select Build > Build Solution or press Ctrl+Shift+B to verify that the project
compiles without error.

Add a console app to the solution


Add a console application that uses the class library. The app will prompt the user to enter a string and report
whether the string begins with an uppercase character.
1. Add a new .NET console application named "ShowCase" to the solution.
a. Right-click on the solution in Solution Explorer and select Add > New project .
b. On the Add a new project page, enter console in the search box. Choose C# or Visual Basic
from the Language list, and then choose All platforms from the Platform list.
c. Choose the Console Application template, and then choose Next .
d. On the Configure your new project page, enter ShowCase in the Project name box. Then
choose Next .
e. On the Additional information page, select .NET 6 (Long-term suppor t) in the Framework
box. Then choose Create .
2. In the code window for the Program.cs or Program.vb file, 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();

string? input = Console.ReadLine();


if (string.IsNullOrEmpty(input)) break;
Console.WriteLine($"Input: {input}");
Console.WriteLine("Begins with uppercase? " +
$"{(input.StartsWithUpper() ? "Yes" : "No")}");
Console.WriteLine();
row += 4;
} while (true);
return;

// Declare a ResetConsole local method


void ResetConsole()
{
if (row > 0)
{
Console.WriteLine("Press any key to continue...");
Console.ReadKey();
}
Console.Clear();
Console.WriteLine($"{Environment.NewLine}Press <Enter> only to exit; otherwise, enter a
string and press <Enter>:{Environment.NewLine}");
row = 3;
}
}
}
Imports UtilityLibraries

Module Program
Dim row As Integer = 0

Sub Main()
Do
If row = 0 OrElse row >= 25 Then ResetConsole()

Dim input As String = Console.ReadLine()


If String.IsNullOrEmpty(input) Then Return

Console.WriteLine($"Input: {input} {"Begins with uppercase? ",30}: " +


$"{If(input.StartsWithUpper(), "Yes", "No")} {Environment.NewLine}")
row += 3
Loop While True
End Sub

Private Sub ResetConsole()


If row > 0 Then
Console.WriteLine("Press any key to continue...")
Console.ReadKey()
End If
Console.Clear()
Console.WriteLine($"{Environment.NewLine}Press <Enter> only to exit; otherwise, enter a
string and press <Enter>:{Environment.NewLine}")
row = 3
End Sub
End Module

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.

Add a project reference


Initially, the new console app project doesn't have access to the class library. To allow it to call methods in the
class library, create a project reference to the class library project.
1. In Solution Explorer , right-click the ShowCase project's Dependencies node, and select Add Project
Reference .
2. In the Reference Manager dialog, select the StringLibrar y project, and select OK .

Run the app


1. In Solution Explorer , right-click the ShowCase project and select Set as Star tUp Project in the
context menu.
2. Press Ctrl+F5 to compile and run the program without debugging.

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 .

Create a class library project


1. Add a new .NET class library project named "StringLibrary" to the solution.
a. Right-click on the solution in Solution Explorer and select Add > New Project .
b. On the Add a new project page, enter librar y in the search box. Choose C# or Visual Basic
from the Language list, and then choose All platforms from the Platform list. Choose the Class
Librar y template, and then choose Next .
c. On the Configure your new project page, enter StringLibrar y in the Project name box, and
then choose Next .
d. On the Additional information page, select .NET 5.0 (Current) , and then choose Create .
2. Check to make sure that the library targets the correct version of .NET. Right-click on the library project in
Solution Explorer , and then select Proper ties . The Target Framework text box shows that the project
targets .NET 5.0.
3. If you're using Visual Basic, clear the text in the Root namespace text box.

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

Dim ch As Char = str(0)


Return Char.IsUpper(ch)
End Function
End Module
End Namespace

The class library, UtilityLibraries.StringLibrary , contains a method named StartsWithUpper . This


method returns a Boolean value that indicates whether the current string instance begins with an
uppercase character. The Unicode standard distinguishes uppercase characters from lowercase
characters. The Char.IsUpper(Char) method returns true if a character is uppercase.
StartsWithUpper is implemented as an extension method so that you can call it as if it were a member of
the String class.
5. On the menu bar, select Build > Build Solution or press Ctrl+Shift+B to verify that the project
compiles without error.

Add a console app to the solution


Add a console application that uses the class library. The app will prompt the user to enter a string and report
whether the string begins with an uppercase character.
1. Add a new .NET console application named "ShowCase" to the solution.
a. Right-click on the solution in Solution Explorer and select Add > New project .
b. On the Add a new project page, enter console in the search box. Choose C# or Visual Basic
from the Language list, and then choose All platforms from the Platform list.
c. Choose the Console Application template, and then choose Next .
d. On the Configure your new project page, enter ShowCase in the Project name box. Then
choose Next .
e. On the Additional information page, select .NET 5.0 (Current) in the Target Framework box.
Then choose Create .
2. In the code window for the Program.cs or Program.vb file, 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();

string? input = Console.ReadLine();


if (string.IsNullOrEmpty(input)) break;
Console.WriteLine($"Input: {input} {"Begins with uppercase? ",30}: " +
$"{(input.StartsWithUpper() ? "Yes" : "No")}{Environment.NewLine}");
row += 3;
} while (true);
return;

// Declare a ResetConsole local method


void ResetConsole()
{
if (row > 0)
{
Console.WriteLine("Press any key to continue...");
Console.ReadKey();
}
Console.Clear();
Console.WriteLine($"{Environment.NewLine}Press <Enter> only to exit; otherwise, enter a
string and press <Enter>:{Environment.NewLine}");
row = 3;
}
}
}
Imports UtilityLibraries

Module Program
Dim row As Integer = 0

Sub Main()
Do
If row = 0 OrElse row >= 25 Then ResetConsole()

Dim input As String = Console.ReadLine()


If String.IsNullOrEmpty(input) Then Return

Console.WriteLine($"Input: {input} {"Begins with uppercase? ",30}: " +


$"{If(input.StartsWithUpper(), "Yes", "No")} {Environment.NewLine}")
row += 3
Loop While True
End Sub

Private Sub ResetConsole()


If row > 0 Then
Console.WriteLine("Press any key to continue...")
Console.ReadKey()
End If
Console.Clear()
Console.WriteLine($"{Environment.NewLine}Press <Enter> only to exit; otherwise, enter a
string and press <Enter>:{Environment.NewLine}")
row = 3
End Sub
End Module

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.

Add a project reference


Initially, the new console app project doesn't have access to the class library. To allow it to call methods in the
class library, create a project reference to the class library project.
1. In Solution Explorer , right-click the ShowCase project's Dependencies node, and select Add Project
Reference .
2. In the Reference Manager dialog, select the StringLibrar y project, and select OK .

Run the app


1. In Solution Explorer , right-click the ShowCase project and select Set as Star tUp Project in the
context menu.
2. Press Ctrl+F5 to compile and run the program without debugging.

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.

Create a unit test project


Unit tests provide automated software testing during your development and publishing. MSTest is one of three
test frameworks you can choose from. The others are xUnit and nUnit.
1. Start Visual Studio.
2. Open the ClassLibraryProjects solution you created in Create a .NET class library using Visual Studio.
3. Add a new unit test project named "StringLibraryTest" to the solution.
a. Right-click on the solution in Solution Explorer and select Add > New project .
b. On the Add a new project page, enter mstest in the search box. Choose C# or Visual Basic
from the Language list, and then choose All platforms from the Platform list.
c. Choose the MSTest Test Project template, and then choose Next .
d. On the Configure your new project page, enter StringLibrar yTest in the Project name box.
Then choose Next .
e. On the Additional information page, select .NET 6 (Long-term suppor t) in the Framework
box. Then choose Create .
4. Visual Studio creates the project and opens the class file in the code window with the following code. If
the language you want to use is not shown, change the language selector at the top of the page.

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.

Add a project reference


For the test project to work with the StringLibrary class, add a reference in the StringLibrar yTest project to
the StringLibrary project.
1. In Solution Explorer , right-click the Dependencies node of the StringLibrar yTest project and select
Add Project Reference from the context menu.
2. In the Reference Manager dialog, expand the Projects node, and select the box next to StringLibrar y .
Adding a reference to the StringLibrary assembly allows the compiler to find StringLibrar y methods
while compiling the StringLibrar yTest project.
3. Select OK .

Add and run unit test methods


When Visual Studio runs a unit test, it executes each method that is marked with the TestMethodAttribute
attribute in a class that is marked with the TestClassAttribute attribute. A test method ends when the first failure
is found or when all tests contained in the method have succeeded.
The most common tests call members of the Assert class. Many assert methods include at least two parameters,
one of which is the expected test result and the other of which is the actual test result. Some of the Assert
class's most frequently called methods are shown in the following table:

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.IsFalse Verifies that a condition is false . The assert fails if the


condition is true .
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 ), 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.

string[] words = { "alphabet", "Error", "zebra", "abc", "αυτοκινητοβιομηχανία", "государство",


"1234", ".", ";", " " };

Dim words() As String = { "alphabet", "Error", "zebra", "abc", "αυτοκινητοβιομηχανία", "государство",


"1234", ".", ";", " " }

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.

3. Select the failed test, TestDoesNotStartWith .


The Test Explorer window 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.

Test the Release version of the library


Now that the tests have all passed when running the Debug build of the library, run the tests an additional time
against the Release build of the library. A number of factors, including compiler optimizations, can sometimes
produce different behavior between Debug and Release builds.
To test the Release build:
1. In the Visual Studio toolbar, change the build configuration from Debug to Release .

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.

Create a unit test project


Unit tests provide automated software testing during your development and publishing. MSTest is one of three
test frameworks you can choose from. The others are xUnit and nUnit.
1. Start Visual Studio.
2. Open the ClassLibraryProjects solution you created in Create a .NET class library using Visual Studio.
3. Add a new unit test project named "StringLibraryTest" to the solution.
a. Right-click on the solution in Solution Explorer and select Add > New project .
b. On the Add a new project page, enter mstest in the search box. Choose C# or Visual Basic
from the Language list, and then choose All platforms from the Platform list.
c. Choose the MSTest Test Project template, and then choose Next .
d. On the Configure your new project page, enter StringLibrar yTest in the Project name box.
Then choose Next .
e. On the Additional information page, select .NET 5.0 (Current) in the Target Framework box.
Then choose Create .
4. Visual Studio creates the project and opens the class file in the code window with the following code. If
the language you want to use is not shown, change the language selector at the top of the page.

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.

Add a project reference


For the test project to work with the StringLibrary class, add a reference in the StringLibrar yTest project to
the StringLibrary project.
1. In Solution Explorer , right-click the Dependencies node of the StringLibrar yTest project and select
Add Project Reference from the context menu.
2. In the Reference Manager dialog, expand the Projects node, and select the box next to StringLibrar y .
Adding a reference to the StringLibrary assembly allows the compiler to find StringLibrar y methods
while compiling the StringLibrar yTest project.
3. Select OK .

Add and run unit test methods


When Visual Studio runs a unit test, it executes each method that is marked with the TestMethodAttribute
attribute in a class that is marked with the TestClassAttribute attribute. A test method ends when the first failure
is found or when all tests contained in the method have succeeded.
The most common tests call members of the Assert class. Many assert methods include at least two parameters,
one of which is the expected test result and the other of which is the actual test result. Some of the Assert
class's most frequently called methods are shown in the following table:

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.IsFalse Verifies that a condition is false . The assert fails if the


condition is true .
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 ), 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.

string[] words = { "alphabet", "Error", "zebra", "abc", "αυτοκινητοβιομηχανία", "государство",


"1234", ".", ";", " " };

Dim words() As String = { "alphabet", "Error", "zebra", "abc", "αυτοκινητοβιομηχανία", "государство",


"1234", ".", ";", " " }

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.

3. Select the failed test, TestDoesNotStartWith .


The Test Explorer window 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.

Test the Release version of the library


Now that the tests have all passed when running the Debug build of the library, run the tests an additional time
against the Release build of the library. A number of factors, including compiler optimizations, can sometimes
produce different behavior between Debug and Release builds.
To test the Release build:
1. In the Visual Studio toolbar, change the build configuration from Debug to Release .

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.

Create the app


Create a .NET console app project named "HelloWorld".
1. Start Visual Studio Code.
2. Select File > Open Folder (File > Open... on macOS) from the main menu.
3. In the Open Folder dialog, create a HelloWorld folder and select it. Then click Select Folder (Open on
macOS).
The folder name becomes the project name and the namespace name by default. You'll add code later in
the tutorial that assumes the project namespace is HelloWorld .
4. In the Do you trust the authors of the files in this folder? dialog, select Yes, I trust the authors .
5. Open the Terminal in Visual Studio Code by selecting View > Terminal from the main menu.
The Terminal opens with the command prompt in the HelloWorld folder.
6. In the Terminal , enter the following command:

dotnet new console --framework net6.0

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!");

7. Replace the contents of Program.cs with the following code:


namespace HelloWorld
{
class Program
{
static void Main(string[] args)
{
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.

Run the app


Run the following command in the Terminal :

dotnet run

The program displays "Hello World!" and ends.


Enhance the app
Enhance the application to prompt the user for their name and display it along with the date and time.
1. Open Program.cs.
2. Replace the contents of the Main method in Program.cs, which is the line that calls Console.WriteLine ,
with the following code:

Console.WriteLine("What is your name?");


var name = Console.ReadLine();
var currentDate = DateTime.Now;
Console.WriteLine($"{Environment.NewLine}Hello, {name}, on {currentDate:d} at {currentDate:t}!");
Console.Write($"{Environment.NewLine}Press any key to exit...");
Console.ReadKey(true);

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.

4. Run the program again:

dotnet run

5. Respond to the prompt by entering a name and pressing the Enter key.

6. 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 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.

Create the app


Create a .NET console app project named "HelloWorld".
1. Start Visual Studio Code.
2. Select File > Open Folder (File > Open... on macOS) from the main menu.
3. In the Open Folder dialog, create a HelloWorld folder and click Select Folder (Open on macOS).
The folder name becomes the project name and the namespace name by default. You'll add code later in
the tutorial that assumes the project namespace is HelloWorld .
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 HelloWorld folder.
5. In the Terminal , enter the following command:

dotnet new console --framework net5.0

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.

Run the app


Run the following command in the Terminal :

dotnet run

The program displays "Hello World!" and ends.


Enhance the app
Enhance the application to prompt the user for their name and display it along with the date and time.
1. Open Program.cs by clicking on it.
The first time you open a C# file in Visual Studio Code, OmniSharp loads in the editor.

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:

Console.WriteLine("What is your name?");


var name = Console.ReadLine();
var currentDate = DateTime.Now;
Console.WriteLine($"{Environment.NewLine}Hello, {name}, on {currentDate:d} at {currentDate:t}!");
Console.Write($"{Environment.NewLine}Press any key to exit...");
Console.ReadKey(true);

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.

5. Run the program again:

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.

Use Debug build configuration


Debug and Release are .NET's built-in build configurations. You use the Debug build configuration for debugging
and the Release configuration for the final release distribution.
In the Debug configuration, a program compiles with full symbolic debug information and no optimization.
Optimization complicates debugging, because the relationship between source code and generated instructions
is more complex. The release configuration of a program has no symbolic debug information and is fully
optimized.
By default, Visual Studio Code launch settings use the Debug build configuration, so you don't need to change it
before debugging.
1. Start Visual Studio Code.
2. Open the folder of the project that you created 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",

3. Save your changes.

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.

Use the Debug Console


The Debug Console window lets you interact with the application you're debugging. You can change the value
of variables to see how it affects your program.
1. Select the Debug Console tab.
2. Enter name = "Gracie" at the prompt at the bottom of the Debug Console window and press the Enter
key.

3. Enter currentDate = DateTime.Parse("2019-11-16T17:25:00Z").ToUniversalTime() at the bottom of the


Debug Console window and press the Enter key.
The Variables window displays the new values of the name and currentDate variables.
4. Continue program execution by selecting the Continue button in the toolbar. Another way to continue is
by pressing F5.

5. Select the Terminal tab again.


The values displayed in the console window correspond to the changes you made in the Debug
Console .

6. Press any key to exit the application and stop debugging.

Set a conditional breakpoint


The program displays the string that the user enters. What happens if the user doesn't enter anything? You can
test this with a useful debugging feature called a conditional breakpoint.
1. Right-click (Ctrl-click on macOS) on the red dot that represents the breakpoint. In the context menu,
select Edit Breakpoint to open a dialog that lets you enter a conditional expression.

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. Select the Continue button on the toolbar to continue program execution.


7. Select the Terminal tab, and press any key to exit the program and stop debugging.
8. Clear the breakpoint by clicking on the dot in the left margin of the code window. Other ways to clear a
breakpoint are by pressing F9 or choosing Run > Toggle Breakpoint from the menu while the line of
code is selected.
9. If you get a warning that the breakpoint condition will be lost, select Remove Breakpoint .

Step through a program


Visual Studio Code also allows you to step line by line through a program and monitor its execution. Ordinarily,
you'd set a breakpoint and follow program flow through a small part of your program code. Since this program
is small, you can step through the entire program.
1. Set a breakpoint on the opening curly brace of the Main method.
2. Press F5 to start debugging.
Visual Studio Code highlights the breakpoint line.
At this point, the Variables window shows that the args array is empty, and name and currentDate
have default values.
3. Select Run > Step Into or press F11.

Visual Studio Code highlights the next line.


4. Select Run > Step Into or press F11.
Visual Studio Code runs the Console.WriteLine for the name prompt and highlights the next line of
execution. The next line is the Console.ReadLine for the name . The Variables window is unchanged, and
the Terminal tab shows the "What is your name?" prompt.
5. Select Run > Step Into or press F11.
Visual Studio highlights the name variable assignment. The Variables window shows that name is still
null .

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.

11. Select the Terminal tab.


The terminal displays "Press any key to exit..."
12. Press any key to exit the program.

Use Release build configuration


Once you've tested the Debug version of your application, you should also compile and test the Release version.
The Release version incorporates compiler optimizations that can affect the behavior of an application. For
example, compiler optimizations that are designed to improve performance can create race conditions in
multithreaded applications.
To build and test the Release version of your console application, open the Terminal and run the following
command:

dotnet run --configuration Release

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.

Use Debug build configuration


Debug and Release are .NET Core's built-in build configurations. You use the Debug build configuration for
debugging and the Release configuration for the final release distribution.
In the Debug configuration, a program compiles with full symbolic debug information and no optimization.
Optimization complicates debugging, because the relationship between source code and generated instructions
is more complex. The release configuration of a program has no symbolic debug information and is fully
optimized.
By default, Visual Studio Code launch settings use the Debug build configuration, so you don't need to change it
before debugging.
1. Start Visual Studio Code.
2. Open the folder of the project that you created 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",

3. Save your changes.

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.

Use the Debug Console


The Debug Console window lets you interact with the application you're debugging. You can change the value
of variables to see how it affects your program.
1. Select the Debug Console tab.
2. Enter name = "Gracie" at the prompt at the bottom of the Debug Console window and press the Enter
key.

3. Enter currentDate = DateTime.Parse("2019-11-16T17:25:00Z").ToUniversalTime() at the bottom of the


Debug Console window and press the Enter key.
The Variables window displays the new values of the name and currentDate variables.
4. Continue program execution by selecting the Continue button in the toolbar. Another way to continue is
by pressing F5.

5. Select the Terminal tab again.


The values displayed in the console window correspond to the changes you made in the Debug
Console .

6. Press any key to exit the application and stop debugging.

Set a conditional breakpoint


The program displays the string that the user enters. What happens if the user doesn't enter anything? You can
test this with a useful debugging feature called a conditional breakpoint.
1. Right-click (Ctrl-click on macOS) on the red dot that represents the breakpoint. In the context menu,
select Edit Breakpoint to open a dialog that lets you enter a conditional expression.

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. Select the Continue button on the toolbar to continue program execution.


7. Select the Terminal tab, and press any key to exit the program and stop debugging.
8. Clear the breakpoint by clicking on the dot in the left margin of the code window. Other ways to clear a
breakpoint are by pressing F9 or choosing Run > Toggle Breakpoint from the menu while the line of
code is selected.
9. If you get a warning that the breakpoint condition will be lost, select Remove Breakpoint .

Step through a program


Visual Studio Code also allows you to step line by line through a program and monitor its execution. Ordinarily,
you'd set a breakpoint and follow program flow through a small part of your program code. Since this program
is small, you can step through the entire program.
1. Set a breakpoint on the opening curly brace of the Main method.
2. Press F5 to start debugging.
Visual Studio Code highlights the breakpoint line.
At this point, the Variables window shows that the args array is empty, and name and currentDate
have default values.
3. Select Run > Step Into or press F11.

Visual Studio Code highlights the next line.


4. Select Run > Step Into or press F11.
Visual Studio Code executes the Console.WriteLine for the name prompt and highlights the next line of
execution. The next line is the Console.ReadLine for the name . The Variables window is unchanged, and
the Terminal tab shows the "What is your name?" prompt.
5. Select Run > Step Into or press F11.
Visual Studio highlights the name variable assignment. The Variables window shows that name is still
null .

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.

11. Select the Terminal tab.


The terminal displays "Press any key to exit..."
12. Press any key to exit the program.

Use Release build configuration


Once you've tested the Debug version of your application, you should also compile and test the Release version.
The Release version incorporates compiler optimizations that can affect the behavior of an application. For
example, compiler optimizations that are designed to improve performance can create race conditions in
multithreaded applications.
To build and test the Release version of your console application, open the Terminal and run the following
command:

dotnet run --configuration Release

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.

Publish the app


1. Start Visual Studio Code.
2. Open the HelloWorld project folder that you created in Create a .NET console application using Visual
Studio Code.
3. Choose View > Terminal from the main menu.
The terminal opens in the HelloWorld folder.
4. Run the following command:

dotnet publish --configuration Release

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:

Microsoft (R) Build Engine version 16.7.0+b89cb5fde for .NET


Copyright (C) Microsoft Corporation. All rights reserved.
Determining projects to restore...
All projects are up-to-date for restore.
HelloWorld -> C:\Projects\HelloWorld\bin\Release\net6.0\HelloWorld.dll
HelloWorld -> C:\Projects\HelloWorld\bin\Release\net6.0\publish\

Inspect the files


By default, the publishing process creates a framework-dependent deployment, which is a type of deployment
where the published application runs on a machine that has the .NET runtime installed. To run the published app
you can use the executable file or run the dotnet HelloWorld.dll command from a command prompt.
In the following steps, you'll look at the files created by the publish process.
1. Select the Explorer in the left navigation bar.
2. Expand bin/Release/net6.0/publish.

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.

Run the published app


1. In Explorer , right-click the publish folder (Ctrl-click on macOS), and select Open in Terminal .

2. On Windows or Linux, run the app by using the executable.


a. On Windows, enter .\HelloWorld.exe and press Enter.
b. On Linux, enter ./HelloWorld and press Enter.
c. Enter a name in response to the prompt, and press any key to exit.
3. On any platform, run the app by using the dotnet command:
a. Enter dotnet HelloWorld.dll and press Enter.
b. Enter a name in response to the prompt, and press any key to exit.

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.

Publish the app


1. Start Visual Studio Code.
2. Open the HelloWorld project folder that you created in Create a .NET console application using Visual
Studio Code.
3. Choose View > Terminal from the main menu.
The terminal opens in the HelloWorld folder.
4. Run the following command:

dotnet publish --configuration Release

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:

Microsoft (R) Build Engine version 16.7.0+b89cb5fde for .NET


Copyright (C) Microsoft Corporation. All rights reserved.
Determining projects to restore...
All projects are up-to-date for restore.
HelloWorld -> C:\Projects\HelloWorld\bin\Release\net5.0\HelloWorld.dll
HelloWorld -> C:\Projects\HelloWorld\bin\Release\net5.0\publish\

Inspect the files


By default, the publishing process creates a framework-dependent deployment, which is a type of deployment
where the published application runs on a machine that has the .NET runtime installed. To run the published app
you can use the executable file or run the dotnet HelloWorld.dll command from a command prompt.
In the following steps, you'll look at the files created by the publish process.
1. Select the Explorer in the left navigation bar.
2. Expand bin/Release/net5.0/publish.

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.

Run the published app


1. In Explorer , right-click the publish folder (Ctrl-click on macOS), and select Open in Integrated
Terminal .

2. On Windows or Linux, run the app by using the executable.


a. On Windows, enter .\HelloWorld.exe and press Enter.
b. On Linux, enter ./HelloWorld and press Enter.
c. Enter a name in response to the prompt, and press any key to exit.
3. On any platform, run the app by using the dotnet command:
a. Enter dotnet HelloWorld.dll and press Enter.
b. Enter a name in response to the prompt, and press any key to exit.

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:

dotnet new sln

The terminal output looks like the following example:

The template "Solution File" was created successfully.

Create a class library project


Add a new .NET class library project named "StringLibrary" to the solution.
1. In the terminal, run the following command to create the library project:
dotnet new classlib -o StringLibrary

The -o or --output command specifies the location to place the generated output.
The terminal output looks like the following example:

The template "Class library" was created successfully.


Processing post-creation actions...
Running 'dotnet restore' on StringLibrary\StringLibrary.csproj...
Determining projects to restore...
Restored C:\Projects\ClassLibraryProjects\StringLibrary\StringLibrary.csproj (in 328 ms).
Restore succeeded.

2. Run the following command to add the library project to the solution:

dotnet sln add StringLibrary/StringLibrary.csproj

The terminal output looks like the following example:

Project `StringLibrary\StringLibrary.csproj` added 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;

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);
}
}

The class library, UtilityLibraries.StringLibrary , contains a method named StartsWithUpper . This


method returns a Boolean value that indicates whether the current string instance begins with an
uppercase character. The Unicode standard distinguishes uppercase characters from lowercase
characters. The Char.IsUpper(Char) method returns true if a character is uppercase.
StartsWithUpper is implemented as an extension method so that you can call it as if it were a member of
the String class.
5. Save the file.
6. Run the following command to build the solution and verify that the project compiles without error.

dotnet build

The terminal output looks like the following example:

Microsoft (R) Build Engine version 16.7.0+b89cb5fde for .NET


Copyright (C) Microsoft Corporation. All rights reserved.
Determining projects to restore...
All projects are up-to-date for restore.
StringLibrary -> C:\Projects\ClassLibraryProjects\StringLibrary\bin\Debug\net6.0\StringLibrary.dll
Build succeeded.
0 Warning(s)
0 Error(s)
Time Elapsed 00:00:02.78

Add a console app to the solution


Add a console application that uses the class library. The app will prompt the user to enter a string and report
whether the string begins with an uppercase character.
1. In the terminal, run the following command to create the console app project:

dotnet new console -o ShowCase

The terminal output looks like the following example:

The template "Console Application" was created successfully.


Processing post-creation actions...
Running 'dotnet restore' on ShowCase\ShowCase.csproj...
Determining projects to restore...
Restored C:\Projects\ClassLibraryProjects\ShowCase\ShowCase.csproj (in 210 ms).
Restore succeeded.

2. Run the following command to add the console app project to the solution:

dotnet sln add ShowCase/ShowCase.csproj

The terminal output looks like the following example:

Project `ShowCase\ShowCase.csproj` added 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();

string? input = Console.ReadLine();


if (string.IsNullOrEmpty(input)) break;
Console.WriteLine($"Input: {input}");
Console.WriteLine("Begins with uppercase? " +
$"{(input.StartsWithUpper() ? "Yes" : "No")}");
Console.WriteLine();
row += 4;
} while (true);
return;

// Declare a ResetConsole local method


void ResetConsole()
{
if (row > 0)
{
Console.WriteLine("Press any key to continue...");
Console.ReadKey();
}
Console.Clear();
Console.WriteLine($"{Environment.NewLine}Press <Enter> only to exit; otherwise, enter a
string and press <Enter>:{Environment.NewLine}");
row = 3;
}
}
}

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.

Add a project reference


Initially, the new console app project doesn't have access to the class library. To allow it to call methods in the
class library, create a project reference to the class library project.
1. Run the following command:

dotnet add ShowCase/ShowCase.csproj reference StringLibrary/StringLibrary.csproj

The terminal output looks like the following example:


Reference `..\StringLibrary\StringLibrary.csproj` added to the project.

Run the app


1. Run the following command in the terminal:

dotnet run --project ShowCase/ShowCase.csproj

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>:

A string that starts with an uppercase letter


Input: A string that starts with an uppercase letter
Begins with uppercase? : Yes

a string that starts with a lowercase letter


Input: a string that starts with a lowercase letter
Begins with uppercase? : No

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:

dotnet new sln

The terminal output looks like the following example:

The template "Solution File" was created successfully.

Create a class library project


Add a new .NET class library project named "StringLibrary" to the solution.
1. In the terminal, run the following command to create the library project:

dotnet new classlib -o StringLibrary

The -o or --output command specifies the location to place the generated output.
The terminal output looks like the following example:

The template "Class library" was created successfully.


Processing post-creation actions...
Running 'dotnet restore' on StringLibrary\StringLibrary.csproj...
Determining projects to restore...
Restored C:\Projects\ClassLibraryProjects\StringLibrary\StringLibrary.csproj (in 328 ms).
Restore succeeded.

2. Run the following command to add the library project to the solution:

dotnet sln add StringLibrary/StringLibrary.csproj

The terminal output looks like the following example:

Project `StringLibrary\StringLibrary.csproj` added 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);
}
}
}

The class library, UtilityLibraries.StringLibrary , contains a method named StartsWithUpper . This


method returns a Boolean value that indicates whether the current string instance begins with an
uppercase character. The Unicode standard distinguishes uppercase characters from lowercase
characters. The Char.IsUpper(Char) method returns true if a character is uppercase.
StartsWithUpper is implemented as an extension method so that you can call it as if it were a member of
the String class. The question mark ( ? ) after string indicates that the string may be null.
5. Save the file.
6. Run the following command to build the solution and verify that the project compiles without error.

dotnet build

The terminal output looks like the following example:

Microsoft (R) Build Engine version 16.7.0+b89cb5fde for .NET


Copyright (C) Microsoft Corporation. All rights reserved.
Determining projects to restore...
All projects are up-to-date for restore.
StringLibrary -> C:\Projects\ClassLibraryProjects\StringLibrary\bin\Debug\net5.0\StringLibrary.dll
Build succeeded.
0 Warning(s)
0 Error(s)
Time Elapsed 00:00:02.78

Add a console app to the solution


Add a console application that uses the class library. The app will prompt the user to enter a string and report
whether the string begins with an uppercase character.
1. In the terminal, run the following command to create the console app project:

dotnet new console -o ShowCase

The terminal output looks like the following example:

The template "Console Application" was created successfully.


Processing post-creation actions...
Running 'dotnet restore' on ShowCase\ShowCase.csproj...
Determining projects to restore...
Restored C:\Projects\ClassLibraryProjects\ShowCase\ShowCase.csproj (in 210 ms).
Restore succeeded.

2. Run the following command to add the console app project to the solution:

dotnet sln add ShowCase/ShowCase.csproj

The terminal output looks like the following example:

Project `ShowCase\ShowCase.csproj` added 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();

string? input = Console.ReadLine();


if (string.IsNullOrEmpty(input)) break;
Console.WriteLine($"Input: {input} {"Begins with uppercase? ",30}: " +
$"{(input.StartsWithUpper() ? "Yes" : "No")}{Environment.NewLine}");
row += 3;
} while (true);
return;

// Declare a ResetConsole local method


void ResetConsole()
{
if (row > 0)
{
Console.WriteLine("Press any key to continue...");
Console.ReadKey();
}
Console.Clear();
Console.WriteLine($"{Environment.NewLine}Press <Enter> only to exit; otherwise, enter a
string and press <Enter>:{Environment.NewLine}");
row = 3;
}
}
}

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.

Add a project reference


Initially, the new console app project doesn't have access to the class library. To allow it to call methods in the
class library, create a project reference to the class library project.
1. Run the following command:

dotnet add ShowCase/ShowCase.csproj reference StringLibrary/StringLibrary.csproj

The terminal output looks like the following example:

Reference `..\StringLibrary\StringLibrary.csproj` added to the project.


Run the app
1. Run the following command in the terminal:

dotnet run --project ShowCase/ShowCase.csproj

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>:

A string that starts with an uppercase letter


Input: A string that starts with an uppercase letter
Begins with uppercase? : Yes

a string that starts with a lowercase letter


Input: a string that starts with a lowercase letter
Begins with uppercase? : No

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.

Create a unit test project


Unit tests provide automated software testing during your development and publishing. The testing framework
that you use in this tutorial is MSTest. MSTest is one of three test frameworks you can choose from. The others
are xUnit and nUnit.
1. Start Visual Studio Code.
2. Open the ClassLibraryProjects solution you created in Create a .NET class library using Visual Studio
Code.
3. Create a unit test project named "StringLibraryTest".

dotnet new mstest -o StringLibraryTest

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

Add a project reference


For the test project to work with the StringLibrary class, add a reference in the StringLibraryTest project to
the StringLibrary project.
1. Run the following command:

dotnet add StringLibraryTest/StringLibraryTest.csproj reference StringLibrary/StringLibrary.csproj

Add and run unit test methods


When Visual Studio invokes a unit test, it runs each method that is marked with the TestMethodAttribute
attribute in a class that is marked with the TestClassAttribute attribute. A test method ends when the first failure
is found or when all tests contained in the method have succeeded.
The most common tests call members of the Assert class. Many assert methods include at least two parameters,
one of which is the expected test result and the other of which is the actual test result. Some of the Assert
class's most frequently called methods are shown in the following table:

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.IsFalse Verifies that a condition is false . The assert fails if the


condition is true .

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 all tests passed.

Starting test execution, please wait...


A total of 1 test files matched the specified pattern.

Passed! - Failed: 0, Passed: 3, Skipped: 0, Total: 3, Duration: 3 ms -


StringLibraryTest.dll (net6.0)

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

string[] words = { "alphabet", "Error", "zebra", "abc", "αυτοκινητοβιομηχανία", "государство",


"1234", ".", ";", " " };

2. 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.

Starting test execution, please wait...


A total of 1 test files matched the specified pattern.
Failed TestDoesNotStartWithUpper [28 ms]
Error Message:
Assert.IsFalse failed. Expected for 'Error': false; Actual: True
Stack Trace:
at StringLibraryTest.UnitTest1.TestDoesNotStartWithUpper() in
C:\ClassLibraryProjects\StringLibraryTest\UnitTest1.cs:line 33

Failed! - Failed: 1, Passed: 2, Skipped: 0, Total: 3, Duration: 31 ms -


StringLibraryTest.dll (net5.0)

3. Remove the string "Error" that you added in step 1. Rerun the test and the tests pass.

Test the Release version of the library


Now that the tests have all passed when running the Debug build of the library, run the tests an additional time
against the Release build of the library. A number of factors, including compiler optimizations, can sometimes
produce different behavior between Debug and Release builds.
1. Run the tests with the Release build configuration:

dotnet test StringLibraryTest/StringLibraryTest.csproj --configuration Release


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.

Create a unit test project


Unit tests provide automated software testing during your development and publishing. The testing framework
that you use in this tutorial is MSTest. MSTest is one of three test frameworks you can choose from. The others
are xUnit and nUnit.
1. Start Visual Studio Code.
2. Open the ClassLibraryProjects solution you created in Create a .NET class library using Visual Studio
Code.
3. Create a unit test project named "StringLibraryTest".

dotnet new mstest -o StringLibraryTest

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.

dotnet sln add StringLibraryTest/StringLibraryTest.csproj

Add a project reference


For the test project to work with the StringLibrary class, add a reference in the StringLibraryTest project to
the StringLibrary project.
1. Run the following command:

dotnet add StringLibraryTest/StringLibraryTest.csproj reference StringLibrary/StringLibrary.csproj

Add and run unit test methods


When Visual Studio runs a unit test, it executes each method that is marked with the TestMethodAttribute
attribute in a class that is marked with the TestClassAttribute attribute. A test method ends when the first failure
is found or when all tests contained in the method have succeeded.
The most common tests call members of the Assert class. Many assert methods include at least two parameters,
one of which is the expected test result and the other of which is the actual test result. Some of the Assert
class's most frequently called methods are shown in the following table:

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.IsFalse Verifies that a condition is false . The assert fails if the


condition is true .

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:

dotnet test StringLibraryTest/StringLibraryTest.csproj


The terminal output shows that all tests passed.

Starting test execution, please wait...


A total of 1 test files matched the specified pattern.

Passed! - Failed: 0, Passed: 3, Skipped: 0, Total: 3, Duration: 3 ms -


StringLibraryTest.dll (net5.0)

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

string[] words = { "alphabet", "Error", "zebra", "abc", "αυτοκινητοβιομηχανία", "государство",


"1234", ".", ";", " " };

2. 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.

Starting test execution, please wait...


A total of 1 test files matched the specified pattern.
Failed TestDoesNotStartWithUpper [28 ms]
Error Message:
Assert.IsFalse failed. Expected for 'Error': false; Actual: True
Stack Trace:
at StringLibraryTest.UnitTest1.TestDoesNotStartWithUpper() in
C:\ClassLibraryProjects\StringLibraryTest\UnitTest1.cs:line 33

Failed! - Failed: 1, Passed: 2, Skipped: 0, Total: 3, Duration: 31 ms -


StringLibraryTest.dll (net5.0)

3. Remove the string "Error" that you added in step 1. Rerun the test and the tests pass.

Test the Release version of the library


Now that the tests have all passed when running the Debug build of the library, run the tests an additional time
against the Release build of the library. A number of factors, including compiler optimizations, can sometimes
produce different behavior between Debug and Release builds.
1. Run the tests with the Release build configuration:

dotnet test StringLibraryTest/StringLibraryTest.csproj --configuration Release

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

Create the app


1. Start Visual Studio for Mac.
2. Select New in the start window.

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.

Run the app


1. Press ⌘↵ (option+command+enter) to run the app without debugging.
2. Close the Terminal window.

Enhance the app


Enhance the application to prompt the user for their name and display it along with the date and time.
1. In Program.cs, replace the contents of the Main method, which is the line that calls Console.WriteLine ,
with the following code:

Console.WriteLine("What is your name?");


var name = Console.ReadLine();
var currentDate = DateTime.Now;
Console.WriteLine($"{Environment.NewLine}Hello, {name}, on {currentDate:d} at {currentDate:t}!");
Console.Write($"{Environment.NewLine}Press any key to exit...");
Console.ReadKey(true);

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.

3. Respond to the prompt by entering a name and pressing enter.

4. Close the terminal.

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.

Use Debug build configuration


Debug and Release are Visual Studio's built-in build configurations. You use the Debug build configuration for
debugging and the Release configuration for the final release distribution.
In the Debug configuration, a program compiles with full symbolic debug information and no optimization.
Optimization complicates debugging, because the relationship between source code and generated instructions
is more complex. The release configuration of a program has no symbolic debug information and is fully
optimized.
By default, Visual Studio for Mac uses the Debug build configuration, so you don't need to change it before
debugging.
1. Start Visual Studio for Mac.
2. Open the project that you created in Create a .NET console application using Visual Studio for Mac.
The current build configuration is shown on the toolbar. The following toolbar image shows that Visual
Studio is configured to compile the Debug version of the app:

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.

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 View > Debug Pads > Immediate .
2. Enter name = "Gracie" in the Immediate window and press enter.
3. Enter currentDate = currentDate.AddDays(1) in the Immediate window and press enter.
The Immediate window displays the new value of the string variable and the properties of the DateTime
value.
The Locals window displays the values of variables that are defined in the currently executing method.
The values of the variables that you just changed are updated in the Locals window.

4. Press ⌘↵ (command+enter) to continue debugging.


The values displayed in the terminal correspond to the changes you made in the Immediate window.
If you don't see the Terminal, select Terminal - HelloWorld in the bottom navigation bar.

5. Press any key to exit the program.


6. Close the terminal window.

Set a conditional breakpoint


The program displays a string that the user enters. What happens if the user doesn't enter anything? You can
test this with a useful debugging feature called a conditional breakpoint.
1. ctrl-click on the red dot that represents the breakpoint. In the context menu, select Edit Breakpoint .
2. In the Edit Breakpoint dialog, enter the following code in the field that follows And the following
condition is true , and select Apply .

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.

Step through a program


Visual Studio also allows you to step line by line through a program and monitor its execution. Ordinarily, you'd
set a breakpoint and follow program flow through a small part of your program code. Since this program is
small, you can step through the entire program.
1. Set a breakpoint on the curly brace that marks the start of the Main method (press command+\).
2. Press ⌘↵ (command+enter) to start debugging.
Visual Studio stops on the line with the breakpoint.
3. Press ⇧⌘I (shift+command+I) or select Run > Step Into to advance one line.
Visual Studio highlights and displays an arrow beside the next line of execution.
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 terminal.
4. Press ⇧⌘I (shift+command+I).
Visual Studio highlights the statement that includes the name variable assignment. The Locals window
shows that name is null , and the terminal displays the string "What is your name?".
5. Respond to the prompt by entering a string in the console window and pressing enter.
6. Press ⇧⌘I (shift+command+I).
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 terminal displays the
string you entered at the prompt.
7. Press ⇧⌘I (shift+command+I).
The Locals window shows the value of the currentDate variable after the assignment from the
DateTime.Now property. The terminal is unchanged.
8. Press ⇧⌘I (shift+command+I).
Visual Studio calls the Console.WriteLine(String, Object, Object) method. The terminal displays the
formatted string.
9. Press ⇧⌘U (shift+command+U) or select Run > Step Out .
The terminal displays a message and waits for you to press a key.
10. Press any key to exit the program.

Use Release build configuration


Once you've tested the Debug version of your application, you should also compile and test the Release version.
The Release version incorporates compiler optimizations that can negatively affect the behavior of an
application. For example, compiler optimizations that are designed to improve performance can create race
conditions in multithreaded applications.
To build and test the Release version of the console application, do the following steps:
1. Change the build configuration on the toolbar from Debug to Release .
2. Press ⌘↵ (option+command+enter) to run without debugging.

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.

Publish the app


1. Start Visual Studio for Mac.
2. Open the HelloWorld project that you created in Create a .NET console application using Visual Studio for
Mac.
3. Make sure that Visual Studio is building the Release version of your application. If necessary, change the
build configuration setting on the toolbar from Debug to Release .

4. From the main menu, choose Build > Publish to Folder....

5. In the Publish to Folder dialog, select Publish .


The publish folder opens, showing the files that were created.

6. Select the gear icon, and select Copy "publish" as Pathname from the context menu.

Inspect the files


The publishing process creates a framework-dependent deployment, which is a type of deployment where the
published application runs on a machine that has the .NET runtime installed. Users can run the published app by
running the dotnet HelloWorld.dll command from a command prompt.
As the preceding 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.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.

Run the published app


1. Open a terminal and navigate to the publish folder. To do that, enter cd and then paste the path that you
copied earlier. For example:

cd ~/Projects/HelloWorld/HelloWorld/bin/Release/net5.0/publish/

2. Run the app by using the dotnet command:


a. Enter dotnet HelloWorld.dll and press enter.
b. Enter a name in response to the prompt, and press any key to exit.

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.

Create a solution with a class library project


A Visual Studio solution serves as a container for one or more projects. Create a solution and a class library
project in the solution. You'll add additional, related projects to the same solution later.
1. Start Visual Studio for Mac.
2. In the start window, select New Project .
3. In the Choose a template for your new project dialog select Web and Console > Librar y > Class
Librar y , and then select Next .
4. In the Configure your new Class Librar y dialog, choose .NET 5.0 , and select Next .
5. Name the project "StringLibrary" and the solution "ClassLibraryProjects". Leave Create a project
director y within the solution director y selected. Select Create .

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);
}
}
}

8. Press ⌘S (command+S) to save the file.


9. Select Errors in the margin at the bottom of the IDE window to open the Errors panel. Select the Build
Output button.

10. Select Build > Build All from the menu.


The solution builds. The build output panel shows that the build is successful.

Add a console app to the solution


Add a console application that uses the class library. The app will prompt the user to enter a string and report
whether the string begins with an uppercase character.
1. In the Solution pad, ctrl-click the ClassLibraryProjects solution. Add a new Console Application
project by selecting the template from the Web and Console > App templates, and select Next .
2. Select .NET 5.0 as the Target Framework and select Next .
3. Name the project ShowCase . Select Create to create the project in the solution.

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();

string? input = Console.ReadLine();


if (string.IsNullOrEmpty(input)) break;
Console.WriteLine($"Input: {input} {"Begins with uppercase? ",30}: " +
$"{(input.StartsWithUpper() ? "Yes" : "No")}{Environment.NewLine}");
row += 3;
} while (true);
return;

// Declare a ResetConsole local method


void ResetConsole()
{
if (row > 0)
{
Console.WriteLine("Press any key to continue...");
Console.ReadKey();
}
Console.Clear();
Console.WriteLine($"{Environment.NewLine}Press <Enter> only to exit; otherwise, enter a
string and press <Enter>:{Environment.NewLine}");
row = 3;
}
}
}

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.

Add a project reference


Initially, the new console app project doesn't have access to the class library. To allow it to call methods in the
class library, create a project reference to the class library project.
1. In the Solutions pad, ctrl-click the Dependencies node of the new ShowCase project. In the context
menu, select Add Reference .
2. In the References dialog, select StringLibrar y and select OK .

Run the app


1. ctrl-click the ShowCase project and select Run project from the context menu.
2. Try out the program by entering strings and pressing enter, then press enter to exit.
Additional resources
Develop libraries with the .NET CLI
Visual Studio 2019 for Mac Release Notes
.NET Standard versions and the platforms they support.

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.

Create a unit test project


Unit tests provide automated software testing during your development and publishing. MSTest is one of three
test frameworks you can choose from. The others are xUnit and nUnit.
1. Start Visual Studio for Mac.
2. Open the ClassLibraryProjects solution you created in Create a .NET class library using Visual Studio for
Mac.
3. In the Solution pad, ctrl-click the ClassLibraryProjects solution and select Add > New Project .
4. In the New Project dialog, select Tests from the Web and Console node. Select the MSTest Project
followed by Next .

5. Select .NET 5.0 as the Target Framework and select Next .


6. Name the new project "StringLibraryTest" and select Create .
Visual Studio creates a class 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 TestMethod1 .
Each method tagged with [TestMethod] in a test class tagged with [TestClass] is executed automatically
when the unit test is run.

Add a project reference


For the test project to work with the StringLibrary class, add a reference to the StringLibrary project.
1. In the Solution pad, ctrl-click Dependencies under StringLibrar yTest . Select Add Reference from
the context menu.
2. In the References dialog, select the StringLibrar y project. Select OK .
Add and run unit test methods
When Visual Studio runs a unit test, it executes each method that is marked with the TestMethodAttribute
attribute in a class that is marked with the TestClassAttribute attribute. A test method ends when the first failure
is found or when all tests contained in the method have succeeded.
The most common tests call members of the Assert class. Many assert methods include at least two parameters,
one of which is the expected test result and the other of which is the actual test result. Some of the Assert
class's most frequently called methods are shown in the following table:

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.IsFalse Verifies that a condition is false . The assert fails if the


condition is true .

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.

6. Click the Run All button.


All tests pass.
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.

string[] words = { "alphabet", "Error", "zebra", "abc", "αυτοκινητοβιομηχανία", "государство",


"1234", ".", ";", " " };

2. Run the tests again.


This time, the Test Explorer window indicates that two tests succeeded and one failed.

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.

Test the Release version of the library


Now that the tests have all passed when running the Debug build of the library, run the tests an additional time
against the Release build of the library. A number of factors, including compiler optimizations, can sometimes
produce different behavior between Debug and Release builds.
To test the Release build:
1. In the Visual Studio toolbar, change the build configuration from Debug to Release .

2. In the Solution pad, ctrl-click the StringLibrar y project and select Build from the context menu to
recompile the library.

3. Run the unit tests again.


The tests pass.

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.

Use Visual Studio


Create a console app
Debug an app
Publish an app
Create a class library
Unit test a class library
Install and use a package
Create and publish a package
Create an F# console app

Use Visual Studio Code


Choose these tutorials if you want to use Visual Studio Code or some other code editor. All use the CLI for .NET
Core development tasks, so all except the debugging tutorial can be used with any code editor.
Create a console app
Debug an app
Publish an app
Create a class library
Unit test a class library
Install and use a package
Create and publish a package
Create an F# console app

Use Visual Studio for Mac


Create a console app
Debug an app
Publish an app
Create a class library
Unit test a class library
Install and use a package
Create an F# console app

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.

F# and Visual Basic


F# 6 adds several improvements to the F# language and F# Interactive. For more information, see What's new in
F# 6.
Visual Basic has improvements in the Visual Studio experience and Windows Forms project startup.

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

dotnet workload search Searches for available workloads.

dotnet workload install Installs a specified workload.

dotnet workload uninstall Removes a specified workload.

dotnet workload update Updates installed workloads.

dotnet workload repair Reinstalls all installed workloads to repair a broken


installation.

dotnet workload list Lists installed workloads.

For more information, see Optional SDK workloads.

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.

Custom platform guards


The Platform compatibility analyzer recognizes the Is<Platform> methods in the OperatingSystem class, for
example, OperatingSystem.IsWindows(), as platform guards. To allow for custom platform guards, .NET 6
introduces two new attributes that you can use to annotate fields, properties, or methods with a supported or
unsupported platform name:
SupportedOSPlatformGuardAttribute
UnsupportedOSPlatformGuardAttribute

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.

Target framework monikers


Additional OS-specific target framework monikers (TFMs) have been added for .NET 6, for example,
net6.0-android , net6.0-ios , and net6.0-macos . For more information, see .NET 5+ OS-specific TFMs.

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.

NuGet package validation


If you're a NuGet library developer, new package-validation tooling enables you to validate that your packages
are consistent and well-formed. You can determine if:
There are any breaking changes across package versions.
The package has the same set of public APIs for all runtime-specific implementations.
There are any gaps for target-framework or runtime applicability.
For more information, see the Package Validation 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

Microsoft.Extensions.DependencyInjection CreateAsyncScope lets you safely use a using statement


for a service provider that registers an IAsyncDisposable
service.

Microsoft.Extensions.Hosting New ConfigureHostOptions methods simplify application


setup.
N A M ESPA C E IM P RO VEM EN T S

Microsoft.Extensions.Logging Microsoft.Extensions.Logging has a new source generator for


performant logging APIs. The source generator is triggered if
you add the new LoggerMessageAttribute to a partial
logging method. At compile time, the generator generates
the implementation of the partial method, which is
typically faster at run time than existing logging solutions.
For more information, see Compile-time logging source
generation.

New LINQ APIs


Numerous LINQ methods have been added in .NET 6. Most of the new methods listed in the following table
have equivalent methods in the System.Linq.Queryable type.

M ET H O D DESC RIP T IO N

Enumerable.TryGetNonEnumeratedCount<TSource> Attempts to determine the number of elements in a


(IEnumerable<TSource>, Int32) sequence without forcing an enumeration.

Enumerable.Chunk<TSource>(IEnumerable<TSource>, Splits the elements of a sequence into chunks of a specified


Int32) size.

Enumerable.MaxBy and Enumerable.MinBy Finds maximal or minimal elements using a key selector.

Enumerable.DistinctBy, Enumerable.ExceptBy, These new variations of methods that perform set-based


Enumerable.IntersectBy, and Enumerable.UnionBy operations let you specify equality using a key selector
function.

Enumerable.ElementAt<TSource>(IEnumerable<TSource>, Accepts indexes counted from the beginning or end of the


Index) and Enumerable.ElementAtOrDefault<TSource> sequence—for example,
(IEnumerable<TSource>, Index) Enumerable.Range(1, 10).ElementAt(^2) returns 9 .

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)

Enumerable.Max<TSource>(IEnumerable<TSource>, New overloads let you specify a comparer.


IComparer<TSource>) and Enumerable.Min<TSource>
(IEnumerable<TSource>, IComparer<TSource>)

Enumerable.Take<TSource>(IEnumerable<TSource>, Range) Accepts a Range argument to simplify taking a slice of a


sequence—for example, you can use source.Take(2..7)
instead of source.Take(7).Skip(2) .
M ET H O D DESC RIP T IO N

Enumerable.Zip<TFirst,TSecond,TThird> Produces a sequence of tuples with elements from three


(IEnumerable<TFirst>, IEnumerable<TSecond>, specified sequences.
IEnumerable<TThird>)

Date, time, and time zone improvements


The following two structs were added in .NET 6: System.DateOnly and System.TimeOnly. These represent the
date part and the time part of a DateTime, respectively. DateOnly is useful for birthdays and anniversaries, and
TimeOnly is useful for daily alarms and weekly business hours.
You can now use either Internet Assigned Numbers Authority (IANA) or Windows time zone IDs on any
operating system that has time zone data installed. The TimeZoneInfo.FindSystemTimeZoneById(String) method
has been updated to automatically convert its input from a Windows time zone to an IANA time zone (or vice
versa) if the requested time zone is not found on the system. In addition, the new methods
TryConvertIanaIdToWindowsId(String, String) and TryConvertWindowsIdToIanaId have been added for scenarios
when you still need to manually convert from one time zone format to another.
There are a few other time zone improvements as well. For more information, see Date, Time, and Time Zone
Enhancements in .NET 6.

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

Assemblies removed from ❌ ️



Microsoft.AspNetCore.App
shared framework

Blazor: Parameter name ️


✔ ❌ Preview 1
changed in
RequestImageFileAsync
method

Blazor: ❌ ❌
WebEventDescriptor.EventA
rgsType property replaced

Blazor: Byte array interop ️


✔ ❌ Preview 6

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

Identity: Default Bootstrap ❌ ❌


version of UI changed

Kestrel: Log message ️


✔ ❌
attributes changed

Microsoft.AspNetCore.Http. ❌ ️

Features split

Middleware: HTTPS ️
✔ ❌
Redirection Middleware
throws exception on
ambiguous HTTPS ports

Middleware: New Use ️


✔ ❌ Preview 4
overload

Minimal API renames in RC ❌ ❌ RC 1


1

Minimal API renames in RC ❌ ❌ RC 2


2

MVC doesn't buffer ️


✔ ❌ Preview 4
IAsyncEnumerable types
when using
System.Text.Json

Nullable reference type ️


✔ ❌
annotations changed

Obsoleted and removed ️


✔ ❌ Preview 1
APIs

PreserveCompilationContex ❌ ️

t not configured by default

Razor: Compiler no longer ️


✔ ❌ Preview 3
produces a Views assembly

Razor: Logging ID changes ❌ ️


✔ RC1

Razor: RazorEngine APIs ️


✔ ❌ Preview 1
marked obsolete

SignalR: Java Client updated ❌ ️


✔ Preview 4
to RxJava3
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

TryParse and BindAsync ❌ ❌ RC 2


methods are validated

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

Default console logger ️


✔ ❌ Servicing 6.0.6
formatting in container
images

For information on other breaking changes for containers in .NET 6, see .NET 6 Container Release Notes.

Core .NET libraries


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

API obsoletions with non- ️


✔ ❌ Preview 1
default diagnostic IDs

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

File.Replace on Unix throws ️


✔ ❌ Preview 7
exceptions to match
Windows

FileStream locks files with ❌ ️


✔ Preview 1
shared lock on Unix

FileStream no longer ❌ ❌ Preview 4


synchronizes file offset with
OS

FileStream.Position updates ❌ ❌ Preview 4


after ReadAsync or
WriteAsync completes

New diagnostic IDs for ️


✔ ❌ Preview 5
obsoleted APIs

New nullable annotation in ️


✔ ❌ RC 2
AssociatedMetadataTypeTy
peDescriptionProvider
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

New System.Linq.Queryable ️
✔ ❌ Preview 3-4
method overloads

Older framework versions ❌ ️


✔ Preview 5
dropped from package

Parameter names changed ️


✔ ❌ Preview 1

Parameter names in ️
✔ ❌ Preview 1
Stream-derived types

Partial and zero-byte reads ️


✔ ❌ Preview 6
in DeflateStream,
GZipStream, and
CryptoStream

Set timestamp on read-only ❌ ️


✔ Servicing 6.0.2
file on Windows

Standard numeric format ️


✔ ❌ Preview 2
parsing precision

Static abstract members in ❌ ️


✔ Preview 7
interfaces

StringBuilder.Append ❌ ️
✔ RC 1
overloads and evaluation
order

Strong-name APIs throw ❌ ️


✔ Preview 4
PlatformNotSupportedExce
ption

System.Drawing.Common ❌ ❌ Preview 7
only supported on
Windows

System.Security.SecurityCon ️
✔ ❌ RC 1
text is marked obsolete

Task.FromResult may return ❌ ️


✔ Preview 1
singleton

Unhandled exceptions from ️


✔ ❌ Preview 4
a BackgroundService

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

x86 host path on 64-bit ️


✔ ️
✔ Servicing release
Windows

Entity Framework Core


Breaking changes in EF Core 6

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

AddProvider checks for ️


✔ ❌ RC 1
non-null provider

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

Culture creation and case Preview 7


mapping in globalization-
invariant mode

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

Static abstract members in ❌ ️


✔ Preview 7
interfaces

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

Coerce call arguments ️


✔ ️
✔ Preview 1
according to ECMA-335

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

Port removed from SPN for ❌ ️


✔ RC 1
Kerberos and Negotiate

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

C# code in templates not ️


✔ ️
✔ Preview 7
supported by earlier
versions

EditorConfig files implicitly ️


✔ ❌
included

Generate apphost for ️


✔ ❌ Preview 6
macOS

Generate error for duplicate ❌ ️


✔ Preview 1
files in publish output

GetTargetFrameworkProper ❌ ️
✔ Preview 1
ties and
GetNearestTargetFramewor
k removed from
ProjectReference protocol

Install location for x64 ️


✔ ❌ RC 2
emulated on Arm64

MSBuild no longer supports RC 1


calling GetType()

OutputType not ️
✔ ❌ RC 1
automatically set to WinExe

Publish ReadyToRun with -- ️


✔ ❌ 6.0.100
no-restore requires changes

runtimeconfig.dev.json file ❌ ️
✔ 6.0.100
not generated

RuntimeIdentifier warning if ️
✔ ❌ RC 1
self-contained is unspecified

Version requirements for ️


✔ ️
✔ 6.0.300
.NET 6 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

Write reference assemblies ❌ ️


✔ 6.0.200
to IntermediateOutputPath

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

Default serialization format ❌ ️


✔ Servicing 6.0.2
for TimeSpan

IAsyncEnumerable ️
✔ ❌ Preview 4
serialization

JSON source-generation ❌ ️
✔ RC 2
API refactoring

JsonNumberHandlingAttrib ❌ ️
✔ RC 1
ute on collection properties

New JsonSerializer source ❌ ️


✔ Preview 6
generator overloads

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

ScaleControl called only ️


✔ ❌ Servicing 6.0.101
when needed

Some APIs throw ❌ ️


✔ Preview 1-4
ArgumentNullException
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

TreeNodeCollection.Item ❌ ️
✔ Preview 1
throws exception if node is
assigned elsewhere

XML and XSLT


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

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

.NET 5 doesn't replace .NET Framework


.NET 5 and later versions are the main implementation of .NET going forward, but .NET Framework 4.x is still
supported. There are no plans to port the following technologies from .NET Framework to .NET 5, but there are
alternatives in .NET:

T EC H N O LO GY REC O M M EN DED A LT ERN AT IVE

Web Forms ASP.NET Core Blazor or Razor Pages

Windows Workflow (WF) Elsa-Workflows

Windows Communication Foundation


The original implementation of Windows Communication Foundation (WCF) was only supported on Windows.
However, there's a client port available from the .NET Foundation. It's entirely open source, cross platform, and
supported by Microsoft. The core NuGet packages are listed below:
System.ServiceModel.Duplex
System.ServiceModel.Federation
System.ServiceModel.Http
System.ServiceModel.NetTcp
System.ServiceModel.Primitives
System.ServiceModel.Security
The server components that complement the aforementioned client libraries are available through CoreWCF. As
of April 2022, CoreWCF is officially supported by Microsoft. However, for an alternative to WCF, consider gRPC.

.NET 5 doesn't replace .NET Standard


New application development can specify the net5.0 Target Framework Moniker (TFM) for all project types,
including class libraries. Sharing code between .NET 5 workloads is simplified: all you need is the net5.0 TFM.
For .NET 5 apps and libraries, the net5.0 TFM combines and replaces the netcoreapp and netstandard TFMs.
However, if you plan to share code between .NET Framework, .NET Core, and .NET 5 workloads, you can do so by
specifying netstandard2.0 as your TFM. For more information, see .NET Standard.

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 .

For more information on the available C# 9 features, see What's new in C# 9.


Source generators
In addition to some of the highlighted new C# features, source generators are making their way into developer
projects. Source generators allow code that runs during compilation to inspect your program and produce
additional files that are compiled together with the rest of your code.
For more information on source generators, see Introducing C# source generators and C# source generator
samples.

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.

let name = "David"


let age = 36
let message = $"%s{name} is %d{age} years old."

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.

Visual Basic updates


There are no new language features for Visual Basic in .NET 5. However, with .NET 5, Visual Basic support is
extended to:

DESC RIP T IO N DOTNET NEW PA RA M ET ER

Console Application console

Class library classlib

WPF Application wpf

WPF Class library wpflib

WPF Custom Control Library wpfcustomcontrollib

WPF User Control Library wpfusercontrollib

Windows Forms (WinForms) Application winforms

Windows Forms (WinForms) Class library winformslib

Unit Test Project mstest

NUnit 3 Test Project nunit

NUnit 3 Test Item nunit-test

xUnit Test Project xunit

For more information on project templates from the .NET CLI, see dotnet new .

System.Text.Json new features


There are new features in and for System.Text.Json:
Preserve references and handle circular references
HttpClient and HttpContent extension methods
Allow or write numbers in quotes
Support immutable types and C# 9 Records
Support non-public property accessors
Support fields
Conditionally ignore properties
Support non-string-key dictionaries
Allow custom converters to handle null
Copy JsonSerializerOptions
Create JsonSerializerOptions with web defaults

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

ASP.NET Core apps deserialize quoted ️


✔ ❌
numbers

AzureAD.UI and AzureADB2C.UI APIs ️


✔ ❌
obsolete

BinaryFormatter serialization methods ️


✔ ❌
are obsolete

Resource in endpoint routing is ️


✔ ❌
HttpContext

Microsoft-prefixed Azure integration ❌ ️



packages removed

Blazor: Route precedence logic ️


✔ ❌
changed in Blazor apps

Blazor: Updated browser support ️


✔ ️

Blazor: Insignificant whitespace ️


✔ ❌
trimmed by compiler

Blazor: JSObjectReference and ️


✔ ❌
JSInProcessObjectReference types are
internal

Blazor: Target framework of NuGet ❌ ️



packages changed

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

Blazor: RenderTreeFrame readonly ❌ ️



public fields are now properties

Blazor: Updated validation logic for ❌ ️



static web assets

Cryptography APIs not supported on ❌ ️



browser

Extensions: Package reference changes ❌ ️


Kestrel and IIS ️


✔ ❌
BadHttpRequestException types are
obsolete

HttpClient instances created by ️


✔ ❌
IHttpClientFactory log integer status
codes

HttpSys: Client certificate ️


✔ ❌
renegotiation disabled by default

IIS: UrlRewrite middleware query ️


✔ ❌
strings are preserved

Kestrel: Configuration changes ️


✔ ❌
detected by default

Kestrel: Default supported TLS ️


✔ ❌
protocol versions changed

Kestrel: HTTP/2 disabled over TLS on ️


✔ ️

incompatible Windows versions

Kestrel: Libuv transport marked as ️


✔ ❌
obsolete

Obsolete properties on ️
✔ ❌
ConsoleLoggerOptions

ResourceManagerWithCultureStringLo ️
✔ ❌
calizer class and WithCulture interface
member removed

Pubternal APIs removed ️


✔ ❌

Obsolete constructor removed in ️


✔ ❌
request localization middleware

Middleware: Database error page ️


✔ ❌
marked as obsolete

Exception handler middleware throws ️


✔ ️

original exception
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

ObjectModelValidator calls a new ️


✔ ❌
overload of Validate

Cookie name encoding removed ️


✔ ❌

IdentityModel NuGet package versions ❌ ️



updated

SignalR: MessagePack Hub Protocol ️


✔ ❌
options type changed

SignalR: MessagePack Hub Protocol ️


✔ ❌
moved

UseSignalR and UseConnections ️


✔ ❌
methods removed

CSV content type changed to ️


✔ ❌
standards-compliant

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 ️
✔ ❌

Core .NET libraries


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

Assembly-related API changes for ❌ ️



single-file publishing

BinaryFormatter serialization methods ️


✔ ❌
are obsolete
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

Code access security APIs are obsolete ️


✔ ❌

CreateCounterSetInstance throws ️
✔ ❌
InvalidOperationException

Default ActivityIdFormat is W3C ❌ ️


Environment.OSVersion returns the ❌ ️



correct version

FrameworkDescription's value is .NET ️


✔ ❌
not .NET Core

GAC APIs are obsolete ️


✔ ❌

Hardware intrinsic IsSupported checks ❌ ️


IntPtr and UIntPtr implement ️


✔ ❌
IFormattable

LastIndexOf handles empty search ❌ ️



strings

URI paths with non-ASCII characters ❌ ️



on Unix

API obsoletions with non-default ️


✔ ❌
diagnostic IDs

Obsolete properties on ️
✔ ❌
ConsoleLoggerOptions

Complexity of LINQ OrderBy.First ❌ ️


OSPlatform attributes renamed or ️


✔ ❌
removed

Microsoft.DotNet.PlatformAbstractions ❌ ️

package removed

PrincipalPermissionAttribute is ️
✔ ❌
obsolete

Parameter name changes from preview ️


✔ ❌
versions

Parameter name changes in reference ️


✔ ❌
assemblies

Remoting APIs are obsolete ❌ ️


Order of Activity.Tags list is reversed ️


✔ ❌
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

SSE and SSE2 comparison methods ️


✔ ❌
handle NaN

Thread.Abort is obsolete ️
✔ ❌

Uri recognition of UNC paths on Unix ❌ ️


UTF-7 code paths are obsolete ️


✔ ❌

Behavior change for Vector2.Lerp and ️


✔ ❌
Vector4.Lerp

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 APIs not supported on ❌ ️



browser

Cryptography.Oid is init-only ️
✔ ❌

Default TLS cipher suites on Linux ❌ ️


Create() overloads on cryptographic ️


✔ ❌
abstractions are obsolete

Default FeedbackSize value changed ️


✔ ❌

Entity Framework Core


Breaking changes in EF Core 5.0

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

Use ICU libraries on Windows ❌ ️


StringInfo and TextElementEnumerator ❌ ️



are UAX29-compliant

Unicode category changed for Latin-1 ️


✔ ❌
characters

TextInfo.ListSeparator values changed ️


✔ ❌

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

Support for WinRT is removed ❌ ️


Casting RCW to InterfaceIsIInspectable ❌ ️



throws exception

No A/W suffix probing on non- ❌ ️



Windows platforms

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

Cookie path handling conforms to RFC ️


✔ ❌
6265

LocalEndPoint is updated after calling ️


✔ ❌
SendToAsync

MulticastOption.Group doesn't accept ️


✔ ❌
null

Streams allow successive Begin ❌ ️



operations

WinHttpHandler removed from .NET ❌ ️



runtime

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

Error generated when executable ️



project references mismatched
executable

FrameworkReference replaced with ️


✔ ❌
WindowsSdkPackageVersion for
Windows SDK

NETCOREAPP3_1 preprocessor symbol ️


✔ ❌
not defined

OutputType set to WinExe ❌ ️


PublishDepsFilePath behavior change ❌ ️


TargetFramework change from ❌ ️



netcoreapp to net
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

WinForms and WPF apps use ❌ ️



Microsoft.NET.Sdk

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

Code access security APIs are obsolete ️


✔ ❌

PrincipalPermissionAttribute is ️
✔ ❌
obsolete

UTF-7 code paths are 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

ASP.NET Core apps deserialize quoted ️


✔ ❌
numbers

JsonSerializer.Serialize throws ️
✔ ❌
ArgumentNullException

Non-public, parameterless ️
✔ ❌
constructors not used for
deserialization

Options are honored when serializing ️


✔ ❌
key-value pairs

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

Native code can't access Windows ️


✔ ❌
Forms objects

OutputType set to WinExe ❌ ️


DataGridView doesn't reset custom ️


✔ ❌
fonts

Methods throw ArgumentException ️


✔ ❌
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

DataGridView APIs throw ️


✔ ❌
InvalidOperationException

WinForms apps use Microsoft.NET.Sdk ❌ ️


Removed status bar controls ️


✔ ❌

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

OutputType set to WinExe ❌ ️


WPF apps use Microsoft.NET.Sdk ❌ ️



What's new in .NET Core 3.1
9/10/2022 • 3 minutes to read • Edit Online

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

.NET Core 3.1 End of life on December 13, 2022.

.NET Core 3.0 End of life on March 3, 2020.

.NET Core 2.2 End of life on December 23, 2019.

.NET Core 2.1 End of life on August 21, 2021.

For more information, see the .NET and .NET Core support policy.

macOS appHost and notarization


macOS only
Starting with the notarized .NET Core SDK 3.1 for macOS, the appHost setting is disabled by default. For more
information, see macOS Catalina Notarization and the impact on .NET Core downloads and projects.
When the appHost setting is enabled, .NET Core generates a native Mach-O executable when you build or
publish. Your app runs in the context of the appHost when it is run from source code with the dotnet run
command, or by starting the Mach-O executable directly.
Without the appHost, the only way a user can start a framework-dependent app is with the
dotnet <filename.dll> command. An appHost is always created when you publish your app self-contained.

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

dotnet run -p:UseAppHost=true

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.

REM O VED C O N T RO L REC O M M EN DED REP L A C EM EN T A SSO C IAT ED A P IS REM O VED

DataGrid DataGridView DataGridCell


DataGridRow
DataGridTableCollection
DataGridColumnCollection
DataGridTableStyle
DataGridColumnStyle
DataGridLineStyle
DataGridParentRowsLabel
DataGridParentRowsLabelStyle
DataGridBoolColumn
DataGridTextBox
GridColumnStylesCollection
GridTableStylesCollection
HitTestType

ToolBar ToolStrip ToolBarAppearance

ToolBarButton ToolStripButton ToolBarButtonClickEventArgs


ToolBarButtonClickEventHandler
ToolBarButtonStyle
ToolBarTextAlign

ContextMenu ContextMenuStrip

Menu ToolStripDropDown MenuItemCollection


ToolStripDropDownMenu

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

The feature flag is edge://flags/#same-site-by-default-cookies . No compatibility issues were observed when


testing with Microsoft Edge Chromium 78.
El e c t r o n

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;
}
}
}

public void ConfigureServices(IServiceCollection services)


{
services.Configure<CookiePolicyOptions>(options =>
{
options.MinimumSameSitePolicy = SameSiteMode.Unspecified;
options.OnAppendCookie = cookieContext =>
CheckSameSite(cookieContext.Context, cookieContext.CookieOptions);
options.OnDeleteCookie = cookieContext =>
CheckSameSite(cookieContext.Context, cookieContext.CookieOptions);
});
}

public void Configure(IApplicationBuilder app)


{
// Before UseAuthentication or anything else that writes cookies.
app.UseCookiePolicy();

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

Related SameSite patches are forthcoming for:


ASP.NET Core 2.1, 2.2, and 3.0
Microsoft.Owin 4.1
System.Web (for .NET Framework 4.7.2 and later)

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

DataGrid DataGridView DataGridCell, DataGridRow,


DataGridTableCollection,
DataGridColumnCollection,
DataGridTableStyle,
DataGridColumnStyle,
DataGridLineStyle,
DataGridParentRowsLabel,
DataGridParentRowsLabelStyle,
DataGridBoolColumn,
DataGridTextBox,
GridColumnStylesCollection,
GridTableStylesCollection, HitTestType

MainMenu MenuStrip

Menu ToolStripDropDown, MenuItemCollection


ToolStripDropDownMenu

MenuItem ToolStripMenuItem

ToolBar ToolStrip ToolBarAppearance

ToolBarButton ToolStripButton ToolBarButtonClickEventArgs,


ToolBarButtonClickEventHandler,
ToolBarButtonStyle, ToolBarTextAlign

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

CellFormatting event not raised if tooltip is shown


A DataGridView now shows a cell's text and error tooltips when hovered by a mouse and when selected via the
keyboard. If a tooltip is shown, the DataGridView.CellFormatting event is not raised.
Change description
Prior to .NET Core 3.1, a DataGridView that had the ShowCellToolTips property set to true showed a tooltip for
a cell's text and errors when the cell was hovered by a mouse. Tooltips were not shown when a cell was selected
via the keyboard (for example, by using the Tab key, shortcut keys, or arrow navigation). If the user edited a cell,
and then, while the DataGridView was still in edit mode, hovered over a cell that did not have the ToolTipText
property set, a CellFormatting event was raised to format the cell's text for display in the cell.
To meet accessibility standards, starting in .NET Core 3.1, a DataGridView that has the ShowCellToolTips
property set to true shows tooltips for a cell's text and errors not only when the cell is hovered, but also when
it's selected via the keyboard. As a consequence of this change, the CellFormatting event is not raised when cells
that don't have the ToolTipText property set are hovered while the DataGridView is in edit mode. The event is not
raised because the content of the hovered cell is shown as a tooltip instead of being displayed in the cell.
Version introduced
3.1
Recommended action
Refactor any code that depends on the CellFormatting event while the DataGridView is in edit mode.
Category
Windows Forms
Affected APIs
None
What's new in .NET Core 3.0
9/10/2022 • 22 minutes to read • Edit Online

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.

Language improvements C# 8.0


C# 8.0 is also part of this release, which includes the nullable reference types feature, async streams, and more
patterns. For more information about C# 8.0 features, see What's new in C# 8.0.
Tutorials related to C# 8.0 language features:
Tutorial: Express your design intent more clearly with nullable and non-nullable reference types
Tutorial: Generate and consume async streams using C# 8.0 and .NET Core 3.0
Tutorial: Use pattern matching to build type-driven and data-driven algorithms
Language enhancements were added to support the following API features detailed below:
Ranges and indices
Async streams

.NET Standard 2.1


.NET Core 3.0 implements .NET Standard 2.1 . However, the default dotnet new classlib template generates a
project that still targets .NET Standard 2.0 . To target .NET Standard 2.1 , edit your project file and change the
TargetFramework property to netstandard2.1 :

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

macOS appHost and notarization


macOS only
Starting with the notarized .NET Core SDK 3.0 for macOS, the setting to produce a default executable (known as
the appHost) is disabled by default. For more information, see macOS Catalina Notarization and the impact on
.NET Core downloads and projects.
When the appHost setting is enabled, .NET Core generates a native Mach-O executable when you build or
publish. Your app runs in the context of the appHost when it is run from source code with the dotnet run
command, or by starting the Mach-O executable directly.
Without the appHost, the only way a user can start a framework-dependent app is with the
dotnet <filename.dll> command. An appHost is always created when you publish your app self-contained.

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

dotnet run -p:UseAppHost=true

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-

dotnet publish -r win10-x64 -p:PublishSingleFile=true

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>

dotnet publish -r <rid> -c Release

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>

To disable TC completely, use this MSBuild property in your project file:

<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

Cross platform/architecture restrictions


The ReadyToRun compiler doesn't currently support cross-targeting. You must compile on a given target. For
example, if you want R2R images for Windows x64, you need to run the publish command on that environment.
Exceptions to cross-targeting:
Windows x64 can be used to compile Windows Arm32, Arm64, and x86 images.
Windows x86 can be used to compile Windows Arm32 images.
Linux x64 can be used to compile Linux Arm32 and Arm64 images.
For more information, see Ready to Run.

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.

Windows Desktop & COM


.NET Core SDK Windows Installer
The MSI installer for Windows has changed starting with .NET Core 3.0. The SDK installers will now upgrade
SDK feature-band releases in place. Feature bands are defined in the hundreds groups in the patch section of the
version number. For example, 3.0.101 and 3.0.201 are versions in two different feature bands while 3.0.101
and 3.0.199 are in the same feature band. And, when .NET Core SDK 3.0.101 is installed, .NET Core SDK
3.0.100 will be removed from the machine if it exists. When .NET Core SDK 3.0.200 is installed on the same
machine, .NET Core SDK 3.0.101 won't be removed.
For more information about versioning, see Overview of how .NET Core is versioned.
Windows desktop
.NET Core 3.0 supports Windows desktop applications using Windows Presentation Foundation (WPF) and
Windows Forms. These frameworks also support using modern controls and Fluent styling from the Windows
UI XAML Library (WinUI) via XAML islands.
The Windows Desktop component is part of the Windows .NET Core 3.0 SDK.
You can create a new WPF or Windows Forms app with the following dotnet commands:

dotnet new wpf


dotnet new winforms

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

using TcpClient tcpClient = new TcpClient();

await tcpClient.ConnectAsync(targetHost, 443);

using SslStream sslStream = new SslStream(tcpClient.GetStream());

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);

byte[] nonce = new byte[12];


RandomNumberGenerator.Fill(nonce);

// normally this would be your data


byte[] dataToEncrypt = new byte[1234];
byte[] associatedData = new byte[333];
RandomNumberGenerator.Fill(dataToEncrypt);
RandomNumberGenerator.Fill(associatedData);

// these will be filled during the encryption


byte[] tag = new byte[16];
byte[] ciphertext = new byte[dataToEncrypt.Length];

using (AesGcm aesGcm = new AesGcm(key))


{
aesGcm.Encrypt(nonce, dataToEncrypt, ciphertext, tag, associatedData);
}

// tag, nonce, ciphertext, associatedData should be sent to the other part

byte[] decryptedData = new byte[ciphertext.Length];

using (AesGcm aesGcm = new AesGcm(key))


{
aesGcm.Decrypt(nonce, ciphertext, tag, decryptedData, associatedData);
}

// do something with the data


// this should always print that data is the same
Console.WriteLine($"AES-GCM: Decrypted data is {(dataToEncrypt.SequenceEqual(decryptedData) ?
"the same as" : "different than")} original data.");
}
}
}

Cryptographic Key Import/Export


.NET Core 3.0 supports the import and export of asymmetric public and private keys from standard formats. You
don't need to use an X.509 certificate.
All key types, such as RSA, DSA, ECDsa, and ECDiffieHellman, support the following formats:
Public Key
X.509 SubjectPublicKeyInfo
Private key
PKCS#8 PrivateKeyInfo
PKCS#8 EncryptedPrivateKeyInfo
RSA keys also support:
Public Key
PKCS#1 RSAPublicKey
Private key
PKCS#1 RSAPrivateKey
The export methods produce DER-encoded binary data, and the import methods expect the same. If a key is
stored in the text-friendly PEM format, the caller will need to base64-decode the content before calling an
import method.

using System;
using System.Security.Cryptography;

namespace whats_new
{
public static class RSATest
{
public static void Run(string keyFile)
{
using var rsa = RSA.Create();

byte[] keyBytes = System.IO.File.ReadAllBytes(keyFile);


rsa.ImportRSAPrivateKey(keyBytes, out int bytesRead);

Console.WriteLine($"Read {bytesRead} bytes, {keyBytes.Length - bytesRead} extra byte(s) in


file.");
RSAParameters rsaParameters = rsa.ExportParameters(true);
Console.WriteLine(BitConverter.ToString(rsaParameters.D));
}
}
}

PKCS#8 files can be inspected with System.Security.Cryptography.Pkcs.Pkcs8PrivateKeyInfo and PFX/PKCS#12


files can be inspected with System.Security.Cryptography.Pkcs.Pkcs12Info. PFX/PKCS#12 files can be
manipulated with System.Security.Cryptography.Pkcs.Pkcs12Builder.

.NET Core 3.0 API changes


Ranges and indices
The new System.Index type can be used for indexing. You can create one from an int that counts from the
beginning, or with a prefix ^ operator (C#) that counts from the end:

Index i1 = 3; // number 3 from beginning


Index i2 = ^4; // number 4 from end
int[] a = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
Console.WriteLine($"{a[i1]}, {a[i2]}"); // "3, 6"

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:

var slice = a[i1..i2]; // { 3, 4, 5 }

For more information, see the ranges and indices tutorial.


Async streams
The IAsyncEnumerable<T> type is a new asynchronous version of IEnumerable<T>. The language lets you
await foreach over IAsyncEnumerable<T> to consume their elements, and use yield return to them to produce
elements.
The following example demonstrates both production and consumption of async streams. The foreach
statement is async and itself uses yield return to produce an async stream for callers. This pattern (using
yield return ) is the recommended model for producing async streams.

async IAsyncEnumerable<int> GetBigResultsAsync()


{
await foreach (var result in GetResultsAsync())
{
if (result > 20) yield return result;
}
}

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 .

MaxMagnitude(Double, Double) and MinMagnitude(Double, Double)


Corresponds to the maxNumMag and minNumMag IEEE operations, they return the value that is greater or
lesser in magnitude of the two inputs (respectively). For example, Math.MaxMagnitude(2.0, -3.0) would
return -3.0 .
ILogB(Double)
Corresponds to the logB IEEE operation that returns an integral value, it returns the integral base-2 log
of the input parameter. This method is effectively the same as floor(log2(x)) , but done with minimal
rounding error.
ScaleB(Double, Int32)
Corresponds to the scaleB IEEE operation that takes an integral value, it returns effectively
x * pow(2, n) , but is done with minimal rounding error.

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.

Fast built-in JSON support


.NET users have largely relied on Newtonsoft.Json and other popular JSON libraries, which continue to be good
choices. Newtonsoft.Json uses .NET strings as its base datatype, which is UTF-16 under the hood.
The new built-in JSON support is high-performance, low allocation, and works with UTF-8 encoded JSON text.
For more information about the System.Text.Json namespace and types, see the following articles:
JSON serialization in .NET - overview
How to serialize and deserialize JSON in .NET.
How to migrate from Newtonsoft.Json to System.Text.Json
HTTP/2 support
The System.Net.Http.HttpClient type supports the HTTP/2 protocol. If HTTP/2 is enabled, the HTTP protocol
version is negotiated via TLS/ALPN, and HTTP/2 is used if the server elects to use it.
The default protocol remains HTTP/1.1, but HTTP/2 can be enabled in two different ways. First, you can set the
HTTP request message to use HTTP/2:

var client = new HttpClient() { BaseAddress = new Uri("https://localhost:5001") };

// 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);

Second, you can change HttpClient to use HTTP/2 by default:

var client = new HttpClient()


{
BaseAddress = new Uri("https://localhost:5001"),
DefaultRequestVersion = new Version(2, 0)
};

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

"Pubternal" APIs removed


To better maintain the public API surface of ASP.NET Core, most of the types in *.Internal namespaces
(referred to as "pubternal" APIs) have become truly internal. Members in these namespaces were never meant
to be supported as public-facing APIs. The APIs could break in minor releases and often did. Code that depends
on these APIs breaks when updating to ASP.NET Core 3.0.
For more information, see dotnet/aspnetcore#4932 and dotnet/aspnetcore#11312.
Version introduced
3.0
Old behavior
The affected APIs are marked with the public access modifier and exist in *.Internal namespaces.
New behavior
The affected APIs are marked with the internal access modifier and can no longer be used by code outside that
assembly.
Reason for change
The guidance for these "pubternal" APIs was that they:
Could change without notice.
Weren't subject to .NET policies to prevent breaking changes.
Leaving the APIs public (even in the *.Internal namespaces) was confusing to customers.
Recommended action
Stop using these "pubternal" APIs. If you have questions about alternate APIs, open an issue in the
dotnet/aspnetcore repository.
For example, consider the following HTTP request buffering code in an ASP.NET Core 2.2 project. The
EnableRewind extension method exists in the Microsoft.AspNetCore.Http.Internal namespace.

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

Authentication: Google+ deprecated and replaced


Google is starting to shut down Google+ Sign-in for apps as early as January 28, 2019.
Change description
ASP.NET 4.x and ASP.NET Core have been using the Google+ Sign-in APIs to authenticate Google account users
in web apps. The affected NuGet packages are Microsoft.AspNetCore.Authentication.Google for ASP.NET Core
and Microsoft.Owin.Security.Google for Microsoft.Owin with ASP.NET Web Forms and MVC.
Google's replacement APIs use a different data source and format. The mitigations and solutions provided below
account for the structural changes. Apps should verify the data itself still satisfies their requirements. For
example, names, email addresses, profile links, and profile photos may provide subtly different values than
before.
Version introduced
All versions. This change is external to ASP.NET Core.
Recommended action
O w i n w i t h A SP.N E T W e b F o r m s a n d M V C

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

For Microsoft.AspNetCore.Authentication.Google version 2.x, replace your existing call to AddGoogle in


Startup.ConfigureServices with the following code:

.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

Authentication: HttpContext.Authentication property removed


The deprecated Authentication property on HttpContext has been removed.
Change description
As part of dotnet/aspnetcore#6504, the deprecated Authentication property on HttpContext has been
removed. The Authentication property has been deprecated since 2.0. A migration guide was published to
migrate code using this deprecated property to the new replacement APIs. The remaining unused classes / APIs
related to the old ASP.NET Core 1.x authentication stack were removed in commit dotnet/aspnetcore@d7a7c65.
For discussion, see dotnet/aspnetcore#6533.
Version introduced
3.0
Reason for change
ASP.NET Core 1.0 APIs have been replaced by extension methods in
Microsoft.AspNetCore.Authentication.AuthenticationHttpContextExtensions.
Recommended action
See the migration guide.
Category
ASP.NET Core
Affected APIs
Microsoft.AspNetCore.Http.Authentication.AuthenticateInfo
Microsoft.AspNetCore.Http.Authentication.AuthenticationManager
Microsoft.AspNetCore.Http.Authentication.AuthenticationProperties
Microsoft.AspNetCore.Http.Features.Authentication.AuthenticateContext
Microsoft.AspNetCore.Http.Features.Authentication.ChallengeBehavior
Microsoft.AspNetCore.Http.Features.Authentication.ChallengeContext
Microsoft.AspNetCore.Http.Features.Authentication.DescribeSchemesContext
Microsoft.AspNetCore.Http.Features.Authentication.IAuthenticationHandler
Microsoft.AspNetCore.Http.Features.Authentication.IHttpAuthenticationFeature.Handler
Microsoft.AspNetCore.Http.Features.Authentication.SignInContext
Microsoft.AspNetCore.Http.Features.Authentication.SignOutContext
Microsoft.AspNetCore.Http.HttpContext.Authentication

Authentication: Newtonsoft.Json types replaced


In ASP.NET Core 3.0, Newtonsoft.Json types used in Authentication APIs have been replaced with
System.Text.Json types. Except for the following cases, basic usage of the Authentication packages remains
unaffected:
Classes derived from the OAuth providers, such as those from aspnet-contrib.
Advanced claim manipulation implementations.
For more information, see dotnet/aspnetcore#7105. For discussion, see dotnet/aspnetcore#7289.
Version introduced
3.0
Recommended action
For derived OAuth implementations, the most common change is to replace JObject.Parse with
JsonDocument.Parse in the CreateTicketAsync override as shown here. JsonDocument implements IDisposable .
The following list outlines known changes:
ClaimAction.Run(JObject, ClaimsIdentity, String) becomes
ClaimAction.Run(JsonElement userData, ClaimsIdentity identity, string issuer) . All derived implementations
of ClaimAction are similarly affected.
ClaimActionCollectionMapExtensions.MapCustomJson(ClaimActionCollection, String, Func<JObject,String>)
becomes
MapCustomJson(this ClaimActionCollection collection, string claimType, Func<JsonElement, string>
resolver)
ClaimActionCollectionMapExtensions.MapCustomJson(ClaimActionCollection, String, String,
Func<JObject,String>) becomes
MapCustomJson(this ClaimActionCollection collection, string claimType, string valueType,
Func<JsonElement, string> resolver)
OAuthCreatingTicketContext has had one old constructor removed and the other replaced JObject with
JsonElement . The User property and RunClaimActions method have been updated to match.
Success(JObject) now accepts a parameter of type JsonDocument instead of JObject . The Response property
has been updated to match. OAuthTokenResponse is now disposable and will be disposed by OAuthHandler .
Derived OAuth implementations overriding ExchangeCodeAsync don't need to dispose the JsonDocument or
OAuthTokenResponse .
UserInformationReceivedContext.User changed from JObject to JsonDocument .
TwitterCreatingTicketContext.User changed from JObject to JsonElement .
The last parameter of
TwitterHandler.CreateTicketAsync(ClaimsIdentity,AuthenticationProperties,AccessToken,JObject) changed
from JObject to JsonElement . The replacement method is TwitterHandler.CreateTicketAsync(ClaimsIdentity,
AuthenticationProperties, AccessToken, JsonElement).
Category
ASP.NET Core
Affected APIs
Microsoft.AspNetCore.Authentication.Facebook
Microsoft.AspNetCore.Authentication.Google
Microsoft.AspNetCore.Authentication.MicrosoftAccount
Microsoft.AspNetCore.Authentication.OAuth
Microsoft.AspNetCore.Authentication.OpenIdConnect
Microsoft.AspNetCore.Authentication.Twitter

Authentication: OAuthHandler ExchangeCodeAsync signature changed


In ASP.NET Core 3.0, the signature of OAuthHandler.ExchangeCodeAsync was changed from:

protected virtual System.Threading.Tasks.Task<Microsoft.AspNetCore.Authentication.OAuth.OAuthTokenResponse>


ExchangeCodeAsync(string code, string redirectUri) { throw null; }

To:

protected virtual System.Threading.Tasks.Task<Microsoft.AspNetCore.Authentication.OAuth.OAuthTokenResponse>


ExchangeCodeAsync(Microsoft.AspNetCore.Authentication.OAuth.OAuthCodeExchangeContext context) { throw null;
}
Version introduced
3.0
Old behavior
The code and redirectUri strings were passed as separate arguments.
New behavior
Code and are properties on OAuthCodeExchangeContext that can be set via the
RedirectUri
OAuthCodeExchangeContext constructor. The new OAuthCodeExchangeContext type is the only argument passed to
OAuthHandler.ExchangeCodeAsync .

Reason for change


This change allows additional parameters to be provided in a non-breaking manner. There's no need to create
new ExchangeCodeAsync overloads.
Recommended action
Construct an OAuthCodeExchangeContext with the appropriate code and redirectUri values. An
AuthenticationProperties instance must be provided. This single OAuthCodeExchangeContext instance can be
passed to OAuthHandler.ExchangeCodeAsync instead of multiple arguments.
Category
ASP.NET Core
Affected APIs
OAuthHandler<TOptions>.ExchangeCodeAsync(String, String)

Authorization: AddAuthorization overload moved to different assembly


The core AddAuthorization methods that used to reside in Microsoft.AspNetCore.Authorization were renamed
to AddAuthorizationCore . The old AddAuthorization methods still exist, but are in the
Microsoft.AspNetCore.Authorization.Policy assembly instead. Apps using both methods should see no impact.
Note that Microsoft.AspNetCore.Authorization.Policy now ships in the shared framework rather than a
standalone package as discussed in Shared framework: Assemblies removed from Microsoft.AspNetCore.App.
Version introduced
3.0
Old behavior
AddAuthorization methods existed in Microsoft.AspNetCore.Authorization .
New behavior
AddAuthorization methods exist in Microsoft.AspNetCore.Authorization.Policy . AddAuthorizationCore is the
new name for the old methods.
Reason for change
AddAuthorization is a better method name for adding all common services needed for authorization.
Recommended action
Either add a reference to Microsoft.AspNetCore.Authorization.Policy or use AddAuthorizationCore instead.
Category
ASP.NET Core
Affected APIs
Microsoft.Extensions.DependencyInjection.AuthorizationServiceCollectionExtensions.AddAuthorization(IServiceC
ollection, Action<AuthorizationOptions>)

Authorization: IAllowAnonymous removed from AuthorizationFilterContext.Filters


As of ASP.NET Core 3.0, MVC doesn't add AllowAnonymousFilters for [AllowAnonymous] attributes that were
discovered on controllers and action methods. This change is addressed locally for derivatives of
AuthorizeAttribute, but it's a breaking change for IAsyncAuthorizationFilter and IAuthorizationFilter
implementations. Such implementations wrapped in a [TypeFilter] attribute are a popular and supported way to
achieve strongly-typed, attribute-based authorization when both configuration and dependency injection are
required.
Version introduced
3.0
Old behavior
IAllowAnonymous appeared in the AuthorizationFilterContext.Filters collection. Testing for the interface's
presence was a valid approach to override or disable the filter on individual controller methods.
New behavior
IAllowAnonymousno longer appears in the AuthorizationFilterContext.Filters collection.
IAsyncAuthorizationFilterimplementations that are dependent on the old behavior typically cause intermittent
HTTP 401 Unauthorized or HTTP 403 Forbidden responses.
Reason for change
A new endpoint routing strategy was introduced in ASP.NET Core 3.0.
Recommended action
Search the endpoint metadata for IAllowAnonymous . For example:

var endpoint = context.HttpContext.GetEndpoint();


if (endpoint?.Metadata?.GetMetadata<IAllowAnonymous>() != null)
{
}

An example of this technique is seen in this HasAllowAnonymous method.


Category
ASP.NET Core
Affected APIs
None

Authorization: IAuthorizationPolicyProvider implementations require new method


In ASP.NET Core 3.0, a new GetFallbackPolicyAsync method was added to IAuthorizationPolicyProvider . This
fallback policy is used by the authorization middleware when no policy is specified.
For more information, see dotnet/aspnetcore#9759.
Version introduced
3.0
Old behavior
Implementations of IAuthorizationPolicyProvider didn't require a GetFallbackPolicyAsync method.
New behavior
Implementations of IAuthorizationPolicyProvider require a GetFallbackPolicyAsync method.
Reason for change
A new method was needed for the new AuthorizationMiddleware to use when no policy is specified.
Recommended action
Add the GetFallbackPolicyAsync method to your implementations of IAuthorizationPolicyProvider .
Category
ASP.NET Core
Affected APIs
Microsoft.AspNetCore.Authorization.IAuthorizationPolicyProvider

Caching: CompactOnMemoryPressure property removed


The ASP.NET Core 3.0 release removed the obsolete MemoryCacheOptions APIs.
Change description
This change is a follow-up to aspnet/Caching#221. For discussion, see dotnet/extensions#1062.
Version introduced
3.0
Old behavior
MemoryCacheOptions.CompactOnMemoryPressure property was available.
New behavior
The MemoryCacheOptions.CompactOnMemoryPressure property has been removed.
Reason for change
Automatically compacting the cache caused problems. To avoid unexpected behavior, the cache should only be
compacted when needed.
Recommended action
To compact the cache, downcast to MemoryCache and call Compact when needed.
Category
ASP.NET Core
Affected APIs
MemoryCacheOptions.CompactOnMemoryPressure

Caching: Microsoft.Extensions.Caching.SqlServer uses new SqlClient package


The Microsoft.Extensions.Caching.SqlServer package will use the new Microsoft.Data.SqlClient package
instead of System.Data.SqlClient package. This change could cause slight behavioral breaking changes. For
more information, see Introducing the new Microsoft.Data.SqlClient.
Version introduced
3.0
Old behavior
The Microsoft.Extensions.Caching.SqlServer package used the System.Data.SqlClient package.
New behavior
Microsoft.Extensions.Caching.SqlServer is now using the Microsoft.Data.SqlClient package.
Reason for change
Microsoft.Data.SqlClient is a new package that is built off of System.Data.SqlClient . It's where all new feature
work will be done from now on.
Recommended action
Customers shouldn't need to worry about this breaking change unless they were using types returned by the
Microsoft.Extensions.Caching.SqlServer package and casting them to System.Data.SqlClient types. For
example, if someone was casting a DbConnection to the old SqlConnection type, they would need to change the
cast to the new Microsoft.Data.SqlClient.SqlConnection type.
Category
ASP.NET Core
Affected APIs
None

Caching: ResponseCaching "pubternal" types changed to internal


In ASP.NET Core 3.0, "pubternal" types in ResponseCaching have been changed to internal .
In addition, default implementations of IResponseCachingPolicyProvider and IResponseCachingKeyProvider are
no longer added to services as part of the AddResponseCaching method.
Change description
In ASP.NET Core, "pubternal" types are declared as public but reside in a namespace suffixed with .Internal .
While these types are public, they have no support policy and are subject to breaking changes. Unfortunately,
accidental use of these types has been common, resulting in breaking changes to these projects and limiting the
ability to maintain the framework.
Version introduced
3.0
Old behavior
These types were publicly visible, but unsupported.
New behavior
These types are now internal .
Reason for change
The internal scope better reflects the unsupported policy.
Recommended action
Copy types that are used by your app or library.
Category
ASP.NET Core
Affected APIs
Microsoft.AspNetCore.ResponseCaching.Internal.CachedResponse
Microsoft.AspNetCore.ResponseCaching.Internal.CachedVaryByRules
Microsoft.AspNetCore.ResponseCaching.Internal.IResponseCache
Microsoft.AspNetCore.ResponseCaching.Internal.IResponseCacheEntry
Microsoft.AspNetCore.ResponseCaching.Internal.IResponseCachingKeyProvider
Microsoft.AspNetCore.ResponseCaching.Internal.IResponseCachingPolicyProvider
Microsoft.AspNetCore.ResponseCaching.Internal.MemoryResponseCache
Microsoft.AspNetCore.ResponseCaching.Internal.ResponseCachingContext
Microsoft.AspNetCore.ResponseCaching.Internal.ResponseCachingKeyProvider
Microsoft.AspNetCore.ResponseCaching.Internal.ResponseCachingPolicyProvider
Microsoft.AspNetCore.ResponseCaching.ResponseCachingMiddleware.ResponseCachingMiddleware(RequestDelegate,
IOptions<ResponseCachingOptions>, ILoggerFactory, IResponseCachingPolicyProvider, IResponseCache,
IResponseCachingKeyProvider)

Data Protection: DataProtection.Blobs uses new Azure Storage APIs


Azure.Extensions.AspNetCore.DataProtection.Blobs depends on the Azure Storage libraries. These libraries
renamed their assemblies, packages, and namespaces. Starting in ASP.NET Core 3.0,
Azure.Extensions.AspNetCore.DataProtection.Blobs uses the new Azure.Storage. -prefixed APIs and packages.

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

Hosting: AspNetCoreModule V1 removed from Windows Hosting Bundle


Starting with ASP.NET Core 3.0, the Windows Hosting Bundle won't contain AspNetCoreModule (ANCM) V1.
ANCM V2 is backwards compatible with ANCM OutOfProcess and is recommended for use with ASP.NET Core
3.0 apps.
For discussion, see dotnet/aspnetcore#7095.
Version introduced
3.0
Old behavior
ANCM V1 is included in the Windows Hosting Bundle.
New behavior
ANCM V1 isn't included in the Windows Hosting Bundle.
Reason for change
ANCM V2 is backwards compatible with ANCM OutOfProcess and is recommended for use with ASP.NET Core
3.0 apps.
Recommended action
Use ANCM V2 with ASP.NET Core 3.0 apps.
If ANCM V1 is required, it can be installed using the ASP.NET Core 2.1 or 2.2 Windows Hosting Bundle.
This change will break ASP.NET Core 3.0 apps that:
Explicitly opted into using ANCM V1 with <AspNetCoreModuleName>AspNetCoreModule</AspNetCoreModuleName> .
Have a custom web.config file with
<add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModule" resourceType="Unspecified" /> .
Category
ASP.NET Core
Affected APIs
None

Hosting: Generic host restricts Startup constructor injection


The only types the generic host supports for Startup class constructor injection are IHostEnvironment ,
IWebHostEnvironment , and IConfiguration . Apps using WebHost are unaffected.

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:

public void Configure(IApplicationBuilder app, IOptions<MyOptions> options)

Category
ASP.NET Core
Affected APIs
None

Hosting: HTTPS redirection enabled for IIS out-of-process apps


Version 13.0.19218.0 of the ASP.NET Core Module (ANCM) for hosting via IIS out-of-process enables an existing
HTTPS redirection feature for ASP.NET Core 3.0 and 2.2 apps.
For discussion, see dotnet/AspNetCore#15243.
Version introduced
3.0
Old behavior
The ASP.NET Core 2.1 project template first introduced support for HTTPS middleware methods like
UseHttpsRedirection and UseHsts. Enabling HTTPS redirection required the addition of configuration, since apps
in development don't use the default port of 443. HTTP Strict Transport Security (HSTS) is active only if the
request is already using HTTPS. Localhost is skipped by default.
New behavior
In ASP.NET Core 3.0, the IIS HTTPS scenario was enhanced. With the enhancement, an app could discover the
server's HTTPS ports and make UseHttpsRedirection work by default. The in-process component accomplished
port discovery with the IServerAddresses feature, which only affects ASP.NET Core 3.0 apps because the in-
process library is versioned with the framework. The out-of-process component changed to automatically add
the ASPNETCORE_HTTPS_PORT environment variable. This change affected both ASP.NET Core 2.2 and 3.0 apps
because the out-of-process component is shared globally. ASP.NET Core 2.1 apps aren't affected because they
use a prior version of ANCM by default.
The preceding behavior was modified in ASP.NET Core 3.0.1 and 3.1.0 Preview 3 to reverse the behavior changes
in ASP.NET Core 2.x. These changes only affect IIS out-of-process apps.
As detailed above, installing ASP.NET Core 3.0.0 had the side effect of also activating the UseHttpsRedirection
middleware in ASP.NET Core 2.x apps. A change was made to ANCM in ASP.NET Core 3.0.1 and 3.1.0 Preview 3
such that installing them no longer has this effect on ASP.NET Core 2.x apps. The ASPNETCORE_HTTPS_PORT
environment variable that ANCM populated in ASP.NET Core 3.0.0 was changed to ASPNETCORE_ANCM_HTTPS_PORT
in ASP.NET Core 3.0.1 and 3.1.0 Preview 3. UseHttpsRedirection was also updated in these releases to
understand both the new and old variables. ASP.NET Core 2.x won't be updated. As a result, it reverts to the
previous behavior of being disabled by default.
Reason for change
Improved ASP.NET Core 3.0 functionality.
Recommended action
No action is required if you want all clients to use HTTPS. To allow some clients to use HTTP, take one of the
following steps:
Remove the calls to UseHttpsRedirection and UseHsts from your project's Startup.Configure method,
and redeploy the app.
In your web.config file, set the ASPNETCORE_HTTPS_PORT environment variable to an empty string. This
change can occur directly on the server without redeploying the app. For example:
<aspNetCore processPath="dotnet" arguments=".\WebApplication3.dll" stdoutLogEnabled="false"
stdoutLogFile="\\?\%home%\LogFiles\stdout" >
<environmentVariables>
<environmentVariable name="ASPNETCORE_HTTPS_PORT" value="" />
</environmentVariables>
</aspNetCore>

UseHttpsRedirection can still be:


Activated manually in ASP.NET Core 2.x by setting the ASPNETCORE_HTTPS_PORT environment variable to the
appropriate port number (443 in most production scenarios).
Deactivated in ASP.NET Core 3.x by defining ASPNETCORE_ANCM_HTTPS_PORT with an empty string value. This
value is set in the same fashion as the preceding ASPNETCORE_HTTPS_PORT example.

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)

Hosting: IHostingEnvironment and IApplicationLifetime types marked obsolete and replaced


New types have been introduced to replace existing IHostingEnvironment and IApplicationLifetime types.
Version introduced
3.0
Old behavior
There were two different IHostingEnvironment and IApplicationLifetime types from
Microsoft.Extensions.Hosting and Microsoft.AspNetCore.Hosting .
New behavior
The old types have been marked as obsolete and replaced with new types.
Reason for change
When Microsoft.Extensions.Hosting was introduced in ASP.NET Core 2.1, some types like IHostingEnvironment
and IApplicationLifetime were copied from Microsoft.AspNetCore.Hosting . Some ASP.NET Core 3.0 changes
cause apps to include both the Microsoft.Extensions.Hosting and Microsoft.AspNetCore.Hosting namespaces.
Any use of those duplicate types causes an "ambiguous reference" compiler error when both namespaces are
referenced.
Recommended action
Replaced any usages of the old types with the newly introduced types as below:
Obsolete types (warning):
Microsoft.Extensions.Hosting.IHostingEnvironment
Microsoft.AspNetCore.Hosting.IHostingEnvironment
Microsoft.Extensions.Hosting.IApplicationLifetime
Microsoft.AspNetCore.Hosting.IApplicationLifetime
Microsoft.Extensions.Hosting.EnvironmentName
Microsoft.AspNetCore.Hosting.EnvironmentName
New types:
Microsoft.Extensions.Hosting.IHostEnvironment
Microsoft.AspNetCore.Hosting.IWebHostEnvironment : IHostEnvironment
Microsoft.Extensions.Hosting.IHostApplicationLifetime
Microsoft.Extensions.Hosting.Environments
The new IHostEnvironment IsDevelopmentand IsProduction extension methods are in the
Microsoft.Extensions.Hosting namespace. That namespace may need to be added to your project.
Category
ASP.NET Core
Affected APIs
Microsoft.AspNetCore.Hosting.EnvironmentName
Microsoft.AspNetCore.Hosting.IApplicationLifetime
Microsoft.AspNetCore.Hosting.IHostingEnvironment
Microsoft.Extensions.Hosting.EnvironmentName
Microsoft.Extensions.Hosting.IApplicationLifetime
Microsoft.Extensions.Hosting.IHostingEnvironment

Hosting: ObjectPoolProvider removed from WebHostBuilder dependencies


As part of making ASP.NET Core more pay for play, the ObjectPoolProvider was removed from the main set of
dependencies. Specific components relying on ObjectPoolProvider now add it themselves.
For discussion, see dotnet/aspnetcore#5944.
Version introduced
3.0
Old behavior
WebHostBuilder provides ObjectPoolProvider by default in the DI container.
New behavior
WebHostBuilder no longer provides ObjectPoolProvider by default in the DI container.
Reason for change
This change was made to make ASP.NET Core more pay for play.
Recommended action
If your component requires ObjectPoolProvider , it needs to be added to your dependencies via the
IServiceCollection .

Category
ASP.NET Core
Affected APIs
None

HTTP: DefaultHttpContext extensibility removed


As part of ASP.NET Core 3.0 performance improvements, the extensibility of DefaultHttpContext was removed.
The class is now sealed . For more information, see dotnet/aspnetcore#6504.
If your unit tests use Mock<DefaultHttpContext> , use Mock<HttpContext> or new DefaultHttpContext() instead.
For discussion, see dotnet/aspnetcore#6534.
Version introduced
3.0
Old behavior
Classes can derive from DefaultHttpContext .
New behavior
Classes can't derive from DefaultHttpContext .
Reason for change
The extensibility was provided initially to allow pooling of the HttpContext , but it introduced unnecessary
complexity and impeded other optimizations.
Recommended action
If you're using Mock<DefaultHttpContext> in your unit tests, begin using Mock<HttpContext> instead.
Category
ASP.NET Core
Affected APIs
Microsoft.AspNetCore.Http.DefaultHttpContext

HTTP: HeaderNames constants changed to static readonly


Starting in ASP.NET Core 3.0 Preview 5, the fields in Microsoft.Net.Http.Headers.HeaderNames changed from
const to static readonly .

For discussion, see dotnet/aspnetcore#9514.


Version introduced
3.0
Old behavior
These fields used to be const .
New behavior
These fields are now static readonly .
Reason for change
The change:
Prevents the values from being embedded across assembly boundaries, allowing for value corrections as
needed.
Enables faster reference equality checks.
Recommended action
Recompile against 3.0. Source code using these fields in the following ways can no longer do so:
As an attribute argument
As a case in a switch statement
When defining another const
To work around the breaking change, switch to using self-defined header name constants or string literals.
Category
ASP.NET Core
Affected APIs
Microsoft.Net.Http.Headers.HeaderNames

HTTP: Response body infrastructure changes


The infrastructure backing an HTTP response body has changed. If you're using HttpResponse directly, you
shouldn't need to make any code changes. Read further if you're wrapping or replacing HttpResponse.Body or
accessing HttpContext.Features .
Version introduced
3.0
Old behavior
There were three APIs associated with the HTTP response body:
IHttpResponseFeature.Body
IHttpSendFileFeature.SendFileAsync
IHttpBufferingFeature.DisableResponseBuffering

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

HTTP: Some cookie SameSite defaults changed to None


SameSite is an option for cookies that can help mitigate some Cross-Site Request Forgery (CSRF) attacks. When
this option was initially introduced, inconsistent defaults were used across various ASP.NET Core APIs. The
inconsistency has led to confusing results. As of ASP.NET Core 3.0, these defaults are better aligned. You must
opt in to this feature on a per-component basis.
Version introduced
3.0
Old behavior
Similar ASP.NET Core APIs used different default SameSiteMode values. An example of the inconsistency is seen
in HttpResponse.Cookies.Append(String, String) and
HttpResponse.Cookies.Append(String, String, CookieOptions) , which defaulted to SameSiteMode.None and
SameSiteMode.Lax , respectively.

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

HTTP: Synchronous IO disabled in all servers


Starting with ASP.NET Core 3.0, synchronous server operations are disabled by default.
Change description
AllowSynchronousIO is an option in each server that enables or disables synchronous IO APIs like
HttpRequest.Body.Read , HttpResponse.Body.Write , and Stream.Flush . These APIs have long been a source of
thread starvation and app hangs. Starting in ASP.NET Core 3.0 Preview 3, these synchronous operations are
disabled by default.
Affected servers:
Kestrel
HttpSys
IIS in-process
TestServer
Expect errors similar to:
Synchronous operations are disallowed. Call ReadAsync or set AllowSynchronousIO to true instead.
Synchronous operations are disallowed. Call WriteAsync or set AllowSynchronousIO to true instead.
Synchronous operations are disallowed. Call FlushAsync or set AllowSynchronousIO to true instead.

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:

var syncIOFeature = HttpContext.Features.Get<IHttpBodyControlFeature>();


if (syncIOFeature != null)
{
syncIOFeature.AllowSynchronousIO = true;
}

If you have trouble with a TextWriter or another stream calling a synchronous API in Dispose , call the new
DisposeAsync API instead.

For discussion, see dotnet/aspnetcore#7644.


Version introduced
3.0
Old behavior
HttpRequest.Body.Read , HttpResponse.Body.Write , and Stream.Flush were allowed by default.
New behavior
These synchronous APIs are disallowed by default:
Expect errors similar to:
Synchronous operations are disallowed. Call ReadAsync or set AllowSynchronousIO to true instead.
Synchronous operations are disallowed. Call WriteAsync or set AllowSynchronousIO to true instead.
Synchronous operations are disallowed. Call FlushAsync or set AllowSynchronousIO to true instead.

Reason for change


These synchronous APIs have long been a source of thread starvation and app hangs. Starting in ASP.NET Core
3.0 Preview 3, the synchronous operations are disabled by default.
Recommended action
Use the asynchronous versions of the methods. The behavior can also be overridden on a per-request basis as a
temporary mitigation.

var syncIOFeature = HttpContext.Features.Get<IHttpBodyControlFeature>();


if (syncIOFeature != null)
{
syncIOFeature.AllowSynchronousIO = true;
}

Category
ASP.NET Core
Affected APIs
Stream.Flush
Stream.Read
Stream.Write

Identity: AddDefaultUI method overload removed


Starting with ASP.NET Core 3.0, the IdentityBuilderUIExtensions.AddDefaultUI(IdentityBuilder,UIFramework)
method overload no longer exists.
Version introduced
3.0
Reason for change
This change was a result of adoption of the static web assets feature.
Recommended action
Call IdentityBuilderUIExtensions.AddDefaultUI(IdentityBuilder) instead of the overload that takes two arguments.
If you're using Bootstrap 3, also add the following line to a <PropertyGroup> element in your project file:

<IdentityUIFrameworkVersion>Bootstrap3</IdentityUIFrameworkVersion>

Category
ASP.NET Core
Affected APIs
IdentityBuilderUIExtensions.AddDefaultUI(IdentityBuilder,UIFramework)

Identity: Default Bootstrap version of UI changed


Starting in ASP.NET Core 3.0, Identity UI defaults to using version 4 of Bootstrap.
Version introduced
3.0
Old behavior
The services.AddDefaultIdentity<IdentityUser>().AddDefaultUI(); method call was the same as
services.AddDefaultIdentity<IdentityUser>().AddDefaultUI(UIFramework.Bootstrap3);

New behavior
The services.AddDefaultIdentity<IdentityUser>().AddDefaultUI(); method call is the same as
services.AddDefaultIdentity<IdentityUser>().AddDefaultUI(UIFramework.Bootstrap4);

Reason for change


Bootstrap 4 was released during ASP.NET Core 3.0 timeframe.
Recommended action
You're impacted by this change if you use the default Identity UI and have added it in Startup.ConfigureServices
as shown in the following example:

services.AddDefaultIdentity<IdentityUser>().AddDefaultUI();

Take one of the following actions:


Migrate your app to use Bootstrap 4 using their migration guide.
Update Startup.ConfigureServices to enforce usage of Bootstrap 3. For example:

services.AddDefaultIdentity<IdentityUser>().AddDefaultUI(UIFramework.Bootstrap3);

Category
ASP.NET Core
Affected APIs
None

Identity: SignInAsync throws exception for unauthenticated identity


By default, SignInAsync throws an exception for principals / identities in which IsAuthenticated is false .
Version introduced
3.0
Old behavior
SignInAsync accepts any principals / identities, including identities in which IsAuthenticated is false .
New behavior
By default, SignInAsync throws an exception for principals / identities in which IsAuthenticated is false .
There's a new flag to suppress this behavior, but the default behavior has changed.
Reason for change
The old behavior was problematic because, by default, these principals were rejected by [Authorize] /
RequireAuthenticatedUser() .

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

Identity: SignInManager constructor accepts new parameter


Starting with ASP.NET Core 3.0, a new IUserConfirmation<TUser> parameter was added to the SignInManager
constructor. For more information, see dotnet/aspnetcore#8356.
Version introduced
3.0
Reason for change
The motivation for the change was to add support for new email / confirmation flows in Identity.
Recommended action
If manually constructing a SignInManager , provide an implementation of IUserConfirmation or grab one from
dependency injection to provide.
Category
ASP.NET Core
Affected APIs
SignInManager<TUser>

Identity: UI uses static web assets feature


ASP.NET Core 3.0 introduced a static web assets feature, and Identity UI has adopted it.
Change description
As a result of Identity UI adopting the static web assets feature:
Framework selection is accomplished by using the IdentityUIFrameworkVersion property in your project file.
Bootstrap 4 is the default UI framework for Identity UI. Bootstrap 3 has reached end of life, and you should
consider migrating to a supported version.
Version introduced
3.0
Old behavior
The default UI framework for Identity UI was Bootstrap 3 . The UI framework could be configured using a
parameter to the AddDefaultUI method call in Startup.ConfigureServices .
New behavior
The default UI framework for Identity UI is Bootstrap 4 . The UI framework must be configured in your project
file, instead of in the AddDefaultUI method call.
Reason for change
Adoption of the static web assets feature required that the UI framework configuration move to MSBuild. The
decision on which framework to embed is a build-time decision, not a runtime decision.
Recommended action
Review your site UI to ensure the new Bootstrap 4 components are compatible. If necessary, use the
IdentityUIFrameworkVersion MSBuild property to revert to Bootstrap 3. Add the property to a <PropertyGroup>
element in your project file:

<IdentityUIFrameworkVersion>Bootstrap3</IdentityUIFrameworkVersion>

Category
ASP.NET Core
Affected APIs
IdentityBuilderUIExtensions.AddDefaultUI(IdentityBuilder, UIFramework)

Kestrel: Connection adapters removed


As part of the move to move "pubternal" APIs to public , the concept of an IConnectionAdapter was removed
from Kestrel. Connection adapters are being replaced with connection middleware (similar to HTTP middleware
in the ASP.NET Core pipeline, but for lower-level connections). HTTPS and connection logging have moved from
connection adapters to connection middleware. Those extension methods should continue to work seamlessly,
but the implementation details have changed.
For more information, see dotnet/aspnetcore#11412. For discussion, see dotnet/aspnetcore#11475.
Version introduced
3.0
Old behavior
Kestrel extensibility components were created using IConnectionAdapter .
New behavior
Kestrel extensibility components are created as middleware.
Reason for change
This change is intended to provide a more flexible extensibility architecture.
Recommended action
Convert any implementations of IConnectionAdapter to use the new middleware pattern as shown here.
Category
ASP.NET Core
Affected APIs
Microsoft.AspNetCore.Server.Kestrel.Core.Adapter.Internal.IConnectionAdapter

Kestrel: Empty HTTPS assembly removed


The assembly Microsoft.AspNetCore.Server.Kestrel.Https has been removed.
Version introduced
3.0
Reason for change
In ASP.NET Core 2.1, the contents of Microsoft.AspNetCore.Server.Kestrel.Https were moved to
Microsoft.AspNetCore.Server.Kestrel.Core. This change was done in a non-breaking way using
[TypeForwardedTo] attributes.

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

Kestrel: Request trailer headers moved to new collection


In prior versions, Kestrel added HTTP/1.1 chunked trailer headers into the request headers collection when the
request body was read to the end. This behavior caused concerns about ambiguity between headers and trailers.
The decision was made to move the trailers to a new collection.
HTTP/2 request trailers were unavailable in ASP.NET Core 2.2 but are now also available in this new collection in
ASP.NET Core 3.0.
New request extension methods have been added to access these trailers.
HTTP/1.1 trailers are available once the entire request body has been read.
HTTP/2 trailers are available once they're received from the client. The client won't send the trailers until the
entire request body has been at least buffered by the server. You may need to read the request body to free up
buffer space. Trailers are always available if you read the request body to the end. The trailers mark the end of
the body.
Version introduced
3.0
Old behavior
Request trailer headers would be added to the HttpRequest.Headers collection.
New behavior
Request trailer headers aren't present in the HttpRequest.Headers collection. Use the following extension
methods on HttpRequest to access them:
GetDeclaredTrailers() - Gets the request "Trailer" header that lists which trailers to expect after the body.
SupportsTrailers() - Indicates if the request supports receiving trailer headers.
CheckTrailersAvailable() - Determines if the request supports trailers and if they're available for reading.
GetTrailer(string trailerName) - Gets the requested trailing header from the response.
Reason for change
Trailers are a key feature in scenarios like gRPC. Merging the trailers in to request headers was confusing to
users.
Recommended action
Use the trailer-related extension methods on HttpRequest to access trailers.
Category
ASP.NET Core
Affected APIs
HttpRequest.Headers

Kestrel: Transport abstractions removed and made public


As part of moving away from "pubternal" APIs, the Kestrel transport layer APIs are exposed as a public interface
in the Microsoft.AspNetCore.Connections.Abstractions library.
Version introduced
3.0
Old behavior
Transport-related abstractions were available in the
Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions library.
The ListenOptions.NoDelay property was available.
New behavior
The IConnectionListener interface was introduced in the Microsoft.AspNetCore.Connections.Abstractions
library to expose the most used functionality from the ...Transport.Abstractions library.
The NoDelay is now available in transport options ( LibuvTransportOptions and SocketTransportOptions ).
SchedulingMode is no longer available.

Reason for change


ASP.NET Core 3.0 has moved away from "pubternal" APIs.
Recommended action
Category
ASP.NET Core
Affected APIs
None

Localization: ResourceManagerWithCultureStringLocalizer and WithCulture marked obsolete


The ResourceManagerWithCultureStringLocalizer class and WithCulture interface member are often sources of
confusion for users of localization, especially when creating their own IStringLocalizer implementation. These
items give the user the impression that an IStringLocalizer instance is "per-language, per-resource". In reality,
the instances should only be "per-resource". The language searched for is determined by the
CultureInfo.CurrentUICulture at execution time. To eliminate the source of confusion, the APIs were marked as
obsolete in ASP.NET Core 3.0 Preview 3. The APIs will be removed in a future release.
For context, see dotnet/aspnetcore#3324. For discussion, see dotnet/aspnetcore#7756.
Version introduced
3.0
Old behavior
Methods weren't marked as Obsolete .
New behavior
Methods are marked Obsolete .
Reason for change
The APIs represented a use case that isn't recommended. There was confusion about the design of localization.
Recommended action
The recommendation is to use ResourceManagerStringLocalizer instead. Let the culture be set by the
CurrentCulture . If that isn't an option, create and use a copy of ResourceManagerWithCultureStringLocalizer.

Category
ASP.NET Core
Affected APIs
ResourceManagerWithCultureStringLocalizer
ResourceManagerStringLocalizer.WithCulture

Logging: DebugLogger class made internal


Prior to ASP.NET Core 3.0, DebugLogger 's access modifier was public . In ASP.NET Core 3.0, the access modifier
changed to internal .
Version introduced
3.0
Reason for change
The change is being made to:
Enforce consistency with other logger implementations such as ConsoleLogger .
Reduce the API surface.
Recommended action
Use the AddDebug ILoggingBuilder extension method to enable debug logging. DebugLoggerProvider is also
still public in the event the service needs to be registered manually.
Category
ASP.NET Core
Affected APIs
Microsoft.Extensions.Logging.Debug.DebugLogger

MVC: Async suffix trimmed from controller action names


As part of addressing dotnet/aspnetcore#4849, ASP.NET Core MVC trims the suffix Async from action names by
default. Starting with ASP.NET Core 3.0, this change affects both routing and link generation.
Version introduced
3.0
Old behavior
Consider the following ASP.NET Core MVC controller:

public class ProductController : Controller


{
public async IActionResult ListAsync()
{
var model = await DbContext.Products.ToListAsync();
return View(model);
}
}

The action is routable via Product/ListAsync . Link generation requires specifying the Async suffix. For example:

<a asp-controller="Product" asp-action="ListAsync">List</a>

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:

<a asp-controller="Product" asp-action="List">List</a>

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;
});

Reason for change


By convention, asynchronous .NET methods are suffixed with Async . However, when a method defines an MVC
action, it's undesirable to use the Async suffix.
Recommended action
If your app depends on MVC actions preserving the name's Async suffix, choose one of the following
mitigations:
Use the [ActionName] attribute to preserve the original name.
Disable the renaming entirely by setting MvcOptions.SuppressAsyncSuffixInActionNames to false in
Startup.ConfigureServices :

services.AddMvc(options =>
{
options.SuppressAsyncSuffixInActionNames = false;
});

Category
ASP.NET Core
Affected APIs
None

MVC: JsonResult moved to Microsoft.AspNetCore.Mvc.Core


JsonResult has moved to the Microsoft.AspNetCore.Mvc.Core assembly. This type used to be defined in
Microsoft.AspNetCore.Mvc.Formatters.Json. An assembly-level [TypeForwardedTo] attribute was added to
Microsoft.AspNetCore.Mvc.Formatters.Json to address this issue for the majority of users. Apps that use third-
party libraries may encounter issues.
Version introduced
3.0 Preview 6
Old behavior
An app using a 2.2-based library builds successfully.
New behavior
An app using a 2.2-based library fails compilation. An error containing a variation of the following text is
provided:

The type 'JsonResult' exists in both 'Microsoft.AspNetCore.Mvc.Core, Version=3.0.0.0, Culture=neutral,


PublicKeyToken=adb9793829ddae60' and 'Microsoft.AspNetCore.Mvc.Formatters.Json, Version=2.0.0.0,
Culture=neutral, PublicKeyToken=adb9793829ddae60'

For an example of such an issue, see dotnet/aspnetcore#7220.


Reason for change
Platform-level changes to the composition of ASP.NET Core as described at aspnet/Announcements#325.
Recommended action
Libraries compiled against the 2.2 version of Microsoft.AspNetCore.Mvc.Formatters.Json may need to recompile
to address the problem for all consumers. If affected, contact the library author. Request recompilation of the
library to target ASP.NET Core 3.0.
Category
ASP.NET Core
Affected APIs
Microsoft.AspNetCore.Mvc.JsonResult

MVC: Precompilation tool deprecated


In ASP.NET Core 1.1, the Microsoft.AspNetCore.Mvc.Razor.ViewCompilation (MVC precompilation tool) package
was introduced to add support for publish-time compilation of Razor files (.cshtml files). In ASP.NET Core 2.1, the
Razor SDK was introduced to expand upon features of the precompilation tool. The Razor SDK added support
for build- and publish-time compilation of Razor files. The SDK verifies the correctness of .cshtml files at build
time while improving on app startup time. The Razor SDK is on by default, and no gesture is required to start
using it.
In ASP.NET Core 3.0, the ASP.NET Core 1.1-era MVC precompilation tool was removed. Earlier package versions
will continue receiving important bug and security fixes in the patch release.
Version introduced
3.0
Old behavior
The Microsoft.AspNetCore.Mvc.Razor.ViewCompilation package was used to pre-compile MVC Razor views.
New behavior
The Razor SDK natively supports this functionality. The Microsoft.AspNetCore.Mvc.Razor.ViewCompilation package
is no longer updated.
Reason for change
The Razor SDK provides more functionality and verifies the correctness of .cshtml files at build time. The SDK
also improves app startup time.
Recommended action
For users of ASP.NET Core 2.1 or later, update to use the native support for precompilation in the Razor SDK. If
bugs or missing features prevent migration to the Razor SDK, open an issue at dotnet/aspnetcore.
Category
ASP.NET Core
Affected APIs
None

MVC: "Pubternal" types changed to internal


In ASP.NET Core 3.0, all "pubternal" types in MVC were updated to either be public in a supported namespace
or internal as appropriate.
Change description
In ASP.NET Core, "pubternal" types are declared as public but reside in a .Internal -suffixed namespace. While
these types are public , they have no support policy and are subject to breaking changes. Unfortunately,
accidental use of these types has been common, resulting in breaking changes to these projects and limiting the
ability to maintain the framework.
Version introduced
3.0
Old behavior
Some types in MVC were public but in a .Internal namespace. These types had no support policy and were
subject to breaking changes.
New behavior
All such types are updated either to be public in a supported namespace or marked as internal .
Reason for change
Accidental use of the "pubternal" types has been common, resulting in breaking changes to these projects and
limiting the ability to maintain the framework.
Recommended action
If you're using types that have become truly public and have been moved into a new, supported namespace,
update your references to match the new namespaces.
If you're using types that have become marked as internal , you'll need to find an alternative. The previously
"pubternal" types were never sup