Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Document what's new in ASP.NET Core for .NET 9 Preview 5 #32692

Closed
danroth27 opened this issue May 29, 2024 · 10 comments
Closed

Document what's new in ASP.NET Core for .NET 9 Preview 5 #32692

danroth27 opened this issue May 29, 2024 · 10 comments
Assignees
Labels
9.0 .NET 9 aspnet-core/svc release-notes/subsvc Source - Docs.ms Docs Customer feedback via GitHub Issue

Comments

@danroth27
Copy link
Member

Description

Update the "What's new in ASP.NET Core 9.0" for .NET 9 Preview 5

Page URL

https://learn.microsoft.com/en-us/aspnet/core/release-notes/aspnetcore-9.0?view=aspnetcore-8.0

Content source URL

https://github.com/dotnet/AspNetCore.Docs/blob/main/aspnetcore/release-notes/aspnetcore-9.0.md

Document ID

4e75ad25-2c3f-b28e-6a91-ac79a9c683b6

Article author

@Rick-Anderson @tdykstra @guardrex

@mkArtakMSFT
Copy link
Member

@MackinnonBuck please add a comment documenting the ReconnectionUI work that you've done.

@mkArtakMSFT
Copy link
Member

mkArtakMSFT commented May 29, 2024

@javiercn please add a comment with the Static Assets compression work that you've done.
Also the new APIs for getting the current RenderMode please.

@mkArtakMSFT
Copy link
Member

@halter73 please add a comment documenting the AuthenticationStateProvider work.

@MackinnonBuck
Copy link
Member

MackinnonBuck commented Jun 7, 2024

Improved Blazor Server reconnection experience:

The following changes have been made to the default Blazor Server reconnection experience:

  • Reconnect timing now uses an exponential backoff strategy. The first several reconnection attempts will happen in rapid succession before a delay gradually gets introduced between attempts. This behavior can be customized by specifying a function to compute the retry interval. For example:
    Blazor.start({
      circuit: {
        reconnectionOptions: {
          retryIntervalMilliseconds: (previousAttempts, maxRetries) => previousAttempts >= maxRetries ? null : previousAttempts * 1000,
        },
      },
    });
  • When the user navigates back to an app with a disconnected circuit, a reconnect attempt gets immediately made rather than waiting for the duration of the next reconnect interval. This especially improves the user experience when navigating to an app in a browser tab that has gone to sleep.
  • If a reconnection attempt reaches the server, but reconnection fails because server had already released the circuit, a refresh occurs automatically. This prevents the user from having to manually refresh the page if it's likely going to result in a successful reconnection.
  • The styling of the default reconnect UI has been modernized.

@javiercn
Copy link
Member

javiercn commented Jun 7, 2024

Detect the current component render mode at runtime

We've introduced an API to make easier to answer 3 questions many component authors have. Making some scenarios more straightforward. These questions are:

  • Where is my component currently running.
  • Is my component running in an interactive environment.
  • What is the assigned render-mode for my component.

ComponentBase (and per extension your components) offer a new Platform property (soon to be renamed RendererInfo) that exposes a `(Name, and IsInteractive) properties.

  • Platform.Name answers the question "where am I currently running" and it can be Static, Server, WebAssembly or WebView.
  • Platform.IsInteractive indicates whether the platform supports interactivity. This is true for all implementations except Static.

Finally, the other property ComponentBase exposes is AssignedRenderMode. This property exposes the render mode value defined in the component hierarchy (if any) via the render-mode attribute on a root component or the [RenderMode] attribute. Its values can be InteractiveServer, InteractiveAuto or InteractiveWebassembly.

These values are most useful during prerendering, as they allow you to know where the component will transition to after prerendering, and you might use that to render different content.

For example, if you create a Form component and the form is going to be rendered interactively, you might choose to disable the inputs during prerendering, until the component becomes interactive and enables them.

Alternatively, if the component is not going to be rendered in an interactive context, you might render markup to support performing any action through regular web mechanics.

Optimizing static web asset delivery

A big part of delivering performant web applications involves optimizing asset delivery to the browser. This process entails many aspects, among some of them are:

  • Using ETags and Last-Modified.
  • Setting up proper caching headers.
  • Serving compressed versions of the assets when possible.
  • Etc.

To this effect, we are introducing a new functionality called MapStaticAssets. MapStaticAssets works by combining work done at build/publish time to gather information about all the static resources in your application with a runtime library that is capable of processing that information and using it to better serve the files to the browser.

MapStaticAssets can replace UseStaticFiles in most situations, however, its optimized for serving the assets that your app has knowledge off at build and publish time. This means that if your app serves assets from other locations on disk, or embedded resources, etc. then using UseStaticFiles is still the right choice.

What are the things that MapStaticAssets does that UseStaticFiles doesn't?

  • Build time compression for all the assets in the app, gzip during development and gzip + brotli during publish. All assets are compressed trying to reduce the size to the minimum.
  • Content based ETags: The Etags for each resource are the Base64 encoded string of the SHA-256 hash of the content. This ensures that the browser doesn't have to download the file again unless its contents change.

What are some of the gains that we can expect:

This is the default Razor Pages template (did we mention that this works for all UI flavors, Blazor, MVC, Razor Pages or your own custom framework?)

File Original Compressed % Reduction
bootstrap.min.css 163 17.5 89.26%
jquery.js 89.6 28 68.75%
bootstrap.min.js 78.5 20 74.52%

For a total of 331.1 KB uncompressed vs 65.5 KB compressed.

This is the reduction that you get if you use the Fluent UI Blazor components library:

File Original Compressed % Reduction
fluent.js 384 73 80.99%
fluent.css 94 11 88.30%

For a total of 478 KB uncompressed to 84 KB compressed.

Or, if you use other popular Blazor component libraries like MudBlazor:

File Original Compressed Reduction
MudBlazor.min.css 541 37.5 93.07%
MudBlazor.min.js 47.4 9.2 80.59%

For a total of 588.4 KB to 46.7 KB

The best part is that all of this happens automatically for the app after using MapStaticAssets. When you decide to bring in a new library or copy some new JS/CSS library to your project, you don't have to do anything. It'll get optimized as part of the build and served to the browser faster, which is especially important for mobile environments with lower bandwidth or spotty connections.

You might be wondering, if I have turn on dynamic compression on the server, how do I benefit from this? To begin, this approach is simpler, because there is no server specific configuration for you to figure out.

Then, even in this situation, you still benefit from leveraging MapStaticAssets instead of letting your IIS or other server do the compression for you. This is for two reasons:

  • You are able to spend extra time during the build process to ensure that the assets are as small as they can be. How much smaller? If we take MudBlazor as an example, IIS will compress the CSS bundle at around 90Kb, while brotli with max settings will result in 37Kb. That is still a whopping 59% size reduction or 41% of its dynamically compressed size.

@BethMassi
Copy link
Contributor

BethMassi commented Jun 7, 2024

.NET MAUI Blazor Hybrid and Web Solution Template

We are providing a new solution template in .NET 9 starting in Preview 5 to make it easier to create .NET MAUI native and Blazor web client apps that share the same UI. This allows you to create client apps that can target Android, iOS, Mac, Windows and Web maximizing code reuse.

The template allows you to choose a Blazor interactive render mode for the web app and will create the appropriate projects for you, including a Blazor Web App and a .NET MAUI Blazor Hybrid app. It will then wire them up to use a shared Razor Class Library that has all of the UI components and pages. It also includes sample code that shows you how to use service injection to provide different interface implementations for the Blazor Hybrid and Blazor Web App. In .NET 8 this is a manual process documented here: Build a .NET MAUI Blazor Hybrid app with a Blazor Web App.

To get started, install the .NET 9 SDK (Preview 5 or higher) then install the .NET MAUI workload which contains the template.

dotnet workload install maui

You can then create the template from the commandline like this:

dotnet new maui-blazor-web

Alternative, you can use the template from Visual Studio:

TODO: Show screen capture of the template in Visual Studio

Note: Currently Blazor hybrid apps do not ignore the Blazor rendering modes if they are defined at the per page/component level and will throw an error. This work will be completed in a subsequent preview of .NET 9. For more details see #51235.

@halter73
Copy link
Member

halter73 commented Jun 8, 2024

Simplified authentication state serialization for Blazor Web Apps

When you create a new Blazor Web App project with authentication using "Individual Accounts" and you enable WebAssembly-based interactivity, the project will include a custom AuthenticationStateProvider in both the server and client projects to flow the user's authentication state to the browser. Authenticating on the server rather than the client allows the app to access authentication state during prerendering and before the WebAssembly runtime is initialized. The custom AuthenticationStateProvider implementations use the PersistentComponentState service to serialize the authentication state into HTML comments and then read it back from WebAssembly to create a new AuthenticationState instance. This works well if you've started from the Blazor Web App project template and selected the "Individual Accounts" option, but it's a lot of code to implement yourself or copy if you're trying to add authentication to an existing project.

To make this easier, .NET 9 Preview 5 introduces AddAuthenticationStateSerialization and AddAuthenticationStateDeserialization APIs that can be called in the server and client projects:

// Server Program.cs
builder.Services.AddRazorComponents()
    .AddInteractiveWebAssemblyComponents()
    .AddAuthenticationStateSerialization();
// Client Program.cs
builder.Services.AddAuthorizationCore();
builder.Services.AddCascadingAuthenticationState();
builder.Services.AddAuthenticationStateDeserialization();

By default, this will only serialize the server-side name and role claims for access in the browser. If you want to include all claims, you can write the following on the server instead:

// Server Program.cs
builder.Services.AddRazorComponents()
    .AddInteractiveWebAssemblyComponents()
    .AddAuthenticationStateSerialization(options => options.SerializeAllClaims = true);

The Blazor Web App project template has been updated to use these APIs, so you can try out using the new template.

@guardrex
Copy link
Collaborator

Progress report:

  • I have three of five reference article DRAFTs up for review now.
  • The fourth of five is the Simplified authentication state serialization entry, which I'll take care of right after lunch 🥪☕.
  • The fifth will be the Blazor-specific static files work. I'll merely go with a cross-link to what Rick publishes for this evening and place the reference article content in the morning.
  • I haven't touched any of the Blazor What's New content yet. That will be addressed last later today ... and after Render mode /8 #32787 is merged.

I'll report back here later to confirm today's goals are achieved.

@guardrex
Copy link
Collaborator

guardrex commented Jun 10, 2024

Progress report:

All reference article content merged and cross-linked. What's New content for Blazor merged. 🍻

PR list ...

@guardrex
Copy link
Collaborator

guardrex commented Jun 11, 2024

I'm working on the Blazor-specific MapStaticAssets coverage. Done! Just waiting to hear if it will be reviewed or not.

FYI (I noticed in passing): The main doc set's Static Files article hasn't been updated for the new middleware:

https://learn.microsoft.com/en-us/aspnet/core/fundamentals/static-files?view=aspnetcore-9.0

Nevermind! That's covered by an open issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
9.0 .NET 9 aspnet-core/svc release-notes/subsvc Source - Docs.ms Docs Customer feedback via GitHub Issue
Projects
None yet
Development

No branches or pull requests

10 participants