.NET 7
Rainer Stropek | @rstropek
.NET 7 Status
- STS version
- .NET 6 was LTS
- Currently in RC
Introduction
Rainer Stropek
- Passionate software developers for 25+ years
ย - Microsoft MVP, Regional Director
ย - Trainer, Teacher, Mentor
ย - ๐ community
It is fast
๐๏ธ
Docker
Base Images
- https://hub.docker.com/_/microsoft-dotnet
- Base image types
- SDK
- ASP.NET Core
- Runtime
- Runtime dependencies
- .NET Monitor tool
- .NET Samples
- Fresh! ๐ฅฌ
- Including previews, RCs
Tagging
- .NET Version
- latest (stable)
- Major (e.g. 6.0, 7.0)
- Minor (e.g. 6.0.401, 7.0.100-rc.1)
- OS Type & Version
- Debian (e.g. 6.0-bullseye-slim)
- Alpine
- Ubuntu
- Windows Nano Server
- Windows Server Core
- Processor Architecture
- amd64 (e.g. 6.0-bullseye-slim-amd64)
- arm64, arm32
Multi-Stage Build
# https://hub.docker.com/_/microsoft-dotnet
FROM mcr.microsoft.com/dotnet/sdk:7.0 AS build
WORKDIR /source
# copy csproj and restore as distinct layers
COPY aspnetapp/*.csproj .
RUN dotnet restore --use-current-runtime
# copy everything else and build app
COPY aspnetapp/. .
RUN dotnet publish -c Release -o /app --use-current-runtime \
--self-contained false --no-restore
# final stage/image
FROM mcr.microsoft.com/dotnet/aspnet:7.0
WORKDIR /app
COPY --from=build /app .
ENTRYPOINT ["dotnet", "aspnetapp.dll"]
Build
Runtime
Challenge
- Non-trivial solutions consist of multiple projects
- Each project needs to be dockerized
- Where to put Dockerfiles?
- In project folder โก๏ธ solution-level config files missing in build context
- In solution folder โก๏ธ Dockerfiles are not in the project they belong to
- Specify complicated parameters during docker build
- Example:
- Centralized Package Mangement ๐, new in .NET 6/7 (demo)
Solution
Demo
Time!
Demo
# SLN folder is the current folder
dotnet publish --os linux --arch x64 -p:PublishProfile=DefaultContainer
docker images dotnet7api
docker tag <image-id> rstropek/dotnet7api
docker run -it --rm --name dotnet7api rstropek/dotnet7api
"Distroless" Images
- Ubuntu containers with ASP.NET Core apps are big
- Only solution until now: Alpine (supported by .NET)
- Everything you have in your container can be attacked
ย - Solution approach: "Distroless" images
- Slimmed down Linux distro plus all the app really needs
- No need for e.g. grep, cat, bash, etc.
- No root user
ย
- New: .NET in Chiseled Ubuntu Containers
.NET in Chiseled Ubuntu Containers
- ~50% smaller than regular Ubuntu
- Alpine is still an option
- Chiseled Ubuntu closer to Ubuntu dev env (e.g. no musl)
- No chiseled images for SDK
- Enhanced security
- Non-root images
- Secure supply chain between Canonical and MS
- Commercial support by Ubuntu
ย - And BTW: .NET 6 is now available in Ubuntu with a single
apt install command ๐๐-
sudo apt install dotnet6
-
Demo
Time!
Demo
# Based on previous demo
docker images dotnet7api
# Note size
# Add to .csproj:
# <ContainerBaseImage>mcr.microsoft.com/dotnet/nightly/aspnet:7.0-jammy-chiseled</ContainerBaseImage>
# Rebuild
dotnet publish --os linux --arch x64 -p:PublishProfile=DefaultContainer
docker images dotnet7api
# Note size difference
docker run -it --rm --name dotnet7api <image-id>
ref fields in
ref structs
Quick Recap: Ref Structs, Spans
ref structs can now contain ref fields
var v = 42;
var c = new Container<int>(ref v);
Console.WriteLine(c.Value);
// Change v. As c has a reference to v, c.Value changes, too.
v = 43;
Console.WriteLine(c.Value);
ref struct Container<T>
{
ref T value;
public Container(ref T value)
{
this.value = ref value;
}
public T Value
{
get => this.value;
set => this.value = value;
}
public void ChangeRef(ref T value) => this.value = ref value;
}
Demo
Time!
JSON Enhancements
Various JSON Enhancements
JSON Contract Customization
- Sometimes you want to influence serialization without changing the type
- E.g. external library, simply doesn't fit
- Now you can customize the JSON contract ๐
Demo
Time!
Regex Enhancements
RegEx Enhancements
- Regex became faster โก
- Lots of internal optimizations ๐
- Opt-out from backtracking with new RegexOptions.NonBacktrackingย option
- New StringSyntaxย attribute to enable editor support for custom methods
- RegEx Generator ๐ค
- Including analyzer and fixer to generate GeneratedRegex
Demo
Time!
Various Small
Improvements
Linq Enhancements
var data = new[] { 2, 1, 3 };
var sorted = data.Order();
// instead of
// var sorted = data.OrderBy(e => e);
var sortedDesc = data.OrderByDescending();
// instead of
// var sortedDesc = data.OrderByDescending(e => e);
LibraryImport
Demo
Time!
System.IO.Stream Enhancements
- Tedious to read an exact number of bytes using Stream.Read ๐
- New methods on System.IO.Stream
- ReadExactly
- ReadAtLeast
- Throw exception if stream ends unexpectedly
Nullable Annotations
- In all recent .NET versions, Microsoft and the community annotated additional libraries for nullablity
- In .NET 7: Microsoft.Extensions.*
- Want to learn more about nullablity?
Trimming,
Native AOT
ย
Trimming
- .NET 6: Types in the user project are fully preserved
- Only libs with <IsTrimmable>true</IsTrimmable>ย were trimmed
- .NET 7: All assemblies are trimmed by default
- If published with trimming or if using NativeAOT
- TrimMode fullย is now the default
- Use TrimMode partialย to revert to .NET 6 trimming behavior
- Problem: Types that are accessed using Reflection at runtime
- E.g. JSON deserialization with System.Text.Json
- โSolutions
- Configure trimming ๐
- Avoid reflection, prefer Code Generators
Quick Recap: Code Generators
- Runs during compilation
- Inspects your program (using Roslyn)
- Produces additional files that are compiled together with your app
Demo
Time!
Native AOT
- .NET has multiple AOT flavors
- crossgen2/ReadyToRun for client and server
- Mono AOT for mobile and WASM
- New in .NET 7: Native AOT
- Targets console apps and native libraries ๐
- <PublishAot>true</PublishAot>
- Limitations apply
- No code generation at runtime
- No loading of .NET assemblies at runtime
- Prepare for Native AOT: Make sure your libs/apps ๐ can be trimmed
- Code generators!
.NET 7 ๐ค
Rainer Stropek | @rstropek
.NET 7 Intro
By Rainer Stropek
.NET 7 Intro
- 732