Create an account


Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
ASP.NET Core and Blazor updates in .NET Core 3.0 Preview 9

#1
ASP.NET Core and Blazor updates in .NET Core 3.0 Preview 9

<div style="margin: 5px 5% 10px 5%;"><img src="https://www.sickgaming.net/blog/wp-content/uploads/2019/09/asp-net-core-and-blazor-updates-in-net-core-3-0-preview-9.jpg" width="150" height="150" title="" alt="" /></div><div><div class="row justify-content-center">
<div class="col-md-4">
<div><img src="https://www.sickgaming.net/blog/wp-content/uploads/2019/09/asp-net-core-and-blazor-updates-in-net-core-3-0-preview-9.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">
<p>September 4th, 2019</p>
</p></div>
<p><!-- .entry-meta --> </p>
<p><a href="https://devblogs.microsoft.com/dotnet/announcing-net-core-3-0-preview-9/">.NET Core 3.0 Preview 9 is now available</a> and it contains a number of improvements and updates to ASP.NET Core and Blazor.</p>
<p>Here’s the list of what’s new in this preview:</p>
<ul>
<li>Blazor event handlers and data binding attributes moved to Microsoft.AspNetCore.Components.Web</li>
<li>Blazor routing improvements
<ul>
<li>Render content using a specific layout</li>
<li>Routing decoupled from authorization</li>
<li>Route to components from multiple assemblies</li>
</ul>
</li>
<li>Render multiple Blazor components from MVC views or pages</li>
<li>Smarter reconnection for Blazor Server apps</li>
<li>Utility base component classes for managing a dependency injection scope</li>
<li>Razor component unit test framework prototype</li>
<li>Helper methods for returning Problem Details from controllers</li>
<li>New client API for gRPC</li>
<li>Support for async streams in streaming gRPC responses</li>
</ul>
<p>Please see the <a href="https://aka.ms/netcore3releasenotes">release notes</a> for additional details and known issues.</p>
<h2>Get started</h2>
<p>To get started with ASP.NET Core in .NET Core 3.0 Preview 9 <a href="https://aka.ms/netcore3download">install the .NET Core 3.0 Preview 9 SDK</a>.</p>
<p>If you’re on Windows using Visual Studio, <a href="https://visualstudio.com/preview">install the latest preview of Visual Studio 2019</a>.</p>
<p><em>.NET Core 3.0 Preview 9 requires Visual Studio 2019 16.3 Preview 3 or later</em>.</p>
<p>To install the latest Blazor WebAssembly template also run the following command:</p>
<pre><code>dotnet new -i Microsoft.AspNetCore.Blazor.Templates::3.0.0-preview9.19424.4
</code></pre>
<h2>Upgrade an existing project</h2>
<p>To upgrade an existing ASP.NET Core app to .NET Core 3.0 Preview 9, follow the <a href="https://docs.microsoft.com/en-us/aspnet/core/migration/22-to-30">migrations steps in the ASP.NET Core docs</a>.</p>
<p>Please also see the full list of <a href="https://github.com/aspnet/announcements/issues?utf8=%E2%9C%93&amp;q=is%3Aissue+label%3A3.0.0+label%3A%22Breaking+change%22">breaking changes</a> in ASP.NET Core 3.0.</p>
<p>To upgrade an existing ASP.NET Core 3.0 Preview 8 project to Preview 9:</p>
<ul>
<li>Update all Microsoft.AspNetCore.* package references to 3.0.0-preview9.19424.4</li>
<li>In Blazor apps and libraries:
<ul>
<li>Add a using statement for <code>Microsoft.AspNetCore.Components.Web</code> in your top level <em>_Imports.razor</em> file (see <a href="https://devblogs.microsoft.com/aspnet/asp-net-core-and-blazor-updates-in-net-core-3-0-preview-9/#blazor-web-attributes-moved">Blazor event handlers and data binding attributes moved to Microsoft.AspNetCore.Components.Web</a> below for details)</li>
<li>Add a using statement for <code>Microsoft.AspNetCore.Components.Authorization</code> in your top level <em>_Imports.razor</em> file.</li>
<li>Update all Blazor component parameters to be public.</li>
<li>Update implementations of <code>IJSRuntime</code> to return <code>ValueTask&lt;T&gt;</code>.</li>
<li>Replace calls to <code>MapBlazorHub&lt;TComponent&gt;</code> with a single call to <code>MapBlazorHub</code>.</li>
<li>Update calls to <code>RenderComponentAsync</code> and <code>RenderStaticComponentAsync</code> to use the new overloads to <code>RenderComponentAsync</code> that take a <code>RenderMode</code> parameter (see <a href="https://devblogs.microsoft.com/aspnet/asp-net-core-and-blazor-updates-in-net-core-3-0-preview-9/#multiple-components-in-views-or-pages">Render multiple Blazor components from MVC views or pages</a> below for details).</li>
<li>Update <em>App.razor</em> to use the updated <code>Router</code> component (see <a href="https://devblogs.microsoft.com/aspnet/asp-net-core-and-blazor-updates-in-net-core-3-0-preview-9/#blazor-routing-improvements">Blazor routing improvements</a> below for details).</li>
<li>(Optional) Remove page specific <em>_Imports.razor</em> file with the <code>@layout</code> directive to use the default layout specified through the router instead.</li>
<li>Remove any use of the <code>PageDisplay</code> component and replace with <code>LayoutView</code>, <code>RouteView</code>, or <code>AuthorizeRouteView</code> as appropriate (see <a href="https://devblogs.microsoft.com/aspnet/asp-net-core-and-blazor-updates-in-net-core-3-0-preview-9/#blazor-routing-improvements">Blazor routing improvements</a> below for details).</li>
<li>Replace uses of <code>IUriHelper</code> with <code>NavigationManager</code>.</li>
<li>Remove any use of <code>@refConfuseduppressField</code>.</li>
<li>Replace the previous <code>RevalidatingAuthenticationStateProvider</code> code with the new <code>RevalidatingIdentityAuthenticationStateProvider</code> code from the project template.</li>
<li>Replace <code>Microsoft.AspNetCore.Components.UIEventArgs</code> with <code>System.EventArgs</code> and remove the “UI” prefix from all <code>EventArgs</code> derived types (<code>UIChangeEventArgs</code> -&gt; <code>ChangeEventArgs</code>, etc.).</li>
<li>Replace <code>DotNetObjectRef</code> with <code>DotNetObjectReference</code>.</li>
<li>Replace <code>OnAfterRender()</code> and <code>OnAfterRenderAsync()</code> implementations with <code>OnAfterRender(bool firstRender)</code> or <code>OnAfterRenderAsync(bool firstRender)</code>.</li>
</ul>
</li>
<li>In gRPC projects:
<ul>
<li>Update calls to <code>GrpcClient.Create</code> with a call <code>GrpcChannel.ForAddress</code> to create a new gRPC channel and new up your typed gRPC clients using this channel.</li>
<li>Rebuild any project or project dependency that uses gRPC code generation for an ABI change in which all clients inherit from <code>ClientBase</code> instead of <code>LiteClientBase</code>. There are no code changes required for this change. </li>
<li>Please also see the <a href="https://github.com/grpc/grpc-dotnet/issues/485">grpc-dotnet announcement</a> for all changes.</li>
</ul>
</li>
</ul>
<p>You should now be all set to use .NET Core 3.0 Preview 9!</p>
<h2>Blazor event handlers and data binding attributes moved to Microsoft.AspNetCore.Components.Web</h2>
<p>In this release we moved the set of bindings and event handlers available for HTML elements into the Microsoft.AspNetCore.Components.Web.dll assembly and into the <code>Microsoft.AspNetCore.Components.Web</code> namespace. This change was made to isolate the web specific aspects of the Blazor programming from the core programming model. This section provides additional details on how to upgrade your existing projects to react to this change.</p>
<h3>Blazor apps</h3>
<p>Open the application’s root <em>_Imports.razor</em> and add <code>@using Microsoft.AspNetCore.Components.Web</code>. Blazor apps get a reference to the Microsoft.AspNetCore.Components.Web package implicitly without any additional package references, so adding a reference to this package isn’t necessary.</p>
<h3>Blazor libraries</h3>
<p>Add a package reference to the Microsoft.AspNetCore.Components.Web package package if you don’t already have one. Then open the root <em>_Imports.razor</em> file for the project (create the file if you don’t already have it) and add <code>@using Microsoft.AspNetCore.Components.Web</code>.</p>
<h3>Troubleshooting guidance</h3>
<p>With the correct references and using statement for <code>Microsoft.AspNetCore.Components.Web</code>, event handlers like <code>@onclick</code> and <code>@bind</code> should be bold font and colorized as shown below when using Visual Studio.</p>
<p><img src="https://www.sickgaming.net/blog/wp-content/uploads/2019/09/asp-net-core-and-blazor-updates-in-net-core-3-0-preview-9.png" alt="Events and binding working in Visual Studio"></p>
<p>If <code>@bind</code> or <code>@onclick</code> are colorized as a normal HTML attribute, then the <code>@using</code> statement is missing.</p>
<p><img src="https://www.sickgaming.net/blog/wp-content/uploads/2019/09/asp-net-core-and-blazor-updates-in-net-core-3-0-preview-9-1.png" alt="Events and binding not recognized"></p>
<p>If you’re missing a using statement for the <code>Microsoft.AspNetCore.Components.Web</code> namespace, you may see build failures. For example, the following build error for the code shown above indicates that the <code>@bind</code> attribute wasn’t recognized:</p>
<pre><code>CS0169 The field 'Index.text' is never used
CS0428 Cannot convert method group 'Submit' to non-delegate type 'object'. Did you intend to invoke the method?
</code></pre>
<p>In other cases you may get a runtime exception and the app fails to render. For example, the following runtime exception seen in the browser console indicates that the <code>@onclick</code> attribute wasn’t recognized:</p>
<pre><code>Error: There was an error applying batch 2.
DOMException: Failed to execute 'setAttribute' on 'Element': '@onclick' is not a valid attribute name.
</code></pre>
<p>Add a using statement for the <code>Microsoft.AspNetCore.Components.Web</code> namespace to address these issues. If adding the using statement fixed the problem, consider moving to the using statement app’s root <em>_Imports.razor</em> so it will apply to all files.</p>
<p>If you add the <code>Microsoft.AspNetCore.Components.Web</code> namespace but get the following build error, then you’re missing a package reference to the Microsoft.AspNetCore.Components.Web package:</p>
<pre><code>CS0234 The type or namespace name 'Web' does not exist in the namespace 'Microsoft.AspNetCore.Components' (are you missing an assembly reference?)
</code></pre>
<p>Add a package reference to the Microsoft.AspNetCore.Components.Web package to address the issue.</p>
<h2>Blazor routing improvements</h2>
<p>In this release we’ve revised the Blazor <code>Router</code> component to make it more flexible and to enable new scenarios. The <code>Router</code> component in Blazor handles rendering the correct component that matches the current address. Routable components are marked with the <code>@page</code> directive, which adds the <code>RouteAttribute</code> to the generated component classes. If the current address matches a route, then the <code>Router</code> renders the contents of its <code>Found</code> parameter. If no route matches, then the <code>Router</code> component renders the contents of its <code>NotFound</code> parameter.</p>
<p>To render the component with the matched route, use the new <code>RouteView</code> component passing in the supplied <code>RouteData</code> from the <code>Router</code> along with any desired parameters. The <code>RouteView</code> component will render the matched component with its layout if it has one. You can also optionally specify a default layout to use if the matched component doesn’t have one.</p>
<pre><code class="razor">&lt;Router AppAssembly="typeof(Program).Assembly"&gt; &lt;Found Context="routeData"&gt; &lt;RouteView RouteData="routeData" DefaultLayout="typeof(MainLayout)" /&gt; &lt;/Found&gt; &lt;NotFound&gt; &lt;h1&gt;Page not found&lt;/h1&gt; &lt;p&gt;Sorry, but there's nothing here!&lt;/p&gt; &lt;/NotFound&gt;
&lt;/Router&gt;
</code></pre>
<h3>Render content using a specific layout</h3>
<p>To render a component using a particular layout, use the new <code>LayoutView</code> component. This is useful when specifying content for not found pages that you still want to use the app’s layout.</p>
<pre><code class="razor">&lt;Router AppAssembly="typeof(Program).Assembly"&gt; &lt;Found Context="routeData"&gt; &lt;RouteView RouteData="routeData" DefaultLayout="typeof(MainLayout)" /&gt; &lt;/Found&gt; &lt;NotFound&gt; &lt;LayoutView Layout="typeof(MainLayout)"&gt; &lt;h1&gt;Page not found&lt;/h1&gt; &lt;p&gt;Sorry, but there's nothing here!&lt;/p&gt; &lt;/LayoutView&gt; &lt;/NotFound&gt;
&lt;/Router&gt;
</code></pre>
<h3>Routing decoupled from authorization</h3>
<p>Authorization is no longer handled directly by the <code>Router</code>. Instead, you use the <code>AuthorizeRouteView</code> component. The <code>AuthorizeRouteView</code> component is a <code>RouteView</code> that will only render the matched component if the user is authorized. Authorization rules for specific components are specified using the <code>AuthorizeAttribute</code>. The <code>AuthorizeRouteView</code> component also sets up the <code>AuthenticationState</code> as a cascading value if there isn’t one already. Otherwise, you can still manually setup the <code>AuthenticationState</code> as a cascading value using the <code>CascadingAuthenticationState</code> component.</p>
<pre><code class="razor">&lt;Router AppAssembly="@typeof(Program).Assembly"&gt; &lt;Found Context="routeData"&gt; &lt;AuthorizeRouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" /&gt; &lt;/Found&gt; &lt;NotFound&gt; &lt;CascadingAuthenticationState&gt; &lt;LayoutView Layout="@typeof(MainLayout)"&gt; &lt;p&gt;Sorry, there's nothing at this address.&lt;/p&gt; &lt;/LayoutView&gt; &lt;/CascadingAuthenticationState&gt; &lt;/NotFound&gt;
&lt;/Router&gt;
</code></pre>
<p>You can optionally set the <code>NotAuthorized</code> and <code>Authorizing</code> parameters of the <code>AuthorizedRouteView</code> component to specify content to display if the user is not authorized or authorization is still in progress.</p>
<pre><code class="razor">&lt;Router AppAssembly="@typeof(Program).Assembly"&gt; &lt;Found Context="routeData"&gt; &lt;AuthorizeRouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)"&gt; &lt;NotAuthorized&gt; &lt;p&gt;Nope, nope!&lt;/p&gt; &lt;/NotAuthorized&gt; &lt;/AuthorizeRouteView&gt; &lt;/Found&gt;
&lt;/Router&gt;
</code></pre>
<h3>Route to components from multiple assemblies</h3>
<p>You can now specify additional assemblies for the <code>Router</code> component to consider when searching for routable components. These assemblies will be considered in addition to the specified <code>AppAssembly</code>. You specify these assemblies using the <code>AdditionalAssemblies</code> parameter. For example, if <code>Component1</code> is a routable component defined in a referenced class library, then you can support routing to this component like this:</p>
<pre><code class="razor">&lt;Router AppAssembly="typeof(Program).Assembly" AdditionalAssemblies="new[] { typeof(Component1).Assembly }&gt; ...
&lt;/Router&gt;
</code></pre>
<h2>Render multiple Blazor components from MVC views or pages</h2>
<p>We’ve reenabled support for rendering multiple components from a view or page in a Blazor Server app. To render a component from a .cshtml file, use the <code>Html.RenderComponentAsync&lt;TComponent&gt;(RenderMode renderMode, object parameters)</code> HTML helper method with the desired <code>RenderMode</code>.</p>
<table>
<thead>
<tr>
<th>RenderMode</th>
<th>Description</th>
<th>Supports parameters?</th>
</tr>
</thead>
<tbody>
<tr>
<td>Static</td>
<td>Statically render the component with the specified parameters.</td>
<td>Yes</td>
</tr>
<tr>
<td>Server</td>
<td>Render a marker where the component should be rendered interactively by the Blazor Server app.</td>
<td>No</td>
</tr>
<tr>
<td>ServerPrerendered</td>
<td>Statically prerender the component along with a marker to indicate the component should later be rendered interactively by the Blazor Server app.</td>
<td>No</td>
</tr>
</tbody>
</table>
<p>Support for stateful prerendering has been removed in this release due to security concerns. You can no longer prerender components and then connect back to the same component state when the app loads. We may reenable this feature in a future release post .NET Core 3.0.</p>
<p>Blazor Server apps also no longer require that the entry point components be registered in the app’s <code>Configure</code> method. Only a single call to <code>MapBlazorHub()</code> is required.</p>
<h2>Smarter reconnection for Blazor Server apps</h2>
<p>Blazor Server apps are stateful and require an active connection to the server in order to function. If the network connection is lost, the app will try to reconnect to the server. If the connection can be reestablished but the server state is lost, then reconnection will fail. Blazor Server apps will now detect this condition and recommend the user to refresh the browser instead of retrying to connect.</p>
<p><img src="https://www.sickgaming.net/blog/wp-content/uploads/2019/09/asp-net-core-and-blazor-updates-in-net-core-3-0-preview-9-2.png" alt="Blazor Server reconnect rejected"></p>
<h2>Utility base component classes for managing a dependency injection scope</h2>
<p>In ASP.NET Core apps, scoped services are typically scoped to the current request. After the request completes, any scoped or transient services are disposed by the dependency injection (DI) system. In Blazor Server apps, the request scope lasts for the duration of the client connection, which can result in transient and scoped services living much longer than expected.</p>
<p>To scope services to the lifetime of a component you can use the new <code>OwningComponentBase</code> and <code>OwningComponentBase&lt;TService&gt;</code> base classes. These base classes expose a <code>ScopedServices</code> property of type <code>IServiceProvider</code> that can be used to resolve services that are scoped to the lifetime of the component. To author a component that inherits from a base class in Razor use the <code>@inherits</code> directive.</p>
<pre><code class="razor">@page "/users"
@attribute [Authorize]
@inherits OwningComponentBase&lt;Data.ApplicationDbContext&gt; &lt;h1&gt;Users (@Service.Users.Count())&lt;/h1&gt;
&lt;ul&gt; @foreach (var user in Service.Users) { &lt;li&gt;@user.UserName&lt;/li&gt; }
&lt;/ul&gt;
</code></pre>
<p>Note: Services injected into the component using <code>@inject</code> or the <code>InjectAttribute</code> are <em>not</em> created in the component’s scope and will still be tied to the request scope.</p>
<h2>Razor component unit test framework prototype</h2>
<p>We’ve started experimenting with building a unit test framework for Razor components. You can read about the prototype in Steve Sanderson’s <a href="http://blog.stevensanderson.com/2019/08/29/blazor-unit-testing-prototype/">Unit testing Blazor components – a prototype</a> blog post. While this work won’t ship with .NET Core 3.0, we’d still love to get your feedback early in the design process. Take a look at the <a href="https://github.com/SteveSandersonMS/BlazorUnitTestingPrototype">code on GitHub</a> and let us know what you think!</p>
<h2>Helper methods for returning Problem Details from controllers</h2>
<p>Problem Details is a standardized format for returning error information from an HTTP endpoint. We’ve added new <code>Problem</code> and <code>ValidationProblem</code> method overloads to controllers that use optional parameters to simplify returning Problem Detail responses.</p>
<pre><code class="csharp">[Route("/error")]
public ActionResult&lt;ProblemDetails&gt; HandleError()
{ return Problem(title: "An error occurred while processing your request", statusCode: 500);
}
</code></pre>
<h2>New client API for gRPC</h2>
<p>To improve compatibility with the existing <code>Grpc.Core</code> implementation, we’ve changed our client API to use gRPC channels. The channel is where gRPC configuration is set and it is used to create strongly typed clients. The new API provides a more consistent client experience with <code>Grpc.Core</code>, making it easier to switch between using the two libraries.</p>
<pre><code class="csharp">// Old
using var httpClient = new HttpClient() { BaseAddress = new Uri("https://localhost:5001") };
var client = GrpcClient.Create&lt;GreeterClient&gt;(httpClient); // New
var channel = GrpcChannel.ForAddress("https://localhost:5001");
var client = new GreeterClient(channel); var reply = await client.GreetAsync(new HelloRequest { Name = "Santa" });
</code></pre>
<h2>Support for async streams in streaming gRPC responses</h2>
<p>gRPC streaming responses return a custom <code>IAsyncStreamReader</code> type that can be iterated on to receive all response messages in a streaming response. With the addition of async streams in C# 8, we’ve added a new extension method that makes for a more ergonomic API while consuming streaming responses.</p>
<pre><code class="csharp">// Old
while (await requestStream.MoveNext(CancellationToken.None))
{ var message = requestStream.Current; // …
} // New and improved
await foreach (var message in requestStream.ReadAllAsync())
{ // …
}
</code></pre>
<h2>Give feedback</h2>
<p>We hope you enjoy the new features in this preview release of ASP.NET Core and Blazor! Please let us know what you think by filing issues on <a href="https://github.com/aspnet/aspnetcore/issues">GitHub</a>.</p>
<p>Thanks for trying out ASP.NET Core and Blazor!</p>
<div class="authorinfoarea">
<div><img src="https://www.sickgaming.net/blog/wp-content/uploads/2019/09/asp-net-core-and-blazor-updates-in-net-core-3-0-preview-9.jpg" width="96" height="96" alt="Daniel Roth" class="avatar avatar-96 wp-user-avatar wp-user-avatar-96 alignnone photo"></div>
<div>
<h5><a class="no-underline" aria-label="Daniel Roth" target="_blank" href="https://devblogs.microsoft.com/aspnet/author/danroth27/" rel="noopener noreferrer">Daniel Roth</a></h5>
<p>Principal Program Manager,&nbsp;ASP.NET</p>
<p><strong>Follow Daniel</strong>&nbsp;&nbsp;&nbsp;<a class="no-underline stayinformed" aria-label="Daniel Roth Twitter profile" target="_blank" href="https://twitter.com/danroth27" rel="noopener noreferrer"><i class="fa fa-twitter"></i></a><a class="no-underline stayinformed" aria-label="Daniel Roth GitHub profile" target="_blank" href="https://github.com/danroth27" rel="noopener noreferrer"><i class="fa fa-github"></i></a><a class="no-underline stayinformed hvr-pop" aria-label="Daniel Roth RSS Feed" target="_blank" href="https://devblogs.microsoft.com/aspnet/author/danroth27/feed/" rel="noopener noreferrer"></a></p>
</p></div>
</p></div>
</div>


https://www.sickgaming.net/blog/2019/09/...preview-9/
Reply



Forum Jump:


Users browsing this thread:
1 Guest(s)

Forum software by © MyBB Theme © iAndrew 2016