Having covered the Net8 links, here's some highlights.
It's not a huge game-changing release. We can just change the TargetFramework and get some performance benefits, without rewriting or adding anything. The biggest changes are probably in Blazor, which seem to fulfil the promise of the technology. Only two new C# constructs, both of which are a bit more concise: collection initializers and primary constructors. The AOT is potentially interesting, but probably something for later .net versions. First Microsoft have to rework more of ASP, and then common libraries and techniques need to evolve to be compatible.
Performance
There are lots of perf improvements under the covers, in .net, asp, blazor...
Blazor
Blazor had 2 main models that look similar but are fundamentally different; server-side razor pages/websockets and compiled to browser webassembly. Net8 is a major release to add a new mode, Server-side rendering (SSR), and provide a simple way to move between the models (rendermode) within the same application, and even the same page (what was global to the project can now be component based).
NB: the _Imports.razor should have a import to refer to rendermode
Components/pages can have the rendermode directive - default (not specified) is static (or technically, inherit from parent), the other options are InteractiveServer, InteractiveClient and InteractiveAuto (= server, then client). You can specify this on the top of routable pages, or specify it on the component instance. InteractiveClient components must live in the client project, not the server project (so you download them; you don't want to download server-side components with entity framework etc).
This is the server side configuration for interactive server/client components.
{
var builder = WebApplication.CreateBuilder(args);
// Add services
builder.Services.AddRazorComponents()
//add interactive SERVER components (websockets)
.AddInteractiveServerComponents()
//add interactive WASM components (in the browser)
.AddInteractiveWebAssemblyComponents();
var app = builder.Build();
// Other stuff omitted.
app.UseStaticFiles();
app.MapRazorComponents<App>()
.AddInteractiveServerRenderMode()
.AddInteractiveWebAssemblyRenderMode()
.AddAdditionalAssemblies(typeof(ClientSideCmponent).Assembly);
app.Run();
}
There's a new extension, .webcil, for webassembly, to avoid downloading .dll files which corporate security used to block.
Asp.net - keyed services and routing
You could do keyed services with 3rd party DI frameworks like Autofac, but now the built-in DI supports it (add an attribute [FromKeyedServices(key)]).
Consuming in Blazor with an attribute:
public IMyService Service { get; set; } = default!;
Visual Studio colour-codes routes and uses analysers to spot problems.
Aspire (preview)
Aspire is a builder for cloud (i.e. Azure) applications. It's intended for developers, and uses C# code (not yaml!) to orchestrate your dependencies into containers. Most of the configuration glue is done for you (including specifying ports and connection strings, using internal service discovery), and it automatically adds best practices like metrics, logging and the Polly retry project. There are two new Visual Studio projects, AppHost (the startup project) and ServiceDefaults. Launching the AppHost brings up a developer dashboard to check the status.
Primary ctors on classes
You could do it with (immutable) Records before, but now you can do them on classes. You don't need constructor boilerplate- it is defined on the class line (you can also have conventional ctor overloads). Note the parameters are not hidden fields, they are initialization values; the values are captured in the properties. For simpler classes and DI, this makes sense. If you need logic, you need explicit constructors.
{
public string Name { get; } = name;
}
Collection initializing
Until .net 8 you initialize arrays/lists with curly brackets {} and a type or new().
var list = new List<int> { 1, 2, 3 };
Now you can use square brackets [] instead of curlies (like in javascript). It's always an enumerable to fill any array/list type.
You can concatenate/shallow copy stuff with the .. spread operator (also familiar from javascript)
int[] part2 = [4, 5, 6];
int[] all = [..part1, ..part2, 7, 8, 9];
AOT
AOT/Ahead-of-time compilation compiles .net into native code, so it starts faster and runs quicker.
- First check if can work in AOT: In the csproj, add IsAotCompatible true
- If ok, in the csproj, add PublishAot true
The huge limitation is you can't use reflection, which is used all over the place (any serialization including json, regex, things like automapper or even your DI scanning an assembly to map the interfaces to classes). Source generators (compile-time rewriting) can remove the reflection, and the asp team has done it for MinimalApis, but not for MVC/webapi/blazor.