ASP.NET Core updates in .NET 5 Preview 8 - Printable Version +- Sick Gaming (https://www.sickgaming.net) +-- Forum: Programming (https://www.sickgaming.net/forum-76.html) +--- Forum: C#, Visual Basic, & .Net Frameworks (https://www.sickgaming.net/forum-79.html) +--- Thread: ASP.NET Core updates in .NET 5 Preview 8 (/thread-97179.html) |
ASP.NET Core updates in .NET 5 Preview 8 - xSicKxBot - 09-11-2020 ASP.NET Core updates in .NET 5 Preview 8 <div style="margin: 5px 5% 10px 5%;"><img src="https://www.sickgaming.net/blog/wp-content/uploads/2020/08/asp-net-core-updates-in-net-5-preview-8.jpg" width="150" height="150" title="" alt="" /></div><div><div class="row justify-content-center"> <div class="col-md-4"> <div><img loading="lazy" src="https://www.sickgaming.net/blog/wp-content/uploads/2020/08/asp-net-core-updates-in-net-5-preview-8.jpg" width="58" height="58" alt="Daniel Roth" class="avatar avatar-58 wp-user-avatar wp-user-avatar-58 alignnone photo"></p> <p>Daniel</p> </div> </div> </div> <div class="entry-meta entry-meta-layout"> <p>August 25th, 2020</p> </p></div> <p><!-- .entry-meta --> </p> <p><a href="https://devblogs.microsoft.com/dotnet/announcing-net-5-0-preview-8/">.NET 5 Preview 8 is now available</a> and is ready for evaluation. Here’s what’s new in this release:</p> <ul> <li>Azure Active Directory authentication with Microsoft.Identity.Web</li> <li>CSS isolation for Blazor components</li> <li>Lazy loading in Blazor WebAssembly</li> <li>Updated Blazor WebAssembly globalization support</li> <li>New <code>InputRadio</code> Blazor component</li> <li>Set UI focus in Blazor apps</li> <li>Influencing the HTML head in Blazor apps</li> <li><code>IAsyncDisposable</code> for Blazor components</li> <li>Control Blazor component instantiation</li> <li>Protected browser storage</li> <li>Model binding and validation with C# 9 record types</li> <li>Improvements to <code>DynamicRouteValueTransformer</code></li> <li>Auto refresh with <code>dotnet watch</code></li> <li>Console Logger Formatter</li> <li>JSON Console Logger</li> </ul> <p>See the <a href="https://github.com/dotnet/core/blob/master/release-notes/5.0">.NET 5 release notes</a> for additional details and known issues.</p> <h2 id="get-started">Get started</h2> <p>To get started with ASP.NET Core in .NET 5 Preview 8 <a href="https://dotnet.microsoft.com/download/dotnet-core/5.0">install the .NET 5 SDK</a>.</p> <p>You need to use <a href="https://visualstudio.microsoft.com/vs/preview/">Visual Studio 2019 16.8 Preview 2</a> or newer to use .NET 5 Preview 8. .NET 5 is also supported with the latest <a href="https://docs.microsoft.com/visualstudio/mac/install-preview">preview</a> of <a href="https://visualstudio.microsoft.com/">Visual Studio for Mac</a>. To use .NET 5 with <a href="https://visualstudio.microsoft.com/">Visual Studio Code</a>, install the latest version of the <a href="https://code.visualstudio.com/Docs/languages/csharp">C# extension</a>.</p> <h2 id="upgrade-an-existing-project">Upgrade an existing project</h2> <p>To upgrade an existing ASP.NET Core app from .NET 5 Preview 7 to .NET 5 Preview 8:</p> <ul> <li>Update all Microsoft.AspNetCore.* package references to <code>5.0.0-preview.8.*</code>.</li> <li>Update all Microsoft.Extensions.* package references to <code>5.0.0-preview.8.*</code>.</li> <li>Update System.Net.Http.Json package references to <code>5.0.0-preview.8.*</code>.</li> </ul> <p>That’s it! You should be all ready to go.</p> <p>See also the full list of <a href="https://github.com/aspnet/announcements/issues?q=is%3Aopen+is%3Aissue+milestone%3A5.0+label%3A%22Breaking+change%22">breaking changes</a> in ASP.NET Core for .NET 5.</p> <h2 id="whats-new">What’s new?</h2> <h3 id="azure-active-directory-authentication-with-microsoft-identity-web">Azure Active Directory authentication with Microsoft.Identity.Web</h3> <p>The ASP.NET Core project templates now integrate with <a href="https://github.com/AzureAD/microsoft-identity-web/">Microsoft.Identity.Web</a> to handle authentication with Azure Activity Directory (Azure AD). The Microsoft.Identity.Web package provides a better experience for authentication through Azure AD as well as an easier way to access Azure resources on behalf of your users, including Microsoft Graph. Check out the Microsoft.Identity.Web <a href="https://github.com/Azure-Samples/active-directory-aspnetcore-webapp-openidconnect-v2">sample</a> that take you from a simple login through multi-tenancy, using Azure APIs, using Microsoft Graph, and protecting your own APIs. Microsoft.Identity.Web will be generally available alongside .NET 5.</p> <h3 id="css-isolation-for-blazor-components">CSS isolation for Blazor components</h3> <p>Blazor now supports defining CSS styles that are scoped to a given component. Component specific CSS styles make it easier to reason about the styles in your app and to avoid unintentional side effects from global styles. You define component specific styles in a <em>.razor.css</em> file the matches the name of the <em>.razor</em> file for the component.</p> <p>For example, let’s say you have a component <em>MyComponent.razor</em> file that looks like this:</p> <p><em>MyComponent.razor</em></p> <pre><code class="html"><h1>My Component</h1> <ul class="cool-list"> <li>Item1</li> <li>Item2</li> </ul> </code></pre> <p>You can then define a <em>MyComponent.razor.css</em> with the styles for MyComponent:</p> <p><em>MyComponent.razor.css</em></p> <pre><code class="css">h1 { font-family: 'Comic Sans MS' } .cool-list li { color: red; } </code></pre> <p>The styles in <em>MyComponent.razor.css</em> will only get applied to the rendered output of MyComponent; the <code>h1</code> elements rendered by other components, for example, are not affected.</p> <p>To write a selector in component specific styles that affects child components, use the <code>::deep</code> combinator.</p> <pre><code class="css">.parent ::deep .child { color: red; } </code></pre> <p>By using the <code>::deep</code> combinator, only the <code>.parent</code> class selector is scoped to the component; the <code>.child</code> class selector is not scoped, and will match content from child components.</p> <p>Blazor achieves CSS isolation by rewriting the CSS selectors as part of the build so that they only match markup rendered by the component. Blazor then bundles together the rewritten CSS files and makes the bundle available to the app as a static web asset at the path <em>_framework/scoped.styles.css</em>.</p> <p>While Blazor doesn’t natively support CSS preprocessors like Sass or Less, you can still use CSS preprocessors to generate component specific styles before they are rewritten as part of the building the project.</p> <h3 id="lazy-loading-in-blazor-webassembly">Lazy loading in Blazor WebAssembly</h3> <p>Lazy loading enables you to improve the load time of your Blazor WebAssembly app by deferring the download of specific app dependencies until they are required. Lazy loading may be helpful if your Blazor WebAssembly app has large dependencies that are only used for specific parts of the app.</p> <p>To delay the loading of an assembly, you add it to the <code>BlazorWebAssemblyLazyLoad</code> item group in your project file:</p> <p>Assemblies marked for lazy loading must be explicitly loaded by the app before they are used. To lazy load assemblies at runtime, use the <code>LazyAssemblyLoader</code> service:</p> <pre><code class="razor">@inject LazyAssemblyLoader LazyAssemblyLoader @code { var assemblies = await LazyAssemblyLoader.LoadAssembliesAsync(new string[] { "Lib1.dll" }); } </code></pre> <p>To lazy load assemblies for a specific page, use the <code>OnNavigateAsync</code> event on the <code>Router</code> component. The <code>OnNavigateAsync</code> event is fired on every page navigation and can be used to lazy load assemblies for a particular route. You can also lazily load the entire page for a route by passing any lazy loaded assemblies as additional assemblies to the <code>Router</code>.</p> <p>The following examples demonstrates using the <code>LazyAssemblyLoader</code> service to lazy load a specific dependency (<em>Lib1.dll</em>) when the user navigates to <em>/page1</em>. The lazy loaded assembly is then added to the additional assemblies list passed to the <code>Router</code> component, so that it can discover any routable components in that assembly.</p> <pre><code class="razor">@using System.Reflection @using Microsoft.AspNetCore.Components.Routing @using Microsoft.AspNetCore.Components.WebAssembly.Services @inject LazyAssemblyLoader LazyAssemblyLoader <Router AppAssembly="typeof(Program).Assembly" AdditionalAssemblies="lazyLoadedAssemblies" OnNavigateAsync="@OnNavigateAsync"> <Navigating> <div> <p>Loading the requested page...</p> </div> </Navigating> <Found Context="routeData"> <RouteView RouteData="@routeData" DefaultLayout="typeof(MainLayout)" /> </Found> <NotFound> <LayoutView Layout="typeof(MainLayout)"> <p>Sorry, there is nothing at this address.</p> </LayoutView> </NotFound> </Router> @code { private List<Assembly> lazyLoadedAssemblies = new List<Assembly>(); private async Task OnNavigateAsync(NavigationContext args) { if (args.Path.EndsWith("/page1")) { var assemblies = await LazyAssemblyLoader.LoadAssembliesAsync(new string[] { "Lib1.dll" }); lazyLoadedAssemblies.AddRange(assemblies); } } } </code></pre> <h3 id="updated-blazor-webassembly-globalization-support">Updated Blazor WebAssembly globalization support</h3> <p>.NET 5 Preview 8 reintroduces globalization support for Blazor WebAssembly based on International Components for Unicode (ICU). Part of introducing the ICU data and logic is optimizing these payloads for download size. This work is not fully completed yet. We expect to reduce the size of the ICU data in future .NET 5 preview updates.</p> <h3 id="new-inputradio-blazor-component">New <code>InputRadio</code> Blazor component</h3> <p>Blazor in .NET 5 now includes built-in <code>InputRadio</code> and <code>InputRadioGroup</code> components. These components simplify data binding to radio button groups with integrated <a href="https://docs.microsoft.com/aspnet/core/blazor/forms-validation">validation</a> alongside the other Blazor form input components.</p> <pre><code class="razor">Opinion about blazor: <InputRadioGroup @bind-Value="survey.OpinionAboutBlazor"> @foreach (var opinion in opinions) { <div class="form-check"> <InputRadio class="form-check-input" id="@opinion.id" Value="@opinion.id" /> <label class="form-check-label" for="@opinion.id">@opinion.label</label> </div> } </InputRadioGroup> </code></pre> <h3 id="set-ui-focus-in-blazor-apps">Set UI focus in Blazor apps</h3> <p>Blazor now has a <code>FocusAsync</code> convenience method on <code>ElementReference</code> for setting the UI focus on that element.</p> <pre><code class="razor"><button @onclick="() => textInput.FocusAsync()">Set focus</button> <input @ref="textInput"/> </code></pre> <h3 id="iasyncdisposable-support-for-blazor-components"><code>IAsyncDisposable</code> support for Blazor components</h3> <p>Blazor components now support the <code>IAsyncDisposable</code> interface for the asynchronous release of allocated resources.</p> <h3 id="control-blazor-component-instantiation">Control Blazor component instantiation</h3> <p>You can now control how Blazor components are instantiated by providing your own <code>IComponentActivator</code> service implementation.</p> <p>Thank you <a href="https://github.com/stsrki">Mladen Macanović</a> for this Blazor feature contribution!</p> <h3 id="influencing-the-html-head-in-blazor-apps">Influencing the HTML head in Blazor apps</h3> <p>Use the new <code>Title</code>, <code>Link</code>, and <code>Meta</code> components to programmatically set the title of a page and dynamically add <code>link</code> and <code>meta</code> tags to the HTML head in a Blazor app.</p> <p>To use the new <code>Title</code>, <code>Link</code>, and <code>Meta</code> components:</p> <ol> <li>Add a package reference to the Microsoft.AspNetCore.Components.Web.Extensions package.</li> <li>Include a script reference to <em>_content/Microsoft.AspNetCore.Components.Web.Extensions/headManager.js</em>.</li> <li>Add a <code>@using</code> directive for <code>Microsoft.AspNetCore.Components.Web.Extensions.Head</code>.</li> </ol> <p>The following example programmatically sets the page title to show the number of unread user notifications, and updates the page icon a as well:</p> <pre><code class="razor">@if (unreadNotificationsCount > 0) { var title = $"Notifications ({unreadNotificationsCount})"; <Title Value="title"></Title> <Link rel="icon" href="icon-unread.ico" /> } </code></pre> <h3 id="protected-browser-storage">Protected browser storage</h3> <p>In Blazor Server apps, you may want to persist app state in local or session storage so that the app can rehydrate it later if needed. When storing app state in the user’s browser, you also need to ensure that it hasn’t been tampered with.</p> <p>Blazor in .NET 5 helps solve this problem by providing two new services: <code>ProtectedLocalStorage</code> and <code>ProtectedSessionStorage</code>. These services help you store state in local and session storage respectively, and they take care of protecting the stored data using the ASP.NET Core data protection APIs.</p> <p>To use the new protected browser storage services:</p> <ol> <li>Add a package reference to Microsoft.AspNetCore.Components.Web.Extensions.</li> <li>Configure the services by calling <code>services.AddProtectedBrowserStorage()</code> from <code>Startup.ConfigureServcies</code>.</li> <li> <p>Inject either <code>ProtectedLocalStorage</code> and <code>ProtectedSessionStorage</code> into your component implementation:</p> <pre><code class="razor">@inject ProtectedLocalStorage ProtectedLocalStorage @inject ProtectedSessionStorage ProtectedSessionStorage </code></pre> </li> <li> <p>Use the desired service to get, set, and delete state asynchronously:</p> <pre><code class="csharp">private async Task IncrementCount() { await ProtectedLocalStorage.SetAsync("count", ++currentCount); } </code></pre> </li> </ol> <h3 id="model-binding-and-validation-with-c-9-record-types">Model binding and validation with C# 9 record types</h3> <p>You can now use C# 9 record types with model binding in an MVC controller or a Razor Page. Record types are a great way to model data being transmitted over the wire.</p> <p>For example, the <code>PersonController</code> below uses the <code>Person</code> record type with model binding and form validation:</p> <p>“`C# public record Person([Required] string Name, [Range(0, 150)] int Age);</p> <p>public class PersonController { public IActionResult Index() => View();</p> <p>[HttpPost] public IActionResult Index(Person person) { // … } }</p> <pre><code><br />*Person/Index.cshtml* ```razor @model Person Name: <input asp-for="Model.Name" /> <span asp-validation-for="Model.Name" /> Age: <input asp-for="Model.Age" /> <span asp-validation-for="Model.Age" /> </code></pre> <h3 id="improvements-to-dynamicroutevaluetransformer">Improvements to <code>DynamicRouteValueTransformer</code></h3> <p>ASP.NET Core in .NET Core 3.1 introduced <code>DynamicRouteValueTransformer</code> as a way to use use a custom endpoint to dynamically select an MVC controller action or a razor page. In .NET 5 Preview 8 you can now pass state to your <code>DynamicRouteValueTransformer</code> and filter the set of endpoints chosen.</p> <h3 id="auto-refresh-with-dotnet-watch">Auto refresh with <code>dotnet watch</code></h3> <p>In .NET 5, running <code>dotnet watch</code> on an ASP.NET Core project will now both launch the default browser and auto refresh the browser as you make changes to your code. This means you can open an ASP.NET Core project in your favorite text editor, run <code>dotnet watch</code> run once, and then focus on your code changes while the tooling handles rebuilding, restarting, and reloading your app. We expect to bring the auto refresh functionality to Visual Studio in the future as well.</p> <h3 id="console-logger-formatter">Console Logger Formatter</h3> <p>We’ve made improvements to the console log provider in the <code>Microsoft.Extensions.Logging</code> library. Developers can now implement a <a href="https://github.com/dotnet/runtime/issues/34742">custom <code>ConsoleFormatter</code></a> to exercise complete control over formatting and colorization of the console output. The formatter APIs allow for rich formatting by implementing a subset of the <code>VT-100</code> (supported by most modern terminals) escape sequences. The console logger can parse out escape sequences on unsupported terminals allowing you to author a single formatter for all terminals.</p> <h3 id="json-console-logger">JSON Console Logger</h3> <p>In addition to support for custom formatters, we’ve also added a built-in JSON formatter that emits structured JSON logs to the console. You can switch from the default <code>simple</code> logger to JSON, add to following snippet to your <code>Program.cs</code>:</p> <pre><code class="diff">public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) + .ConfigureLogging(logging => + { + logging.AddJsonConsole(options => + { + options.JsonWriterOptions = new JsonWriterOptions() { Indented = true }; + }); + }) .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup<Startup>(); }); </code></pre> <p>Once enabled, log messages emitted to the console are now JSON formatted.</p> <pre><code class="json">{ "EventId": 0, "LogLevel": "Information", "Category": "Microsoft.Hosting.Lifetime", "Message": "Now listening on: https://localhost:5001", "State": { "Message": "Now listening on: https://localhost:5001", "address": "https://localhost:5001", "{OriginalFormat}": "Now listening on: {address}" } } </code></pre> <h2 id="give-feedback">Give feedback</h2> <p>We hope you enjoy this release of ASP.NET Core in .NET 5! We are eager to hear about your experiences with this latest .NET 5 release. Let us know what you think by filing issues on <a href="https://github.com/dotnet/aspnetcore/issues">GitHub</a>.</p> <p>Thanks for trying out ASP.NET Core!</p> </div> https://www.sickgaming.net/blog/2020/08/25/asp-net-core-updates-in-net-5-preview-8/ |